Bläddra i källkod

Make DNS records and queries case-insensitive

    RFC434 states that DNS Servers should be case insensitive
    This commit makes sure that all DNS queries will be translated
    to lower ASCII characters and all svcRecords will be saved in
    lower case to abide by the RFC

    Relates to https://github.com/moby/moby/issues/21169

Signed-off-by: Arko Dasgupta <arko.dasgupta@docker.com>
Arko Dasgupta 6 år sedan
förälder
incheckning
313d2b8a74
3 ändrade filer med 29 tillägg och 20 borttagningar
  1. 7 2
      libnetwork/network.go
  2. 1 1
      libnetwork/resolver.go
  3. 21 17
      libnetwork/resolver_test.go

+ 7 - 2
libnetwork/network.go

@@ -1381,14 +1381,18 @@ func delIPToName(ipMap setmatrix.SetMatrix, name, serviceID string, ip net.IP) {
 }
 
 func addNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) {
-	svcMap.Insert(name, svcMapEntry{
+	// Since DNS name resolution is case-insensitive, Use the lower-case form
+	// of the name as the key into svcMap
+	lowerCaseName := strings.ToLower(name)
+	svcMap.Insert(lowerCaseName, svcMapEntry{
 		ip:        epIP.String(),
 		serviceID: serviceID,
 	})
 }
 
 func delNameToIP(svcMap setmatrix.SetMatrix, name, serviceID string, epIP net.IP) {
-	svcMap.Remove(name, svcMapEntry{
+	lowerCaseName := strings.ToLower(name)
+	svcMap.Remove(lowerCaseName, svcMapEntry{
 		ip:        epIP.String(),
 		serviceID: serviceID,
 	})
@@ -1956,6 +1960,7 @@ func (n *network) ResolveName(req string, ipType int) ([]net.IP, bool) {
 	}
 
 	req = strings.TrimSuffix(req, ".")
+	req = strings.ToLower(req)
 	ipSet, ok := sr.svcMap.Get(req)
 
 	if ipType == types.IPv6 {

+ 1 - 1
libnetwork/resolver.go

@@ -366,8 +366,8 @@ func (r *resolver) ServeDNS(w dns.ResponseWriter, query *dns.Msg) {
 	if query == nil || len(query.Question) == 0 {
 		return
 	}
-	name := query.Question[0].Name
 
+	name := query.Question[0].Name
 	switch query.Question[0].Qtype {
 	case dns.TypeA:
 		resp, err = r.handleIPQuery(name, query, types.IPv4)

+ 21 - 17
libnetwork/resolver_test.go

@@ -126,29 +126,33 @@ func TestDNSIPQuery(t *testing.T) {
 	r := NewResolver(resolverIPSandbox, false, sb.Key(), sb.(*sandbox))
 
 	// test name1's IP is resolved correctly with the default A type query
-	q := new(dns.Msg)
-	q.SetQuestion("name1", dns.TypeA)
-	r.(*resolver).ServeDNS(w, q)
-	resp := w.GetResponse()
-	checkNonNullResponse(t, resp)
-	t.Log("Response: ", resp.String())
-	checkDNSResponseCode(t, resp, dns.RcodeSuccess)
-	checkDNSAnswersCount(t, resp, 1)
-	checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA)
-	if answer, ok := resp.Answer[0].(*dns.A); ok {
-		if !bytes.Equal(answer.A, net.ParseIP("192.168.0.1")) {
-			t.Fatalf("IP response in Answer %v does not match 192.168.0.1", answer.A)
+	// Also make sure DNS lookups are case insensitive
+	names := []string{"name1", "NaMe1"}
+	for _, name := range names {
+		q := new(dns.Msg)
+		q.SetQuestion(name, dns.TypeA)
+		r.(*resolver).ServeDNS(w, q)
+		resp := w.GetResponse()
+		checkNonNullResponse(t, resp)
+		t.Log("Response: ", resp.String())
+		checkDNSResponseCode(t, resp, dns.RcodeSuccess)
+		checkDNSAnswersCount(t, resp, 1)
+		checkDNSRRType(t, resp.Answer[0].Header().Rrtype, dns.TypeA)
+		if answer, ok := resp.Answer[0].(*dns.A); ok {
+			if !bytes.Equal(answer.A, net.ParseIP("192.168.0.1")) {
+				t.Fatalf("IP response in Answer %v does not match 192.168.0.1", answer.A)
+			}
+		} else {
+			t.Fatal("Answer of type A not found")
 		}
-	} else {
-		t.Fatal("Answer of type A not found")
+		w.ClearResponse()
 	}
-	w.ClearResponse()
 
 	// test MX query with name1 results in Success response with 0 answer records
-	q = new(dns.Msg)
+	q := new(dns.Msg)
 	q.SetQuestion("name1", dns.TypeMX)
 	r.(*resolver).ServeDNS(w, q)
-	resp = w.GetResponse()
+	resp := w.GetResponse()
 	checkNonNullResponse(t, resp)
 	t.Log("Response: ", resp.String())
 	checkDNSResponseCode(t, resp, dns.RcodeSuccess)