net/interfaces, net/netns: add node attributes to control default interface getting and binding

With #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 #7184
Updates #7188

Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This commit is contained in:
Mihai Parparita
2023-02-08 10:30:06 -08:00
committed by Mihai Parparita
parent fb84ccd82d
commit 62f4df3257
6 changed files with 50 additions and 1 deletions

View File

@@ -13,6 +13,7 @@ import (
"runtime"
"sort"
"strings"
"sync/atomic"
"tailscale.com/hostinfo"
"tailscale.com/net/netaddr"
@@ -756,3 +757,14 @@ func HasCGNATInterface() (bool, error) {
}
return hasCGNATInterface, nil
}
var disableAlternateDefaultRouteInterface atomic.Bool
// SetDisableAlternateDefaultRouteInterface disables the optional external/
// alternate mechanism for getting the default route network interface.
//
// Currently, this only changes the behaviour on BSD-like sytems (FreeBSD and
// Darwin).
func SetDisableAlternateDefaultRouteInterface(v bool) {
disableAlternateDefaultRouteInterface.Store(v)
}

View File

@@ -40,9 +40,15 @@ func defaultRoute() (d DefaultRouteDetails, err error) {
// owns the default route. It returns the first IPv4 or IPv6 default route it
// finds (it does not prefer one or the other).
func DefaultRouteInterfaceIndex() (int, error) {
disabledAlternateDefaultRouteInterface := false
if f := defaultRouteInterfaceIndexFunc.Load(); f != nil {
if ifIndex := f(); ifIndex != 0 {
return ifIndex, nil
if !disableAlternateDefaultRouteInterface.Load() {
return ifIndex, nil
} else {
disabledAlternateDefaultRouteInterface = true
log.Printf("interfaces_bsd: alternate default route interface function disabled, would have returned interface %d", ifIndex)
}
}
// Fallthrough if we can't use the alternate implementation.
}
@@ -75,6 +81,9 @@ func DefaultRouteInterfaceIndex() (int, error) {
continue
}
if isDefaultGateway(rm) {
if disabledAlternateDefaultRouteInterface {
log.Printf("interfaces_bsd: alternate default route interface function disabled, default implementation returned %d", rm.Index)
}
return rm.Index, nil
}
}