From fd38020bf403b180868559822f8dbdc057aab3ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Fri, 12 Apr 2024 09:24:49 +0800 Subject: [PATCH] Improve loopback detector --- experimental/libbox/config.go | 3 +- experimental/libbox/platform/interface.go | 10 +---- experimental/libbox/service.go | 6 +-- outbound/direct.go | 2 +- outbound/direct_loopback_detect.go | 21 ++++++--- route/interface_finder.go | 54 ----------------------- route/router.go | 17 +++---- 7 files changed, 26 insertions(+), 87 deletions(-) delete mode 100644 route/interface_finder.go diff --git a/experimental/libbox/config.go b/experimental/libbox/config.go index bad61dbc..3b1d9f1d 100644 --- a/experimental/libbox/config.go +++ b/experimental/libbox/config.go @@ -9,7 +9,6 @@ import ( "github.com/sagernet/sing-box" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/process" - "github.com/sagernet/sing-box/experimental/libbox/platform" "github.com/sagernet/sing-box/option" "github.com/sagernet/sing-tun" "github.com/sagernet/sing/common/control" @@ -75,7 +74,7 @@ func (s *platformInterfaceStub) UsePlatformInterfaceGetter() bool { return true } -func (s *platformInterfaceStub) Interfaces() ([]platform.NetworkInterface, error) { +func (s *platformInterfaceStub) Interfaces() ([]control.Interface, error) { return nil, os.ErrInvalid } diff --git a/experimental/libbox/platform/interface.go b/experimental/libbox/platform/interface.go index 54d35fa3..b250c8ae 100644 --- a/experimental/libbox/platform/interface.go +++ b/experimental/libbox/platform/interface.go @@ -2,7 +2,6 @@ package platform import ( "context" - "net/netip" "github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/common/process" @@ -20,16 +19,9 @@ type Interface interface { UsePlatformDefaultInterfaceMonitor() bool CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor UsePlatformInterfaceGetter() bool - Interfaces() ([]NetworkInterface, error) + Interfaces() ([]control.Interface, error) UnderNetworkExtension() bool ClearDNSCache() ReadWIFIState() adapter.WIFIState process.Searcher } - -type NetworkInterface struct { - Index int - MTU int - Name string - Addresses []netip.Prefix -} diff --git a/experimental/libbox/service.go b/experimental/libbox/service.go index 030aee8d..2d755d0d 100644 --- a/experimental/libbox/service.go +++ b/experimental/libbox/service.go @@ -192,14 +192,14 @@ func (w *platformInterfaceWrapper) UsePlatformInterfaceGetter() bool { return w.iif.UsePlatformInterfaceGetter() } -func (w *platformInterfaceWrapper) Interfaces() ([]platform.NetworkInterface, error) { +func (w *platformInterfaceWrapper) Interfaces() ([]control.Interface, error) { interfaceIterator, err := w.iif.GetInterfaces() if err != nil { return nil, err } - var interfaces []platform.NetworkInterface + var interfaces []control.Interface for _, netInterface := range iteratorToArray[*NetworkInterface](interfaceIterator) { - interfaces = append(interfaces, platform.NetworkInterface{ + interfaces = append(interfaces, control.Interface{ Index: int(netInterface.Index), MTU: int(netInterface.MTU), Name: netInterface.Name, diff --git a/outbound/direct.go b/outbound/direct.go index 49ac760e..11f650e4 100644 --- a/outbound/direct.go +++ b/outbound/direct.go @@ -51,7 +51,7 @@ func NewDirect(router adapter.Router, logger log.ContextLogger, tag string, opti domainStrategy: dns.DomainStrategy(options.DomainStrategy), fallbackDelay: time.Duration(options.FallbackDelay), dialer: outboundDialer, - loopBack: newLoopBackDetector(), + loopBack: newLoopBackDetector(router), } if options.ProxyProtocol != 0 { return nil, E.New("Proxy Protocol is deprecated and removed in sing-box 1.6.0") diff --git a/outbound/direct_loopback_detect.go b/outbound/direct_loopback_detect.go index 62cff876..1469b9d0 100644 --- a/outbound/direct_loopback_detect.go +++ b/outbound/direct_loopback_detect.go @@ -5,21 +5,22 @@ import ( "net/netip" "sync" + "github.com/sagernet/sing-box/adapter" M "github.com/sagernet/sing/common/metadata" N "github.com/sagernet/sing/common/network" ) type loopBackDetector struct { - // router adapter.Router + router adapter.Router connAccess sync.RWMutex packetConnAccess sync.RWMutex connMap map[netip.AddrPort]netip.AddrPort packetConnMap map[uint16]uint16 } -func newLoopBackDetector( /*router adapter.Router*/ ) *loopBackDetector { +func newLoopBackDetector(router adapter.Router) *loopBackDetector { return &loopBackDetector{ - // router: router, + router: router, connMap: make(map[netip.AddrPort]netip.AddrPort), packetConnMap: make(map[uint16]uint16), } @@ -31,12 +32,12 @@ func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn { return conn } if udpConn, isUDPConn := conn.(abstractUDPConn); isUDPConn { - /*if !source.Addr().IsLoopback() { + if !source.Addr().IsLoopback() { _, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr()) if err != nil { return conn } - }*/ + } if !N.IsPublicAddr(source.Addr()) { return conn } @@ -57,6 +58,12 @@ func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn, destination M.Soc if !source.IsValid() { return conn } + if !source.Addr().IsLoopback() { + _, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr()) + if err != nil { + return conn + } + } l.packetConnAccess.Lock() l.packetConnMap[source.Port()] = destination.AddrPort().Port() l.packetConnAccess.Unlock() @@ -74,12 +81,12 @@ func (l *loopBackDetector) CheckPacketConn(source netip.AddrPort, local netip.Ad if !source.IsValid() { return false } - /*if !source.Addr().IsLoopback() { + if !source.Addr().IsLoopback() { _, err := l.router.InterfaceFinder().InterfaceByAddr(source.Addr()) if err != nil { return false } - }*/ + } if N.IsPublicAddr(source.Addr()) { return false } diff --git a/route/interface_finder.go b/route/interface_finder.go deleted file mode 100644 index 850f091f..00000000 --- a/route/interface_finder.go +++ /dev/null @@ -1,54 +0,0 @@ -package route - -import ( - "net" - - "github.com/sagernet/sing/common/control" -) - -var _ control.InterfaceFinder = (*myInterfaceFinder)(nil) - -type myInterfaceFinder struct { - interfaces []net.Interface -} - -func (f *myInterfaceFinder) update() error { - ifs, err := net.Interfaces() - if err != nil { - return err - } - f.interfaces = ifs - return nil -} - -func (f *myInterfaceFinder) updateInterfaces(interfaces []net.Interface) { - f.interfaces = interfaces -} - -func (f *myInterfaceFinder) InterfaceIndexByName(name string) (interfaceIndex int, err error) { - for _, netInterface := range f.interfaces { - if netInterface.Name == name { - return netInterface.Index, nil - } - } - netInterface, err := net.InterfaceByName(name) - if err != nil { - return - } - f.update() - return netInterface.Index, nil -} - -func (f *myInterfaceFinder) InterfaceNameByIndex(index int) (interfaceName string, err error) { - for _, netInterface := range f.interfaces { - if netInterface.Index == index { - return netInterface.Name, nil - } - } - netInterface, err := net.InterfaceByIndex(index) - if err != nil { - return - } - f.update() - return netInterface.Name, nil -} diff --git a/route/router.go b/route/router.go index 15d8ef10..f2fe1a6d 100644 --- a/route/router.go +++ b/route/router.go @@ -79,7 +79,7 @@ type Router struct { transportDomainStrategy map[dns.Transport]dns.DomainStrategy dnsReverseMapping *DNSReverseMapping fakeIPStore adapter.FakeIPStore - interfaceFinder myInterfaceFinder + interfaceFinder *control.DefaultInterfaceFinder autoDetectInterface bool defaultInterface string defaultMark int @@ -124,6 +124,7 @@ func NewRouter( needFindProcess: hasRule(options.Rules, isProcessRule) || hasDNSRule(dnsOptions.Rules, isProcessDNSRule) || options.FindProcess, defaultDetour: options.Final, defaultDomainStrategy: dns.DomainStrategy(dnsOptions.Strategy), + interfaceFinder: control.NewDefaultInterfaceFinder(), autoDetectInterface: options.AutoDetectInterface, defaultInterface: options.DefaultInterface, defaultMark: options.DefaultMark, @@ -305,7 +306,7 @@ func NewRouter( } router.networkMonitor = networkMonitor networkMonitor.RegisterCallback(func() { - _ = router.interfaceFinder.update() + _ = router.interfaceFinder.Update() }) interfaceMonitor, err := tun.NewDefaultInterfaceMonitor(router.networkMonitor, router.logger, tun.DefaultInterfaceMonitorOptions{ OverrideAndroidVPN: options.OverrideAndroidVPN, @@ -1063,24 +1064,18 @@ func (r *Router) match0(ctx context.Context, metadata *adapter.InboundContext, d } func (r *Router) InterfaceFinder() control.InterfaceFinder { - return &r.interfaceFinder + return r.interfaceFinder } func (r *Router) UpdateInterfaces() error { if r.platformInterface == nil || !r.platformInterface.UsePlatformInterfaceGetter() { - return r.interfaceFinder.update() + return r.interfaceFinder.Update() } else { interfaces, err := r.platformInterface.Interfaces() if err != nil { return err } - r.interfaceFinder.updateInterfaces(common.Map(interfaces, func(it platform.NetworkInterface) net.Interface { - return net.Interface{ - Name: it.Name, - Index: it.Index, - MTU: it.MTU, - } - })) + r.interfaceFinder.UpdateInterfaces(interfaces) return nil } }