mirror of https://github.com/tailscale/tailscale/
Merge 043a1a4e0b into aadc4f2ef4
commit
3fc997c678
@ -0,0 +1,45 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package osrouter
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
"tailscale.com/net/tsaddr"
|
||||
)
|
||||
|
||||
// windowsSubnetRouteMetric is an intentionally "high" route metric used for
|
||||
// non-Tailscale routes (e.g. advertised subnet routes) on Windows.
|
||||
//
|
||||
// Rationale: when a Windows client is physically on a LAN that's also
|
||||
// advertised via a subnet router, Windows may otherwise prefer the Tailscale
|
||||
// route due to a low Tailscale interface metric, resulting in local traffic
|
||||
// being sent to (and dependent on) the subnet router.
|
||||
//
|
||||
// See https://github.com/tailscale/tailscale/issues/12248.
|
||||
const windowsSubnetRouteMetric = uint32(5000)
|
||||
|
||||
// windowsRouteMetric returns the route metric to use when installing routes on
|
||||
// Windows.
|
||||
//
|
||||
// For exit-node default routes and single-host Tailscale routes, we keep the
|
||||
// metric low so the routes behave as expected. For advertised subnet routes, we
|
||||
// set a higher metric so on-link / locally-connected routes win when present.
|
||||
func windowsRouteMetric(route netip.Prefix) uint32 {
|
||||
if !route.IsValid() {
|
||||
return 0
|
||||
}
|
||||
// Default route (exit node) should stay preferred when configured.
|
||||
if route.Bits() == 0 {
|
||||
return 0
|
||||
}
|
||||
// Single-host Tailscale routes should stay preferred.
|
||||
if route.IsSingleIP() && tsaddr.IsTailscaleIP(route.Addr().Unmap()) {
|
||||
return 0
|
||||
}
|
||||
// Everything else (notably: advertised subnet routes) should not override
|
||||
// on-link routes with the same prefix.
|
||||
return windowsSubnetRouteMetric
|
||||
}
|
||||
|
||||
@ -0,0 +1,58 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package osrouter
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
"tailscale.com/net/tsaddr"
|
||||
)
|
||||
|
||||
func TestWindowsRouteMetric(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
route netip.Prefix
|
||||
want uint32
|
||||
}{
|
||||
{
|
||||
name: "default_route_v4",
|
||||
route: netip.MustParsePrefix("0.0.0.0/0"),
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "default_route_v6",
|
||||
route: netip.MustParsePrefix("::/0"),
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "tailscale_service_ip_v4_single_host",
|
||||
route: netip.PrefixFrom(tsaddr.TailscaleServiceIP(), 32),
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "tailscale_service_ip_v6_single_host",
|
||||
route: netip.PrefixFrom(tsaddr.TailscaleServiceIPv6(), 128),
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "advertised_subnet_v4",
|
||||
route: netip.MustParsePrefix("192.168.1.0/24"),
|
||||
want: windowsSubnetRouteMetric,
|
||||
},
|
||||
{
|
||||
name: "advertised_subnet_v6",
|
||||
route: netip.MustParsePrefix("fd00::/64"),
|
||||
want: windowsSubnetRouteMetric,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := windowsRouteMetric(tt.route); got != tt.want {
|
||||
t.Fatalf("windowsRouteMetric(%v)=%v; want %v", tt.route, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue