tunnel.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package tunneldns
  2. import (
  3. "net"
  4. "strconv"
  5. "sync"
  6. "github.com/coredns/coredns/core/dnsserver"
  7. "github.com/coredns/coredns/plugin"
  8. "github.com/coredns/coredns/plugin/cache"
  9. "github.com/pkg/errors"
  10. "github.com/rs/zerolog"
  11. )
  12. const (
  13. LogFieldAddress = "address"
  14. LogFieldURL = "url"
  15. MaxUpstreamConnsDefault = 5
  16. )
  17. // Listener is an adapter between CoreDNS server and Warp runnable
  18. type Listener struct {
  19. server *dnsserver.Server
  20. wg sync.WaitGroup
  21. log *zerolog.Logger
  22. }
  23. // Create a CoreDNS server plugin from configuration
  24. func createConfig(address string, port uint16, p plugin.Handler) *dnsserver.Config {
  25. c := &dnsserver.Config{
  26. Zone: ".",
  27. Transport: "dns",
  28. ListenHosts: []string{address},
  29. Port: strconv.FormatUint(uint64(port), 10),
  30. }
  31. c.AddPlugin(func(next plugin.Handler) plugin.Handler { return p })
  32. return c
  33. }
  34. // Start blocks for serving requests
  35. func (l *Listener) Start(readySignal chan struct{}) error {
  36. defer close(readySignal)
  37. l.log.Info().Str(LogFieldAddress, l.server.Address()).Msg("Starting DNS over HTTPS proxy server")
  38. // Start UDP listener
  39. if udp, err := l.server.ListenPacket(); err == nil {
  40. l.wg.Add(1)
  41. go func() {
  42. _ = l.server.ServePacket(udp)
  43. l.wg.Done()
  44. }()
  45. } else {
  46. return errors.Wrap(err, "failed to create a UDP listener")
  47. }
  48. // Start TCP listener
  49. tcp, err := l.server.Listen()
  50. if err == nil {
  51. l.wg.Add(1)
  52. go func() {
  53. _ = l.server.Serve(tcp)
  54. l.wg.Done()
  55. }()
  56. }
  57. return errors.Wrap(err, "failed to create a TCP listener")
  58. }
  59. // Stop signals server shutdown and blocks until completed
  60. func (l *Listener) Stop() error {
  61. if err := l.server.Stop(); err != nil {
  62. return err
  63. }
  64. l.wg.Wait()
  65. return nil
  66. }
  67. // CreateListener configures the server and bound sockets
  68. func CreateListener(address string, port uint16, upstreams []string, bootstraps []string, maxUpstreamConnections int, log *zerolog.Logger) (*Listener, error) {
  69. // Build the list of upstreams
  70. upstreamList := make([]Upstream, 0)
  71. for _, url := range upstreams {
  72. log.Info().Str(LogFieldURL, url).Msg("Adding DNS upstream")
  73. upstream, err := NewUpstreamHTTPS(url, bootstraps, maxUpstreamConnections, log)
  74. if err != nil {
  75. return nil, errors.Wrap(err, "failed to create HTTPS upstream")
  76. }
  77. upstreamList = append(upstreamList, upstream)
  78. }
  79. // Create a local cache with HTTPS proxy plugin
  80. chain := cache.New()
  81. chain.Next = ProxyPlugin{
  82. Upstreams: upstreamList,
  83. }
  84. // Format an endpoint
  85. endpoint := "dns://" + net.JoinHostPort(address, strconv.FormatUint(uint64(port), 10))
  86. // Create the actual middleware server
  87. server, err := dnsserver.NewServer(endpoint, []*dnsserver.Config{createConfig(address, port, NewMetricsPlugin(chain))})
  88. if err != nil {
  89. return nil, err
  90. }
  91. return &Listener{server: server, log: log}, nil
  92. }