@ -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 . pa rseViaDomain( domain , typ ) ; ok {
if ip , ok := r . re solv eViaDomain( 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,
}
}
}
}
// pa rseViaDomain synthesizes an IP address for quad-A DNS requests of the form
// re solv eViaDomain 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 ) pa rseViaDomain( domain dnsname . FQDN , typ dns . Type ) ( netip . Addr , bool ) {
func ( r * Resolver ) re solv eViaDomain( 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