mirror of
https://github.com/tailscale/tailscale.git
synced 2026-10-23 03:37:19 +09:00
net/net{mon,ns},tsconst: avoid enumerating all interfaces when retrieving the default
Change-Id: I4c6a9d9ed791788fb0567154ee1dbe0f6a2c52a2
This commit is contained in:
4 files changed
+58
-42
No files matched your search
@@ -15,12 +15,16 @@ import (
|
||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||
"tailscale.com/feature/buildfeatures"
|
||||
"tailscale.com/tsconst"
|
||||
"tailscale.com/util/mak"
|
||||
"tailscale.com/util/must"
|
||||
)
|
||||
|
||||
const (
|
||||
fallbackInterfaceMetric = uint32(0) // Used if we cannot get the actual interface metric
|
||||
)
|
||||
|
||||
var wintunInterfaceGUID = must.Get(windows.GUIDFromString(tsconst.WintunInterfaceGUID))
|
||||
|
||||
func init() {
|
||||
likelyHomeRouterIP = likelyHomeRouterIPWindows
|
||||
if buildfeatures.HasUseProxy {
|
||||
@@ -152,45 +156,41 @@ func getInterfaces(family winipcfg.AddressFamily, flags winipcfg.GAAFlags, match
|
||||
// GetWindowsDefault returns the interface that has the non-Tailscale
|
||||
// default route for the given address family.
|
||||
//
|
||||
// It returns (nil, nil) if no interface is found.
|
||||
// It returns (0, nil) if no interface is found.
|
||||
//
|
||||
// The family must be one of AF_INET or AF_INET6.
|
||||
func GetWindowsDefault(family winipcfg.AddressFamily) (*winipcfg.IPAdapterAddresses, error) {
|
||||
ifs, err := getInterfaces(family, winipcfg.GAAFlagIncludeAllInterfaces, func(iface *winipcfg.IPAdapterAddresses) bool {
|
||||
switch iface.IfType {
|
||||
case winipcfg.IfTypeSoftwareLoopback:
|
||||
return false
|
||||
func GetWindowsDefault(family winipcfg.AddressFamily) (winipcfg.LUID, error) {
|
||||
type ipInterfaceKey struct {
|
||||
winipcfg.LUID
|
||||
winipcfg.AddressFamily
|
||||
}
|
||||
var ipInterfaces map[ipInterfaceKey]*winipcfg.MibIPInterfaceRow
|
||||
getIPInterface := func(luid winipcfg.LUID, family winipcfg.AddressFamily) (*winipcfg.MibIPInterfaceRow, error) {
|
||||
if ipif, ok := ipInterfaces[ipInterfaceKey{luid, family}]; ok {
|
||||
return ipif, nil
|
||||
}
|
||||
switch family {
|
||||
case windows.AF_INET:
|
||||
if iface.Flags&winipcfg.IPAAFlagIpv4Enabled == 0 {
|
||||
return false
|
||||
}
|
||||
case windows.AF_INET6:
|
||||
if iface.Flags&winipcfg.IPAAFlagIpv6Enabled == 0 {
|
||||
return false
|
||||
}
|
||||
ipif, err := luid.IPInterface(family)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return iface.OperStatus == winipcfg.IfOperStatusUp && notTailscaleInterface(iface)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
mak.Set(&ipInterfaces, ipInterfaceKey{luid, family}, ipif)
|
||||
return ipif, nil
|
||||
}
|
||||
|
||||
routes, err := winipcfg.GetIPForwardTable2(family)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return 0, err
|
||||
}
|
||||
|
||||
bestMetric := ^uint32(0)
|
||||
var bestIface *winipcfg.IPAdapterAddresses
|
||||
var bestIface winipcfg.LUID
|
||||
for _, route := range routes {
|
||||
if route.DestinationPrefix.PrefixLength != 0 {
|
||||
// Not a default route.
|
||||
continue
|
||||
}
|
||||
iface := ifs[route.InterfaceLUID]
|
||||
if iface == nil {
|
||||
ipif, err := getIPInterface(route.InterfaceLUID, family)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -201,17 +201,21 @@ func GetWindowsDefault(family winipcfg.AddressFamily) (*winipcfg.IPAdapterAddres
|
||||
// metric offset specified in the Metric member of the
|
||||
// MIB_IPFORWARD_ROW2 structure and the interface
|
||||
// metric specified in this member for IPv4"
|
||||
metric := route.Metric
|
||||
switch family {
|
||||
case windows.AF_INET:
|
||||
metric += iface.Ipv4Metric
|
||||
case windows.AF_INET6:
|
||||
metric += iface.Ipv6Metric
|
||||
metric := route.Metric + ipif.Metric
|
||||
if metric >= bestMetric {
|
||||
continue
|
||||
}
|
||||
if metric < bestMetric {
|
||||
bestMetric = metric
|
||||
bestIface = iface
|
||||
|
||||
iface, err := route.InterfaceLUID.Interface()
|
||||
if err != nil || iface.OperStatus != winipcfg.IfOperStatusUp {
|
||||
continue
|
||||
}
|
||||
if iface.InterfaceGUID == wintunInterfaceGUID {
|
||||
continue
|
||||
}
|
||||
|
||||
bestMetric = metric
|
||||
bestIface = route.InterfaceLUID
|
||||
}
|
||||
|
||||
return bestIface, nil
|
||||
@@ -221,14 +225,18 @@ func defaultRoute() (d DefaultRouteDetails, err error) {
|
||||
// We always return the IPv4 default route.
|
||||
// TODO(bradfitz): adjust API if/when anything cares. They could in theory differ, though,
|
||||
// in which case we might send traffic to the wrong interface.
|
||||
iface, err := GetWindowsDefault(windows.AF_INET)
|
||||
luid, err := GetWindowsDefault(windows.AF_INET)
|
||||
if err != nil {
|
||||
return d, err
|
||||
}
|
||||
if iface != nil {
|
||||
d.InterfaceName = iface.FriendlyName()
|
||||
if luid != 0 {
|
||||
iface, err := luid.Interface()
|
||||
if err != nil {
|
||||
return d, err
|
||||
}
|
||||
d.InterfaceName = iface.Alias()
|
||||
d.InterfaceDesc = iface.Description()
|
||||
d.InterfaceIndex = int(iface.IfIndex)
|
||||
d.InterfaceIndex = int(iface.InterfaceIndex)
|
||||
}
|
||||
return d, nil
|
||||
}
|
||||
|
||||
@@ -19,15 +19,19 @@ import (
|
||||
"tailscale.com/types/logger"
|
||||
)
|
||||
|
||||
func interfaceIndex(iface *winipcfg.IPAdapterAddresses) uint32 {
|
||||
if iface == nil {
|
||||
func interfaceIndex(luid winipcfg.LUID) (uint32, error) {
|
||||
if luid == 0 {
|
||||
// The zero ifidx means "unspecified". If we end up passing zero
|
||||
// to bindSocket*(), it unsets the binding and lets the socket
|
||||
// behave as normal again, which is what we want if there's no
|
||||
// default route we can use.
|
||||
return 0
|
||||
return 0, nil
|
||||
}
|
||||
return iface.IfIndex
|
||||
iface, err := luid.Interface()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return iface.InterfaceIndex, nil
|
||||
}
|
||||
|
||||
func defaultInterfaceIndex(family winipcfg.AddressFamily) (uint32, error) {
|
||||
@@ -36,7 +40,7 @@ func defaultInterfaceIndex(family winipcfg.AddressFamily) (uint32, error) {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return interfaceIndex(iface), nil
|
||||
return interfaceIndex(iface)
|
||||
}
|
||||
|
||||
func control(logf logger.Logf, _ *netmon.Monitor) func(network, address string, c syscall.RawConn) error {
|
||||
|
||||
@@ -7,11 +7,12 @@ import (
|
||||
"github.com/tailscale/wireguard-go/tun"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||
"tailscale.com/tsconst"
|
||||
)
|
||||
|
||||
func init() {
|
||||
tun.WintunTunnelType = "Tailscale"
|
||||
guid, err := windows.GUIDFromString("{37217669-42da-4657-a55b-0d995d328250}")
|
||||
guid, err := windows.GUIDFromString(tsconst.WintunInterfaceGUID)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@ package tsconst
|
||||
const WintunInterfaceDesc = "Tailscale Tunnel"
|
||||
const WintunInterfaceDesc0_14 = "Wintun Userspace Tunnel"
|
||||
|
||||
// WintunInterfaceGUID is the GUID of the Tailscale interface on Windows.
|
||||
const WintunInterfaceGUID = "{37217669-42da-4657-a55b-0d995d328250}"
|
||||
|
||||
// TailnetLockNotTrustedMsg is the error message used by tailnet lock
|
||||
// and sniffed (via substring) out of an error sent over the network.
|
||||
const TailnetLockNotTrustedMsg = "this node is not trusted by Tailnet Lock"
|
||||
Reference in new issue
Block a user