wgengine/router: don't touch interface routes
Developed by a cast of dozens.
Fixes #1448
Signed-off-by: David Anderson <danderson@tailscale.com>
(cherry picked from commit fa6110e47b
)
bradfitz/proposed_1.4.6
parent
f7ef32da5f
commit
bbb0e84cf1
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/tailscale/wireguard-go/tun"
|
"github.com/tailscale/wireguard-go/tun"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||||
|
"inet.af/netaddr"
|
||||||
"tailscale.com/net/interfaces"
|
"tailscale.com/net/interfaces"
|
||||||
"tailscale.com/wgengine/winnet"
|
"tailscale.com/wgengine/winnet"
|
||||||
)
|
)
|
||||||
|
@ -378,7 +379,7 @@ func configureInterface(cfg *Config, tun *tun.NativeTun) (retErr error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var errAcc error
|
var errAcc error
|
||||||
err = syncRoutes(iface, deduplicatedRoutes)
|
err = syncRoutes(iface, deduplicatedRoutes, cfg.LocalAddrs)
|
||||||
if err != nil && errAcc == nil {
|
if err != nil && errAcc == nil {
|
||||||
log.Printf("setroutes: %v", err)
|
log.Printf("setroutes: %v", err)
|
||||||
errAcc = err
|
errAcc = err
|
||||||
|
@ -659,9 +660,29 @@ func getInterfaceRoutes(ifc *winipcfg.IPAdapterAddresses, family winipcfg.Addres
|
||||||
return
|
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.
|
// syncRoutes incrementally sets multiples routes on an interface.
|
||||||
// This avoids a full ifc.FlushRoutes call.
|
// 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)
|
routes, err := getInterfaceRoutes(ifc, windows.AF_INET)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -669,6 +690,11 @@ func syncRoutes(ifc *winipcfg.IPAdapterAddresses, want []*winipcfg.RouteData) er
|
||||||
|
|
||||||
got := make([]*winipcfg.RouteData, 0, len(routes))
|
got := make([]*winipcfg.RouteData, 0, len(routes))
|
||||||
for _, r := range 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{
|
got = append(got, &winipcfg.RouteData{
|
||||||
Destination: r.DestinationPrefix.IPNet(),
|
Destination: r.DestinationPrefix.IPNet(),
|
||||||
NextHop: r.NextHop.IP(),
|
NextHop: r.NextHop.IP(),
|
||||||
|
|
Loading…
Reference in New Issue