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  }