ipn/ipnlocal: for IPv6-only nodes, publish IPv6 MagicDNS records of peers

See https://github.com/tailscale/tailscale/issues/2970#issuecomment-931885268

Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2021-10-04 07:54:16 -07:00 committed by Brad Fitzpatrick
parent 45f51d4fa6
commit 22a1a5d7cf
3 changed files with 55 additions and 4 deletions

View File

@ -86,6 +86,40 @@ func TestDNSConfigForNetmap(t *testing.T) {
}, },
}, },
}, },
{
// An ephemeral node with only an IPv6 address
// should get IPv6 records for all its peers,
// even if they have IPv4.
name: "v6_only_self",
nm: &netmap.NetworkMap{
Name: "myname.net",
Addresses: ipps("fe75::1"),
Peers: []*tailcfg.Node{
{
Name: "peera.net",
Addresses: ipps("100.102.0.1", "100.102.0.2", "fe75::1001"),
},
{
Name: "b.net",
Addresses: ipps("100.102.0.1", "100.102.0.2", "fe75::2"),
},
{
Name: "v6-only.net",
Addresses: ipps("fe75::3"), // no IPv4, so we don't ignore IPv6
},
},
},
prefs: &ipn.Prefs{},
want: &dns.Config{
Routes: map[dnsname.FQDN][]dnstype.Resolver{},
Hosts: map[dnsname.FQDN][]netaddr.IP{
"b.net.": ips("fe75::2"),
"myname.net.": ips("fe75::1"),
"peera.net.": ips("fe75::1001"),
"v6-only.net.": ips("fe75::3"),
},
},
},
{ {
name: "extra_records", name: "extra_records",
nm: &netmap.NetworkMap{ nm: &netmap.NetworkMap{

View File

@ -1817,6 +1817,10 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, prefs *ipn.Prefs, logf logger.Log
Hosts: map[dnsname.FQDN][]netaddr.IP{}, Hosts: map[dnsname.FQDN][]netaddr.IP{},
} }
// selfV6Only is whether we only have IPv6 addresses ourselves.
selfV6Only := tsaddr.PrefixesContainsFunc(nm.Addresses, tsaddr.PrefixIs6) &&
!tsaddr.PrefixesContainsFunc(nm.Addresses, tsaddr.PrefixIs4)
// Populate MagicDNS records. We do this unconditionally so that // Populate MagicDNS records. We do this unconditionally so that
// quad-100 can always respond to MagicDNS queries, even if the OS // quad-100 can always respond to MagicDNS queries, even if the OS
// isn't configured to make MagicDNS resolution truly // isn't configured to make MagicDNS resolution truly
@ -1830,12 +1834,19 @@ func dnsConfigForNetmap(nm *netmap.NetworkMap, prefs *ipn.Prefs, logf logger.Log
if err != nil { if err != nil {
return // TODO: propagate error? return // TODO: propagate error?
} }
have4 := tsaddr.PrefixesContainsFunc(addrs, func(p netaddr.IPPrefix) bool { return p.IP().Is4() }) have4 := tsaddr.PrefixesContainsFunc(addrs, tsaddr.PrefixIs4)
var ips []netaddr.IP var ips []netaddr.IP
for _, addr := range addrs { for _, addr := range addrs {
// Remove IPv6 addresses for now, as we don't if selfV6Only {
// guarantee that the peer node actually can speak if addr.IP().Is6() {
// IPv6 correctly. ips = append(ips, addr.IP())
}
continue
}
// If this node has an IPv4 address, then
// remove peers' IPv6 addresses for now, as we
// don't guarantee that the peer node actually
// can speak IPv6 correctly.
// //
// https://github.com/tailscale/tailscale/issues/1152 // https://github.com/tailscale/tailscale/issues/1152
// tracks adding the right capability reporting to // tracks adding the right capability reporting to

View File

@ -185,3 +185,9 @@ func IPsContainsFunc(ips []netaddr.IP, f func(netaddr.IP) bool) bool {
} }
return false return false
} }
// PrefixIs4 reports whether p is an IPv4 prefix.
func PrefixIs4(p netaddr.IPPrefix) bool { return p.IP().Is4() }
// PrefixIs6 reports whether p is an IPv6 prefix.
func PrefixIs6(p netaddr.IPPrefix) bool { return p.IP().Is6() }