resolver_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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. "gotest.tools/v3/skip"
  15. )
  16. // a simple/null address type that will be used to fake a local address for unit testing
  17. type tstaddr struct {
  18. }
  19. func (a *tstaddr) Network() string { return "tcp" }
  20. func (a *tstaddr) String() string { return "127.0.0.1" }
  21. // a simple writer that implements dns.ResponseWriter for unit testing purposes
  22. type tstwriter struct {
  23. localAddr net.Addr
  24. msg *dns.Msg
  25. }
  26. func (w *tstwriter) WriteMsg(m *dns.Msg) (err error) {
  27. w.msg = m
  28. return nil
  29. }
  30. func (w *tstwriter) Write(m []byte) (int, error) { return 0, nil }
  31. func (w *tstwriter) LocalAddr() net.Addr {
  32. if w.localAddr != nil {
  33. return w.localAddr
  34. }
  35. return new(tstaddr)
  36. }
  37. func (w *tstwriter) RemoteAddr() net.Addr { return new(tstaddr) }
  38. func (w *tstwriter) TsigStatus() error { return nil }
  39. func (w *tstwriter) TsigTimersOnly(b bool) {}
  40. func (w *tstwriter) Hijack() {}
  41. func (w *tstwriter) Close() error { return nil }
  42. func (w *tstwriter) GetResponse() *dns.Msg { return w.msg }
  43. func (w *tstwriter) ClearResponse() { w.msg = nil }
  44. func checkNonNullResponse(t *testing.T, m *dns.Msg) {
  45. t.Helper()
  46. if m == nil {
  47. t.Fatal("Null DNS response found. Non Null response msg expected.")
  48. }
  49. }
  50. func checkDNSAnswersCount(t *testing.T, m *dns.Msg, expected int) {
  51. t.Helper()
  52. answers := len(m.Answer)
  53. if answers != expected {
  54. t.Fatalf("Expected number of answers in response: %d. Found: %d", expected, answers)
  55. }
  56. }
  57. func checkDNSResponseCode(t *testing.T, m *dns.Msg, expected int) {
  58. t.Helper()
  59. if m.MsgHdr.Rcode != expected {
  60. t.Fatalf("Expected DNS response code: %d. Found: %d", expected, m.MsgHdr.Rcode)
  61. }
  62. }
  63. func checkDNSRRType(t *testing.T, actual, expected uint16) {
  64. t.Helper()
  65. if actual != expected {
  66. t.Fatalf("Expected DNS Rrtype: %d. Found: %d", expected, actual)
  67. }
  68. }
  69. func TestDNSIPQuery(t *testing.T) {
  70. skip.If(t, runtime.GOOS == "windows", "test only works on linux")
  71. defer testutils.SetupTestOSContext(t)()
  72. c, err := New()
  73. if err != nil {
  74. t.Fatal(err)
  75. }
  76. defer c.Stop()
  77. n, err := c.NewNetwork("bridge", "dtnet1", "", nil)
  78. if err != nil {
  79. t.Fatal(err)
  80. }
  81. defer func() {
  82. if err := n.Delete(); err != nil {
  83. t.Fatal(err)
  84. }
  85. }()
  86. ep, err := n.CreateEndpoint("testep")
  87. if err != nil {
  88. t.Fatal(err)
  89. }
  90. sb, err := c.NewSandbox("c1")
  91. if err != nil {
  92. t.Fatal(err)
  93. }
  94. defer func() {
  95. if err := sb.Delete(); err != nil {
  96. t.Fatal(err)
  97. }
  98. }()
  99. // we need the endpoint only to populate ep_list for the sandbox as part of resolve_name
  100. // it is not set as a target for name resolution and does not serve any other purpose
  101. err = ep.Join(sb)
  102. if err != nil {
  103. t.Fatal(err)
  104. }
  105. // add service records which are used to resolve names. These are the real targets for the DNS querries
  106. n.(*network).addSvcRecords("ep1", "name1", "svc1", net.ParseIP("192.168.0.1"), net.IP{}, true, "test")
  107. w := new(tstwriter)
  108. // the unit tests right now will focus on non-proxyed DNS requests
  109. r := NewResolver(resolverIPSandbox, false, sb)
  110. // test name1's IP is resolved correctly with the default A type query
  111. // Also make sure DNS lookups are case insensitive
  112. names := []string{"name1", "NaMe1"}
  113. for _, name := range names {
  114. q := new(dns.Msg)
  115. q.SetQuestion(name, dns.TypeA)
  116. r.serveDNS(w, q)
  117. resp := w.GetResponse()
  118. checkNonNullResponse(t, resp)
  119. t.Log("Response: ", resp.String())
  120. checkDNSResponseCode(t, resp, dns.RcodeSuccess)
  121. checkDNSAnswersCount(t, resp, 1)
  122. checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA)
  123. if answer, ok := resp.Answer[0].(*dns.A); ok {
  124. if !answer.A.Equal(net.ParseIP("192.168.0.1")) {
  125. t.Fatalf("IP response in Answer %v does not match 192.168.0.1", answer.A)
  126. }
  127. } else {
  128. t.Fatal("Answer of type A not found")
  129. }
  130. w.ClearResponse()
  131. }
  132. // test MX query with name1 results in Success response with 0 answer records
  133. q := new(dns.Msg)
  134. q.SetQuestion("name1", dns.TypeMX)
  135. r.serveDNS(w, q)
  136. resp := w.GetResponse()
  137. checkNonNullResponse(t, resp)
  138. t.Log("Response: ", resp.String())
  139. checkDNSResponseCode(t, resp, dns.RcodeSuccess)
  140. checkDNSAnswersCount(t, resp, 0)
  141. w.ClearResponse()
  142. // test MX query with non existent name results in ServFail response with 0 answer records
  143. // since this is a unit test env, we disable proxying DNS above which results in ServFail rather than NXDOMAIN
  144. q = new(dns.Msg)
  145. q.SetQuestion("nonexistent", dns.TypeMX)
  146. r.serveDNS(w, q)
  147. resp = w.GetResponse()
  148. checkNonNullResponse(t, resp)
  149. t.Log("Response: ", resp.String())
  150. checkDNSResponseCode(t, resp, dns.RcodeServerFailure)
  151. w.ClearResponse()
  152. }
  153. func newDNSHandlerServFailOnce(requests *int) func(w dns.ResponseWriter, r *dns.Msg) {
  154. return func(w dns.ResponseWriter, r *dns.Msg) {
  155. m := new(dns.Msg)
  156. m.SetReply(r)
  157. m.Compress = false
  158. if *requests == 0 {
  159. m.SetRcode(r, dns.RcodeServerFailure)
  160. }
  161. *requests = *requests + 1
  162. if err := w.WriteMsg(m); err != nil {
  163. logrus.WithError(err).Error("Error writing dns response")
  164. }
  165. }
  166. }
  167. func waitForLocalDNSServer(t *testing.T) {
  168. retries := 0
  169. maxRetries := 10
  170. for retries < maxRetries {
  171. t.Log("Try connecting to DNS server ...")
  172. // this test and retry mechanism only works for TCP. With UDP there is no
  173. // connection and the test becomes inaccurate leading to unpredictable results
  174. tconn, err := net.DialTimeout("tcp", "127.0.0.1:53", 10*time.Second)
  175. retries = retries + 1
  176. if err != nil {
  177. if oerr, ok := err.(*net.OpError); ok {
  178. // server is probably initializing
  179. if oerr.Err == syscall.ECONNREFUSED {
  180. continue
  181. }
  182. } else {
  183. // something is wrong: we should stop for analysis
  184. t.Fatal(err)
  185. }
  186. }
  187. if tconn != nil {
  188. tconn.Close()
  189. break
  190. }
  191. }
  192. }
  193. func TestDNSProxyServFail(t *testing.T) {
  194. skip.If(t, runtime.GOOS == "windows", "test only works on linux")
  195. osctx := testutils.SetupTestOSContextEx(t)
  196. defer osctx.Cleanup(t)
  197. c, err := New()
  198. if err != nil {
  199. t.Fatal(err)
  200. }
  201. defer c.Stop()
  202. n, err := c.NewNetwork("bridge", "dtnet2", "", nil)
  203. if err != nil {
  204. t.Fatal(err)
  205. }
  206. defer func() {
  207. if err := n.Delete(); err != nil {
  208. t.Fatal(err)
  209. }
  210. }()
  211. sb, err := c.NewSandbox("c1")
  212. if err != nil {
  213. t.Fatal(err)
  214. }
  215. defer func() {
  216. if err := sb.Delete(); err != nil {
  217. t.Fatal(err)
  218. }
  219. }()
  220. var nRequests int
  221. // initialize a local DNS server and configure it to fail the first query
  222. dns.HandleFunc(".", newDNSHandlerServFailOnce(&nRequests))
  223. // use TCP for predictable results. Connection tests (to figure out DNS server initialization) don't work with UDP
  224. server := &dns.Server{Addr: "127.0.0.1:53", Net: "tcp"}
  225. srvErrCh := make(chan error, 1)
  226. osctx.Go(t, func() {
  227. srvErrCh <- server.ListenAndServe()
  228. })
  229. defer func() {
  230. server.Shutdown() //nolint:errcheck
  231. if err := <-srvErrCh; err != nil {
  232. t.Error(err)
  233. }
  234. }()
  235. waitForLocalDNSServer(t)
  236. t.Log("DNS Server can be reached")
  237. w := new(tstwriter)
  238. r := NewResolver(resolverIPSandbox, true, sb)
  239. q := new(dns.Msg)
  240. q.SetQuestion("name1.", dns.TypeA)
  241. var localDNSEntries []extDNSEntry
  242. extTestDNSEntry := extDNSEntry{IPStr: "127.0.0.1", HostLoopback: true}
  243. // configure two external DNS entries and point both to local DNS server thread
  244. localDNSEntries = append(localDNSEntries, extTestDNSEntry)
  245. localDNSEntries = append(localDNSEntries, extTestDNSEntry)
  246. // this should generate two requests: the first will fail leading to a retry
  247. r.SetExtServers(localDNSEntries)
  248. r.serveDNS(w, q)
  249. if nRequests != 2 {
  250. t.Fatalf("Expected 2 DNS querries. Found: %d", nRequests)
  251. }
  252. t.Logf("Expected number of DNS requests generated")
  253. }
  254. // Packet 24 extracted from
  255. // https://gist.github.com/vojtad/3bac63b8c91b1ec50e8d8b36047317fa/raw/7d75eb3d3448381bf252ae55ea5123a132c46658/host.pcap
  256. // (https://github.com/moby/moby/issues/44575)
  257. // which is a non-compliant DNS reply > 512B (w/o EDNS(0)) to the query
  258. //
  259. // s3.amazonaws.com. IN A
  260. const oversizedDNSReplyMsg = "\xf5\x11\x81\x80\x00\x01\x00\x20\x00\x00\x00\x00\x02\x73\x33\x09" +
  261. "\x61\x6d\x61\x7a\x6f\x6e\x61\x77\x73\x03\x63\x6f\x6d\x00\x00\x01" +
  262. "\x00\x01\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  263. "\x11\x9e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  264. "\x4c\x66\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  265. "\xda\x10\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  266. "\x01\x3e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  267. "\x88\x68\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  268. "\x66\x9e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  269. "\x5f\x28\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  270. "\x8e\x4e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x36\xe7" +
  271. "\x84\xf0\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd8" +
  272. "\x92\x45\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  273. "\x8f\xa6\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x36\xe7" +
  274. "\xc0\xd0\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  275. "\xfe\x28\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  276. "\xaa\x3d\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  277. "\x4e\x56\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd9" +
  278. "\xea\xb0\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  279. "\x6d\xed\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x04\x00\x04\x34\xd8" +
  280. "\x28\x00\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd9" +
  281. "\xe9\x78\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd9" +
  282. "\x6e\x9e\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd9" +
  283. "\x45\x86\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x34\xd8" +
  284. "\x30\x38\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x36\xe7" +
  285. "\xc6\xa8\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x00\x00\x04\x03\x05" +
  286. "\x01\x9d\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  287. "\xa8\xe8\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  288. "\x64\xa6\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd8" +
  289. "\x3c\x48\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd8" +
  290. "\x35\x20\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  291. "\x54\xf6\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  292. "\x5d\x36\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x34\xd9" +
  293. "\x30\x36\xc0\x0c\x00\x01\x00\x01\x00\x00\x00\x05\x00\x04\x36\xe7" +
  294. "\x83\x90"
  295. // Regression test for https://github.com/moby/moby/issues/44575
  296. func TestOversizedDNSReply(t *testing.T) {
  297. srv, err := net.ListenPacket("udp", "127.0.0.1:0")
  298. assert.NilError(t, err)
  299. defer srv.Close()
  300. go func() {
  301. buf := make([]byte, 65536)
  302. for {
  303. n, src, err := srv.ReadFrom(buf)
  304. if errors.Is(err, net.ErrClosed) {
  305. return
  306. }
  307. t.Logf("[<-%v]\n%s", src, hex.Dump(buf[:n]))
  308. if n < 2 {
  309. continue
  310. }
  311. resp := []byte(oversizedDNSReplyMsg)
  312. resp[0], resp[1] = buf[0], buf[1] // Copy query ID into response.
  313. _, err = srv.WriteTo(resp, src)
  314. if errors.Is(err, net.ErrClosed) {
  315. return
  316. }
  317. if err != nil {
  318. t.Log(err)
  319. }
  320. }
  321. }()
  322. srvAddr := srv.LocalAddr().(*net.UDPAddr)
  323. rsv := NewResolver("", true, noopDNSBackend{})
  324. rsv.SetExtServers([]extDNSEntry{
  325. {IPStr: srvAddr.IP.String(), port: uint16(srvAddr.Port), HostLoopback: true},
  326. })
  327. // The resolver logs lots of valuable info at level debug. Redirect it
  328. // to t.Log() so the log spew is emitted only if the test fails.
  329. defer redirectLogrusTo(t)()
  330. w := &tstwriter{localAddr: srv.LocalAddr()}
  331. q := new(dns.Msg).SetQuestion("s3.amazonaws.com.", dns.TypeA)
  332. rsv.serveDNS(w, q)
  333. resp := w.GetResponse()
  334. checkNonNullResponse(t, resp)
  335. t.Log("Response: ", resp.String())
  336. checkDNSResponseCode(t, resp, dns.RcodeSuccess)
  337. assert.Assert(t, len(resp.Answer) >= 1)
  338. checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA)
  339. }
  340. func redirectLogrusTo(t *testing.T) func() {
  341. oldLevel, oldOut := logrus.StandardLogger().Level, logrus.StandardLogger().Out
  342. logrus.StandardLogger().SetLevel(logrus.DebugLevel)
  343. logrus.SetOutput(tlogWriter{t})
  344. return func() {
  345. logrus.StandardLogger().SetLevel(oldLevel)
  346. logrus.StandardLogger().SetOutput(oldOut)
  347. }
  348. }
  349. type tlogWriter struct{ t *testing.T }
  350. func (w tlogWriter) Write(p []byte) (n int, err error) {
  351. w.t.Logf("%s", p)
  352. return len(p), nil
  353. }
  354. type noopDNSBackend struct{ DNSBackend }
  355. func (noopDNSBackend) ResolveName(name string, iplen int) ([]net.IP, bool) { return nil, false }
  356. func (noopDNSBackend) ExecFunc(f func()) error { f(); return nil }
  357. func (noopDNSBackend) NdotsSet() bool { return false }
  358. func (noopDNSBackend) HandleQueryResp(name string, ip net.IP) {}
  359. func TestReplySERVFAIL(t *testing.T) {
  360. cases := []struct {
  361. name string
  362. q *dns.Msg
  363. proxyDNS bool
  364. }{
  365. {
  366. name: "InternalError",
  367. q: new(dns.Msg).SetQuestion("_sip._tcp.example.com.", dns.TypeSRV),
  368. },
  369. {
  370. name: "ProxyDNS=false",
  371. q: new(dns.Msg).SetQuestion("example.com.", dns.TypeA),
  372. },
  373. {
  374. name: "ProxyDNS=true", // No extDNS servers configured -> no answer from any upstream
  375. q: new(dns.Msg).SetQuestion("example.com.", dns.TypeA),
  376. proxyDNS: true,
  377. },
  378. }
  379. for _, tt := range cases {
  380. t.Run(tt.name, func(t *testing.T) {
  381. defer redirectLogrusTo(t)
  382. rsv := NewResolver("", tt.proxyDNS, badSRVDNSBackend{})
  383. w := &tstwriter{}
  384. rsv.serveDNS(w, tt.q)
  385. resp := w.GetResponse()
  386. checkNonNullResponse(t, resp)
  387. t.Log("Response: ", resp.String())
  388. checkDNSResponseCode(t, resp, dns.RcodeServerFailure)
  389. })
  390. }
  391. }
  392. type badSRVDNSBackend struct{ noopDNSBackend }
  393. func (badSRVDNSBackend) ResolveService(name string) ([]*net.SRV, []net.IP) {
  394. return []*net.SRV{nil, nil, nil}, nil // Mismatched slice lengths
  395. }