github.com/rish1988/moby@v25.0.2+incompatible/libnetwork/resolver_unix_test.go (about) 1 //go:build !windows 2 3 package libnetwork 4 5 import ( 6 "net" 7 "testing" 8 9 "github.com/docker/docker/internal/testutils/netnsutils" 10 "github.com/miekg/dns" 11 ) 12 13 // test only works on linux 14 func TestDNSIPQuery(t *testing.T) { 15 defer netnsutils.SetupTestOSContext(t)() 16 c, err := New() 17 if err != nil { 18 t.Fatal(err) 19 } 20 defer c.Stop() 21 22 n, err := c.NewNetwork("bridge", "dtnet1", "", nil) 23 if err != nil { 24 t.Fatal(err) 25 } 26 defer func() { 27 if err := n.Delete(); err != nil { 28 t.Fatal(err) 29 } 30 }() 31 32 ep, err := n.CreateEndpoint("testep") 33 if err != nil { 34 t.Fatal(err) 35 } 36 37 sb, err := c.NewSandbox("c1") 38 if err != nil { 39 t.Fatal(err) 40 } 41 42 defer func() { 43 if err := sb.Delete(); err != nil { 44 t.Fatal(err) 45 } 46 }() 47 48 // we need the endpoint only to populate ep_list for the sandbox as part of resolve_name 49 // it is not set as a target for name resolution and does not serve any other purpose 50 err = ep.Join(sb) 51 if err != nil { 52 t.Fatal(err) 53 } 54 55 // add service records which are used to resolve names. These are the real targets for the DNS querries 56 n.addSvcRecords("ep1", "name1", "svc1", net.ParseIP("192.168.0.1"), net.IP{}, true, "test") 57 58 w := new(tstwriter) 59 // the unit tests right now will focus on non-proxyed DNS requests 60 r := NewResolver(resolverIPSandbox, false, sb) 61 62 // test name1's IP is resolved correctly with the default A type query 63 // Also make sure DNS lookups are case insensitive 64 names := []string{"name1.", "NaMe1."} 65 for _, name := range names { 66 q := new(dns.Msg) 67 q.SetQuestion(name, dns.TypeA) 68 r.serveDNS(w, q) 69 resp := w.GetResponse() 70 checkNonNullResponse(t, resp) 71 t.Log("Response: ", resp.String()) 72 checkDNSResponseCode(t, resp, dns.RcodeSuccess) 73 checkDNSAnswersCount(t, resp, 1) 74 checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA) 75 if answer, ok := resp.Answer[0].(*dns.A); ok { 76 if !answer.A.Equal(net.ParseIP("192.168.0.1")) { 77 t.Fatalf("IP response in Answer %v does not match 192.168.0.1", answer.A) 78 } 79 } else { 80 t.Fatal("Answer of type A not found") 81 } 82 w.ClearResponse() 83 } 84 85 // test MX query with name1 results in Success response with 0 answer records 86 q := new(dns.Msg) 87 q.SetQuestion("name1.", dns.TypeMX) 88 r.serveDNS(w, q) 89 resp := w.GetResponse() 90 checkNonNullResponse(t, resp) 91 t.Log("Response: ", resp.String()) 92 checkDNSResponseCode(t, resp, dns.RcodeSuccess) 93 checkDNSAnswersCount(t, resp, 0) 94 w.ClearResponse() 95 96 // test MX query with non existent name results in ServFail response with 0 answer records 97 // since this is a unit test env, we disable proxying DNS above which results in ServFail rather than NXDOMAIN 98 q = new(dns.Msg) 99 q.SetQuestion("nonexistent.", dns.TypeMX) 100 r.serveDNS(w, q) 101 resp = w.GetResponse() 102 checkNonNullResponse(t, resp) 103 t.Log("Response: ", resp.String()) 104 checkDNSResponseCode(t, resp, dns.RcodeServerFailure) 105 w.ClearResponse() 106 } 107 108 // test only works on linux 109 func TestDNSProxyServFail(t *testing.T) { 110 osctx := netnsutils.SetupTestOSContextEx(t) 111 defer osctx.Cleanup(t) 112 113 c, err := New() 114 if err != nil { 115 t.Fatal(err) 116 } 117 defer c.Stop() 118 119 n, err := c.NewNetwork("bridge", "dtnet2", "", nil) 120 if err != nil { 121 t.Fatal(err) 122 } 123 defer func() { 124 if err := n.Delete(); err != nil { 125 t.Fatal(err) 126 } 127 }() 128 129 sb, err := c.NewSandbox("c1") 130 if err != nil { 131 t.Fatal(err) 132 } 133 134 defer func() { 135 if err := sb.Delete(); err != nil { 136 t.Fatal(err) 137 } 138 }() 139 140 var nRequests int 141 // initialize a local DNS server and configure it to fail the first query 142 dns.HandleFunc(".", newDNSHandlerServFailOnce(&nRequests)) 143 // use TCP for predictable results. Connection tests (to figure out DNS server initialization) don't work with UDP 144 server := &dns.Server{Addr: "127.0.0.1:53", Net: "tcp"} 145 srvErrCh := make(chan error, 1) 146 osctx.Go(t, func() { 147 srvErrCh <- server.ListenAndServe() 148 }) 149 defer func() { 150 server.Shutdown() //nolint:errcheck 151 if err := <-srvErrCh; err != nil { 152 t.Error(err) 153 } 154 }() 155 156 waitForLocalDNSServer(t) 157 t.Log("DNS Server can be reached") 158 159 w := new(tstwriter) 160 r := NewResolver(resolverIPSandbox, true, sb) 161 q := new(dns.Msg) 162 q.SetQuestion("name1.", dns.TypeA) 163 164 var localDNSEntries []extDNSEntry 165 extTestDNSEntry := extDNSEntry{IPStr: "127.0.0.1", HostLoopback: true} 166 167 // configure two external DNS entries and point both to local DNS server thread 168 localDNSEntries = append(localDNSEntries, extTestDNSEntry) 169 localDNSEntries = append(localDNSEntries, extTestDNSEntry) 170 171 // this should generate two requests: the first will fail leading to a retry 172 r.SetExtServers(localDNSEntries) 173 r.serveDNS(w, q) 174 if nRequests != 2 { 175 t.Fatalf("Expected 2 DNS querries. Found: %d", nRequests) 176 } 177 t.Logf("Expected number of DNS requests generated") 178 }