Skip to content

Commit 62f4df3

Browse files
committed
net/interfaces, net/netns: add node attributes to control default interface getting and binding
With tailscale#6566 we started to more aggressively bind to the default interface on Darwin. We are seeing some reports of the wrong cellular interface being chosen on iOS. To help with the investigation, this adds to knobs to control the behavior changes: - CapabilityDebugDisableAlternateDefaultRouteInterface disables the alternate function that we use to get the default interface on macOS and iOS (implemented in tailscale/corp#8201). We still log what it would have returned so we can see if it gets things wrong. - CapabilityDebugDisableBindConnToInterface is a bigger hammer that disables binding of connections to the default interface altogether. Updates tailscale#7184 Updates tailscale#7188 Signed-off-by: Mihai Parparita <mihai@tailscale.com>
1 parent fb84ccd commit 62f4df3

File tree

6 files changed

+50
-1
lines changed

6 files changed

+50
-1
lines changed

ipn/ipnlocal/local.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3840,6 +3840,8 @@ func (b *LocalBackend) setNetMapLocked(nm *netmap.NetworkMap) {
38403840

38413841
// See the netns package for documentation on what this capability does.
38423842
netns.SetBindToInterfaceByRoute(hasCapability(nm, tailcfg.CapabilityBindToInterfaceByRoute))
3843+
interfaces.SetDisableAlternateDefaultRouteInterface(hasCapability(nm, tailcfg.CapabilityDebugDisableAlternateDefaultRouteInterface))
3844+
netns.SetDisableBindConnToInterface(hasCapability(nm, tailcfg.CapabilityDebugDisableBindConnToInterface))
38433845

38443846
b.setTCPPortsInterceptedFromNetmapAndPrefsLocked(b.pm.CurrentPrefs())
38453847
if nm == nil {

net/interfaces/interfaces.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"runtime"
1414
"sort"
1515
"strings"
16+
"sync/atomic"
1617

1718
"tailscale.com/hostinfo"
1819
"tailscale.com/net/netaddr"
@@ -756,3 +757,14 @@ func HasCGNATInterface() (bool, error) {
756757
}
757758
return hasCGNATInterface, nil
758759
}
760+
761+
var disableAlternateDefaultRouteInterface atomic.Bool
762+
763+
// SetDisableAlternateDefaultRouteInterface disables the optional external/
764+
// alternate mechanism for getting the default route network interface.
765+
//
766+
// Currently, this only changes the behaviour on BSD-like sytems (FreeBSD and
767+
// Darwin).
768+
func SetDisableAlternateDefaultRouteInterface(v bool) {
769+
disableAlternateDefaultRouteInterface.Store(v)
770+
}

net/interfaces/interfaces_bsd.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,15 @@ func defaultRoute() (d DefaultRouteDetails, err error) {
4040
// owns the default route. It returns the first IPv4 or IPv6 default route it
4141
// finds (it does not prefer one or the other).
4242
func DefaultRouteInterfaceIndex() (int, error) {
43+
disabledAlternateDefaultRouteInterface := false
4344
if f := defaultRouteInterfaceIndexFunc.Load(); f != nil {
4445
if ifIndex := f(); ifIndex != 0 {
45-
return ifIndex, nil
46+
if !disableAlternateDefaultRouteInterface.Load() {
47+
return ifIndex, nil
48+
} else {
49+
disabledAlternateDefaultRouteInterface = true
50+
log.Printf("interfaces_bsd: alternate default route interface function disabled, would have returned interface %d", ifIndex)
51+
}
4652
}
4753
// Fallthrough if we can't use the alternate implementation.
4854
}
@@ -75,6 +81,9 @@ func DefaultRouteInterfaceIndex() (int, error) {
7581
continue
7682
}
7783
if isDefaultGateway(rm) {
84+
if disabledAlternateDefaultRouteInterface {
85+
log.Printf("interfaces_bsd: alternate default route interface function disabled, default implementation returned %d", rm.Index)
86+
}
7887
return rm.Index, nil
7988
}
8089
}

net/netns/netns.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ func SetBindToInterfaceByRoute(v bool) {
4242
bindToInterfaceByRoute.Store(v)
4343
}
4444

45+
var disableBindConnToInterface atomic.Bool
46+
47+
// SetDisableBindConnToInterface disables the (normal) behavior of binding
48+
// connections to the default network interface.
49+
//
50+
// Currently, this only has an effect on Darwin.
51+
func SetDisableBindConnToInterface(v bool) {
52+
disableBindConnToInterface.Store(v)
53+
}
54+
4555
// Listener returns a new net.Listener with its Control hook func
4656
// initialized as necessary to run in logical network namespace that
4757
// doesn't route back into Tailscale.

net/netns/netns_darwin.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ func controlLogf(logf logger.Logf, network, address string, c syscall.RawConn) e
4242
return nil
4343
}
4444

45+
if disableBindConnToInterface.Load() {
46+
logf("netns_darwin: binding connection to interfaces disabled")
47+
return nil
48+
}
49+
4550
idx, err := getInterfaceIndex(logf, address)
4651
if err != nil {
4752
// callee logged

tailcfg/tailcfg.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,6 +1765,17 @@ const (
17651765
// details on the behaviour of this capability.
17661766
CapabilityBindToInterfaceByRoute = "https://tailscale.com/cap/bind-to-interface-by-route"
17671767

1768+
// CapabilityDebugDisableAlternateDefaultRouteInterface changes how Darwin
1769+
// nodes get the default interface. There is an optional hook (used by the
1770+
// macOS and iOS clients) to override the default interface, this capability
1771+
// disables that and uses the default behavior (of parsing the routing
1772+
// table).
1773+
CapabilityDebugDisableAlternateDefaultRouteInterface = "https://tailscale.com/cap/debug-disable-alternate-default-route-interface"
1774+
1775+
// CapabilityDebugDisableBindConnToInterface disables the automatic binding
1776+
// of connections to the default network interface on Darwin nodes.
1777+
CapabilityDebugDisableBindConnToInterface = "https://tailscale.com/cap/debug-disable-bind-conn-to-interface"
1778+
17681779
// CapabilityTailnetLockAlpha indicates the node is in the tailnet lock alpha,
17691780
// and initialization of tailnet lock may proceed.
17701781
//

0 commit comments

Comments
 (0)