diff --git a/component/iface/iface.go b/component/iface/iface.go index a0fa4d5b..a56b3432 100644 --- a/component/iface/iface.go +++ b/component/iface/iface.go @@ -13,9 +13,9 @@ type Interface struct { Index int MTU int Name string - Addresses []netip.Prefix HardwareAddr net.HardwareAddr Flags net.Flags + Addresses []netip.Prefix } var ( @@ -65,9 +65,9 @@ func Interfaces() (map[string]*Interface, error) { Index: iface.Index, MTU: iface.MTU, Name: iface.Name, - Addresses: ipNets, HardwareAddr: iface.HardwareAddr, Flags: iface.Flags, + Addresses: ipNets, } } diff --git a/go.mod b/go.mod index 9405a2f1..5758ffd0 100644 --- a/go.mod +++ b/go.mod @@ -27,7 +27,7 @@ require ( github.com/metacubex/sing-quic v0.0.0-20250119013740-2a19cce83925 github.com/metacubex/sing-shadowsocks v0.2.8 github.com/metacubex/sing-shadowsocks2 v0.2.2 - github.com/metacubex/sing-tun v0.4.5 + github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04 github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82 github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589 github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422 diff --git a/go.sum b/go.sum index 9660cf30..44d174b7 100644 --- a/go.sum +++ b/go.sum @@ -119,8 +119,8 @@ github.com/metacubex/sing-shadowsocks v0.2.8 h1:wIhlaigswzjPw4hej75sEvWte3QR0+AJ github.com/metacubex/sing-shadowsocks v0.2.8/go.mod h1:X3x88XtJpBxG0W0/ECOJL6Ib0SJ3xdniAkU/6/RMWU0= github.com/metacubex/sing-shadowsocks2 v0.2.2 h1:eaf42uVx4Lr21S6MDYs0ZdTvGA0GEhDpb9no4+gdXPo= github.com/metacubex/sing-shadowsocks2 v0.2.2/go.mod h1:BhOug03a/RbI7y6hp6q+6ITM1dXjnLTmeWBHSTwvv2Q= -github.com/metacubex/sing-tun v0.4.5 h1:kWSyQzuzHI40r50OFBczfWIDvMBMy1RIk+JsXeBPRB0= -github.com/metacubex/sing-tun v0.4.5/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0= +github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04 h1:B211C+i/I8CWf4I/BaAV0mmkEHrDBJ0XR9EWxjPbFEg= +github.com/metacubex/sing-tun v0.4.6-0.20250312042506-6d3b4dc05c04/go.mod h1:V0N4rr0dWPBEE20ESkTXdbtx2riQYcb6YtwC5w/9wl0= github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82 h1:zZp5uct9+/0Hb1jKGyqDjCU4/72t43rs7qOq3Rc9oU8= github.com/metacubex/sing-vmess v0.1.14-0.20250228002636-abc39e113b82/go.mod h1:nE7Mdzj/QUDwgRi/8BASPtsxtIFZTHA4Yst5GgwbGCQ= github.com/metacubex/sing-wireguard v0.0.0-20241126021510-0827d417b589 h1:Z6bNy0HLTjx6BKIkV48sV/yia/GP8Bnyb5JQuGgSGzg= diff --git a/listener/sing_tun/iface.go b/listener/sing_tun/iface.go index 543d206c..ed152b69 100644 --- a/listener/sing_tun/iface.go +++ b/listener/sing_tun/iface.go @@ -2,11 +2,12 @@ package sing_tun import ( "errors" + "net" "net/netip" "github.com/metacubex/mihomo/component/iface" - "github.com/sagernet/sing/common/control" + "github.com/metacubex/sing-tun/control" ) type defaultInterfaceFinder struct{} @@ -33,33 +34,49 @@ func (f *defaultInterfaceFinder) Interfaces() []control.Interface { var errNoSuchInterface = errors.New("no such network interface") -func (f *defaultInterfaceFinder) InterfaceIndexByName(name string) (int, error) { +func (f *defaultInterfaceFinder) ByName(name string) (*control.Interface, error) { ifaces, err := iface.Interfaces() if err != nil { - return 0, err + return nil, err } for _, netInterface := range ifaces { if netInterface.Name == name { - return netInterface.Index, nil + return (*control.Interface)(netInterface), nil } } - return 0, errNoSuchInterface + _, err = net.InterfaceByName(name) + if err == nil { + err = f.Update() + if err != nil { + return nil, err + } + return f.ByName(name) + } + return nil, errNoSuchInterface } -func (f *defaultInterfaceFinder) InterfaceNameByIndex(index int) (string, error) { +func (f *defaultInterfaceFinder) ByIndex(index int) (*control.Interface, error) { ifaces, err := iface.Interfaces() if err != nil { - return "", err + return nil, err } for _, netInterface := range ifaces { if netInterface.Index == index { - return netInterface.Name, nil + return (*control.Interface)(netInterface), nil } } - return "", errNoSuchInterface + _, err = net.InterfaceByIndex(index) + if err == nil { + err = f.Update() + if err != nil { + return nil, err + } + return f.ByIndex(index) + } + return nil, errNoSuchInterface } -func (f *defaultInterfaceFinder) InterfaceByAddr(addr netip.Addr) (*control.Interface, error) { +func (f *defaultInterfaceFinder) ByAddr(addr netip.Addr) (*control.Interface, error) { ifaces, err := iface.Interfaces() if err != nil { return nil, err diff --git a/listener/sing_tun/server.go b/listener/sing_tun/server.go index 342defaf..0ab5afee 100644 --- a/listener/sing_tun/server.go +++ b/listener/sing_tun/server.go @@ -23,6 +23,7 @@ import ( "github.com/metacubex/mihomo/log" tun "github.com/metacubex/sing-tun" + "github.com/metacubex/sing-tun/control" "github.com/sagernet/sing/common" E "github.com/sagernet/sing/common/exceptions" F "github.com/sagernet/sing/common/format" @@ -291,7 +292,12 @@ func New(options LC.Tun, tunnel C.Tunnel, additions ...inbound.Addition) (l *Lis return } l.defaultInterfaceMonitor = defaultInterfaceMonitor - defaultInterfaceMonitor.RegisterCallback(func(event int) { + defaultInterfaceMonitor.RegisterCallback(func(defaultInterface *control.Interface, event int) { + if defaultInterface != nil { + log.Warnln("[TUN] default interface changed by monitor, => %s", defaultInterface.Name) + } else { + log.Errorln("[TUN] default interface lost by monitor") + } iface.FlushCache() resolver.ResetConnection() // reset resolver's connection after default interface changed }) @@ -534,9 +540,19 @@ type cDialerInterfaceFinder struct { defaultInterfaceMonitor tun.DefaultInterfaceMonitor } +func (d *cDialerInterfaceFinder) DefaultInterfaceName(destination netip.Addr) string { + if netInterface, _ := DefaultInterfaceFinder.ByAddr(destination); netInterface != nil { + return netInterface.Name + } + if netInterface := d.defaultInterfaceMonitor.DefaultInterface(); netInterface != nil { + return netInterface.Name + } + return "" +} + func (d *cDialerInterfaceFinder) FindInterfaceName(destination netip.Addr) string { for _, dest := range []netip.Addr{destination, netip.IPv4Unspecified(), netip.IPv6Unspecified()} { - autoDetectInterfaceName := d.defaultInterfaceMonitor.DefaultInterfaceName(dest) + autoDetectInterfaceName := d.DefaultInterfaceName(dest) if autoDetectInterfaceName == d.tunName { log.Warnln("[TUN] Auto detect interface for %s get same name with tun", destination.String()) } else if autoDetectInterfaceName == "" || autoDetectInterfaceName == "" {