diff --git a/wgengine/router/ifconfig_windows.go b/wgengine/router/ifconfig_windows.go index 486915e6e..74b9ae335 100644 --- a/wgengine/router/ifconfig_windows.go +++ b/wgengine/router/ifconfig_windows.go @@ -20,6 +20,7 @@ import ( "github.com/tailscale/wireguard-go/tun" "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg" + "inet.af/netaddr" "tailscale.com/net/interfaces" "tailscale.com/wgengine/winnet" ) @@ -378,7 +379,7 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) { } var errAcc error - err = syncRoutes(iface, deduplicatedRoutes) + err = syncRoutes(iface, deduplicatedRoutes, cfg.LocalAddrs) if err != nil && errAcc == nil { log.Printf("setroutes: %v", err) errAcc = err @@ -659,9 +660,29 @@ func getInterfaceRoutes(ifc *winipcfg.IPAdapterAddresses, family winipcfg.Addres return } +// isSingleRouteInPrefixes reports whether r is a single-address +// prefix that appears in pfxs. +func isSingleRouteInPrefixes(r net.IPNet, pfxs []netaddr.IPPrefix) bool { + rr, ok := netaddr.FromStdIPNet(&r) + if !ok { + return false + } + if !rr.IsSingleIP() { + return false + } + for _, pfx := range pfxs { + if pfx == rr { + return true + } + } + return false +} + // syncRoutes incrementally sets multiples routes on an interface. // This avoids a full ifc.FlushRoutes call. -func syncRoutes(ifc *winipcfg.IPAdapterAddresses, want []*winipcfg.RouteData) error { +// dontDelete is a list of interface address routes that the +// synchronization logic should never delete. +func syncRoutes(ifc *winipcfg.IPAdapterAddresses, want []*winipcfg.RouteData, dontDelete []netaddr.IPPrefix) error { routes, err := getInterfaceRoutes(ifc, windows.AF_INET) if err != nil { return err @@ -669,6 +690,11 @@ func syncRoutes(ifc *winipcfg.IPAdapterAddresses, want []*winipcfg.RouteData) er got := make([]*winipcfg.RouteData, 0, len(routes)) for _, r := range routes { + if isSingleRouteInPrefixes(r.DestinationPrefix.IPNet(), dontDelete) { + // See issue 1448: we don't want to touch the routes added + // by Windows for our interface addresses. + continue + } got = append(got, &winipcfg.RouteData{ Destination: r.DestinationPrefix.IPNet(), NextHop: r.NextHop.IP(),