resolver_test.go 12 KB

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