mirror of
https://github.com/XTLS/Xray-core.git
synced 2026-09-23 01:27:04 +00:00
Revert "TUN inbound: Refine Windows support (#6478)"
This reverts commit c7245c0336.
This commit is contained in:
+134
-142
@@ -3,14 +3,14 @@
|
|||||||
package tun
|
package tun
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
go_errors "errors"
|
go_errors "errors"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/xtls/xray-core/common/errors"
|
"github.com/xtls/xray-core/common/errors"
|
||||||
@@ -31,14 +31,13 @@ func procyield(cycles uint32)
|
|||||||
type WindowsTun struct {
|
type WindowsTun struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
options *Config
|
options *Config
|
||||||
adapter *wintun.Adapter
|
adapter *wintun.Adapter
|
||||||
session wintun.Session
|
session wintun.Session
|
||||||
readWait windows.Handle
|
readWait windows.Handle
|
||||||
luid winipcfg.LUID
|
luid winipcfg.LUID
|
||||||
cbr winipcfg.ChangeCallback
|
changeCallback winipcfg.ChangeCallback
|
||||||
cbi winipcfg.ChangeCallback
|
closed bool
|
||||||
closed bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WindowsTun implements Tun
|
// WindowsTun implements Tun
|
||||||
@@ -86,37 +85,23 @@ func open(name, desc string) (*wintun.Adapter, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *WindowsTun) Start() (err error) {
|
func (t *WindowsTun) Start() error {
|
||||||
var address4, address6 bool
|
var has4, has6 bool
|
||||||
addresses := make([]netip.Prefix, 0, len(t.options.Gateway))
|
allowedIPs := make([]netip.Prefix, 0, len(t.options.AutoSystemRoutingTable))
|
||||||
for _, cidr := range t.options.Gateway {
|
for _, route := range t.options.AutoSystemRoutingTable {
|
||||||
prefix := netip.MustParsePrefix(cidr)
|
allowedIPs = append(allowedIPs, netip.MustParsePrefix(route))
|
||||||
if prefix.Addr().Is4() {
|
|
||||||
address4 = true
|
|
||||||
} else {
|
|
||||||
address6 = true
|
|
||||||
}
|
|
||||||
addresses = append(addresses, prefix)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dns := make([]netip.Addr, 0, len(t.options.DNS))
|
|
||||||
for _, ip := range t.options.DNS {
|
|
||||||
dns = append(dns, netip.MustParseAddr(ip))
|
|
||||||
}
|
|
||||||
|
|
||||||
var route4, route6 bool
|
|
||||||
routesMap := make(map[winipcfg.RouteData]struct{})
|
routesMap := make(map[winipcfg.RouteData]struct{})
|
||||||
for _, cidr := range t.options.AutoSystemRoutingTable {
|
for _, ip := range allowedIPs {
|
||||||
prefix := netip.MustParsePrefix(cidr)
|
|
||||||
route := winipcfg.RouteData{
|
route := winipcfg.RouteData{
|
||||||
Destination: prefix.Masked(),
|
Destination: ip.Masked(),
|
||||||
Metric: 0,
|
Metric: 0,
|
||||||
}
|
}
|
||||||
if prefix.Addr().Is4() {
|
if ip.Addr().Is4() {
|
||||||
route4 = true
|
has4 = true
|
||||||
route.NextHop = netip.IPv4Unspecified()
|
route.NextHop = netip.IPv4Unspecified()
|
||||||
} else {
|
} else {
|
||||||
route6 = true
|
has6 = true
|
||||||
route.NextHop = netip.IPv6Unspecified()
|
route.NextHop = netip.IPv6Unspecified()
|
||||||
}
|
}
|
||||||
routesMap[route] = struct{}{}
|
routesMap[route] = struct{}{}
|
||||||
@@ -126,40 +111,24 @@ func (t *WindowsTun) Start() (err error) {
|
|||||||
r := route
|
r := route
|
||||||
routesData = append(routesData, &r)
|
routesData = append(routesData, &r)
|
||||||
}
|
}
|
||||||
|
err := t.luid.SetRoutes(routesData)
|
||||||
var retryTimes int
|
if err != nil {
|
||||||
var firstErr error
|
return errors.New("unable to set routes").Base(err)
|
||||||
startOver:
|
|
||||||
if retryTimes > 0 {
|
|
||||||
if retryTimes > 15 {
|
|
||||||
return windows.ERROR_NOT_FOUND
|
|
||||||
}
|
|
||||||
errors.LogErrorInner(context.Background(), firstErr, "Interface configuration failed, retrying attempt ", retryTimes, "/15")
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
}
|
||||||
retryTimes++
|
|
||||||
for _, family := range []winipcfg.AddressFamily{windows.AF_INET, windows.AF_INET6} {
|
if len(t.options.Gateway) > 0 {
|
||||||
if family == windows.AF_INET && route4 || family == windows.AF_INET6 && route6 {
|
addresses := make([]netip.Prefix, 0, len(t.options.Gateway))
|
||||||
err = t.luid.SetRoutesForFamily(family, routesData)
|
for _, address := range t.options.Gateway {
|
||||||
if err != nil {
|
addresses = append(addresses, netip.MustParsePrefix(address))
|
||||||
firstErr = errors.New("unable to set routes").Base(err)
|
|
||||||
if err == windows.ERROR_NOT_FOUND {
|
|
||||||
goto startOver
|
|
||||||
}
|
|
||||||
return firstErr
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if family == windows.AF_INET && address4 || family == windows.AF_INET6 && address6 {
|
err := t.luid.SetIPAddresses(addresses)
|
||||||
err = t.luid.SetIPAddressesForFamily(family, addresses)
|
if err != nil {
|
||||||
if err != nil {
|
return errors.New("unable to set ips").Base(err)
|
||||||
firstErr = errors.New("unable to set ips").Base(err)
|
|
||||||
if err == windows.ERROR_NOT_FOUND {
|
|
||||||
goto startOver
|
|
||||||
}
|
|
||||||
return firstErr
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ipif, err := t.luid.IPInterface(family)
|
}
|
||||||
|
|
||||||
|
if has4 {
|
||||||
|
ipif, err := t.luid.IPInterface(windows.AF_INET)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -167,45 +136,56 @@ startOver:
|
|||||||
ipif.DadTransmits = 0
|
ipif.DadTransmits = 0
|
||||||
ipif.ManagedAddressConfigurationSupported = false
|
ipif.ManagedAddressConfigurationSupported = false
|
||||||
ipif.OtherStatefulConfigurationSupported = false
|
ipif.OtherStatefulConfigurationSupported = false
|
||||||
if family == windows.AF_INET && (address4 || route4) || family == windows.AF_INET6 && (address6 || route6) {
|
ipif.NLMTU = t.options.MTU
|
||||||
ipif.NLMTU = t.options.MTU
|
ipif.UseAutomaticMetric = false
|
||||||
}
|
ipif.Metric = 0
|
||||||
if family == windows.AF_INET && route4 || family == windows.AF_INET6 && route6 {
|
|
||||||
ipif.UseAutomaticMetric = false
|
|
||||||
ipif.Metric = 0
|
|
||||||
}
|
|
||||||
err = ipif.Set()
|
err = ipif.Set()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
firstErr = errors.New("unable to set metric and MTU").Base(err)
|
return err
|
||||||
if err == windows.ERROR_NOT_FOUND {
|
|
||||||
goto startOver
|
|
||||||
}
|
|
||||||
return firstErr
|
|
||||||
}
|
}
|
||||||
err = t.luid.SetDNS(family, dns, nil)
|
}
|
||||||
|
if has6 {
|
||||||
|
ipif, err := t.luid.IPInterface(windows.AF_INET6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
firstErr = errors.New("unable to set DNS").Base(err)
|
return err
|
||||||
if err == windows.ERROR_NOT_FOUND {
|
}
|
||||||
goto startOver
|
ipif.RouterDiscoveryBehavior = winipcfg.RouterDiscoveryDisabled
|
||||||
}
|
ipif.DadTransmits = 0
|
||||||
return firstErr
|
ipif.ManagedAddressConfigurationSupported = false
|
||||||
|
ipif.OtherStatefulConfigurationSupported = false
|
||||||
|
ipif.NLMTU = t.options.MTU
|
||||||
|
ipif.UseAutomaticMetric = false
|
||||||
|
ipif.Metric = 0
|
||||||
|
err = ipif.Set()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(t.options.DNS) > 0 {
|
||||||
|
dns := make([]netip.Addr, 0, len(t.options.DNS))
|
||||||
|
for _, ip := range t.options.DNS {
|
||||||
|
dns = append(dns, netip.MustParseAddr(ip))
|
||||||
|
}
|
||||||
|
err := t.luid.SetDNS(windows.AF_INET, dns, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = t.luid.SetDNS(windows.AF_INET6, dns, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if updater != nil {
|
if updater != nil {
|
||||||
t.cbr, err = winipcfg.RegisterRouteChangeCallback(func(notificationType winipcfg.MibNotificationType, route *winipcfg.MibIPforwardRow2) {
|
t.changeCallback, err = winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) {
|
||||||
updater.Update()
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
t.cbi, err = winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) {
|
|
||||||
updater.Update()
|
updater.Update()
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -217,26 +197,12 @@ func (t *WindowsTun) Close() error {
|
|||||||
}
|
}
|
||||||
t.closed = true
|
t.closed = true
|
||||||
|
|
||||||
if t.cbr != nil {
|
if t.changeCallback != nil {
|
||||||
t.cbr.Unregister()
|
t.changeCallback.Unregister()
|
||||||
}
|
|
||||||
if t.cbi != nil {
|
|
||||||
t.cbi.Unregister()
|
|
||||||
}
|
|
||||||
if t.luid != 0 {
|
|
||||||
t.luid.FlushRoutes(windows.AF_INET)
|
|
||||||
t.luid.FlushIPAddresses(windows.AF_INET)
|
|
||||||
t.luid.FlushDNS(windows.AF_INET)
|
|
||||||
t.luid.FlushRoutes(windows.AF_INET6)
|
|
||||||
t.luid.FlushIPAddresses(windows.AF_INET6)
|
|
||||||
t.luid.FlushDNS(windows.AF_INET6)
|
|
||||||
}
|
|
||||||
if t.session != (wintun.Session{}) {
|
|
||||||
t.session.End()
|
|
||||||
}
|
|
||||||
if t.adapter != nil {
|
|
||||||
t.adapter.Close()
|
|
||||||
}
|
}
|
||||||
|
t.session.End()
|
||||||
|
_ = t.adapter.Close()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -345,49 +311,75 @@ func setinterface(network, address string, fd uintptr, iface *net.Interface) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func findOutboundInterface(tunIndex int, fixedName string) (*net.Interface, error) {
|
func findOutboundInterface(tunIndex int, fixedName string) (*net.Interface, error) {
|
||||||
if fixedName != "" {
|
interfaces, err := net.Interfaces()
|
||||||
return net.InterfaceByName(fixedName)
|
|
||||||
}
|
|
||||||
|
|
||||||
r, err := winipcfg.GetIPForwardTable2(windows.AF_UNSPEC)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
lowestMetric := ^uint32(0)
|
|
||||||
index := uint32(0)
|
|
||||||
lowestMetricWifi := ^uint32(0)
|
|
||||||
indexWifi := uint32(0)
|
|
||||||
for i := range r {
|
|
||||||
if r[i].DestinationPrefix.PrefixLength != 0 || r[i].InterfaceIndex == uint32(tunIndex) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
ifrow, err := r[i].InterfaceLUID.Interface()
|
|
||||||
if err != nil || ifrow.OperStatus != winipcfg.IfOperStatusUp {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
iface, err := r[i].InterfaceLUID.IPInterface(windows.AF_INET)
|
if fixedName != "" {
|
||||||
if err != nil {
|
for _, iface := range interfaces {
|
||||||
iface, err = r[i].InterfaceLUID.IPInterface(windows.AF_INET6)
|
if iface.Index != tunIndex && iface.Name == fixedName {
|
||||||
if err != nil {
|
return &iface, nil
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
if ifrow.Type == windows.IF_TYPE_IEEE80211 {
|
var candidates []struct {
|
||||||
if r[i].Metric+iface.Metric < lowestMetricWifi {
|
index int
|
||||||
lowestMetricWifi = r[i].Metric + iface.Metric
|
score int
|
||||||
indexWifi = r[i].InterfaceIndex
|
}
|
||||||
}
|
for i, iface := range interfaces {
|
||||||
|
if iface.Index == tunIndex {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if r[i].Metric+iface.Metric < lowestMetric {
|
if strings.Contains(iface.Name, "vEthernet") {
|
||||||
lowestMetric = r[i].Metric + iface.Metric
|
continue
|
||||||
index = r[i].InterfaceIndex
|
|
||||||
}
|
}
|
||||||
|
if iface.Flags&net.FlagUp == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if iface.Flags&net.FlagLoopback != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addrs, err := iface.Addrs()
|
||||||
|
if err != nil || len(addrs) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
candidates = append(candidates, struct {
|
||||||
|
index int
|
||||||
|
score int
|
||||||
|
}{i, scoreWindowsInterface(&iface, addrs)})
|
||||||
}
|
}
|
||||||
if indexWifi != 0 {
|
|
||||||
index = indexWifi
|
sort.Slice(candidates, func(i, j int) bool {
|
||||||
|
if candidates[i].score != candidates[j].score {
|
||||||
|
return candidates[i].score > candidates[j].score
|
||||||
|
}
|
||||||
|
return interfaces[candidates[i].index].Name < interfaces[candidates[j].index].Name
|
||||||
|
})
|
||||||
|
if len(candidates) == 0 {
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
return net.InterfaceByIndex(int(index))
|
|
||||||
|
iface := interfaces[candidates[0].index]
|
||||||
|
return &iface, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func scoreWindowsInterface(iface *net.Interface, addrs []net.Addr) int {
|
||||||
|
score := 0
|
||||||
|
|
||||||
|
name := strings.ToLower(iface.Name)
|
||||||
|
if strings.Contains(name, "wlan") || strings.Contains(name, "wi-fi") {
|
||||||
|
score += 2
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if strings.HasPrefix(addr.String(), "192.168.") {
|
||||||
|
score++
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return score
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user