From bb7be74756e23d4385a91a9608fd68eddd5a249a Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Wed, 28 Sep 2022 17:19:30 -0700 Subject: [PATCH] net/dns/publicdns: permit more NextDNS profile bits in its IPv6 suffix I brain-o'ed the math earlier. The NextDNS prefix is /32 (actually /33, but will guarantee last bit is 0), so we have 128-32 = 96 bits (12 bytes) of config/profile ID that we can extract. NextDNS doesn't currently use all those, but might. Updates #2452 Change-Id: I249bd28500c781e45425fd00fd3f46893ae226a2 Signed-off-by: Brad Fitzpatrick --- net/dns/publicdns/publicdns.go | 10 +++++----- net/dns/publicdns/publicdns_test.go | 13 +++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/net/dns/publicdns/publicdns.go b/net/dns/publicdns/publicdns.go index 6ffd1cd2f..215cbef14 100644 --- a/net/dns/publicdns/publicdns.go +++ b/net/dns/publicdns/publicdns.go @@ -37,15 +37,15 @@ func DoHEndpointFromIP(ip netip.Addr) (dohBase string, dohOnly bool, ok bool) { } // NextDNS DoH URLs are of the form "https://dns.nextdns.io/c3a884" - // where the path component is the lower 8 bytes of the IPv6 address + // where the path component is the lower 12 bytes of the IPv6 address // in lowercase hex without any zero padding. if nextDNSv6RangeA.Contains(ip) || nextDNSv6RangeB.Contains(ip) { a := ip.As16() var sb strings.Builder const base = "https://dns.nextdns.io/" - sb.Grow(len(base) + 8) + sb.Grow(len(base) + 12) sb.WriteString(base) - for _, b := range bytes.TrimLeft(a[8:], "\x00") { + for _, b := range bytes.TrimLeft(a[4:], "\x00") { fmt.Fprintf(&sb, "%02x", b) } return sb.String(), true, true @@ -100,7 +100,7 @@ func DoHIPsOfBase(dohBase string) []netip.Addr { // conventional for them and not required (it'll already be in the DoH path). // (Really we shouldn't use either IPv4 or IPv6 anycast for DoH once we // resolve "dns.nextdns.io".) - if b, err := hex.DecodeString(hexStr); err == nil && len(b) <= 8 && len(b) > 0 { + if b, err := hex.DecodeString(hexStr); err == nil && len(b) <= 12 && len(b) > 0 { return []netip.Addr{ nextDNSv4One, nextDNSv4Two, @@ -215,7 +215,7 @@ var ( // nextDNSv6Gen generates a NextDNS IPv6 address from the upper 8 bytes in the // provided ip and using id as the lowest 0-8 bytes. func nextDNSv6Gen(ip netip.Addr, id []byte) netip.Addr { - if len(id) > 8 { + if len(id) > 12 { return netip.Addr{} } a := ip.As16() diff --git a/net/dns/publicdns/publicdns_test.go b/net/dns/publicdns/publicdns_test.go index 3e58e4463..2246931e3 100644 --- a/net/dns/publicdns/publicdns_test.go +++ b/net/dns/publicdns/publicdns_test.go @@ -86,6 +86,19 @@ func TestDoHIPsOfBase(t *testing.T) { "2a07:a8c1::c3:a884", ), }, + { + base: "https://dns.nextdns.io/112233445566778899aabbcc", + want: ips( + "45.90.28.0", + "45.90.30.0", + "2a07:a8c0:1122:3344:5566:7788:99aa:bbcc", + "2a07:a8c1:1122:3344:5566:7788:99aa:bbcc", + ), + }, + { + base: "https://dns.nextdns.io/112233445566778899aabbccdd", + want: ips(), // nothing; profile length is over 12 bytes + }, { base: "https://dns.nextdns.io/c3a884/with/more/stuff", want: ips(