tunnel.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package tunneldns
  2. import (
  3. "net"
  4. "os"
  5. "os/signal"
  6. "strconv"
  7. "sync"
  8. "syscall"
  9. "github.com/cloudflare/cloudflared/cmd/cloudflared/cliutil"
  10. "github.com/cloudflare/cloudflared/cmd/cloudflared/config"
  11. "github.com/cloudflare/cloudflared/logger"
  12. "github.com/cloudflare/cloudflared/metrics"
  13. "github.com/coredns/coredns/core/dnsserver"
  14. "github.com/coredns/coredns/plugin"
  15. "github.com/coredns/coredns/plugin/cache"
  16. "github.com/pkg/errors"
  17. "github.com/urfave/cli/v2"
  18. )
  19. // Listener is an adapter between CoreDNS server and Warp runnable
  20. type Listener struct {
  21. server *dnsserver.Server
  22. wg sync.WaitGroup
  23. logger logger.Service
  24. }
  25. // Run implements a foreground runner
  26. func Run(c *cli.Context) error {
  27. logDirectory, logLevel := config.FindLogSettings()
  28. logger, err := logger.New(logger.DefaultFile(logDirectory), logger.LogLevelString(logLevel))
  29. if err != nil {
  30. return cliutil.PrintLoggerSetupError("error setting up logger", err)
  31. }
  32. metricsListener, err := net.Listen("tcp", c.String("metrics"))
  33. if err != nil {
  34. logger.Fatalf("Failed to open the metrics listener: %s", err)
  35. }
  36. go metrics.ServeMetrics(metricsListener, nil, logger)
  37. listener, err := CreateListener(c.String("address"), uint16(c.Uint("port")), c.StringSlice("upstream"), c.StringSlice("bootstrap"), logger)
  38. if err != nil {
  39. logger.Errorf("Failed to create the listeners: %s", err)
  40. return err
  41. }
  42. // Try to start the server
  43. readySignal := make(chan struct{})
  44. err = listener.Start(readySignal)
  45. if err != nil {
  46. logger.Errorf("Failed to start the listeners: %s", err)
  47. return listener.Stop()
  48. }
  49. <-readySignal
  50. // Wait for signal
  51. signals := make(chan os.Signal, 10)
  52. signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
  53. defer signal.Stop(signals)
  54. <-signals
  55. // Shut down server
  56. err = listener.Stop()
  57. if err != nil {
  58. logger.Errorf("failed to stop: %s", err)
  59. }
  60. return err
  61. }
  62. // Create a CoreDNS server plugin from configuration
  63. func createConfig(address string, port uint16, p plugin.Handler) *dnsserver.Config {
  64. c := &dnsserver.Config{
  65. Zone: ".",
  66. Transport: "dns",
  67. ListenHosts: []string{address},
  68. Port: strconv.FormatUint(uint64(port), 10),
  69. }
  70. c.AddPlugin(func(next plugin.Handler) plugin.Handler { return p })
  71. return c
  72. }
  73. // Start blocks for serving requests
  74. func (l *Listener) Start(readySignal chan struct{}) error {
  75. defer close(readySignal)
  76. l.logger.Infof("Starting DNS over HTTPS proxy server on: %s", l.server.Address())
  77. // Start UDP listener
  78. if udp, err := l.server.ListenPacket(); err == nil {
  79. l.wg.Add(1)
  80. go func() {
  81. l.server.ServePacket(udp)
  82. l.wg.Done()
  83. }()
  84. } else {
  85. return errors.Wrap(err, "failed to create a UDP listener")
  86. }
  87. // Start TCP listener
  88. tcp, err := l.server.Listen()
  89. if err == nil {
  90. l.wg.Add(1)
  91. go func() {
  92. l.server.Serve(tcp)
  93. l.wg.Done()
  94. }()
  95. }
  96. return errors.Wrap(err, "failed to create a TCP listener")
  97. }
  98. // Stop signals server shutdown and blocks until completed
  99. func (l *Listener) Stop() error {
  100. if err := l.server.Stop(); err != nil {
  101. return err
  102. }
  103. l.wg.Wait()
  104. return nil
  105. }
  106. // CreateListener configures the server and bound sockets
  107. func CreateListener(address string, port uint16, upstreams []string, bootstraps []string, logger logger.Service) (*Listener, error) {
  108. // Build the list of upstreams
  109. upstreamList := make([]Upstream, 0)
  110. for _, url := range upstreams {
  111. logger.Infof("Adding DNS upstream - url: %s", url)
  112. upstream, err := NewUpstreamHTTPS(url, bootstraps, logger)
  113. if err != nil {
  114. return nil, errors.Wrap(err, "failed to create HTTPS upstream")
  115. }
  116. upstreamList = append(upstreamList, upstream)
  117. }
  118. // Create a local cache with HTTPS proxy plugin
  119. chain := cache.New()
  120. chain.Next = ProxyPlugin{
  121. Upstreams: upstreamList,
  122. }
  123. // Format an endpoint
  124. endpoint := "dns://" + net.JoinHostPort(address, strconv.FormatUint(uint64(port), 10))
  125. // Create the actual middleware server
  126. server, err := dnsserver.NewServer(endpoint, []*dnsserver.Config{createConfig(address, port, NewMetricsPlugin(chain))})
  127. if err != nil {
  128. return nil, err
  129. }
  130. return &Listener{server: server, logger: logger}, nil
  131. }