From 54ba6194f7604b53a026d9e003fba7585f33baf3 Mon Sep 17 00:00:00 2001 From: Denton Gentry Date: Fri, 26 Mar 2021 18:38:05 -0700 Subject: [PATCH] interfaces: allow IPv6 ULA as a valid address. IPv6 Unique Local Addresses are sometimes used with Network Prefix Translation to reach the Internet. In that respect their use is similar to the private IPv4 address ranges 10/8, 172.16/12, and 192.168/16. Treat them as sufficient for AnyInterfaceUp(), but specifically exclude Tailscale's own IPv6 ULA prefix to avoid mistakenly trying to bootstrap Tailscale using Tailscale. This helps in supporting Google Cloud Run, where the addresses are 169.254.8.1/32 and fddf:3978:feb1:d745::c001/128 on eth1. Signed-off-by: Denton Gentry --- net/interfaces/interfaces.go | 3 ++- net/interfaces/interfaces_test.go | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/net/interfaces/interfaces.go b/net/interfaces/interfaces.go index f2988af34..d04b75177 100644 --- a/net/interfaces/interfaces.go +++ b/net/interfaces/interfaces.go @@ -500,7 +500,8 @@ func isPrivateIP(ip netaddr.IP) bool { } func isGlobalV6(ip netaddr.IP) bool { - return v6Global1.Contains(ip) + return v6Global1.Contains(ip) || + (tsaddr.IsULA(ip) && !tsaddr.TailscaleULARange().Contains(ip)) } func mustCIDR(s string) netaddr.IPPrefix { diff --git a/net/interfaces/interfaces_test.go b/net/interfaces/interfaces_test.go index ab0ee3734..fb7b213c2 100644 --- a/net/interfaces/interfaces_test.go +++ b/net/interfaces/interfaces_test.go @@ -7,6 +7,8 @@ package interfaces import ( "encoding/json" "testing" + + "inet.af/netaddr" ) func TestGetState(t *testing.T) { @@ -43,3 +45,24 @@ func TestLikelyHomeRouterIP(t *testing.T) { } t.Logf("myIP = %v; gw = %v", my, gw) } + +func TestIsGlobalV6(t *testing.T) { + tests := []struct { + name string + ip string + want bool + }{ + {"first ULA", "fc00::1", true}, + {"Tailscale", "fd7a:115c:a1e0::1", false}, + {"Cloud Run", "fddf:3978:feb1:d745::1", true}, + {"zeros", "0000:0000:0000:0000:0000:0000:0000:0000", false}, + {"Link Local", "fe80::1", false}, + {"Global", "2602::1", true}, + } + + for _, test := range tests { + if got := isGlobalV6(netaddr.MustParseIP(test.ip)); got != test.want { + t.Errorf("isGlobalV6(%s) = %v, want %v", test.name, got, test.want) + } + } +}