From 2903d42921404777feb3b573487e66a5211dd87d Mon Sep 17 00:00:00 2001 From: Tom Date: Fri, 27 May 2022 14:42:55 -0700 Subject: [PATCH] wgengine/router: delete hardcoded link-local address on Windows (#4740) Fixes #4647 It seems that Windows creates a link-local address for the TUN driver, seemingly based on the (fixed) adapter GUID. This results in a fixed MAC address, which for some reason doesn't handle loopback correctly. Given the derived link-local address is preferred for lookups (thanks LLMNR), traffic which addresses the current node by hostname uses this broken address and never works. To address this, we remove the broken link-local address from the wintun adapter. Signed-off-by: Tom DNetto --- wgengine/router/ifconfig_windows.go | 15 ++++++++++++++- wgengine/router/ifconfig_windows_test.go | 5 +++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/wgengine/router/ifconfig_windows.go b/wgengine/router/ifconfig_windows.go index bffb562d2..c5770afab 100644 --- a/wgengine/router/ifconfig_windows.go +++ b/wgengine/router/ifconfig_windows.go @@ -27,6 +27,8 @@ import ( "tailscale.com/wgengine/winnet" ) +var wintunLinkLocal = netaddr.MustParseIP("fe80::99d0:ec2d:b2e7:536b") + // monitorDefaultRoutes subscribes to route change events and updates // the Tailscale tunnel interface's MTU to match that of the // underlying default route. @@ -576,7 +578,18 @@ func excludeIPv6LinkLocal(in []*net.IPNet) (out []*net.IPNet) { out = in[:0] for _, n := range in { if len(n.IP) == 16 && n.IP.IsLinkLocalUnicast() { - continue + // Windows creates a fixed link-local address for wintun, + // which doesn't seem to route correctly. Unfortunately, LLMNR returns this + // address for lookups by the hostname, and Windows prefers using it. + // This means that local traffic addressed to the machine's hostname breaks. + // + // While we otherwise preserve link-local addresses, we delete + // this one to force lookups to use a working address. + // + // See: https://github.com/tailscale/tailscale/issues/4647 + if ip, ok := netaddr.FromStdIP(n.IP); !ok || wintunLinkLocal != ip { + continue // filter this IPNet + } } out = append(out, n) } diff --git a/wgengine/router/ifconfig_windows_test.go b/wgengine/router/ifconfig_windows_test.go index 44b81c558..0b64d44ec 100644 --- a/wgengine/router/ifconfig_windows_test.go +++ b/wgengine/router/ifconfig_windows_test.go @@ -164,8 +164,9 @@ func TestDeltaNets(t *testing.T) { wantDel: nets("fe80::99d0:ec2d:b2e7:536b/64"), }, { - a: excludeIPv6LinkLocal(nets("100.84.36.11/32", "fe80::99d0:ec2d:b2e7:536b/64")), - b: nets("100.84.36.11/32"), + a: excludeIPv6LinkLocal(nets("100.84.36.11/32", "fe80::99d0:ec2d:b2e7:536b/64")), + b: nets("100.84.36.11/32"), + wantDel: nets("fe80::99d0:ec2d:b2e7:536b/64"), }, { a: []*net.IPNet{