TUN inbound: Fix autoOutboundsInterface on Linux (#6413)

Fixes https://github.com/XTLS/Xray-core/issues/6412
This commit is contained in:
Jasper344612
2026-07-04 09:38:25 +08:00
committed by GitHub
parent 3dc8bf3d8b
commit 3263ae9255
+42 -28
View File
@@ -308,36 +308,37 @@ func findOutboundInterface(tunIndex int, fixedName string) (*net.Interface, erro
return iface, nil
}
probeIPs := []net.IP{
net.ParseIP("8.8.8.8"),
net.ParseIP("2001:4860:4860::8888"),
for _, family := range []int{
netlink.FAMILY_V4,
netlink.FAMILY_V6,
} {
iface, err := findDefaultInterface(family, tunIndex)
if err == nil {
return iface, nil
}
}
for _, ip := range probeIPs {
routes, err := netlink.RouteGet(ip)
if err != nil || len(routes) == 0 {
continue
}
route := routes[0]
if route.LinkIndex == tunIndex {
continue
return nil, errors.New("no usable outbound interface found")
}
func findDefaultInterface(family int, tunIndex int) (*net.Interface, error) {
routes, err := netlink.RouteList(nil, family)
if err != nil {
return nil, err
}
var selected *net.Interface
selectedMetric := -1
for _, route := range routes {
if route.Dst != nil {
ones, _ := route.Dst.Mask.Size()
if ones != 0 {
continue
}
}
link, err := netlink.LinkByIndex(route.LinkIndex)
if err != nil {
continue
}
attrs := link.Attrs()
if attrs.Flags&net.FlagUp == 0 {
continue
}
operState := attrs.OperState
if operState != netlink.OperUp && operState != netlink.OperUnknown {
continue
}
if route.Src == nil || route.Src.IsLoopback() || route.Src.IsLinkLocalUnicast() {
if route.LinkIndex == 0 || route.LinkIndex == tunIndex {
continue
}
@@ -345,8 +346,21 @@ func findOutboundInterface(tunIndex int, fixedName string) (*net.Interface, erro
if err != nil {
continue
}
return iface, nil
if iface.Flags&net.FlagUp == 0 ||
iface.Flags&net.FlagLoopback != 0 {
continue
}
if selected == nil || route.Priority < selectedMetric {
selected = iface
selectedMetric = route.Priority
}
}
return nil, errors.New("no usable outbound interface found")
if selected == nil {
return nil, errors.New("physical default route not found")
}
return selected, nil
}