mirror of
https://github.com/tailscale/tailscale.git
synced 2025-03-28 12:02:23 +00:00
net/dns/resolver: return an empty successful response instead of NXDomain when resolving A records for 4via6 domains
As quad-100 is an authoritative server for 4via6 domains, it should always return responses with a response code of 0 (indicating no error) when resolving records for these domains. If there's no resource record of the specified type (e.g. A), it should return a response with an empty answer section rather than NXDomain. Such a response indicates that there is at least one RR of a different type (e.g., AAAA), suggesting the Windows stub resolver to look for it. Fixes tailscale/corp#20767 Signed-off-by: Nick Khyl <nickk@tailscale.com>
This commit is contained in:
parent
4b6a0c42c8
commit
4cdc4ed7db
@ -610,7 +610,7 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netip.Addr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Special-case: 4via6 DNS names.
|
// Special-case: 4via6 DNS names.
|
||||||
if ip, ok := r.parseViaDomain(domain, typ); ok {
|
if ip, ok := r.resolveViaDomain(domain, typ); ok {
|
||||||
return ip, dns.RCodeSuccess
|
return ip, dns.RCodeSuccess
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -689,7 +689,7 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netip.Addr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseViaDomain synthesizes an IP address for quad-A DNS requests of the form
|
// resolveViaDomain synthesizes an IP address for quad-A DNS requests of the form
|
||||||
// `<IPv4-address-with-hypens-instead-of-dots>-via-<siteid>[.*]`. Two prior formats that
|
// `<IPv4-address-with-hypens-instead-of-dots>-via-<siteid>[.*]`. Two prior formats that
|
||||||
// didn't pan out (due to a Chrome issue and DNS search ndots issues) were
|
// didn't pan out (due to a Chrome issue and DNS search ndots issues) were
|
||||||
// `<IPv4-address>.via-<X>` and the older `via-<X>.<IPv4-address>`,
|
// `<IPv4-address>.via-<X>` and the older `via-<X>.<IPv4-address>`,
|
||||||
@ -697,13 +697,27 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netip.Addr,
|
|||||||
//
|
//
|
||||||
// This exists as a convenient mapping into Tailscales 'Via Range'.
|
// This exists as a convenient mapping into Tailscales 'Via Range'.
|
||||||
//
|
//
|
||||||
|
// It returns a zero netip.Addr and true to indicate a successful response with
|
||||||
|
// an empty answers section if the specified domain is a valid Tailscale 4via6
|
||||||
|
// domain, but the request type is neither quad-A nor ALL.
|
||||||
|
//
|
||||||
// TODO(maisem/bradfitz/tom): `<IPv4-address>.via-<X>` was introduced
|
// TODO(maisem/bradfitz/tom): `<IPv4-address>.via-<X>` was introduced
|
||||||
// (2022-06-02) to work around an issue in Chrome where it would treat
|
// (2022-06-02) to work around an issue in Chrome where it would treat
|
||||||
// "http://via-1.1.2.3.4" as a search string instead of a URL. We should rip out
|
// "http://via-1.1.2.3.4" as a search string instead of a URL. We should rip out
|
||||||
// the old format in early 2023.
|
// the old format in early 2023.
|
||||||
func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netip.Addr, bool) {
|
func (r *Resolver) resolveViaDomain(domain dnsname.FQDN, typ dns.Type) (netip.Addr, bool) {
|
||||||
fqdn := string(domain.WithoutTrailingDot())
|
fqdn := string(domain.WithoutTrailingDot())
|
||||||
if typ != dns.TypeAAAA {
|
switch typ {
|
||||||
|
case dns.TypeA, dns.TypeAAAA, dns.TypeALL:
|
||||||
|
// For Type A requests, we should return a successful response
|
||||||
|
// with an empty answer section rather than an NXDomain
|
||||||
|
// if the specified domain is a valid Tailscale 4via6 domain.
|
||||||
|
//
|
||||||
|
// Therefore, we should continue and parse the domain name first
|
||||||
|
// before deciding whether to return an IPv6 address,
|
||||||
|
// a zero (invalid) netip.Addr and true to indicate a successful empty response,
|
||||||
|
// or a zero netip.Addr and false to indicate that it is not a Tailscale 4via6 domain.
|
||||||
|
default:
|
||||||
return netip.Addr{}, false
|
return netip.Addr{}, false
|
||||||
}
|
}
|
||||||
if len(fqdn) < len("via-X.0.0.0.0") {
|
if len(fqdn) < len("via-X.0.0.0.0") {
|
||||||
@ -756,6 +770,10 @@ func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netip.Addr
|
|||||||
return netip.Addr{}, false // badly formed, don't respond
|
return netip.Addr{}, false // badly formed, don't respond
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if typ == dns.TypeA {
|
||||||
|
return netip.Addr{}, true // the name exists, but cannot be resolved to an IPv4 address
|
||||||
|
}
|
||||||
|
|
||||||
// MapVia will never error when given an IPv4 netip.Prefix.
|
// MapVia will never error when given an IPv4 netip.Prefix.
|
||||||
out, _ := tsaddr.MapVia(uint32(prefix), netip.PrefixFrom(ip4, ip4.BitLen()))
|
out, _ := tsaddr.MapVia(uint32(prefix), netip.PrefixFrom(ip4, ip4.BitLen()))
|
||||||
return out.Addr(), true
|
return out.Addr(), true
|
||||||
|
@ -401,6 +401,12 @@ func TestResolveLocal(t *testing.T) {
|
|||||||
// suffixes are currently hard-coded and not plumbed via the netmap)
|
// suffixes are currently hard-coded and not plumbed via the netmap)
|
||||||
{"via_form3_dec_example.com", dnsname.FQDN("1-2-3-4-via-1.example.com."), dns.TypeAAAA, netip.Addr{}, dns.RCodeRefused},
|
{"via_form3_dec_example.com", dnsname.FQDN("1-2-3-4-via-1.example.com."), dns.TypeAAAA, netip.Addr{}, dns.RCodeRefused},
|
||||||
{"via_form3_dec_examplets.net", dnsname.FQDN("1-2-3-4-via-1.examplets.net."), dns.TypeAAAA, netip.Addr{}, dns.RCodeRefused},
|
{"via_form3_dec_examplets.net", dnsname.FQDN("1-2-3-4-via-1.examplets.net."), dns.TypeAAAA, netip.Addr{}, dns.RCodeRefused},
|
||||||
|
|
||||||
|
// Resolve A and ALL types of resource records.
|
||||||
|
{"via_type_a", dnsname.FQDN("1-2-3-4-via-1."), dns.TypeA, netip.Addr{}, dns.RCodeSuccess},
|
||||||
|
{"via_invalid_type_a", dnsname.FQDN("1-2-3-4-via-."), dns.TypeA, netip.Addr{}, dns.RCodeRefused},
|
||||||
|
{"via_type_all", dnsname.FQDN("1-2-3-4-via-1."), dns.TypeALL, netip.MustParseAddr("fd7a:115c:a1e0:b1a:0:1:1.2.3.4"), dns.RCodeSuccess},
|
||||||
|
{"via_invalid_type_all", dnsname.FQDN("1-2-3-4-via-."), dns.TypeALL, netip.Addr{}, dns.RCodeRefused},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user