Browse Source

Don't follow aliases for NS and SOA records

Previously an aliases record would return the SOA record for the
alias target but NS records for the alias, making it seem like
a delegated zone with incorrect SOA records.

Thanks to Mark Andrews

<https://community.ntppool.org/t/wrong-negative-answers-for-0-openwrt-pool-ntp-org-aaaa/2951>

fixes #136
Ask Bjørn Hansen 2 years ago
parent
commit
163adaac99
3 changed files with 41 additions and 4 deletions
  1. 3 0
      dns/test.example.com.json
  2. 25 3
      server/serve_test.go
  3. 13 1
      zones/zone.go

+ 3 - 0
dns/test.example.com.json

@@ -168,6 +168,9 @@
     "bar-alias": {
     "bar-alias": {
       "alias": "bar"
       "alias": "bar"
     },
     },
+    "root-alias": {
+      "alias": ""
+    },
     "www-alias": {
     "www-alias": {
       "alias": "www"
       "alias": "www"
     },
     },

+ 25 - 3
server/serve_test.go

@@ -81,10 +81,33 @@ func testServing(t *testing.T) {
 	// NOERROR for A request
 	// NOERROR for A request
 	checkRcode(t, r.Rcode, dns.RcodeSuccess, "_status.pgeodns")
 	checkRcode(t, r.Rcode, dns.RcodeSuccess, "_status.pgeodns")
 
 
+	// bar is an alias
 	r = exchange(t, "bar.test.example.com.", dns.TypeA)
 	r = exchange(t, "bar.test.example.com.", dns.TypeA)
 	ip := r.Answer[0].(*dns.A).A
 	ip := r.Answer[0].(*dns.A).A
 	if ip.String() != "192.168.1.2" {
 	if ip.String() != "192.168.1.2" {
 		t.Logf("unexpected A record for bar.test.example.com: %s", ip.String())
 		t.Logf("unexpected A record for bar.test.example.com: %s", ip.String())
+		t.Fail()
+	}
+
+	// bar is an alias to test, the SOA record should be for test
+	r = exchange(t, "_.root-alias.test.example.com.", dns.TypeA)
+	if len(r.Answer) > 0 {
+		t.Errorf("got answers for _.root-alias.test.example.com")
+	}
+	if len(r.Ns) == 0 {
+		t.Fatalf("_.root-alias.test didn't return auth section")
+	}
+	if n := r.Ns[0].(*dns.SOA).Header().Name; n != "test.example.com." {
+		t.Fatalf("_.root-alias.test didn't have test.example.com soa: %s", n)
+	}
+
+	// root-alias is an alias to test (apex), but the NS records shouldn't be on root-alias
+	r = exchange(t, "root-alias.test.example.com.", dns.TypeNS)
+	if len(r.Answer) > 0 {
+		t.Errorf("got unexpected answers for root-alias.test.example.com NS")
+	}
+	if len(r.Ns) == 0 {
+		t.Fatalf("root-alias.test NS didn't return auth section")
 	}
 	}
 
 
 	r = exchange(t, "test.example.com.", dns.TypeSOA)
 	r = exchange(t, "test.example.com.", dns.TypeSOA)
@@ -93,11 +116,10 @@ func testServing(t *testing.T) {
 	assert.Equal(t, 3, int(serial))
 	assert.Equal(t, 3, int(serial))
 
 
 	// no AAAA records for 'bar', so check we get a soa record back
 	// no AAAA records for 'bar', so check we get a soa record back
-	r = exchange(t, "test.example.com.", dns.TypeAAAA)
+	r = exchange(t, "bar.test.example.com.", dns.TypeAAAA)
 	soa2 := r.Ns[0].(*dns.SOA)
 	soa2 := r.Ns[0].(*dns.SOA)
 	if !reflect.DeepEqual(soa, soa2) {
 	if !reflect.DeepEqual(soa, soa2) {
-		t.Logf("AAAA empty NOERROR soa record different from SOA request")
-		t.Fail()
+		t.Errorf("AAAA empty NOERROR soa record different from SOA request")
 	}
 	}
 
 
 	// CNAMEs
 	// CNAMEs

+ 13 - 1
zones/zone.go

@@ -4,6 +4,7 @@ import (
 	"encoding/json"
 	"encoding/json"
 	"log"
 	"log"
 	"net"
 	"net"
+	"slices"
 	"strconv"
 	"strconv"
 	"strings"
 	"strings"
 	"sync"
 	"sync"
@@ -246,9 +247,20 @@ func (z *Zone) FindLabels(s string, targets []string, qts []uint16) []LabelMatch
 					continue
 					continue
 				case dns.TypeMF:
 				case dns.TypeMF:
 					if label.Records[dns.TypeMF] != nil {
 					if label.Records[dns.TypeMF] != nil {
+
+						// don't follow NS and SOA records for aliases
+						aliasQts := slices.DeleteFunc(qts, func(q uint16) bool {
+							if slices.Contains(
+								[]uint16{dns.TypeNS, dns.TypeSOA},
+								q) {
+								return true
+							}
+							return false
+						})
+
 						name = label.FirstRR(dns.TypeMF).(*dns.MF).Mf
 						name = label.FirstRR(dns.TypeMF).(*dns.MF).Mf
 						// TODO: need to avoid loops here somehow
 						// TODO: need to avoid loops here somehow
-						aliases := z.FindLabels(name, targets, qts)
+						aliases := z.FindLabels(name, targets, aliasQts)
 						matches = append(matches, aliases...)
 						matches = append(matches, aliases...)
 						continue
 						continue
 					}
 					}