resolver_test.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. package libnetwork
  2. import (
  3. "bytes"
  4. "net"
  5. "syscall"
  6. "testing"
  7. "time"
  8. "github.com/miekg/dns"
  9. )
  10. // a simple/null address type that will be used to fake a local address for unit testing
  11. type tstaddr struct {
  12. net string
  13. }
  14. func (a *tstaddr) Network() string { return "tcp" }
  15. func (a *tstaddr) String() string { return "127.0.0.1" }
  16. // a simple writer that implements dns.ResponseWriter for unit testing purposes
  17. type tstwriter struct {
  18. msg *dns.Msg
  19. }
  20. func (w *tstwriter) WriteMsg(m *dns.Msg) (err error) {
  21. w.msg = m
  22. return nil
  23. }
  24. func (w *tstwriter) Write(m []byte) (int, error) { return 0, nil }
  25. func (w *tstwriter) LocalAddr() net.Addr { return new(tstaddr) }
  26. func (w *tstwriter) RemoteAddr() net.Addr { return new(tstaddr) }
  27. func (w *tstwriter) TsigStatus() error { return nil }
  28. func (w *tstwriter) TsigTimersOnly(b bool) {}
  29. func (w *tstwriter) Hijack() {}
  30. func (w *tstwriter) Close() error { return nil }
  31. func (w *tstwriter) GetResponse() *dns.Msg { return w.msg }
  32. func (w *tstwriter) ClearResponse() { w.msg = nil }
  33. func checkNonNullResponse(t *testing.T, m *dns.Msg) {
  34. if m == nil {
  35. t.Fatal("Null DNS response found. Non Null response msg expected.")
  36. }
  37. }
  38. func checkNullResponse(t *testing.T, m *dns.Msg) {
  39. if m != nil {
  40. t.Fatal("Non Null DNS response found. Null response msg expected.")
  41. }
  42. }
  43. func checkDNSAnswersCount(t *testing.T, m *dns.Msg, expected int) {
  44. answers := len(m.Answer)
  45. if answers != expected {
  46. t.Fatalf("Expected number of answers in response: %d. Found: %d", expected, answers)
  47. }
  48. }
  49. func checkDNSResponseCode(t *testing.T, m *dns.Msg, expected int) {
  50. if m.MsgHdr.Rcode != expected {
  51. t.Fatalf("Expected DNS response code: %d. Found: %d", expected, m.MsgHdr.Rcode)
  52. }
  53. }
  54. func checkDNSRRType(t *testing.T, actual, expected uint16) {
  55. if actual != expected {
  56. t.Fatalf("Expected DNS Rrtype: %d. Found: %d", expected, actual)
  57. }
  58. }
  59. func TestDNSIPQuery(t *testing.T) {
  60. c, err := New()
  61. if err != nil {
  62. t.Fatal(err)
  63. }
  64. defer c.Stop()
  65. n, err := c.NewNetwork("bridge", "dtnet1", "", nil)
  66. if err != nil {
  67. t.Fatal(err)
  68. }
  69. defer func() {
  70. if err := n.Delete(); err != nil {
  71. t.Fatal(err)
  72. }
  73. }()
  74. ep, err := n.CreateEndpoint("testep")
  75. if err != nil {
  76. t.Fatal(err)
  77. }
  78. sb, err := c.NewSandbox("c1")
  79. if err != nil {
  80. t.Fatal(err)
  81. }
  82. defer func() {
  83. if err := sb.Delete(); err != nil {
  84. t.Fatal(err)
  85. }
  86. }()
  87. // we need the endpoint only to populate ep_list for the sandbox as part of resolve_name
  88. // it is not set as a target for name resolution and does not serve any other purpose
  89. err = ep.Join(sb)
  90. if err != nil {
  91. t.Fatal(err)
  92. }
  93. // add service records which are used to resolve names. These are the real targets for the DNS querries
  94. n.(*network).addSvcRecords("ep1", "name1", "svc1", net.ParseIP("192.168.0.1"), net.IP{}, true, "test")
  95. w := new(tstwriter)
  96. // the unit tests right now will focus on non-proxyed DNS requests
  97. r := NewResolver(resolverIPSandbox, false, sb.Key(), sb.(*sandbox))
  98. // test name1's IP is resolved correctly with the default A type query
  99. // Also make sure DNS lookups are case insensitive
  100. names := []string{"name1", "NaMe1"}
  101. for _, name := range names {
  102. q := new(dns.Msg)
  103. q.SetQuestion(name, dns.TypeA)
  104. r.(*resolver).ServeDNS(w, q)
  105. resp := w.GetResponse()
  106. checkNonNullResponse(t, resp)
  107. t.Log("Response: ", resp.String())
  108. checkDNSResponseCode(t, resp, dns.RcodeSuccess)
  109. checkDNSAnswersCount(t, resp, 1)
  110. checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA)
  111. if answer, ok := resp.Answer[0].(*dns.A); ok {
  112. if !bytes.Equal(answer.A, net.ParseIP("192.168.0.1")) {
  113. t.Fatalf("IP response in Answer %v does not match 192.168.0.1", answer.A)
  114. }
  115. } else {
  116. t.Fatal("Answer of type A not found")
  117. }
  118. w.ClearResponse()
  119. }
  120. // test MX query with name1 results in Success response with 0 answer records
  121. q := new(dns.Msg)
  122. q.SetQuestion("name1", dns.TypeMX)
  123. r.(*resolver).ServeDNS(w, q)
  124. resp := w.GetResponse()
  125. checkNonNullResponse(t, resp)
  126. t.Log("Response: ", resp.String())
  127. checkDNSResponseCode(t, resp, dns.RcodeSuccess)
  128. checkDNSAnswersCount(t, resp, 0)
  129. w.ClearResponse()
  130. // test MX query with non existent name results in ServFail response with 0 answer records
  131. // since this is a unit test env, we disable proxying DNS above which results in ServFail rather than NXDOMAIN
  132. q = new(dns.Msg)
  133. q.SetQuestion("nonexistent", dns.TypeMX)
  134. r.(*resolver).ServeDNS(w, q)
  135. resp = w.GetResponse()
  136. checkNonNullResponse(t, resp)
  137. t.Log("Response: ", resp.String())
  138. checkDNSResponseCode(t, resp, dns.RcodeServerFailure)
  139. w.ClearResponse()
  140. }
  141. func newDNSHandlerServFailOnce(requests *int) func(w dns.ResponseWriter, r *dns.Msg) {
  142. return func(w dns.ResponseWriter, r *dns.Msg) {
  143. m := new(dns.Msg)
  144. m.SetReply(r)
  145. m.Compress = false
  146. if *requests == 0 {
  147. m.SetRcode(r, dns.RcodeServerFailure)
  148. }
  149. *requests = *requests + 1
  150. w.WriteMsg(m)
  151. }
  152. }
  153. func waitForLocalDNSServer(t *testing.T) {
  154. retries := 0
  155. maxRetries := 10
  156. for retries < maxRetries {
  157. t.Log("Try connecting to DNS server ...")
  158. // this test and retry mechanism only works for TCP. With UDP there is no
  159. // connection and the test becomes inaccurate leading to unpredictable results
  160. tconn, err := net.DialTimeout("tcp", "127.0.0.1:53", 10*time.Second)
  161. retries = retries + 1
  162. if err != nil {
  163. if oerr, ok := err.(*net.OpError); ok {
  164. // server is probably initializing
  165. if oerr.Err == syscall.ECONNREFUSED {
  166. continue
  167. }
  168. } else {
  169. // something is wrong: we should stop for analysis
  170. t.Fatal(err)
  171. }
  172. }
  173. if tconn != nil {
  174. tconn.Close()
  175. break
  176. }
  177. }
  178. }
  179. func TestDNSProxyServFail(t *testing.T) {
  180. c, err := New()
  181. if err != nil {
  182. t.Fatal(err)
  183. }
  184. defer c.Stop()
  185. n, err := c.NewNetwork("bridge", "dtnet2", "", nil)
  186. if err != nil {
  187. t.Fatal(err)
  188. }
  189. defer func() {
  190. if err := n.Delete(); err != nil {
  191. t.Fatal(err)
  192. }
  193. }()
  194. sb, err := c.NewSandbox("c1")
  195. if err != nil {
  196. t.Fatal(err)
  197. }
  198. defer func() {
  199. if err := sb.Delete(); err != nil {
  200. t.Fatal(err)
  201. }
  202. }()
  203. var nRequests int
  204. // initialize a local DNS server and configure it to fail the first query
  205. dns.HandleFunc(".", newDNSHandlerServFailOnce(&nRequests))
  206. // use TCP for predictable results. Connection tests (to figure out DNS server initialization) don't work with UDP
  207. server := &dns.Server{Addr: ":53", Net: "tcp"}
  208. go server.ListenAndServe()
  209. defer server.Shutdown()
  210. waitForLocalDNSServer(t)
  211. t.Log("DNS Server can be reached")
  212. w := new(tstwriter)
  213. r := NewResolver(resolverIPSandbox, true, sb.Key(), sb.(*sandbox))
  214. q := new(dns.Msg)
  215. q.SetQuestion("name1.", dns.TypeA)
  216. var localDNSEntries []extDNSEntry
  217. extTestDNSEntry := extDNSEntry{IPStr: "127.0.0.1", HostLoopback: true}
  218. // configure two external DNS entries and point both to local DNS server thread
  219. localDNSEntries = append(localDNSEntries, extTestDNSEntry)
  220. localDNSEntries = append(localDNSEntries, extTestDNSEntry)
  221. // this should generate two requests: the first will fail leading to a retry
  222. r.(*resolver).SetExtServers(localDNSEntries)
  223. r.(*resolver).ServeDNS(w, q)
  224. if nRequests != 2 {
  225. t.Fatalf("Expected 2 DNS querries. Found: %d", nRequests)
  226. }
  227. t.Logf("Expected number of DNS requests generated")
  228. }