Update the routes so that it has a high metric

This commit is contained in:
Owen
2026-07-16 16:55:12 -04:00
parent 10adb416f8
commit 2bad244186
2 changed files with 28 additions and 4 deletions

View File

@@ -11,6 +11,24 @@ import (
"github.com/vishvananda/netlink"
)
// VPNRouteMetric is the route metric/priority assigned to routes we add for
// the tunnel, so that an overlapping local/connected route is always
// preferred over the VPN route to the same destination rather than the two
// silently racing based on insertion order. It needs to be higher than any
// metric a local route is realistically going to have: on Linux, automatic
// metrics assigned by NetworkManager (which also apply to the connected
// subnet route, not just the default route) go up to 600 for Wi-Fi; on
// Windows, automatic interface metrics plus route metric rarely exceed a few
// hundred. 9999 comfortably clears both without needing to query the local
// routing table at add-time.
const VPNRouteMetric = 9999
// DarwinAddRoute adds a route via the BSD routing table. Unlike Linux/Windows,
// BSD's routing table has no per-route metric - preference between an
// overlapping local route and this VPN route is instead resolved by
// longest-prefix-match, and `route add` (as opposed to `route change`) fails
// rather than replacing an existing route to the same destination, so a local
// route is never displaced by one we add here.
func DarwinAddRoute(destination string, gateway string, interfaceName string) error {
if runtime.GOOS != "darwin" {
return nil
@@ -65,9 +83,12 @@ func LinuxAddRoute(destination string, gateway string, interfaceName string) err
return fmt.Errorf("invalid destination address: %v", err)
}
// Create route
// Create route. Priority is set explicitly (rather than left at the
// default of 0) so that this route never outranks a local/connected
// route to the same destination - see VPNRouteMetric.
route := &netlink.Route{
Dst: ipNet,
Dst: ipNet,
Priority: VPNRouteMetric,
}
if gateway != "" {

View File

@@ -84,8 +84,11 @@ func WindowsAddRoute(destination string, gateway string, interfaceName string) e
return fmt.Errorf("either gateway or interface must be specified")
}
// Add the route using winipcfg
err = luid.AddRoute(prefix, nextHop, 1)
// Add the route using winipcfg. Metric is set explicitly (rather than a
// low value like 1, which would nearly always outrank local routes) so
// that an overlapping local/connected route is preferred over this VPN
// route - see VPNRouteMetric.
err = luid.AddRoute(prefix, nextHop, VPNRouteMetric)
if err != nil {
return fmt.Errorf("failed to add route: %v", err)
}