Browse Source

Use server IP if ECS provided IP is unhelpful

Ask Bjørn Hansen 2 years ago
parent
commit
3a6ec5bfaa
2 changed files with 18 additions and 4 deletions
  1. 15 1
      server/serve.go
  2. 3 3
      server/serve_test.go

+ 15 - 1
server/serve.go

@@ -6,6 +6,7 @@ import (
 	"fmt"
 	"log"
 	"net"
+	"net/netip"
 	"os"
 	"strconv"
 	"strings"
@@ -87,7 +88,15 @@ func (srv *Server) serve(w dns.ResponseWriter, req *dns.Msg, z *zones.Zone) {
 				applog.Println("Got edns-client-subnet", e.Address, e.Family, e.SourceNetmask, e.SourceScope)
 				if e.Address != nil {
 					ecs = e
-					ip = e.Address
+
+					if ecsip, ok := netip.AddrFromSlice(e.Address); ok {
+						if ecsip.IsGlobalUnicast() &&
+							!(ecsip.IsPrivate() ||
+								ecsip.IsLinkLocalMulticast() ||
+								ecsip.IsInterfaceLocalMulticast()) {
+							ip = ecsip.AsSlice()
+						}
+					}
 
 					if qle != nil {
 						qle.HasECS = true
@@ -107,6 +116,11 @@ func (srv *Server) serve(w dns.ResponseWriter, req *dns.Msg, z *zones.Zone) {
 
 	targets, netmask, location := z.Options.Targeting.GetTargets(ip, z.HasClosest)
 
+	// if the ECS IP didn't get targets, try the real IP instead
+	if l := len(targets); (l == 0 || l == 1 && targets[0] == "@") && !ip.Equal(realIP) {
+		targets, netmask, location = z.Options.Targeting.GetTargets(realIP, z.HasClosest)
+	}
+
 	m := &dns.Msg{}
 
 	// setup logging of answers and rcode

+ 3 - 3
server/serve_test.go

@@ -83,9 +83,9 @@ func testServing(t *testing.T) {
 
 	r = exchange(t, "bar.test.example.com.", dns.TypeA)
 	ip := r.Answer[0].(*dns.A).A
-
-	// c.Check(ip.String(), Equals, "192.168.1.2")
-	// c.Check(int(r.Answer[0].Header().Ttl), Equals, 601)
+	if ip.String() != "192.168.1.2" {
+		t.Logf("unexpected A record for bar.test.example.com: %s", ip.String())
+	}
 
 	r = exchange(t, "test.example.com.", dns.TypeSOA)
 	soa := r.Answer[0].(*dns.SOA)