resolver_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. package libnetwork
  2. import (
  3. "context"
  4. "encoding/hex"
  5. "errors"
  6. "net"
  7. "syscall"
  8. "testing"
  9. "time"
  10. "github.com/containerd/log"
  11. "github.com/docker/docker/internal/testutils/netnsutils"
  12. "github.com/miekg/dns"
  13. "github.com/sirupsen/logrus"
  14. "gotest.tools/v3/assert"
  15. is "gotest.tools/v3/assert/cmp"
  16. )
  17. // a simple/null address type that will be used to fake a local address for unit testing
  18. type tstaddr struct {
  19. network string
  20. }
  21. func (a *tstaddr) Network() string {
  22. if a.network != "" {
  23. return a.network
  24. }
  25. return "tcp"
  26. }
  27. func (a *tstaddr) String() string { return "(fake)" }
  28. // a simple writer that implements dns.ResponseWriter for unit testing purposes
  29. type tstwriter struct {
  30. network string
  31. msg *dns.Msg
  32. }
  33. func (w *tstwriter) WriteMsg(m *dns.Msg) (err error) {
  34. w.msg = m
  35. return nil
  36. }
  37. func (w *tstwriter) Write(m []byte) (int, error) { return 0, nil }
  38. func (w *tstwriter) LocalAddr() net.Addr {
  39. return &tstaddr{network: w.network}
  40. }
  41. func (w *tstwriter) RemoteAddr() net.Addr {
  42. return &tstaddr{network: w.network}
  43. }
  44. func (w *tstwriter) TsigStatus() error { return nil }
  45. func (w *tstwriter) TsigTimersOnly(b bool) {}
  46. func (w *tstwriter) Hijack() {}
  47. func (w *tstwriter) Close() error { return nil }
  48. func (w *tstwriter) GetResponse() *dns.Msg { return w.msg }
  49. func (w *tstwriter) ClearResponse() { w.msg = nil }
  50. func checkNonNullResponse(t *testing.T, m *dns.Msg) {
  51. t.Helper()
  52. if m == nil {
  53. t.Fatal("Null DNS response found. Non Null response msg expected.")
  54. }
  55. }
  56. func checkDNSAnswersCount(t *testing.T, m *dns.Msg, expected int) {
  57. t.Helper()
  58. answers := len(m.Answer)
  59. if answers != expected {
  60. t.Fatalf("Expected number of answers in response: %d. Found: %d", expected, answers)
  61. }
  62. }
  63. func checkDNSResponseCode(t *testing.T, m *dns.Msg, expected int) {
  64. t.Helper()
  65. if m.MsgHdr.Rcode != expected {
  66. t.Fatalf("Expected DNS response code: %d. Found: %d", expected, m.MsgHdr.Rcode)
  67. }
  68. }
  69. func checkDNSRRType(t *testing.T, actual, expected uint16) {
  70. t.Helper()
  71. if actual != expected {
  72. t.Fatalf("Expected DNS Rrtype: %d. Found: %d", expected, actual)
  73. }
  74. }
  75. func newDNSHandlerServFailOnce(requests *int) func(w dns.ResponseWriter, r *dns.Msg) {
  76. return func(w dns.ResponseWriter, r *dns.Msg) {
  77. m := new(dns.Msg)
  78. m.SetReply(r)
  79. m.Compress = false
  80. if *requests == 0 {
  81. m.SetRcode(r, dns.RcodeServerFailure)
  82. }
  83. *requests = *requests + 1
  84. if err := w.WriteMsg(m); err != nil {
  85. log.G(context.TODO()).WithError(err).Error("Error writing dns response")
  86. }
  87. }
  88. }
  89. func waitForLocalDNSServer(t *testing.T) {
  90. retries := 0
  91. maxRetries := 10
  92. for retries < maxRetries {
  93. t.Log("Try connecting to DNS server ...")
  94. // this test and retry mechanism only works for TCP. With UDP there is no
  95. // connection and the test becomes inaccurate leading to unpredictable results
  96. tconn, err := net.DialTimeout("tcp", "127.0.0.1:53", 10*time.Second)
  97. retries = retries + 1
  98. if err != nil {
  99. if oerr, ok := err.(*net.OpError); ok {
  100. // server is probably initializing
  101. if oerr.Err == syscall.ECONNREFUSED {
  102. continue
  103. }
  104. } else {
  105. // something is wrong: we should stop for analysis
  106. t.Fatal(err)
  107. }
  108. }
  109. if tconn != nil {
  110. tconn.Close()
  111. break
  112. }
  113. }
  114. }
  115. // Packet 24 extracted from
  116. // https://gist.github.com/vojtad/3bac63b8c91b1ec50e8d8b36047317fa/raw/7d75eb3d3448381bf252ae55ea5123a132c46658/host.pcap
  117. // (https://github.com/moby/moby/issues/44575)
  118. // which is a non-compliant DNS reply > 512B (w/o EDNS(0)) to the query
  119. //
  120. // s3.amazonaws.com. IN A
  121. const oversizedDNSReplyMsg = "\xf5\x11\x81\x80\x00\x01\x00\x20\x00\x00\x00\x00\x02\x73\x33\x09" +
  122. "\x61\x6d\x61\x7a\x6f\x6e\x61\x77\x73\x03\x63\x6f\x6d\x00\x00\x01" +
  123. "\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  124. "\x11\x9e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  125. "\x4c\x66\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  126. "\xda\x10\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  127. "\x01\x3e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  128. "\x88\x68\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  129. "\x66\x9e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  130. "\x5f\x28\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  131. "\x8e\x4e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x36\xe7" +
  132. "\x84\xf0\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd8" +
  133. "\x92\x45\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  134. "\x8f\xa6\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x36\xe7" +
  135. "\xc0\xd0\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  136. "\xfe\x28\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  137. "\xaa\x3d\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  138. "\x4e\x56\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  139. "\xea\xb0\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  140. "\x6d\xed\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  141. "\x28\x00\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd9" +
  142. "\xe9\x78\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd9" +
  143. "\x6e\x9e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd9" +
  144. "\x45\x86\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd8" +
  145. "\x30\x38\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x36\xe7" +
  146. "\xc6\xa8\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x03\x05" +
  147. "\x01\x9d\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  148. "\xa8\xe8\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  149. "\x64\xa6\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd8" +
  150. "\x3c\x48\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd8" +
  151. "\x35\x20\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  152. "\x54\xf6\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  153. "\x5d\x36\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  154. "\x30\x36\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x36\xe7" +
  155. "\x83\x90"
  156. // Regression test for https://github.com/moby/moby/issues/44575
  157. func TestOversizedDNSReply(t *testing.T) {
  158. srv, err := net.ListenPacket("udp", "127.0.0.1:0")
  159. assert.NilError(t, err)
  160. defer srv.Close()
  161. go func() {
  162. buf := make([]byte, 65536)
  163. for {
  164. n, src, err := srv.ReadFrom(buf)
  165. if errors.Is(err, net.ErrClosed) {
  166. return
  167. }
  168. t.Logf("[<-%v]\n%s", src, hex.Dump(buf[:n]))
  169. if n < 2 {
  170. continue
  171. }
  172. resp := []byte(oversizedDNSReplyMsg)
  173. resp[0], resp[1] = buf[0], buf[1] // Copy query ID into response.
  174. _, err = srv.WriteTo(resp, src)
  175. if errors.Is(err, net.ErrClosed) {
  176. return
  177. }
  178. if err != nil {
  179. t.Log(err)
  180. }
  181. }
  182. }()
  183. srvAddr := srv.LocalAddr().(*net.UDPAddr)
  184. rsv := NewResolver("", true, noopDNSBackend{})
  185. // The resolver logs lots of valuable info at level debug. Redirect it
  186. // to t.Log() so the log spew is emitted only if the test fails.
  187. rsv.logger = testLogger(t)
  188. rsv.SetExtServers([]extDNSEntry{
  189. {IPStr: srvAddr.IP.String(), port: uint16(srvAddr.Port), HostLoopback: true},
  190. })
  191. w := &tstwriter{network: srvAddr.Network()}
  192. q := new(dns.Msg).SetQuestion("s3.amazonaws.com.", dns.TypeA)
  193. rsv.serveDNS(w, q)
  194. resp := w.GetResponse()
  195. checkNonNullResponse(t, resp)
  196. t.Log("Response: ", resp.String())
  197. checkDNSResponseCode(t, resp, dns.RcodeSuccess)
  198. assert.Assert(t, len(resp.Answer) >= 1)
  199. checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA)
  200. }
  201. func testLogger(t *testing.T) *logrus.Entry {
  202. logger := logrus.New()
  203. logger.SetLevel(logrus.DebugLevel)
  204. logger.SetOutput(tlogWriter{t})
  205. return logrus.NewEntry(logger)
  206. }
  207. type tlogWriter struct{ t *testing.T }
  208. func (w tlogWriter) Write(p []byte) (n int, err error) {
  209. w.t.Logf("%s", p)
  210. return len(p), nil
  211. }
  212. type noopDNSBackend struct{ DNSBackend }
  213. func (noopDNSBackend) ResolveName(_ context.Context, name string, iplen int) ([]net.IP, bool) {
  214. return nil, false
  215. }
  216. func (noopDNSBackend) ExecFunc(f func()) error { f(); return nil }
  217. func (noopDNSBackend) NdotsSet() bool { return false }
  218. func (noopDNSBackend) HandleQueryResp(name string, ip net.IP) {}
  219. func TestReplySERVFAIL(t *testing.T) {
  220. cases := []struct {
  221. name string
  222. q *dns.Msg
  223. proxyDNS bool
  224. }{
  225. {
  226. name: "InternalError",
  227. q: new(dns.Msg).SetQuestion("_sip._tcp.example.com.", dns.TypeSRV),
  228. },
  229. {
  230. name: "ProxyDNS=false",
  231. q: new(dns.Msg).SetQuestion("example.com.", dns.TypeA),
  232. },
  233. {
  234. name: "ProxyDNS=true", // No extDNS servers configured -> no answer from any upstream
  235. q: new(dns.Msg).SetQuestion("example.com.", dns.TypeA),
  236. proxyDNS: true,
  237. },
  238. }
  239. for _, tt := range cases {
  240. t.Run(tt.name, func(t *testing.T) {
  241. rsv := NewResolver("", tt.proxyDNS, badSRVDNSBackend{})
  242. rsv.logger = testLogger(t)
  243. w := &tstwriter{}
  244. rsv.serveDNS(w, tt.q)
  245. resp := w.GetResponse()
  246. checkNonNullResponse(t, resp)
  247. t.Log("Response: ", resp.String())
  248. checkDNSResponseCode(t, resp, dns.RcodeServerFailure)
  249. })
  250. }
  251. }
  252. type badSRVDNSBackend struct{ noopDNSBackend }
  253. func (badSRVDNSBackend) ResolveService(_ context.Context, _ string) ([]*net.SRV, []net.IP) {
  254. return []*net.SRV{nil, nil, nil}, nil // Mismatched slice lengths
  255. }
  256. func TestProxyNXDOMAIN(t *testing.T) {
  257. mockSOA, err := dns.NewRR(". 86367 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2023051800 1800 900 604800 86400\n")
  258. assert.NilError(t, err)
  259. assert.Assert(t, mockSOA != nil)
  260. serveStarted := make(chan struct{})
  261. srv := &dns.Server{
  262. Net: "udp",
  263. Addr: "127.0.0.1:0",
  264. Handler: dns.HandlerFunc(func(w dns.ResponseWriter, r *dns.Msg) {
  265. msg := new(dns.Msg).SetRcode(r, dns.RcodeNameError)
  266. msg.Ns = append(msg.Ns, dns.Copy(mockSOA))
  267. w.WriteMsg(msg)
  268. }),
  269. NotifyStartedFunc: func() { close(serveStarted) },
  270. }
  271. serveDone := make(chan error, 1)
  272. go func() {
  273. defer close(serveDone)
  274. serveDone <- srv.ListenAndServe()
  275. }()
  276. select {
  277. case err := <-serveDone:
  278. t.Fatal(err)
  279. case <-serveStarted:
  280. }
  281. defer func() {
  282. if err := srv.Shutdown(); err != nil {
  283. t.Error(err)
  284. }
  285. <-serveDone
  286. }()
  287. // This test, by virtue of running a server and client in different
  288. // not-locked-to-thread goroutines, happens to be a good canary for
  289. // whether we are leaking unlocked OS threads set to the wrong network
  290. // namespace. Make a best-effort attempt to detect that situation so we
  291. // are not left chasing ghosts next time.
  292. netnsutils.AssertSocketSameNetNS(t, srv.PacketConn.(*net.UDPConn))
  293. srvAddr := srv.PacketConn.LocalAddr().(*net.UDPAddr)
  294. rsv := NewResolver("", true, noopDNSBackend{})
  295. rsv.SetExtServers([]extDNSEntry{
  296. {IPStr: srvAddr.IP.String(), port: uint16(srvAddr.Port), HostLoopback: true},
  297. })
  298. // The resolver logs lots of valuable info at level debug. Redirect it
  299. // to t.Log() so the log spew is emitted only if the test fails.
  300. rsv.logger = testLogger(t)
  301. w := &tstwriter{network: srvAddr.Network()}
  302. q := new(dns.Msg).SetQuestion("example.net.", dns.TypeA)
  303. rsv.serveDNS(w, q)
  304. resp := w.GetResponse()
  305. checkNonNullResponse(t, resp)
  306. t.Log("Response:\n" + resp.String())
  307. checkDNSResponseCode(t, resp, dns.RcodeNameError)
  308. assert.Assert(t, is.Len(resp.Answer, 0))
  309. assert.Assert(t, is.Len(resp.Ns, 1))
  310. assert.Equal(t, resp.Ns[0].String(), mockSOA.String())
  311. }