|
|
|
@ -550,7 +550,7 @@ func (r *Resolver) resolveLocal(domain dnsname.FQDN, typ dns.Type) (netip.Addr,
|
|
|
|
|
return tsaddr.TailscaleServiceIPv6(), dns.RCodeSuccess
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Special-case: 'via-<siteid>.<ipv4>' queries.
|
|
|
|
|
// Special-case: 4via6 DNS names.
|
|
|
|
|
if ip, ok := r.parseViaDomain(domain, typ); ok {
|
|
|
|
|
return ip, dns.RCodeSuccess
|
|
|
|
|
}
|
|
|
|
@ -630,7 +630,9 @@ 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
|
|
|
|
|
// `<IPv4-address>.via-<X>` and the deprecated form `via-<X>.<IPv4-address>`,
|
|
|
|
|
// `<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
|
|
|
|
|
// `<IPv4-address>.via-<X>` and the older `via-<X>.<IPv4-address>`,
|
|
|
|
|
// where X is a decimal, or hex-encoded number with a '0x' prefix.
|
|
|
|
|
//
|
|
|
|
|
// This exists as a convenient mapping into Tailscales 'Via Range'.
|
|
|
|
@ -650,14 +652,28 @@ func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netip.Addr
|
|
|
|
|
|
|
|
|
|
var siteID string
|
|
|
|
|
var ip4Str string
|
|
|
|
|
if strings.HasPrefix(fqdn, "via-") {
|
|
|
|
|
switch {
|
|
|
|
|
case strings.Contains(fqdn, "-via-"):
|
|
|
|
|
// Format number 3: "192-168-1-2-via-7" or "192-168-1-2-via-7.foo.ts.net."
|
|
|
|
|
// Third time's a charm. The earlier two formats follow after this block.
|
|
|
|
|
firstLabel, domain, _ := strings.Cut(fqdn, ".") // "192-168-1-2-via-7"
|
|
|
|
|
if !(domain == "" || dnsname.HasSuffix(domain, "ts.net") || dnsname.HasSuffix(domain, "tailscale.net")) {
|
|
|
|
|
return netip.Addr{}, false
|
|
|
|
|
}
|
|
|
|
|
v4hyphens, suffix, ok := strings.Cut(firstLabel, "-via-")
|
|
|
|
|
if !ok {
|
|
|
|
|
return netip.Addr{}, false
|
|
|
|
|
}
|
|
|
|
|
siteID = suffix
|
|
|
|
|
ip4Str = strings.ReplaceAll(v4hyphens, "-", ".")
|
|
|
|
|
case strings.HasPrefix(fqdn, "via-"):
|
|
|
|
|
firstDot := strings.Index(fqdn, ".")
|
|
|
|
|
if firstDot < 0 {
|
|
|
|
|
return netip.Addr{}, false // missing dot delimiters
|
|
|
|
|
}
|
|
|
|
|
siteID = fqdn[len("via-"):firstDot]
|
|
|
|
|
ip4Str = fqdn[firstDot+1:]
|
|
|
|
|
} else {
|
|
|
|
|
default:
|
|
|
|
|
lastDot := strings.LastIndex(fqdn, ".")
|
|
|
|
|
if lastDot < 0 {
|
|
|
|
|
return netip.Addr{}, false // missing dot delimiters
|
|
|
|
@ -672,12 +688,12 @@ func (r *Resolver) parseViaDomain(domain dnsname.FQDN, typ dns.Type) (netip.Addr
|
|
|
|
|
|
|
|
|
|
ip4, err := netip.ParseAddr(ip4Str)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return netip.Addr{}, false // badly formed, dont respond
|
|
|
|
|
return netip.Addr{}, false // badly formed, don't respond
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
prefix, err := strconv.ParseUint(siteID, 0, 32)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return netip.Addr{}, false // badly formed, dont respond
|
|
|
|
|
return netip.Addr{}, false // badly formed, don't respond
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MapVia will never error when given an ipv4 netip.Prefix.
|
|
|
|
|