mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-15 23:47:39 +00:00
net/interfaces: redo how we get the default interface on macOS and iOS
With #6566 we added an external mechanism for getting the default interface, and used it on macOS and iOS (see tailscale/corp#8201). The goal was to be able to get the default physical interface even when using an exit node (in which case the routing table would say that the Tailscale utun* interface is the default). However, the external mechanism turns out to be unreliable in some cases, e.g. when multiple cellular interfaces are present/toggled (I have occasionally gotten my phone into a state where it reports the pdp_ip1 interface as the default, even though it can't actually route traffic). It was observed that `ifconfig -v` on macOS reports an "effective interface" for the Tailscale utn* interface, which seems promising. By examining the ifconfig source code, it turns out that this is done via a SIOCGIFDELEGATE ioctl syscall. Though this is a private API, it appears to have been around for a long time (e.g. it's in the 10.13 xnu release at https://opensource.apple.com/source/xnu/xnu-4570.41.2/bsd/net/if_types.h.auto.html) and thus is unlikely to go away. We can thus use this ioctl if the routing table says that a utun* interface is the default, and go back to the simpler mechanism that we had before #6566. Updates #7184 Updates #7188 Signed-off-by: Mihai Parparita <mihai@tailscale.com>
This commit is contained in:

committed by
Mihai Parparita

parent
21fda7f670
commit
fa932fefe7
@@ -19,7 +19,6 @@ import (
|
||||
"golang.org/x/net/route"
|
||||
"golang.org/x/sys/unix"
|
||||
"tailscale.com/net/netaddr"
|
||||
"tailscale.com/syncs"
|
||||
)
|
||||
|
||||
func defaultRoute() (d DefaultRouteDetails, err error) {
|
||||
@@ -40,19 +39,6 @@ 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 {
|
||||
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.
|
||||
}
|
||||
|
||||
// $ netstat -nr
|
||||
// Routing tables
|
||||
// Internet:
|
||||
@@ -81,8 +67,10 @@ 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)
|
||||
if delegatedIndex, err := getDelegatedInterface(rm.Index); err == nil && delegatedIndex != 0 {
|
||||
return delegatedIndex, nil
|
||||
} else if err != nil {
|
||||
log.Printf("interfaces_bsd: could not get delegated interface: %v", err)
|
||||
}
|
||||
return rm.Index, nil
|
||||
}
|
||||
@@ -90,16 +78,6 @@ func DefaultRouteInterfaceIndex() (int, error) {
|
||||
return 0, errors.New("no gateway index found")
|
||||
}
|
||||
|
||||
var defaultRouteInterfaceIndexFunc syncs.AtomicValue[func() int]
|
||||
|
||||
// SetDefaultRouteInterfaceIndexFunc allows an alternate implementation of
|
||||
// DefaultRouteInterfaceIndex to be provided. If none is set, or if f() returns a 0
|
||||
// (indicating an unknown interface index), then the default implementation (that parses
|
||||
// the routing table) will be used.
|
||||
func SetDefaultRouteInterfaceIndexFunc(f func() int) {
|
||||
defaultRouteInterfaceIndexFunc.Store(f)
|
||||
}
|
||||
|
||||
func init() {
|
||||
likelyHomeRouterIP = likelyHomeRouterIPBSDFetchRIB
|
||||
}
|
||||
|
Reference in New Issue
Block a user