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"
|
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||||
"tailscale.com/feature/buildfeatures"
|
"tailscale.com/feature/buildfeatures"
|
||||||
"tailscale.com/tsconst"
|
"tailscale.com/tsconst"
|
||||||
|
"tailscale.com/util/mak"
|
||||||
|
"tailscale.com/util/must"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
fallbackInterfaceMetric = uint32(0) // Used if we cannot get the actual interface metric
|
fallbackInterfaceMetric = uint32(0) // Used if we cannot get the actual interface metric
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var wintunInterfaceGUID = must.Get(windows.GUIDFromString(tsconst.WintunInterfaceGUID))
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
likelyHomeRouterIP = likelyHomeRouterIPWindows
|
likelyHomeRouterIP = likelyHomeRouterIPWindows
|
||||||
if buildfeatures.HasUseProxy {
|
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
|
// GetWindowsDefault returns the interface that has the non-Tailscale
|
||||||
// default route for the given address family.
|
// 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.
|
// The family must be one of AF_INET or AF_INET6.
|
||||||
func GetWindowsDefault(family winipcfg.AddressFamily) (*winipcfg.IPAdapterAddresses, error) {
|
func GetWindowsDefault(family winipcfg.AddressFamily) (winipcfg.LUID, error) {
|
||||||
ifs, err := getInterfaces(family, winipcfg.GAAFlagIncludeAllInterfaces, func(iface *winipcfg.IPAdapterAddresses) bool {
|
type ipInterfaceKey struct {
|
||||||
switch iface.IfType {
|
winipcfg.LUID
|
||||||
case winipcfg.IfTypeSoftwareLoopback:
|
winipcfg.AddressFamily
|
||||||
return false
|
}
|
||||||
|
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 {
|
ipif, err := luid.IPInterface(family)
|
||||||
case windows.AF_INET:
|
if err != nil {
|
||||||
if iface.Flags&winipcfg.IPAAFlagIpv4Enabled == 0 {
|
return nil, err
|
||||||
return false
|
|
||||||
}
|
|
||||||
case windows.AF_INET6:
|
|
||||||
if iface.Flags&winipcfg.IPAAFlagIpv6Enabled == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return iface.OperStatus == winipcfg.IfOperStatusUp && notTailscaleInterface(iface)
|
mak.Set(&ipInterfaces, ipInterfaceKey{luid, family}, ipif)
|
||||||
})
|
return ipif, nil
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
routes, err := winipcfg.GetIPForwardTable2(family)
|
routes, err := winipcfg.GetIPForwardTable2(family)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bestMetric := ^uint32(0)
|
bestMetric := ^uint32(0)
|
||||||
var bestIface *winipcfg.IPAdapterAddresses
|
var bestIface winipcfg.LUID
|
||||||
for _, route := range routes {
|
for _, route := range routes {
|
||||||
if route.DestinationPrefix.PrefixLength != 0 {
|
if route.DestinationPrefix.PrefixLength != 0 {
|
||||||
// Not a default route.
|
// Not a default route.
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
iface := ifs[route.InterfaceLUID]
|
ipif, err := getIPInterface(route.InterfaceLUID, family)
|
||||||
if iface == nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,17 +201,21 @@ func GetWindowsDefault(family winipcfg.AddressFamily) (*winipcfg.IPAdapterAddres
|
|||||||
// metric offset specified in the Metric member of the
|
// metric offset specified in the Metric member of the
|
||||||
// MIB_IPFORWARD_ROW2 structure and the interface
|
// MIB_IPFORWARD_ROW2 structure and the interface
|
||||||
// metric specified in this member for IPv4"
|
// metric specified in this member for IPv4"
|
||||||
metric := route.Metric
|
metric := route.Metric + ipif.Metric
|
||||||
switch family {
|
if metric >= bestMetric {
|
||||||
case windows.AF_INET:
|
continue
|
||||||
metric += iface.Ipv4Metric
|
|
||||||
case windows.AF_INET6:
|
|
||||||
metric += iface.Ipv6Metric
|
|
||||||
}
|
}
|
||||||
if metric < bestMetric {
|
|
||||||
bestMetric = metric
|
iface, err := route.InterfaceLUID.Interface()
|
||||||
bestIface = iface
|
if err != nil || iface.OperStatus != winipcfg.IfOperStatusUp {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
if iface.InterfaceGUID == wintunInterfaceGUID {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
bestMetric = metric
|
||||||
|
bestIface = route.InterfaceLUID
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestIface, nil
|
return bestIface, nil
|
||||||
@@ -221,14 +225,18 @@ func defaultRoute() (d DefaultRouteDetails, err error) {
|
|||||||
// We always return the IPv4 default route.
|
// We always return the IPv4 default route.
|
||||||
// TODO(bradfitz): adjust API if/when anything cares. They could in theory differ, though,
|
// 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.
|
// 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 {
|
if err != nil {
|
||||||
return d, err
|
return d, err
|
||||||
}
|
}
|
||||||
if iface != nil {
|
if luid != 0 {
|
||||||
d.InterfaceName = iface.FriendlyName()
|
iface, err := luid.Interface()
|
||||||
|
if err != nil {
|
||||||
|
return d, err
|
||||||
|
}
|
||||||
|
d.InterfaceName = iface.Alias()
|
||||||
d.InterfaceDesc = iface.Description()
|
d.InterfaceDesc = iface.Description()
|
||||||
d.InterfaceIndex = int(iface.IfIndex)
|
d.InterfaceIndex = int(iface.InterfaceIndex)
|
||||||
}
|
}
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,19 @@ import (
|
|||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
func interfaceIndex(iface *winipcfg.IPAdapterAddresses) uint32 {
|
func interfaceIndex(luid winipcfg.LUID) (uint32, error) {
|
||||||
if iface == nil {
|
if luid == 0 {
|
||||||
// The zero ifidx means "unspecified". If we end up passing zero
|
// The zero ifidx means "unspecified". If we end up passing zero
|
||||||
// to bindSocket*(), it unsets the binding and lets the socket
|
// to bindSocket*(), it unsets the binding and lets the socket
|
||||||
// behave as normal again, which is what we want if there's no
|
// behave as normal again, which is what we want if there's no
|
||||||
// default route we can use.
|
// 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) {
|
func defaultInterfaceIndex(family winipcfg.AddressFamily) (uint32, error) {
|
||||||
@@ -36,7 +40,7 @@ func defaultInterfaceIndex(family winipcfg.AddressFamily) (uint32, error) {
|
|||||||
return 0, err
|
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 {
|
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"
|
"github.com/tailscale/wireguard-go/tun"
|
||||||
"golang.org/x/sys/windows"
|
"golang.org/x/sys/windows"
|
||||||
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
|
||||||
|
"tailscale.com/tsconst"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
tun.WintunTunnelType = "Tailscale"
|
tun.WintunTunnelType = "Tailscale"
|
||||||
guid, err := windows.GUIDFromString("{37217669-42da-4657-a55b-0d995d328250}")
|
guid, err := windows.GUIDFromString(tsconst.WintunInterfaceGUID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,9 @@ package tsconst
|
|||||||
const WintunInterfaceDesc = "Tailscale Tunnel"
|
const WintunInterfaceDesc = "Tailscale Tunnel"
|
||||||
const WintunInterfaceDesc0_14 = "Wintun Userspace 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
|
// TailnetLockNotTrustedMsg is the error message used by tailnet lock
|
||||||
// and sniffed (via substring) out of an error sent over the network.
|
// and sniffed (via substring) out of an error sent over the network.
|
||||||
const TailnetLockNotTrustedMsg = "this node is not trusted by Tailnet Lock"
|
const TailnetLockNotTrustedMsg = "this node is not trusted by Tailnet Lock"
|
||||||
Reference in new issue
Block a user