From df26c63793895506f76a57838de7060844331d6a Mon Sep 17 00:00:00 2001 From: Tom DNetto Date: Wed, 20 Apr 2022 14:35:20 -0700 Subject: [PATCH] net/dns/resolver, net/tsaddr: fix reverse lookups in 4to6 IP range Fixes #4439 Signed-off-by: Tom DNetto --- net/dns/resolver/tsdns.go | 18 ++++++++++++++++-- net/dns/resolver/tsdns_test.go | 1 + net/tsaddr/tsaddr.go | 12 ++++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/net/dns/resolver/tsdns.go b/net/dns/resolver/tsdns.go index 66117a6ef..06a2550d2 100644 --- a/net/dns/resolver/tsdns.go +++ b/net/dns/resolver/tsdns.go @@ -725,6 +725,22 @@ func (r *Resolver) resolveLocalReverse(name dnsname.FQDN) (dnsname.FQDN, dns.RCo return "", dns.RCodeRefused } + r.mu.Lock() + defer r.mu.Unlock() + + // If the requested IP is part of the IPv6 4-to-6 range, it might + // correspond to an IPv4 address (assuming IPv4 is enabled). + if ip4, ok := tsaddr.Tailscale6to4(ip); ok { + fqdn, code := r.fqdnForIPLocked(ip4, name) + if code == dns.RCodeSuccess { + return fqdn, code + } + } + return r.fqdnForIPLocked(ip, name) +} + +// r.mu must be held. +func (r *Resolver) fqdnForIPLocked(ip netaddr.IP, name dnsname.FQDN) (dnsname.FQDN, dns.RCode) { // If someone curiously does a reverse lookup on the DNS IP, we // return a domain that helps indicate that Tailscale is using // this IP for a special purpose and it is not a node on their @@ -733,8 +749,6 @@ func (r *Resolver) resolveLocalReverse(name dnsname.FQDN) (dnsname.FQDN, dns.RCo return dnsSymbolicFQDN, dns.RCodeSuccess } - r.mu.Lock() - defer r.mu.Unlock() ret, ok := r.ipToHost[ip] if !ok { for _, suffix := range r.localDomains { diff --git a/net/dns/resolver/tsdns_test.go b/net/dns/resolver/tsdns_test.go index 5adec2c60..d304d5c97 100644 --- a/net/dns/resolver/tsdns_test.go +++ b/net/dns/resolver/tsdns_test.go @@ -382,6 +382,7 @@ func TestResolveLocalReverse(t *testing.T) { {"ipv6_nxdomain", dnsname.FQDN("0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.ip6.arpa."), "", dns.RCodeNameError}, {"nxdomain", dnsname.FQDN("2.3.4.5.in-addr.arpa."), "", dns.RCodeRefused}, {"magicdns", dnsname.FQDN("100.100.100.100.in-addr.arpa."), dnsSymbolicFQDN, dns.RCodeSuccess}, + {"ipv6_4to6", dnsname.FQDN("4.6.4.6.4.6.2.6.6.9.d.c.3.4.8.4.2.1.b.a.0.e.1.a.c.5.1.1.a.7.d.f.ip6.arpa."), dnsSymbolicFQDN, dns.RCodeSuccess}, } for _, tt := range tests { diff --git a/net/tsaddr/tsaddr.go b/net/tsaddr/tsaddr.go index 85ab89b09..d2e7497e1 100644 --- a/net/tsaddr/tsaddr.go +++ b/net/tsaddr/tsaddr.go @@ -128,6 +128,18 @@ func Tailscale4To6(ipv4 netaddr.IP) netaddr.IP { return netaddr.IPFrom16(ret) } +// Tailscale6to4 returns the IPv4 address corresponding to the given +// tailscale IPv6 address within the 4To6 range. The IPv4 address +// and true are returned if the given address was in the correct range, +// false if not. +func Tailscale6to4(ipv6 netaddr.IP) (netaddr.IP, bool) { + if !ipv6.Is6() || !Tailscale4To6Range().Contains(ipv6) { + return netaddr.IP{}, false + } + v6 := ipv6.As16() + return netaddr.IPv4(100, v6[13], v6[14], v6[15]), true +} + func mustPrefix(v *netaddr.IPPrefix, prefix string) { var err error *v, err = netaddr.ParseIPPrefix(prefix)