diff --git a/go.mod b/go.mod index db4885f..61367e8 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,12 @@ go 1.18 require ( github.com/fsnotify/fsnotify v1.7.0 github.com/go-ole/go-ole v1.3.0 - github.com/sagernet/gvisor v0.0.0-20240214044702-a3d61928a32f + github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.3.2 - github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 + github.com/sagernet/sing v0.3.6 go4.org/netipx v0.0.0-20231129151722-fdeea329fbba - golang.org/x/net v0.21.0 - golang.org/x/sys v0.17.0 + golang.org/x/net v0.22.0 + golang.org/x/sys v0.18.0 ) require ( diff --git a/go.sum b/go.sum index 8b1035b..8b1390b 100644 --- a/go.sum +++ b/go.sum @@ -6,25 +6,23 @@ github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/sagernet/gvisor v0.0.0-20240214044702-a3d61928a32f h1:7hj/CcCkUiC6gfhX4D+QNyodmhfurW2L2Q4qzJ1bPnI= -github.com/sagernet/gvisor v0.0.0-20240214044702-a3d61928a32f/go.mod h1:bLmnT/4M4+yKB6F7JtRsbUr+YJ64yXwFIygjyYDFQzQ= +github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311 h1:eUQ6kJZXK77xYZeeNrBb/7JMv0S0Wkk7EpmKUb3fsfc= +github.com/sagernet/gvisor v0.0.0-20240315080113-799fb6b6d311/go.mod h1:mDrXZSv401qiaFiiIUC59Zp4VG5f4nqXFqDmp5o3hYI= github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/sing v0.3.2 h1:CwWcxUBPkMvwgfe2/zUgY5oHG9qOL8Aob/evIFYK9jo= -github.com/sagernet/sing v0.3.2/go.mod h1:qHySJ7u8po9DABtMYEkNBcOumx7ZZJf/fbv2sfTkNHE= -github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg= -github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/sagernet/sing v0.3.6 h1:dsEdYLKBQlrxUfw1a92x0VdPvR1/BOxQ+HIMyaoEJsQ= +github.com/sagernet/sing v0.3.6/go.mod h1:+60H3Cm91RnL9dpVGWDPHt0zTQImO9Vfqt9a4rSambI= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M= go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= +golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/winfw/winfw.go b/internal/winfw/winfw.go index 7798fcb..f8f17bb 100644 --- a/internal/winfw/winfw.go +++ b/internal/winfw/winfw.go @@ -12,7 +12,6 @@ import ( "github.com/go-ole/go-ole" "github.com/go-ole/go-ole/oleutil" - "github.com/scjalliance/comshim" ) // Firewall related API constants. @@ -250,7 +249,10 @@ func FirewallRuleExistsByName(rules *ole.IDispatch, name string) (bool, error) { // then: // dispatch firewallAPIRelease(u, fwp) func firewallAPIInit() (*ole.IUnknown, *ole.IDispatch, error) { - comshim.Add(1) + err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) + if err != nil { + return nil, nil, fmt.Errorf("Failed to initialize COM: %s", err) + } unknown, err := oleutil.CreateObject("HNetCfg.FwPolicy2") if err != nil { @@ -270,5 +272,5 @@ func firewallAPIInit() (*ole.IUnknown, *ole.IDispatch, error) { func firewallAPIRelease(u *ole.IUnknown, fwp *ole.IDispatch) { fwp.Release() u.Release() - comshim.Done() + ole.CoUninitialize() } diff --git a/monitor_darwin.go b/monitor_darwin.go index 032f329..42f9c36 100644 --- a/monitor_darwin.go +++ b/monitor_darwin.go @@ -42,7 +42,7 @@ func (m *networkUpdateMonitor) loopUpdate() { select { case <-m.done: return - case <-time.After(time.Second): + default: } err := m.loopUpdate0() if err != nil { @@ -67,7 +67,16 @@ func (m *networkUpdateMonitor) loopUpdate1(routeSocketFile *os.File) { defer routeSocketFile.Close() buffer := buf.NewPacket() defer buffer.Release() + done := make(chan struct{}) + go func() { + select { + case <-m.done: + routeSocketFile.Close() + case <-done: + } + }() n, err := routeSocketFile.Read(buffer.FreeBytes()) + close(done) if err != nil { return } @@ -92,57 +101,59 @@ func (m *networkUpdateMonitor) Close() error { } func (m *defaultInterfaceMonitor) checkUpdate() error { - ribMessage, err := route.FetchRIB(unix.AF_UNSPEC, route.RIBTypeRoute, 0) - if err != nil { - return err - } - routeMessages, err := route.ParseRIB(route.RIBTypeRoute, ribMessage) - if err != nil { - return err - } - var defaultInterface *net.Interface - for _, rawRouteMessage := range routeMessages { - routeMessage := rawRouteMessage.(*route.RouteMessage) - if len(routeMessage.Addrs) <= unix.RTAX_NETMASK { - continue - } - destination, isIPv4Destination := routeMessage.Addrs[unix.RTAX_DST].(*route.Inet4Addr) - if !isIPv4Destination { - continue - } - if destination.IP != netip.IPv4Unspecified().As4() { - continue - } - mask, isIPv4Mask := routeMessage.Addrs[unix.RTAX_NETMASK].(*route.Inet4Addr) - if !isIPv4Mask { - continue - } - ones, _ := net.IPMask(mask.IP[:]).Size() - if ones != 0 { - continue - } - routeInterface, err := net.InterfaceByIndex(routeMessage.Index) + var ( + defaultInterface *net.Interface + err error + ) + if m.options.UnderNetworkExtension { + defaultInterface, err = getDefaultInterfaceBySocket() if err != nil { return err } - if routeMessage.Flags&unix.RTF_UP == 0 { - continue + } else { + ribMessage, err := route.FetchRIB(unix.AF_UNSPEC, route.RIBTypeRoute, 0) + if err != nil { + return err } - if routeMessage.Flags&unix.RTF_GATEWAY == 0 { - continue + routeMessages, err := route.ParseRIB(route.RIBTypeRoute, ribMessage) + if err != nil { + return err } - if routeMessage.Flags&unix.RTF_IFSCOPE != 0 { - // continue - } - defaultInterface = routeInterface - break - } - if defaultInterface == nil { - if m.options.UnderNetworkExtension { - defaultInterface, err = getDefaultInterfaceBySocket() + for _, rawRouteMessage := range routeMessages { + routeMessage := rawRouteMessage.(*route.RouteMessage) + if len(routeMessage.Addrs) <= unix.RTAX_NETMASK { + continue + } + destination, isIPv4Destination := routeMessage.Addrs[unix.RTAX_DST].(*route.Inet4Addr) + if !isIPv4Destination { + continue + } + if destination.IP != netip.IPv4Unspecified().As4() { + continue + } + mask, isIPv4Mask := routeMessage.Addrs[unix.RTAX_NETMASK].(*route.Inet4Addr) + if !isIPv4Mask { + continue + } + ones, _ := net.IPMask(mask.IP[:]).Size() + if ones != 0 { + continue + } + routeInterface, err := net.InterfaceByIndex(routeMessage.Index) if err != nil { return err } + if routeMessage.Flags&unix.RTF_UP == 0 { + continue + } + if routeMessage.Flags&unix.RTF_GATEWAY == 0 { + continue + } + if routeMessage.Flags&unix.RTF_IFSCOPE != 0 { + // continue + } + defaultInterface = routeInterface + break } } if defaultInterface == nil { diff --git a/monitor_shared.go b/monitor_shared.go index a76d4ea..f3c5847 100644 --- a/monitor_shared.go +++ b/monitor_shared.go @@ -6,7 +6,6 @@ import ( "errors" "net" "net/netip" - "runtime" "sync" "time" @@ -44,6 +43,7 @@ type defaultInterfaceMonitor struct { defaultInterfaceIndex int androidVPNEnabled bool networkMonitor NetworkUpdateMonitor + checkUpdateTimer *time.Timer element *list.Element[NetworkUpdateCallback] access sync.Mutex callbacks list.List[DefaultInterfaceUpdateCallback] @@ -72,9 +72,13 @@ func (m *defaultInterfaceMonitor) Start() error { } func (m *defaultInterfaceMonitor) delayCheckUpdate() { - if runtime.GOOS == "android" { - time.Sleep(time.Second) + if m.checkUpdateTimer != nil { + m.checkUpdateTimer.Stop() } + m.checkUpdateTimer = time.AfterFunc(time.Second, m.postCheckUpdate) +} + +func (m *defaultInterfaceMonitor) postCheckUpdate() { err := m.updateInterfaces() if err != nil { m.logger.Error("update interfaces: ", err) diff --git a/stack_gvisor_filter.go b/stack_gvisor_filter.go index 4b6ba98..fc6319e 100644 --- a/stack_gvisor_filter.go +++ b/stack_gvisor_filter.go @@ -32,7 +32,7 @@ type networkDispatcherFilter struct { writer N.VectorisedWriter } -func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt stack.PacketBufferPtr) { +func (w *networkDispatcherFilter) DeliverNetworkPacket(protocol tcpip.NetworkProtocolNumber, pkt *stack.PacketBuffer) { var network header.Network if protocol == header.IPv4ProtocolNumber { if headerPackets, loaded := pkt.Data().PullUp(header.IPv4MinimumSize); loaded { diff --git a/stack_gvisor_udp.go b/stack_gvisor_udp.go index 74ce4b5..4fbb0de 100644 --- a/stack_gvisor_udp.go +++ b/stack_gvisor_udp.go @@ -42,7 +42,7 @@ func NewUDPForwarder(ctx context.Context, stack *stack.Stack, handler Handler, u } } -func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt stack.PacketBufferPtr) bool { +func (f *UDPForwarder) HandlePacket(id stack.TransportEndpointID, pkt *stack.PacketBuffer) bool { var upstreamMetadata M.Metadata upstreamMetadata.Source = M.SocksaddrFrom(AddrFromAddress(id.RemoteAddress), id.RemotePort) upstreamMetadata.Destination = M.SocksaddrFrom(AddrFromAddress(id.LocalAddress), id.LocalPort) @@ -174,7 +174,7 @@ func (c *gUDPConn) Close() error { return c.UDPConn.Close() } -func gWriteUnreachable(gStack *stack.Stack, packet stack.PacketBufferPtr, err error) (retErr error) { +func gWriteUnreachable(gStack *stack.Stack, packet *stack.PacketBuffer, err error) (retErr error) { if errors.Is(err, syscall.ENETUNREACH) { if packet.NetworkProtocolNumber == header.IPv4ProtocolNumber { return gWriteUnreachable4(gStack, packet, stack.RejectIPv4WithICMPNetUnreachable) @@ -197,7 +197,7 @@ func gWriteUnreachable(gStack *stack.Stack, packet stack.PacketBufferPtr, err er return nil } -func gWriteUnreachable4(gStack *stack.Stack, packet stack.PacketBufferPtr, icmpCode stack.RejectIPv4WithICMPType) error { +func gWriteUnreachable4(gStack *stack.Stack, packet *stack.PacketBuffer, icmpCode stack.RejectIPv4WithICMPType) error { err := gStack.NetworkProtocolInstance(header.IPv4ProtocolNumber).(stack.RejectIPv4WithHandler).SendRejectionError(packet, icmpCode, true) if err != nil { return wrapStackError(err) @@ -205,7 +205,7 @@ func gWriteUnreachable4(gStack *stack.Stack, packet stack.PacketBufferPtr, icmpC return nil } -func gWriteUnreachable6(gStack *stack.Stack, packet stack.PacketBufferPtr, icmpCode stack.RejectIPv6WithICMPType) error { +func gWriteUnreachable6(gStack *stack.Stack, packet *stack.PacketBuffer, icmpCode stack.RejectIPv6WithICMPType) error { err := gStack.NetworkProtocolInstance(header.IPv6ProtocolNumber).(stack.RejectIPv6WithHandler).SendRejectionError(packet, icmpCode, true) if err != nil { return wrapStackError(err) diff --git a/tun_darwin_gvisor.go b/tun_darwin_gvisor.go index a1f13ae..6d0ef4a 100644 --- a/tun_darwin_gvisor.go +++ b/tun_darwin_gvisor.go @@ -102,10 +102,10 @@ func (e *DarwinEndpoint) ARPHardwareType() header.ARPHardwareType { return header.ARPHardwareNone } -func (e *DarwinEndpoint) AddHeader(buffer stack.PacketBufferPtr) { +func (e *DarwinEndpoint) AddHeader(buffer *stack.PacketBuffer) { } -func (e *DarwinEndpoint) ParseHeader(ptr stack.PacketBufferPtr) bool { +func (e *DarwinEndpoint) ParseHeader(ptr *stack.PacketBuffer) bool { return true } diff --git a/tun_windows_gvisor.go b/tun_windows_gvisor.go index 5bea8d7..3bdf97d 100644 --- a/tun_windows_gvisor.go +++ b/tun_windows_gvisor.go @@ -99,10 +99,10 @@ func (e *WintunEndpoint) ARPHardwareType() header.ARPHardwareType { return header.ARPHardwareNone } -func (e *WintunEndpoint) AddHeader(buffer stack.PacketBufferPtr) { +func (e *WintunEndpoint) AddHeader(buffer *stack.PacketBuffer) { } -func (e *WintunEndpoint) ParseHeader(ptr stack.PacketBufferPtr) bool { +func (e *WintunEndpoint) ParseHeader(ptr *stack.PacketBuffer) bool { return true }