resolver_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524
  1. package libnetwork
  2. import (
  3. "encoding/hex"
  4. "errors"
  5. "net"
  6. "runtime"
  7. "syscall"
  8. "testing"
  9. "time"
  10. "github.com/docker/docker/libnetwork/testutils"
  11. "github.com/miekg/dns"
  12. "github.com/sirupsen/logrus"
  13. "gotest.tools/v3/assert"
  14. is "gotest.tools/v3/assert/cmp"
  15. "gotest.tools/v3/skip"
  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 TestDNSIPQuery(t *testing.T) {
  76. skip.If(t, runtime.GOOS == "windows", "test only works on linux")
  77. defer testutils.SetupTestOSContext(t)()
  78. c, err := New()
  79. if err != nil {
  80. t.Fatal(err)
  81. }
  82. defer c.Stop()
  83. n, err := c.NewNetwork("bridge", "dtnet1", "", nil)
  84. if err != nil {
  85. t.Fatal(err)
  86. }
  87. defer func() {
  88. if err := n.Delete(); err != nil {
  89. t.Fatal(err)
  90. }
  91. }()
  92. ep, err := n.CreateEndpoint("testep")
  93. if err != nil {
  94. t.Fatal(err)
  95. }
  96. sb, err := c.NewSandbox("c1")
  97. if err != nil {
  98. t.Fatal(err)
  99. }
  100. defer func() {
  101. if err := sb.Delete(); err != nil {
  102. t.Fatal(err)
  103. }
  104. }()
  105. // we need the endpoint only to populate ep_list for the sandbox as part of resolve_name
  106. // it is not set as a target for name resolution and does not serve any other purpose
  107. err = ep.Join(sb)
  108. if err != nil {
  109. t.Fatal(err)
  110. }
  111. // add service records which are used to resolve names. These are the real targets for the DNS querries
  112. n.(*network).addSvcRecords("ep1", "name1", "svc1", net.ParseIP("192.168.0.1"), net.IP{}, true, "test")
  113. w := new(tstwriter)
  114. // the unit tests right now will focus on non-proxyed DNS requests
  115. r := NewResolver(resolverIPSandbox, false, sb)
  116. // test name1's IP is resolved correctly with the default A type query
  117. // Also make sure DNS lookups are case insensitive
  118. names := []string{"name1", "NaMe1"}
  119. for _, name := range names {
  120. q := new(dns.Msg)
  121. q.SetQuestion(name, dns.TypeA)
  122. r.serveDNS(w, q)
  123. resp := w.GetResponse()
  124. checkNonNullResponse(t, resp)
  125. t.Log("Response: ", resp.String())
  126. checkDNSResponseCode(t, resp, dns.RcodeSuccess)
  127. checkDNSAnswersCount(t, resp, 1)
  128. checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA)
  129. if answer, ok := resp.Answer[0].(*dns.A); ok {
  130. if !answer.A.Equal(net.ParseIP("192.168.0.1")) {
  131. t.Fatalf("IP response in Answer %v does not match 192.168.0.1", answer.A)
  132. }
  133. } else {
  134. t.Fatal("Answer of type A not found")
  135. }
  136. w.ClearResponse()
  137. }
  138. // test MX query with name1 results in Success response with 0 answer records
  139. q := new(dns.Msg)
  140. q.SetQuestion("name1", dns.TypeMX)
  141. r.serveDNS(w, q)
  142. resp := w.GetResponse()
  143. checkNonNullResponse(t, resp)
  144. t.Log("Response: ", resp.String())
  145. checkDNSResponseCode(t, resp, dns.RcodeSuccess)
  146. checkDNSAnswersCount(t, resp, 0)
  147. w.ClearResponse()
  148. // test MX query with non existent name results in ServFail response with 0 answer records
  149. // since this is a unit test env, we disable proxying DNS above which results in ServFail rather than NXDOMAIN
  150. q = new(dns.Msg)
  151. q.SetQuestion("nonexistent", dns.TypeMX)
  152. r.serveDNS(w, q)
  153. resp = w.GetResponse()
  154. checkNonNullResponse(t, resp)
  155. t.Log("Response: ", resp.String())
  156. checkDNSResponseCode(t, resp, dns.RcodeServerFailure)
  157. w.ClearResponse()
  158. }
  159. func newDNSHandlerServFailOnce(requests *int) func(w dns.ResponseWriter, r *dns.Msg) {
  160. return func(w dns.ResponseWriter, r *dns.Msg) {
  161. m := new(dns.Msg)
  162. m.SetReply(r)
  163. m.Compress = false
  164. if *requests == 0 {
  165. m.SetRcode(r, dns.RcodeServerFailure)
  166. }
  167. *requests = *requests + 1
  168. if err := w.WriteMsg(m); err != nil {
  169. logrus.WithError(err).Error("Error writing dns response")
  170. }
  171. }
  172. }
  173. func waitForLocalDNSServer(t *testing.T) {
  174. retries := 0
  175. maxRetries := 10
  176. for retries < maxRetries {
  177. t.Log("Try connecting to DNS server ...")
  178. // this test and retry mechanism only works for TCP. With UDP there is no
  179. // connection and the test becomes inaccurate leading to unpredictable results
  180. tconn, err := net.DialTimeout("tcp", "127.0.0.1:53", 10*time.Second)
  181. retries = retries + 1
  182. if err != nil {
  183. if oerr, ok := err.(*net.OpError); ok {
  184. // server is probably initializing
  185. if oerr.Err == syscall.ECONNREFUSED {
  186. continue
  187. }
  188. } else {
  189. // something is wrong: we should stop for analysis
  190. t.Fatal(err)
  191. }
  192. }
  193. if tconn != nil {
  194. tconn.Close()
  195. break
  196. }
  197. }
  198. }
  199. func TestDNSProxyServFail(t *testing.T) {
  200. skip.If(t, runtime.GOOS == "windows", "test only works on linux")
  201. osctx := testutils.SetupTestOSContextEx(t)
  202. defer osctx.Cleanup(t)
  203. c, err := New()
  204. if err != nil {
  205. t.Fatal(err)
  206. }
  207. defer c.Stop()
  208. n, err := c.NewNetwork("bridge", "dtnet2", "", nil)
  209. if err != nil {
  210. t.Fatal(err)
  211. }
  212. defer func() {
  213. if err := n.Delete(); err != nil {
  214. t.Fatal(err)
  215. }
  216. }()
  217. sb, err := c.NewSandbox("c1")
  218. if err != nil {
  219. t.Fatal(err)
  220. }
  221. defer func() {
  222. if err := sb.Delete(); err != nil {
  223. t.Fatal(err)
  224. }
  225. }()
  226. var nRequests int
  227. // initialize a local DNS server and configure it to fail the first query
  228. dns.HandleFunc(".", newDNSHandlerServFailOnce(&nRequests))
  229. // use TCP for predictable results. Connection tests (to figure out DNS server initialization) don't work with UDP
  230. server := &dns.Server{Addr: "127.0.0.1:53", Net: "tcp"}
  231. srvErrCh := make(chan error, 1)
  232. osctx.Go(t, func() {
  233. srvErrCh <- server.ListenAndServe()
  234. })
  235. defer func() {
  236. server.Shutdown() //nolint:errcheck
  237. if err := <-srvErrCh; err != nil {
  238. t.Error(err)
  239. }
  240. }()
  241. waitForLocalDNSServer(t)
  242. t.Log("DNS Server can be reached")
  243. w := new(tstwriter)
  244. r := NewResolver(resolverIPSandbox, true, sb)
  245. q := new(dns.Msg)
  246. q.SetQuestion("name1.", dns.TypeA)
  247. var localDNSEntries []extDNSEntry
  248. extTestDNSEntry := extDNSEntry{IPStr: "127.0.0.1", HostLoopback: true}
  249. // configure two external DNS entries and point both to local DNS server thread
  250. localDNSEntries = append(localDNSEntries, extTestDNSEntry)
  251. localDNSEntries = append(localDNSEntries, extTestDNSEntry)
  252. // this should generate two requests: the first will fail leading to a retry
  253. r.SetExtServers(localDNSEntries)
  254. r.serveDNS(w, q)
  255. if nRequests != 2 {
  256. t.Fatalf("Expected 2 DNS querries. Found: %d", nRequests)
  257. }
  258. t.Logf("Expected number of DNS requests generated")
  259. }
  260. // Packet 24 extracted from
  261. // https://gist.github.com/vojtad/3bac63b8c91b1ec50e8d8b36047317fa/raw/7d75eb3d3448381bf252ae55ea5123a132c46658/host.pcap
  262. // (https://github.com/moby/moby/issues/44575)
  263. // which is a non-compliant DNS reply > 512B (w/o EDNS(0)) to the query
  264. //
  265. // s3.amazonaws.com. IN A
  266. const oversizedDNSReplyMsg = "\xf5\x11\x81\x80\x00\x01\x00\x20\x00\x00\x00\x00\x02\x73\x33\x09" +
  267. "\x61\x6d\x61\x7a\x6f\x6e\x61\x77\x73\x03\x63\x6f\x6d\x00\x00\x01" +
  268. "\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  269. "\x11\x9e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  270. "\x4c\x66\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  271. "\xda\x10\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  272. "\x01\x3e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  273. "\x88\x68\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  274. "\x66\x9e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  275. "\x5f\x28\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  276. "\x8e\x4e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x36\xe7" +
  277. "\x84\xf0\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd8" +
  278. "\x92\x45\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  279. "\x8f\xa6\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x36\xe7" +
  280. "\xc0\xd0\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  281. "\xfe\x28\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  282. "\xaa\x3d\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  283. "\x4e\x56\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  284. "\xea\xb0\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  285. "\x6d\xed\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  286. "\x28\x00\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd9" +
  287. "\xe9\x78\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd9" +
  288. "\x6e\x9e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd9" +
  289. "\x45\x86\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd8" +
  290. "\x30\x38\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x36\xe7" +
  291. "\xc6\xa8\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x03\x05" +
  292. "\x01\x9d\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  293. "\xa8\xe8\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  294. "\x64\xa6\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd8" +
  295. "\x3c\x48\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd8" +
  296. "\x35\x20\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  297. "\x54\xf6\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  298. "\x5d\x36\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  299. "\x30\x36\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x36\xe7" +
  300. "\x83\x90"
  301. // Regression test for https://github.com/moby/moby/issues/44575
  302. func TestOversizedDNSReply(t *testing.T) {
  303. srv, err := net.ListenPacket("udp", "127.0.0.1:0")
  304. assert.NilError(t, err)
  305. defer srv.Close()
  306. go func() {
  307. buf := make([]byte, 65536)
  308. for {
  309. n, src, err := srv.ReadFrom(buf)
  310. if errors.Is(err, net.ErrClosed) {
  311. return
  312. }
  313. t.Logf("[<-%v]\n%s", src, hex.Dump(buf[:n]))
  314. if n < 2 {
  315. continue
  316. }
  317. resp := []byte(oversizedDNSReplyMsg)
  318. resp[0], resp[1] = buf[0], buf[1] // Copy query ID into response.
  319. _, err = srv.WriteTo(resp, src)
  320. if errors.Is(err, net.ErrClosed) {
  321. return
  322. }
  323. if err != nil {
  324. t.Log(err)
  325. }
  326. }
  327. }()
  328. srvAddr := srv.LocalAddr().(*net.UDPAddr)
  329. rsv := NewResolver("", true, noopDNSBackend{})
  330. // The resolver logs lots of valuable info at level debug. Redirect it
  331. // to t.Log() so the log spew is emitted only if the test fails.
  332. rsv.logger = testLogger(t)
  333. rsv.SetExtServers([]extDNSEntry{
  334. {IPStr: srvAddr.IP.String(), port: uint16(srvAddr.Port), HostLoopback: true},
  335. })
  336. w := &tstwriter{network: srvAddr.Network()}
  337. q := new(dns.Msg).SetQuestion("s3.amazonaws.com.", dns.TypeA)
  338. rsv.serveDNS(w, q)
  339. resp := w.GetResponse()
  340. checkNonNullResponse(t, resp)
  341. t.Log("Response: ", resp.String())
  342. checkDNSResponseCode(t, resp, dns.RcodeSuccess)
  343. assert.Assert(t, len(resp.Answer) >= 1)
  344. checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA)
  345. }
  346. func testLogger(t *testing.T) *logrus.Logger {
  347. logger := logrus.New()
  348. logger.SetLevel(logrus.DebugLevel)
  349. logger.SetOutput(tlogWriter{t})
  350. return logger
  351. }
  352. type tlogWriter struct{ t *testing.T }
  353. func (w tlogWriter) Write(p []byte) (n int, err error) {
  354. w.t.Logf("%s", p)
  355. return len(p), nil
  356. }
  357. type noopDNSBackend struct{ DNSBackend }
  358. func (noopDNSBackend) ResolveName(name string, iplen int) ([]net.IP, bool) { return nil, false }
  359. func (noopDNSBackend) ExecFunc(f func()) error { f(); return nil }
  360. func (noopDNSBackend) NdotsSet() bool { return false }
  361. func (noopDNSBackend) HandleQueryResp(name string, ip net.IP) {}
  362. func TestReplySERVFAIL(t *testing.T) {
  363. cases := []struct {
  364. name string
  365. q *dns.Msg
  366. proxyDNS bool
  367. }{
  368. {
  369. name: "InternalError",
  370. q: new(dns.Msg).SetQuestion("_sip._tcp.example.com.", dns.TypeSRV),
  371. },
  372. {
  373. name: "ProxyDNS=false",
  374. q: new(dns.Msg).SetQuestion("example.com.", dns.TypeA),
  375. },
  376. {
  377. name: "ProxyDNS=true", // No extDNS servers configured -> no answer from any upstream
  378. q: new(dns.Msg).SetQuestion("example.com.", dns.TypeA),
  379. proxyDNS: true,
  380. },
  381. }
  382. for _, tt := range cases {
  383. t.Run(tt.name, func(t *testing.T) {
  384. rsv := NewResolver("", tt.proxyDNS, badSRVDNSBackend{})
  385. rsv.logger = testLogger(t)
  386. w := &tstwriter{}
  387. rsv.serveDNS(w, tt.q)
  388. resp := w.GetResponse()
  389. checkNonNullResponse(t, resp)
  390. t.Log("Response: ", resp.String())
  391. checkDNSResponseCode(t, resp, dns.RcodeServerFailure)
  392. })
  393. }
  394. }
  395. type badSRVDNSBackend struct{ noopDNSBackend }
  396. func (badSRVDNSBackend) ResolveService(name string) ([]*net.SRV, []net.IP) {
  397. return []*net.SRV{nil, nil, nil}, nil // Mismatched slice lengths
  398. }
  399. func TestProxyNXDOMAIN(t *testing.T) {
  400. mockSOA, err := dns.NewRR(". 86367 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2023051800 1800 900 604800 86400\n")
  401. assert.NilError(t, err)
  402. assert.Assert(t, mockSOA != nil)
  403. serveStarted := make(chan struct{})
  404. srv := &dns.Server{
  405. Net: "udp",
  406. Addr: "127.0.0.1:0",
  407. Handler: dns.HandlerFunc(func(w dns.ResponseWriter, r *dns.Msg) {
  408. msg := new(dns.Msg).SetRcode(r, dns.RcodeNameError)
  409. msg.Ns = append(msg.Ns, dns.Copy(mockSOA))
  410. w.WriteMsg(msg)
  411. }),
  412. NotifyStartedFunc: func() { close(serveStarted) },
  413. }
  414. serveDone := make(chan error, 1)
  415. go func() {
  416. defer close(serveDone)
  417. serveDone <- srv.ListenAndServe()
  418. }()
  419. select {
  420. case err := <-serveDone:
  421. t.Fatal(err)
  422. case <-serveStarted:
  423. }
  424. defer func() {
  425. if err := srv.Shutdown(); err != nil {
  426. t.Error(err)
  427. }
  428. <-serveDone
  429. }()
  430. // This test, by virtue of running a server and client in different
  431. // not-locked-to-thread goroutines, happens to be a good canary for
  432. // whether we are leaking unlocked OS threads set to the wrong network
  433. // namespace. Make a best-effort attempt to detect that situation so we
  434. // are not left chasing ghosts next time.
  435. testutils.AssertSocketSameNetNS(t, srv.PacketConn.(*net.UDPConn))
  436. srvAddr := srv.PacketConn.LocalAddr().(*net.UDPAddr)
  437. rsv := NewResolver("", true, noopDNSBackend{})
  438. rsv.SetExtServers([]extDNSEntry{
  439. {IPStr: srvAddr.IP.String(), port: uint16(srvAddr.Port), HostLoopback: true},
  440. })
  441. // The resolver logs lots of valuable info at level debug. Redirect it
  442. // to t.Log() so the log spew is emitted only if the test fails.
  443. rsv.logger = testLogger(t)
  444. w := &tstwriter{network: srvAddr.Network()}
  445. q := new(dns.Msg).SetQuestion("example.net.", dns.TypeA)
  446. rsv.serveDNS(w, q)
  447. resp := w.GetResponse()
  448. checkNonNullResponse(t, resp)
  449. t.Log("Response:\n" + resp.String())
  450. checkDNSResponseCode(t, resp, dns.RcodeNameError)
  451. assert.Assert(t, is.Len(resp.Answer, 0))
  452. assert.Assert(t, is.Len(resp.Ns, 1))
  453. assert.Equal(t, resp.Ns[0].String(), mockSOA.String())
  454. }