diff --git a/box.go b/box.go index 1908f6db..c013c151 100644 --- a/box.go +++ b/box.go @@ -12,6 +12,7 @@ import ( "github.com/sagernet/sing-box/adapter/endpoint" "github.com/sagernet/sing-box/adapter/inbound" "github.com/sagernet/sing-box/adapter/outbound" + "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/common/dialer" "github.com/sagernet/sing-box/common/taskmonitor" "github.com/sagernet/sing-box/common/tls" @@ -84,7 +85,6 @@ func New(options Options) (*Box, error) { ctx = context.Background() } ctx = service.ContextWithDefaultRegistry(ctx) - endpointRegistry := service.FromContext[adapter.EndpointRegistry](ctx) inboundRegistry := service.FromContext[adapter.InboundRegistry](ctx) outboundRegistry := service.FromContext[adapter.OutboundRegistry](ctx) @@ -101,7 +101,10 @@ func New(options Options) (*Box, error) { ctx = pause.WithDefaultManager(ctx) experimentalOptions := common.PtrValueOrDefault(options.Experimental) - applyDebugOptions(common.PtrValueOrDefault(experimentalOptions.Debug)) + debugOptions := common.PtrValueOrDefault(experimentalOptions.Debug) + applyDebugOptions(debugOptions) + ctx = conntrack.ContextWithDefaultTracker(ctx, debugOptions.OOMKiller, uint64(debugOptions.MemoryLimit)) + var needCacheFile bool var needClashAPI bool var needV2RayAPI bool diff --git a/common/conntrack/conn.go b/common/conntrack/conn.go deleted file mode 100644 index 4773d6a8..00000000 --- a/common/conntrack/conn.go +++ /dev/null @@ -1,54 +0,0 @@ -package conntrack - -import ( - "io" - "net" - - "github.com/sagernet/sing/common/x/list" -) - -type Conn struct { - net.Conn - element *list.Element[io.Closer] -} - -func NewConn(conn net.Conn) (net.Conn, error) { - connAccess.Lock() - element := openConnection.PushBack(conn) - connAccess.Unlock() - if KillerEnabled { - err := KillerCheck() - if err != nil { - conn.Close() - return nil, err - } - } - return &Conn{ - Conn: conn, - element: element, - }, nil -} - -func (c *Conn) Close() error { - if c.element.Value != nil { - connAccess.Lock() - if c.element.Value != nil { - openConnection.Remove(c.element) - c.element.Value = nil - } - connAccess.Unlock() - } - return c.Conn.Close() -} - -func (c *Conn) Upstream() any { - return c.Conn -} - -func (c *Conn) ReaderReplaceable() bool { - return true -} - -func (c *Conn) WriterReplaceable() bool { - return true -} diff --git a/common/conntrack/context.go b/common/conntrack/context.go new file mode 100644 index 00000000..a80170c2 --- /dev/null +++ b/common/conntrack/context.go @@ -0,0 +1,14 @@ +package conntrack + +import ( + "context" + + "github.com/sagernet/sing/service" +) + +func ContextWithDefaultTracker(ctx context.Context, killerEnabled bool, memoryLimit uint64) context.Context { + if service.FromContext[Tracker](ctx) != nil { + return ctx + } + return service.ContextWith[Tracker](ctx, NewDefaultTracker(killerEnabled, memoryLimit)) +} diff --git a/common/conntrack/default.go b/common/conntrack/default.go new file mode 100644 index 00000000..af2b0009 --- /dev/null +++ b/common/conntrack/default.go @@ -0,0 +1,245 @@ +package conntrack + +import ( + "net" + "net/netip" + runtimeDebug "runtime/debug" + "sync" + "time" + + "github.com/sagernet/sing/common" + E "github.com/sagernet/sing/common/exceptions" + "github.com/sagernet/sing/common/memory" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" + "github.com/sagernet/sing/common/x/list" +) + +var _ Tracker = (*DefaultTracker)(nil) + +type DefaultTracker struct { + connAccess sync.RWMutex + connList list.List[net.Conn] + connAddress map[netip.AddrPort]netip.AddrPort + + packetConnAccess sync.RWMutex + packetConnList list.List[AbstractPacketConn] + packetConnAddress map[netip.AddrPort]bool + + pendingAccess sync.RWMutex + pendingList list.List[netip.AddrPort] + + killerEnabled bool + memoryLimit uint64 + killerLastCheck time.Time +} + +func NewDefaultTracker(killerEnabled bool, memoryLimit uint64) *DefaultTracker { + return &DefaultTracker{ + connAddress: make(map[netip.AddrPort]netip.AddrPort), + packetConnAddress: make(map[netip.AddrPort]bool), + killerEnabled: killerEnabled, + memoryLimit: memoryLimit, + } +} + +func (t *DefaultTracker) NewConn(conn net.Conn) (net.Conn, error) { + err := t.KillerCheck() + if err != nil { + conn.Close() + return nil, err + } + t.connAccess.Lock() + element := t.connList.PushBack(conn) + t.connAddress[M.AddrPortFromNet(conn.LocalAddr())] = M.AddrPortFromNet(conn.RemoteAddr()) + t.connAccess.Unlock() + return &Conn{ + Conn: conn, + closeFunc: common.OnceFunc(func() { + t.removeConn(element) + }), + }, nil +} + +func (t *DefaultTracker) NewConnEx(conn net.Conn) (N.CloseHandlerFunc, error) { + err := t.KillerCheck() + if err != nil { + conn.Close() + return nil, err + } + t.connAccess.Lock() + element := t.connList.PushBack(conn) + t.connAddress[M.AddrPortFromNet(conn.LocalAddr())] = M.AddrPortFromNet(conn.RemoteAddr()) + t.connAccess.Unlock() + return N.OnceClose(func(it error) { + t.removeConn(element) + }), nil +} + +func (t *DefaultTracker) NewPacketConn(conn net.PacketConn) (net.PacketConn, error) { + err := t.KillerCheck() + if err != nil { + conn.Close() + return nil, err + } + t.packetConnAccess.Lock() + element := t.packetConnList.PushBack(conn) + t.packetConnAddress[M.AddrPortFromNet(conn.LocalAddr())] = true + t.packetConnAccess.Unlock() + return &PacketConn{ + PacketConn: conn, + closeFunc: common.OnceFunc(func() { + t.removePacketConn(element) + }), + }, nil +} + +func (t *DefaultTracker) NewPacketConnEx(conn AbstractPacketConn) (N.CloseHandlerFunc, error) { + err := t.KillerCheck() + if err != nil { + conn.Close() + return nil, err + } + t.packetConnAccess.Lock() + element := t.packetConnList.PushBack(conn) + t.packetConnAddress[M.AddrPortFromNet(conn.LocalAddr())] = true + t.packetConnAccess.Unlock() + return N.OnceClose(func(it error) { + t.removePacketConn(element) + }), nil +} + +func (t *DefaultTracker) CheckConn(source netip.AddrPort, destination netip.AddrPort) bool { + t.connAccess.RLock() + defer t.connAccess.RUnlock() + return t.connAddress[source] == destination +} + +func (t *DefaultTracker) CheckPacketConn(source netip.AddrPort) bool { + t.packetConnAccess.RLock() + defer t.packetConnAccess.RUnlock() + return t.packetConnAddress[source] +} + +func (t *DefaultTracker) AddPendingDestination(destination netip.AddrPort) func() { + t.pendingAccess.Lock() + defer t.pendingAccess.Unlock() + element := t.pendingList.PushBack(destination) + return func() { + t.pendingAccess.Lock() + defer t.pendingAccess.Unlock() + t.pendingList.Remove(element) + } +} + +func (t *DefaultTracker) CheckDestination(destination netip.AddrPort) bool { + t.pendingAccess.RLock() + defer t.pendingAccess.RUnlock() + for element := t.pendingList.Front(); element != nil; element = element.Next() { + if element.Value == destination { + return true + } + } + return false +} + +func (t *DefaultTracker) KillerCheck() error { + if !t.killerEnabled { + return nil + } + nowTime := time.Now() + if nowTime.Sub(t.killerLastCheck) < 3*time.Second { + return nil + } + t.killerLastCheck = nowTime + if memory.Total() > t.memoryLimit { + t.Close() + go func() { + time.Sleep(time.Second) + runtimeDebug.FreeOSMemory() + }() + return E.New("out of memory") + } + return nil +} + +func (t *DefaultTracker) Count() int { + t.connAccess.RLock() + defer t.connAccess.RUnlock() + t.packetConnAccess.RLock() + defer t.packetConnAccess.RUnlock() + return t.connList.Len() + t.packetConnList.Len() +} + +func (t *DefaultTracker) Close() { + t.connAccess.Lock() + for element := t.connList.Front(); element != nil; element = element.Next() { + element.Value.Close() + } + t.connList.Init() + t.connAccess.Unlock() + t.packetConnAccess.Lock() + for element := t.packetConnList.Front(); element != nil; element = element.Next() { + element.Value.Close() + } + t.packetConnList.Init() + t.packetConnAccess.Unlock() +} + +func (t *DefaultTracker) removeConn(element *list.Element[net.Conn]) { + t.connAccess.Lock() + defer t.connAccess.Unlock() + delete(t.connAddress, M.AddrPortFromNet(element.Value.LocalAddr())) + t.connList.Remove(element) +} + +func (t *DefaultTracker) removePacketConn(element *list.Element[AbstractPacketConn]) { + t.packetConnAccess.Lock() + defer t.packetConnAccess.Unlock() + delete(t.packetConnAddress, M.AddrPortFromNet(element.Value.LocalAddr())) + t.packetConnList.Remove(element) +} + +type Conn struct { + net.Conn + closeFunc func() +} + +func (c *Conn) Close() error { + c.closeFunc() + return c.Conn.Close() +} + +func (c *Conn) Upstream() any { + return c.Conn +} + +func (c *Conn) ReaderReplaceable() bool { + return true +} + +func (c *Conn) WriterReplaceable() bool { + return true +} + +type PacketConn struct { + net.PacketConn + closeFunc func() +} + +func (c *PacketConn) Close() error { + c.closeFunc() + return c.PacketConn.Close() +} + +func (c *PacketConn) Upstream() any { + return c.PacketConn +} + +func (c *PacketConn) ReaderReplaceable() bool { + return true +} + +func (c *PacketConn) WriterReplaceable() bool { + return true +} diff --git a/common/conntrack/killer.go b/common/conntrack/killer.go deleted file mode 100644 index e0a71e5c..00000000 --- a/common/conntrack/killer.go +++ /dev/null @@ -1,35 +0,0 @@ -package conntrack - -import ( - runtimeDebug "runtime/debug" - "time" - - E "github.com/sagernet/sing/common/exceptions" - "github.com/sagernet/sing/common/memory" -) - -var ( - KillerEnabled bool - MemoryLimit uint64 - killerLastCheck time.Time -) - -func KillerCheck() error { - if !KillerEnabled { - return nil - } - nowTime := time.Now() - if nowTime.Sub(killerLastCheck) < 3*time.Second { - return nil - } - killerLastCheck = nowTime - if memory.Total() > MemoryLimit { - Close() - go func() { - time.Sleep(time.Second) - runtimeDebug.FreeOSMemory() - }() - return E.New("out of memory") - } - return nil -} diff --git a/common/conntrack/packet_conn.go b/common/conntrack/packet_conn.go deleted file mode 100644 index c7274637..00000000 --- a/common/conntrack/packet_conn.go +++ /dev/null @@ -1,55 +0,0 @@ -package conntrack - -import ( - "io" - "net" - - "github.com/sagernet/sing/common/bufio" - "github.com/sagernet/sing/common/x/list" -) - -type PacketConn struct { - net.PacketConn - element *list.Element[io.Closer] -} - -func NewPacketConn(conn net.PacketConn) (net.PacketConn, error) { - connAccess.Lock() - element := openConnection.PushBack(conn) - connAccess.Unlock() - if KillerEnabled { - err := KillerCheck() - if err != nil { - conn.Close() - return nil, err - } - } - return &PacketConn{ - PacketConn: conn, - element: element, - }, nil -} - -func (c *PacketConn) Close() error { - if c.element.Value != nil { - connAccess.Lock() - if c.element.Value != nil { - openConnection.Remove(c.element) - c.element.Value = nil - } - connAccess.Unlock() - } - return c.PacketConn.Close() -} - -func (c *PacketConn) Upstream() any { - return bufio.NewPacketConn(c.PacketConn) -} - -func (c *PacketConn) ReaderReplaceable() bool { - return true -} - -func (c *PacketConn) WriterReplaceable() bool { - return true -} diff --git a/common/conntrack/track.go b/common/conntrack/track.go deleted file mode 100644 index 2c3e328b..00000000 --- a/common/conntrack/track.go +++ /dev/null @@ -1,47 +0,0 @@ -package conntrack - -import ( - "io" - "sync" - - "github.com/sagernet/sing/common" - "github.com/sagernet/sing/common/x/list" -) - -var ( - connAccess sync.RWMutex - openConnection list.List[io.Closer] -) - -func Count() int { - if !Enabled { - return 0 - } - return openConnection.Len() -} - -func List() []io.Closer { - if !Enabled { - return nil - } - connAccess.RLock() - defer connAccess.RUnlock() - connList := make([]io.Closer, 0, openConnection.Len()) - for element := openConnection.Front(); element != nil; element = element.Next() { - connList = append(connList, element.Value) - } - return connList -} - -func Close() { - if !Enabled { - return - } - connAccess.Lock() - defer connAccess.Unlock() - for element := openConnection.Front(); element != nil; element = element.Next() { - common.Close(element.Value) - element.Value = nil - } - openConnection.Init() -} diff --git a/common/conntrack/track_disable.go b/common/conntrack/track_disable.go deleted file mode 100644 index 174d8b6e..00000000 --- a/common/conntrack/track_disable.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build !with_conntrack - -package conntrack - -const Enabled = false diff --git a/common/conntrack/track_enable.go b/common/conntrack/track_enable.go deleted file mode 100644 index a4bf9986..00000000 --- a/common/conntrack/track_enable.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build with_conntrack - -package conntrack - -const Enabled = true diff --git a/common/conntrack/tracker.go b/common/conntrack/tracker.go new file mode 100644 index 00000000..ae80414e --- /dev/null +++ b/common/conntrack/tracker.go @@ -0,0 +1,32 @@ +package conntrack + +import ( + "net" + "net/netip" + "time" + + N "github.com/sagernet/sing/common/network" +) + +// TODO: add to N +type AbstractPacketConn interface { + Close() error + LocalAddr() net.Addr + SetDeadline(t time.Time) error + SetReadDeadline(t time.Time) error + SetWriteDeadline(t time.Time) error +} + +type Tracker interface { + NewConn(conn net.Conn) (net.Conn, error) + NewPacketConn(conn net.PacketConn) (net.PacketConn, error) + NewConnEx(conn net.Conn) (N.CloseHandlerFunc, error) + NewPacketConnEx(conn AbstractPacketConn) (N.CloseHandlerFunc, error) + CheckConn(source netip.AddrPort, destination netip.AddrPort) bool + CheckPacketConn(source netip.AddrPort) bool + AddPendingDestination(destination netip.AddrPort) func() + CheckDestination(destination netip.AddrPort) bool + KillerCheck() error + Count() int + Close() +} diff --git a/common/dialer/default.go b/common/dialer/default.go index 77536c43..922c9f60 100644 --- a/common/dialer/default.go +++ b/common/dialer/default.go @@ -28,6 +28,7 @@ var ( ) type DefaultDialer struct { + tracker conntrack.Tracker dialer4 tcpDialer dialer6 tcpDialer udpDialer4 net.Dialer @@ -46,6 +47,7 @@ type DefaultDialer struct { } func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDialer, error) { + tracker := service.FromContext[conntrack.Tracker](ctx) networkManager := service.FromContext[adapter.NetworkManager](ctx) platformInterface := service.FromContext[platform.Interface](ctx) @@ -197,6 +199,7 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial return nil, err } return &DefaultDialer{ + tracker: tracker, dialer4: tcpDialer4, dialer6: tcpDialer6, udpDialer4: udpDialer4, @@ -219,18 +222,26 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address return nil, E.New("invalid address") } if d.networkStrategy == nil { + if address.IsFqdn() { + return nil, E.New("unexpected domain destination") + } + // Since pending check is only used by ndis, it is not performed for non-windows connections which are only supported on platform clients + if d.tracker != nil { + done := d.tracker.AddPendingDestination(address.AddrPort()) + defer done() + } switch N.NetworkName(network) { case N.NetworkUDP: if !address.IsIPv6() { - return trackConn(d.udpDialer4.DialContext(ctx, network, address.String())) + return d.trackConn(d.udpDialer4.DialContext(ctx, network, address.String())) } else { - return trackConn(d.udpDialer6.DialContext(ctx, network, address.String())) + return d.trackConn(d.udpDialer6.DialContext(ctx, network, address.String())) } } if !address.IsIPv6() { - return trackConn(DialSlowContext(&d.dialer4, ctx, network, address)) + return d.trackConn(DialSlowContext(&d.dialer4, ctx, network, address)) } else { - return trackConn(DialSlowContext(&d.dialer6, ctx, network, address)) + return d.trackConn(DialSlowContext(&d.dialer6, ctx, network, address)) } } else { return d.DialParallelInterface(ctx, network, address, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay) @@ -282,17 +293,17 @@ func (d *DefaultDialer) DialParallelInterface(ctx context.Context, network strin if !fastFallback && !isPrimary { d.networkLastFallback.Store(time.Now()) } - return trackConn(conn, nil) + return d.trackConn(conn, nil) } func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { if d.networkStrategy == nil { if destination.IsIPv6() { - return trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr6)) + return d.trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr6)) } else if destination.IsIPv4() && !destination.Addr.IsUnspecified() { - return trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP+"4", d.udpAddr4)) + return d.trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP+"4", d.udpAddr4)) } else { - return trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr4)) + return d.trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr4)) } } else { return d.ListenSerialInterfacePacket(ctx, destination, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay) @@ -329,23 +340,23 @@ func (d *DefaultDialer) ListenSerialInterfacePacket(ctx context.Context, destina return nil, err } } - return trackPacketConn(packetConn, nil) + return d.trackPacketConn(packetConn, nil) } func (d *DefaultDialer) ListenPacketCompat(network, address string) (net.PacketConn, error) { return d.udpListener.ListenPacket(context.Background(), network, address) } -func trackConn(conn net.Conn, err error) (net.Conn, error) { - if !conntrack.Enabled || err != nil { +func (d *DefaultDialer) trackConn(conn net.Conn, err error) (net.Conn, error) { + if d.tracker == nil || err != nil { return conn, err } - return conntrack.NewConn(conn) + return d.tracker.NewConn(conn) } -func trackPacketConn(conn net.PacketConn, err error) (net.PacketConn, error) { - if !conntrack.Enabled || err != nil { +func (d *DefaultDialer) trackPacketConn(conn net.PacketConn, err error) (net.PacketConn, error) { + if err != nil { return conn, err } - return conntrack.NewPacketConn(conn) + return d.tracker.NewPacketConn(conn) } diff --git a/constant/proxy.go b/constant/proxy.go index 3197de60..077f0bec 100644 --- a/constant/proxy.go +++ b/constant/proxy.go @@ -23,6 +23,7 @@ const ( TypeVLESS = "vless" TypeTUIC = "tuic" TypeHysteria2 = "hysteria2" + TypeNDIS = "ndis" ) const ( @@ -80,6 +81,8 @@ func ProxyDisplayName(proxyType string) string { return "Selector" case TypeURLTest: return "URLTest" + case TypeNDIS: + return "NDIS" default: return "Unknown" } diff --git a/debug.go b/debug.go index 2fa962d6..d23e8280 100644 --- a/debug.go +++ b/debug.go @@ -3,7 +3,6 @@ package box import ( "runtime/debug" - "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/option" ) @@ -26,9 +25,5 @@ func applyDebugOptions(options option.DebugOptions) { } if options.MemoryLimit != 0 { debug.SetMemoryLimit(int64(float64(options.MemoryLimit) / 1.5)) - conntrack.MemoryLimit = uint64(options.MemoryLimit) - } - if options.OOMKiller != nil { - conntrack.KillerEnabled = *options.OOMKiller } } diff --git a/experimental/libbox/command_conntrack.go b/experimental/libbox/command_conntrack.go index cf8389a6..800db7c1 100644 --- a/experimental/libbox/command_conntrack.go +++ b/experimental/libbox/command_conntrack.go @@ -5,8 +5,6 @@ import ( "net" runtimeDebug "runtime/debug" "time" - - "github.com/sagernet/sing-box/common/conntrack" ) func (c *CommandClient) CloseConnections() error { @@ -19,7 +17,7 @@ func (c *CommandClient) CloseConnections() error { } func (s *CommandServer) handleCloseConnections(conn net.Conn) error { - conntrack.Close() + tracker.Close() go func() { time.Sleep(time.Second) runtimeDebug.FreeOSMemory() diff --git a/experimental/libbox/command_status.go b/experimental/libbox/command_status.go index f8709ef0..c13c610c 100644 --- a/experimental/libbox/command_status.go +++ b/experimental/libbox/command_status.go @@ -6,7 +6,6 @@ import ( "runtime" "time" - "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/experimental/clashapi" E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/memory" @@ -28,7 +27,7 @@ func (s *CommandServer) readStatus() StatusMessage { var message StatusMessage message.Memory = int64(memory.Inuse()) message.Goroutines = int32(runtime.NumGoroutine()) - message.ConnectionsOut = int32(conntrack.Count()) + message.ConnectionsOut = int32(tracker.Count()) if s.service != nil { message.TrafficAvailable = true diff --git a/experimental/libbox/memory.go b/experimental/libbox/memory.go index b10c6701..6c204932 100644 --- a/experimental/libbox/memory.go +++ b/experimental/libbox/memory.go @@ -7,17 +7,21 @@ import ( "github.com/sagernet/sing-box/common/conntrack" ) +var tracker *conntrack.DefaultTracker + func SetMemoryLimit(enabled bool) { + if tracker != nil { + tracker.Close() + } const memoryLimit = 45 * 1024 * 1024 const memoryLimitGo = memoryLimit / 1.5 if enabled { runtimeDebug.SetGCPercent(10) runtimeDebug.SetMemoryLimit(memoryLimitGo) - conntrack.KillerEnabled = true - conntrack.MemoryLimit = memoryLimit + tracker = conntrack.NewDefaultTracker(true, memoryLimit) } else { runtimeDebug.SetGCPercent(100) runtimeDebug.SetMemoryLimit(math.MaxInt64) - conntrack.KillerEnabled = false + tracker = conntrack.NewDefaultTracker(false, 0) } } diff --git a/experimental/libbox/service.go b/experimental/libbox/service.go index 4906c571..eaa0ac84 100644 --- a/experimental/libbox/service.go +++ b/experimental/libbox/service.go @@ -12,6 +12,7 @@ import ( "github.com/sagernet/sing-box" "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/common/process" "github.com/sagernet/sing-box/common/urltest" C "github.com/sagernet/sing-box/constant" @@ -60,6 +61,7 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box useProcFS: platformInterface.UseProcFS(), } service.MustRegister[platform.Interface](ctx, platformWrapper) + service.MustRegister[conntrack.Tracker](ctx, tracker) instance, err := box.New(box.Options{ Context: ctx, Options: options, diff --git a/go.mod b/go.mod index 64b028f2..9f39a1a3 100644 --- a/go.mod +++ b/go.mod @@ -1,104 +1,105 @@ -module github.com/sagernet/sing-box - -go 1.20 - -require ( - github.com/caddyserver/certmagic v0.20.0 - github.com/cloudflare/circl v1.3.7 - github.com/cretz/bine v0.2.0 - github.com/go-chi/chi/v5 v5.1.0 - github.com/go-chi/render v1.0.3 - github.com/gofrs/uuid/v5 v5.3.0 - github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 - github.com/libdns/alidns v1.0.3 - github.com/libdns/cloudflare v0.1.1 - github.com/logrusorgru/aurora v2.0.3+incompatible - github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa - github.com/mholt/acmez v1.2.0 - github.com/miekg/dns v1.1.62 - github.com/oschwald/maxminddb-golang v1.12.0 - github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1 - github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a - github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 - github.com/sagernet/cors v1.2.1 - github.com/sagernet/fswatch v0.1.1 - github.com/sagernet/gomobile v0.1.4 - github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff - github.com/sagernet/quic-go v0.48.2-beta.1 - github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 - github.com/sagernet/sing v0.6.0-beta.9 - github.com/sagernet/sing-dns v0.4.0-beta.1 - github.com/sagernet/sing-mux v0.3.0-alpha.1 - github.com/sagernet/sing-quic v0.4.0-beta.3 - github.com/sagernet/sing-shadowsocks v0.2.7 - github.com/sagernet/sing-shadowsocks2 v0.2.0 - github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 - github.com/sagernet/sing-tun v0.6.0-beta.7 - github.com/sagernet/sing-vmess v0.2.0-beta.2 - github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 - github.com/sagernet/utls v1.6.7 - github.com/sagernet/wireguard-go v0.0.1-beta.5 - github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 - github.com/spf13/cobra v1.8.1 - github.com/stretchr/testify v1.9.0 - go.uber.org/zap v1.27.0 - go4.org/netipx v0.0.0-20231129151722-fdeea329fbba - golang.org/x/crypto v0.31.0 - golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 - golang.org/x/mod v0.20.0 - golang.org/x/net v0.31.0 - golang.org/x/sys v0.28.0 - golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 - google.golang.org/grpc v1.63.2 - google.golang.org/protobuf v1.33.0 - howett.net/plist v1.0.1 -) - -//replace github.com/sagernet/sing => ../sing - -require ( - github.com/ajg/form v1.5.1 // indirect - github.com/andybalholm/brotli v1.0.6 // indirect - github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect - github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect - github.com/gobwas/httphead v0.1.0 // indirect - github.com/gobwas/pool v0.2.1 // indirect - github.com/google/btree v1.1.3 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-querystring v1.1.0 // indirect - github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect - github.com/hashicorp/yamux v0.1.2 // indirect - github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/josharian/native v1.1.0 // indirect - github.com/klauspost/compress v1.17.4 // indirect - github.com/klauspost/cpuid/v2 v2.2.5 // indirect - github.com/libdns/libdns v0.2.2 // indirect - github.com/mdlayher/netlink v1.7.2 // indirect - github.com/mdlayher/socket v0.4.1 // indirect - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect - github.com/onsi/ginkgo/v2 v2.9.7 // indirect - github.com/pierrec/lz4/v4 v4.1.14 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/quic-go/qpack v0.4.0 // indirect - github.com/quic-go/qtls-go1-20 v0.4.1 // indirect - github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect - github.com/sagernet/nftables v0.3.0-beta.4 // indirect - github.com/spf13/pflag v1.0.5 // indirect - github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect - github.com/vishvananda/netns v0.0.4 // indirect - github.com/zeebo/blake3 v0.2.3 // indirect - go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/text v0.21.0 // indirect - golang.org/x/time v0.7.0 // indirect - golang.org/x/tools v0.24.0 // indirect - golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/blake3 v1.3.0 // indirect -) +module github.com/sagernet/sing-box + +go 1.20 + +require ( + github.com/caddyserver/certmagic v0.20.0 + github.com/cloudflare/circl v1.3.7 + github.com/cretz/bine v0.2.0 + github.com/go-chi/chi/v5 v5.1.0 + github.com/go-chi/render v1.0.3 + github.com/gofrs/uuid/v5 v5.3.0 + github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 + github.com/libdns/alidns v1.0.3 + github.com/libdns/cloudflare v0.1.1 + github.com/logrusorgru/aurora v2.0.3+incompatible + github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa + github.com/mholt/acmez v1.2.0 + github.com/miekg/dns v1.1.62 + github.com/oschwald/maxminddb-golang v1.12.0 + github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1 + github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a + github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 + github.com/sagernet/cors v1.2.1 + github.com/sagernet/fswatch v0.1.1 + github.com/sagernet/gomobile v0.1.4 + github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff + github.com/sagernet/quic-go v0.48.2-beta.1 + github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 + github.com/sagernet/sing v0.6.0-beta.9 + github.com/sagernet/sing-dns v0.4.0-beta.1 + github.com/sagernet/sing-mux v0.3.0-alpha.1 + github.com/sagernet/sing-quic v0.4.0-beta.3 + github.com/sagernet/sing-shadowsocks v0.2.7 + github.com/sagernet/sing-shadowsocks2 v0.2.0 + github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 + github.com/sagernet/sing-tun v0.6.0-beta.7 + github.com/sagernet/sing-vmess v0.2.0-beta.2 + github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 + github.com/sagernet/utls v1.6.7 + github.com/sagernet/wireguard-go v0.0.1-beta.5 + github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 + github.com/spf13/cobra v1.8.1 + github.com/stretchr/testify v1.9.0 + github.com/wiresock/ndisapi-go v0.0.0-20241230094942-3299a7566e08 + go.uber.org/zap v1.27.0 + go4.org/netipx v0.0.0-20231129151722-fdeea329fbba + golang.org/x/crypto v0.31.0 + golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 + golang.org/x/mod v0.20.0 + golang.org/x/net v0.31.0 + golang.org/x/sys v0.28.0 + golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 + google.golang.org/grpc v1.63.2 + google.golang.org/protobuf v1.33.0 + howett.net/plist v1.0.1 +) + +//replace github.com/sagernet/sing => ../sing + +require ( + github.com/ajg/form v1.5.1 // indirect + github.com/andybalholm/brotli v1.0.6 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/gobwas/httphead v0.1.0 // indirect + github.com/gobwas/pool v0.2.1 // indirect + github.com/google/btree v1.1.3 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect + github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect + github.com/hashicorp/yamux v0.1.2 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/josharian/native v1.1.0 // indirect + github.com/klauspost/compress v1.17.4 // indirect + github.com/klauspost/cpuid/v2 v2.2.5 // indirect + github.com/libdns/libdns v0.2.2 // indirect + github.com/mdlayher/netlink v1.7.2 // indirect + github.com/mdlayher/socket v0.4.1 // indirect + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/onsi/ginkgo/v2 v2.9.7 // indirect + github.com/pierrec/lz4/v4 v4.1.14 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/quic-go/qpack v0.4.0 // indirect + github.com/quic-go/qtls-go1-20 v0.4.1 // indirect + github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect + github.com/sagernet/nftables v0.3.0-beta.4 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect + github.com/vishvananda/netns v0.0.4 // indirect + github.com/zeebo/blake3 v0.2.3 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/text v0.21.0 // indirect + golang.org/x/time v0.7.0 // indirect + golang.org/x/tools v0.24.0 // indirect + golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect + gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + lukechampine.com/blake3 v1.3.0 // indirect +) diff --git a/go.sum b/go.sum index bd443e68..d3b1faae 100644 --- a/go.sum +++ b/go.sum @@ -1,229 +1,232 @@ -github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= -github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= -github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= -github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc= -github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg= -github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= -github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= -github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= -github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo= -github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= -github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= -github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= -github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= -github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= -github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= -github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= -github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= -github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= -github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= -github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk= -github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= -github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= -github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= -github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= -github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= -github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= -github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA= -github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= -github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= -github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= -github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= -github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= -github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= -github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ= -github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE= -github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054= -github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU= -github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= -github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= -github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= -github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= -github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= -github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= -github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= -github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= -github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= -github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa h1:9mcjV+RGZVC3reJBNDjjNPyS8PmFG97zq56X7WNaFO4= -github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa/go.mod h1:4tLB5c8U0CxpkFM+AJJB77jEaVDbLH5XQvy42vAGsWw= -github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= -github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= -github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= -github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= -github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= -github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= -github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs= -github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY= -github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= -github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= -github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= -github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= -github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= -github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1 h1:qi+ijeREa0yfAaO+NOcZ81gv4uzOfALUIdhkiIFvmG4= -github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1/go.mod h1:JULDuzTMn2gyZFcjpTVZP4/UuwAdbHJ0bum2RdjXojU= -github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0= -github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= -github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY= -github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k= -github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ= -github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI= -github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs= -github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= -github.com/sagernet/gomobile v0.1.4 h1:WzX9ka+iHdupMgy2Vdich+OAt7TM8C2cZbIbzNjBrJY= -github.com/sagernet/gomobile v0.1.4/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E= -github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff h1:mlohw3360Wg1BNGook/UHnISXhUx4Gd/3tVLs5T0nSs= -github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff/go.mod h1:ehZwnT2UpmOWAHFL48XdBhnd4Qu4hN2O3Ji0us3ZHMw= -github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= -github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= -github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I= -github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8= -github.com/sagernet/quic-go v0.48.2-beta.1 h1:W0plrLWa1XtOWDTdX3CJwxmQuxkya12nN5BRGZ87kEg= -github.com/sagernet/quic-go v0.48.2-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/+or9YMLaG5VeTk4k= -github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= -github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= -github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= -github.com/sagernet/sing v0.6.0-beta.9 h1:P8lKa5hN53fRNAVCIKy5cWd6/kLO5c4slhdsfehSmHs= -github.com/sagernet/sing v0.6.0-beta.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= -github.com/sagernet/sing-dns v0.4.0-beta.1 h1:W1XkdhigwxDOMgMDVB+9kdomCpb7ExsZfB4acPcTZFY= -github.com/sagernet/sing-dns v0.4.0-beta.1/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8= -github.com/sagernet/sing-mux v0.3.0-alpha.1 h1:IgNX5bJBpL41gGbp05pdDOvh/b5eUQ6cv9240+Ngipg= -github.com/sagernet/sing-mux v0.3.0-alpha.1/go.mod h1:FTcImmdfW38Lz7b+HQ+mxxOth1lz4ao8uEnz+MwIJQE= -github.com/sagernet/sing-quic v0.4.0-beta.3 h1:cOBjlhVdRZmBm6hIw1GleERpnTSFdBB2htgx5kQ5uqg= -github.com/sagernet/sing-quic v0.4.0-beta.3/go.mod h1:1UNObFodd8CnS3aCT53x9cigjPSCl3P//8dfBMCwBDM= -github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= -github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= -github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= -github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= -github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 h1:RPrpgAdkP5td0vLfS5ldvYosFjSsZtRPxiyLV6jyKg0= -github.com/sagernet/sing-shadowtls v0.2.0-alpha.2/go.mod h1:0j5XlzKxaWRIEjc1uiSKmVoWb0k+L9QgZVb876+thZA= -github.com/sagernet/sing-tun v0.6.0-beta.7 h1:FCSX8oGBqb0H57AAvfGeeH/jMGYWCOg6XWkN/oeES+0= -github.com/sagernet/sing-tun v0.6.0-beta.7/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE= -github.com/sagernet/sing-vmess v0.2.0-beta.2 h1:obAkAL35X7ql4RnGzDg4dBYIRpGXRKqcN4LyLZpZGSs= -github.com/sagernet/sing-vmess v0.2.0-beta.2/go.mod h1:HGhf9XUdeE2iOWrX0hQNFgXPbKyGlzpeYFyX0c/pykk= -github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= -github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= -github.com/sagernet/utls v1.6.7 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8= -github.com/sagernet/utls v1.6.7/go.mod h1:Uua1TKO/FFuAhLr9rkaVnnrTmmiItzDjv1BUb2+ERwM= -github.com/sagernet/wireguard-go v0.0.1-beta.5 h1:aBEsxJUMEONwOZqKPIkuAcv4zJV5p6XlzEN04CF0FXc= -github.com/sagernet/wireguard-go v0.0.1-beta.5/go.mod h1:jGXij2Gn2wbrWuYNUmmNhf1dwcZtvyAvQoe8Xd8MbUo= -github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc= -github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA= -github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= -github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= -github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA= -github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= -github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= -github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= -github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= -github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= -github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= -github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= -github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= -go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -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/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= -golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= -golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= -golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= -golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= -golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= -golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= -golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= -golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= -golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= -golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE= -golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= -google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= -google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM= -howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= -lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= -lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= +github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= +github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= +github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= +github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/caddyserver/certmagic v0.20.0 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc= +github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cretz/bine v0.2.0 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo= +github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU= +github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= +github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= +github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= +github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= +github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU= +github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM= +github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og= +github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gofrs/uuid/v5 v5.3.0 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk= +github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg= +github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk= +github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= +github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= +github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA= +github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= +github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= +github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= +github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/libdns/alidns v1.0.3 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ= +github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE= +github.com/libdns/cloudflare v0.1.1 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054= +github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU= +github.com/libdns/libdns v0.2.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40= +github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s= +github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= +github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa h1:9mcjV+RGZVC3reJBNDjjNPyS8PmFG97zq56X7WNaFO4= +github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa/go.mod h1:4tLB5c8U0CxpkFM+AJJB77jEaVDbLH5XQvy42vAGsWw= +github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30= +github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE= +github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ= +github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss= +github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0= +github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU= +github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs= +github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY= +github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= +github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs= +github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1 h1:qi+ijeREa0yfAaO+NOcZ81gv4uzOfALUIdhkiIFvmG4= +github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1/go.mod h1:JULDuzTMn2gyZFcjpTVZP4/UuwAdbHJ0bum2RdjXojU= +github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0= +github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM= +github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY= +github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k= +github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ= +github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI= +github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs= +github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o= +github.com/sagernet/gomobile v0.1.4 h1:WzX9ka+iHdupMgy2Vdich+OAt7TM8C2cZbIbzNjBrJY= +github.com/sagernet/gomobile v0.1.4/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E= +github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff h1:mlohw3360Wg1BNGook/UHnISXhUx4Gd/3tVLs5T0nSs= +github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff/go.mod h1:ehZwnT2UpmOWAHFL48XdBhnd4Qu4hN2O3Ji0us3ZHMw= +github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis= +github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= +github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I= +github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8= +github.com/sagernet/quic-go v0.48.2-beta.1 h1:W0plrLWa1XtOWDTdX3CJwxmQuxkya12nN5BRGZ87kEg= +github.com/sagernet/quic-go v0.48.2-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/+or9YMLaG5VeTk4k= +github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc= +github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU= +github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo= +github.com/sagernet/sing v0.6.0-beta.9 h1:P8lKa5hN53fRNAVCIKy5cWd6/kLO5c4slhdsfehSmHs= +github.com/sagernet/sing v0.6.0-beta.9/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak= +github.com/sagernet/sing-dns v0.4.0-beta.1 h1:W1XkdhigwxDOMgMDVB+9kdomCpb7ExsZfB4acPcTZFY= +github.com/sagernet/sing-dns v0.4.0-beta.1/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8= +github.com/sagernet/sing-mux v0.3.0-alpha.1 h1:IgNX5bJBpL41gGbp05pdDOvh/b5eUQ6cv9240+Ngipg= +github.com/sagernet/sing-mux v0.3.0-alpha.1/go.mod h1:FTcImmdfW38Lz7b+HQ+mxxOth1lz4ao8uEnz+MwIJQE= +github.com/sagernet/sing-quic v0.4.0-beta.3 h1:cOBjlhVdRZmBm6hIw1GleERpnTSFdBB2htgx5kQ5uqg= +github.com/sagernet/sing-quic v0.4.0-beta.3/go.mod h1:1UNObFodd8CnS3aCT53x9cigjPSCl3P//8dfBMCwBDM= +github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8= +github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE= +github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg= +github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= +github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 h1:RPrpgAdkP5td0vLfS5ldvYosFjSsZtRPxiyLV6jyKg0= +github.com/sagernet/sing-shadowtls v0.2.0-alpha.2/go.mod h1:0j5XlzKxaWRIEjc1uiSKmVoWb0k+L9QgZVb876+thZA= +github.com/sagernet/sing-tun v0.6.0-beta.7 h1:FCSX8oGBqb0H57AAvfGeeH/jMGYWCOg6XWkN/oeES+0= +github.com/sagernet/sing-tun v0.6.0-beta.7/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE= +github.com/sagernet/sing-vmess v0.2.0-beta.2 h1:obAkAL35X7ql4RnGzDg4dBYIRpGXRKqcN4LyLZpZGSs= +github.com/sagernet/sing-vmess v0.2.0-beta.2/go.mod h1:HGhf9XUdeE2iOWrX0hQNFgXPbKyGlzpeYFyX0c/pykk= +github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= +github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo= +github.com/sagernet/utls v1.6.7 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8= +github.com/sagernet/utls v1.6.7/go.mod h1:Uua1TKO/FFuAhLr9rkaVnnrTmmiItzDjv1BUb2+ERwM= +github.com/sagernet/wireguard-go v0.0.1-beta.5 h1:aBEsxJUMEONwOZqKPIkuAcv4zJV5p6XlzEN04CF0FXc= +github.com/sagernet/wireguard-go v0.0.1-beta.5/go.mod h1:jGXij2Gn2wbrWuYNUmmNhf1dwcZtvyAvQoe8Xd8MbUo= +github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc= +github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA= +github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= +github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= +github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= +github.com/wiresock/ndisapi-go v0.0.0-20241230094942-3299a7566e08 h1:is+7xN6CAKtgxt3mDSl9OQNvjfi6LggugSP07QhDtws= +github.com/wiresock/ndisapi-go v0.0.0-20241230094942-3299a7566e08/go.mod h1:lFE7JYt3LC2UYJ31mRDwl/K35pbtxDnkSDlXrYzgyqg= +github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY= +github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= +github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg= +github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ= +github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo= +github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +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/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= +golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ= +golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg= +golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= +golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE= +golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= +google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= +google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM= +howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= +lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= +lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= diff --git a/include/ndis.go b/include/ndis.go new file mode 100644 index 00000000..12d404b3 --- /dev/null +++ b/include/ndis.go @@ -0,0 +1,12 @@ +//go:build windows && with_gvisor + +package include + +import ( + "github.com/sagernet/sing-box/adapter/inbound" + "github.com/sagernet/sing-box/protocol/ndis" +) + +func registerNDISInbound(registry *inbound.Registry) { + ndis.RegisterInbound(registry) +} diff --git a/include/ndis_nongvisor_stub.go b/include/ndis_nongvisor_stub.go new file mode 100644 index 00000000..f82f91d4 --- /dev/null +++ b/include/ndis_nongvisor_stub.go @@ -0,0 +1,20 @@ +//go:build windows && !with_gvisor + +package include + +import ( + "context" + + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/adapter/inbound" + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing-tun" +) + +func registerNDISInbound(registry *inbound.Registry) { + inbound.Register[option.NDISInboundOptions](registry, C.TypeNDIS, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.NDISInboundOptions) (adapter.Inbound, error) { + return nil, tun.ErrGVisorNotIncluded + }) +} diff --git a/include/ndis_nonwindows_stub.go b/include/ndis_nonwindows_stub.go new file mode 100644 index 00000000..e260eb0d --- /dev/null +++ b/include/ndis_nonwindows_stub.go @@ -0,0 +1,20 @@ +//go:build !windows + +package include + +import ( + "context" + + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/adapter/inbound" + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing-box/option" + E "github.com/sagernet/sing/common/exceptions" +) + +func registerNDISInbound(registry *inbound.Registry) { + inbound.Register[option.NDISInboundOptions](registry, C.TypeNDIS, func(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.NDISInboundOptions) (adapter.Inbound, error) { + return nil, E.New("NDIS is only supported in windows") + }) +} diff --git a/include/registry.go b/include/registry.go index e71ffb0c..b4fb2a1b 100644 --- a/include/registry.go +++ b/include/registry.go @@ -51,6 +51,7 @@ func InboundRegistry() *inbound.Registry { registerQUICInbounds(registry) registerStubForRemovedInbounds(registry) + registerNDISInbound(registry) return registry } diff --git a/option/debug.go b/option/debug.go index 0b0b825a..a223e6e9 100644 --- a/option/debug.go +++ b/option/debug.go @@ -13,7 +13,7 @@ type DebugOptions struct { PanicOnFault *bool `json:"panic_on_fault,omitempty"` TraceBack string `json:"trace_back,omitempty"` MemoryLimit MemoryBytes `json:"memory_limit,omitempty"` - OOMKiller *bool `json:"oom_killer,omitempty"` + OOMKiller bool `json:"oom_killer,omitempty"` } type MemoryBytes uint64 diff --git a/option/ndis.go b/option/ndis.go new file mode 100644 index 00000000..768667f2 --- /dev/null +++ b/option/ndis.go @@ -0,0 +1,17 @@ +package option + +import ( + "net/netip" + + "github.com/sagernet/sing/common/json/badoption" +) + +type NDISInboundOptions struct { + Network NetworkList `json:"network,omitempty"` + RouteAddress badoption.Listable[netip.Prefix] `json:"route_address,omitempty"` + RouteAddressSet badoption.Listable[string] `json:"route_address_set,omitempty"` + RouteExcludeAddress badoption.Listable[netip.Prefix] `json:"route_exclude_address,omitempty"` + RouteExcludeAddressSet badoption.Listable[string] `json:"route_exclude_address_set,omitempty"` + InterfaceName string `json:"interface_name,omitempty"` + UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"` +} diff --git a/protocol/ndis/endpoint.go b/protocol/ndis/endpoint.go new file mode 100644 index 00000000..2eab108a --- /dev/null +++ b/protocol/ndis/endpoint.go @@ -0,0 +1,110 @@ +//go:build windows + +package ndis + +import ( + "sync" + + "github.com/sagernet/gvisor/pkg/buffer" + "github.com/sagernet/gvisor/pkg/tcpip" + "github.com/sagernet/gvisor/pkg/tcpip/header" + "github.com/sagernet/gvisor/pkg/tcpip/stack" + + "github.com/wiresock/ndisapi-go" + "github.com/wiresock/ndisapi-go/driver" +) + +var _ stack.LinkEndpoint = (*ndisEndpoint)(nil) + +type ndisEndpoint struct { + filter *driver.QueuedPacketFilter + mtu uint32 + address tcpip.LinkAddress + dispatcher stack.NetworkDispatcher +} + +func (e *ndisEndpoint) MTU() uint32 { + return e.mtu +} + +func (e *ndisEndpoint) SetMTU(mtu uint32) { +} + +func (e *ndisEndpoint) MaxHeaderLength() uint16 { + return header.EthernetMinimumSize +} + +func (e *ndisEndpoint) LinkAddress() tcpip.LinkAddress { + return e.address +} + +func (e *ndisEndpoint) SetLinkAddress(addr tcpip.LinkAddress) { +} + +func (e *ndisEndpoint) Capabilities() stack.LinkEndpointCapabilities { + return 0 +} + +func (e *ndisEndpoint) Attach(dispatcher stack.NetworkDispatcher) { + e.dispatcher = dispatcher +} + +func (e *ndisEndpoint) IsAttached() bool { + return e.dispatcher != nil +} + +func (e *ndisEndpoint) Wait() { +} + +func (e *ndisEndpoint) ARPHardwareType() header.ARPHardwareType { + return header.ARPHardwareEther +} + +func (e *ndisEndpoint) AddHeader(pkt *stack.PacketBuffer) { + eth := header.Ethernet(pkt.LinkHeader().Push(header.EthernetMinimumSize)) + fields := header.EthernetFields{ + SrcAddr: pkt.EgressRoute.LocalLinkAddress, + DstAddr: pkt.EgressRoute.RemoteLinkAddress, + Type: pkt.NetworkProtocolNumber, + } + eth.Encode(&fields) +} + +func (e *ndisEndpoint) ParseHeader(pkt *stack.PacketBuffer) bool { + _, ok := pkt.LinkHeader().Consume(header.EthernetMinimumSize) + return ok +} + +func (e *ndisEndpoint) Close() { +} + +func (e *ndisEndpoint) SetOnCloseAction(f func()) { +} + +var bufferPool = sync.Pool{ + New: func() any { + return new(ndisapi.IntermediateBuffer) + }, +} + +func (e *ndisEndpoint) WritePackets(list stack.PacketBufferList) (int, tcpip.Error) { + for _, packetBuffer := range list.AsSlice() { + ndisBuf := bufferPool.Get().(*ndisapi.IntermediateBuffer) + viewList, offset := packetBuffer.AsViewList() + var view *buffer.View + for view = viewList.Front(); view != nil && offset >= view.Size(); view = view.Next() { + offset -= view.Size() + } + index := copy(ndisBuf.Buffer[:], view.AsSlice()[offset:]) + for view = view.Next(); view != nil; view = view.Next() { + index += copy(ndisBuf.Buffer[index:], view.AsSlice()) + } + ndisBuf.Length = uint32(index) + err := e.filter.InsertPacketToMstcp(ndisBuf) + bufferPool.Put(ndisBuf) + if err != nil { + return 0, &tcpip.ErrAborted{} + } + } + return list.Len(), nil +} diff --git a/protocol/ndis/inbound.go b/protocol/ndis/inbound.go new file mode 100644 index 00000000..28b51e97 --- /dev/null +++ b/protocol/ndis/inbound.go @@ -0,0 +1,203 @@ +//go:build windows + +package ndis + +import ( + "context" + "net" + "net/netip" + "time" + + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/adapter/inbound" + "github.com/sagernet/sing-box/common/conntrack" + "github.com/sagernet/sing-box/common/taskmonitor" + C "github.com/sagernet/sing-box/constant" + "github.com/sagernet/sing-box/log" + "github.com/sagernet/sing-box/option" + "github.com/sagernet/sing/common" + E "github.com/sagernet/sing/common/exceptions" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" + "github.com/sagernet/sing/common/x/list" + "github.com/sagernet/sing/service" + + "github.com/wiresock/ndisapi-go" + "go4.org/netipx" +) + +func RegisterInbound(registry *inbound.Registry) { + inbound.Register[option.NDISInboundOptions](registry, C.TypeNDIS, NewInbound) +} + +type Inbound struct { + inbound.Adapter + ctx context.Context + router adapter.Router + logger log.ContextLogger + api *ndisapi.NdisApi + tracker conntrack.Tracker + routeAddress []netip.Prefix + routeExcludeAddress []netip.Prefix + routeRuleSet []adapter.RuleSet + routeRuleSetCallback []*list.Element[adapter.RuleSetUpdateCallback] + routeExcludeRuleSet []adapter.RuleSet + routeExcludeRuleSetCallback []*list.Element[adapter.RuleSetUpdateCallback] + stack *Stack +} + +func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.NDISInboundOptions) (adapter.Inbound, error) { + api, err := ndisapi.NewNdisApi() + if err != nil { + return nil, E.Cause(err, "create NDIS API") + } + //if !api.IsDriverLoaded() { + // return nil, E.New("missing NDIS driver") + //} + networkManager := service.FromContext[adapter.NetworkManager](ctx) + trackerOut := service.FromContext[conntrack.Tracker](ctx) + var udpTimeout time.Duration + if options.UDPTimeout != 0 { + udpTimeout = time.Duration(options.UDPTimeout) + } else { + udpTimeout = C.UDPTimeout + } + var ( + routeRuleSet []adapter.RuleSet + routeExcludeRuleSet []adapter.RuleSet + ) + for _, routeAddressSet := range options.RouteAddressSet { + ruleSet, loaded := router.RuleSet(routeAddressSet) + if !loaded { + return nil, E.New("parse route_address_set: rule-set not found: ", routeAddressSet) + } + ruleSet.IncRef() + routeRuleSet = append(routeRuleSet, ruleSet) + } + for _, routeExcludeAddressSet := range options.RouteExcludeAddressSet { + ruleSet, loaded := router.RuleSet(routeExcludeAddressSet) + if !loaded { + return nil, E.New("parse route_exclude_address_set: rule-set not found: ", routeExcludeAddressSet) + } + ruleSet.IncRef() + routeExcludeRuleSet = append(routeExcludeRuleSet, ruleSet) + } + trackerIn := conntrack.NewDefaultTracker(false, 0) + return &Inbound{ + Adapter: inbound.NewAdapter(C.TypeNDIS, tag), + ctx: ctx, + router: router, + logger: logger, + api: api, + tracker: trackerIn, + routeRuleSet: routeRuleSet, + routeExcludeRuleSet: routeExcludeRuleSet, + stack: &Stack{ + ctx: ctx, + logger: logger, + network: networkManager, + trackerIn: trackerIn, + trackerOut: trackerOut, + api: api, + udpTimeout: udpTimeout, + routeAddress: options.RouteAddress, + routeExcludeAddress: options.RouteExcludeAddress, + }, + }, nil +} + +func (t *Inbound) Start(stage adapter.StartStage) error { + switch stage { + case adapter.StartStateStart: + monitor := taskmonitor.New(t.logger, C.StartTimeout) + var ( + routeAddressSet []*netipx.IPSet + routeExcludeAddressSet []*netipx.IPSet + ) + for _, routeRuleSet := range t.routeRuleSet { + ipSets := routeRuleSet.ExtractIPSet() + if len(ipSets) == 0 { + t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeRuleSet.Name()) + } + t.routeRuleSetCallback = append(t.routeRuleSetCallback, routeRuleSet.RegisterCallback(t.updateRouteAddressSet)) + routeRuleSet.DecRef() + routeAddressSet = append(routeAddressSet, ipSets...) + } + for _, routeExcludeRuleSet := range t.routeExcludeRuleSet { + ipSets := routeExcludeRuleSet.ExtractIPSet() + if len(ipSets) == 0 { + t.logger.Warn("route_exclude_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name()) + } + t.routeExcludeRuleSetCallback = append(t.routeExcludeRuleSetCallback, routeExcludeRuleSet.RegisterCallback(t.updateRouteAddressSet)) + routeExcludeRuleSet.DecRef() + routeExcludeAddressSet = append(routeExcludeAddressSet, ipSets...) + } + t.stack.routeAddressSet = routeAddressSet + t.stack.routeExcludeAddressSet = routeExcludeAddressSet + monitor.Start("starting NDIS stack") + t.stack.handler = t + err := t.stack.Start() + monitor.Finish() + if err != nil { + return E.Cause(err, "starting NDIS stack") + } + } + return nil +} + +func (t *Inbound) Close() error { + if t.api != nil { + t.stack.Close() + t.api.Close() + } + return nil +} + +func (t *Inbound) PrepareConnection(network string, source M.Socksaddr, destination M.Socksaddr) error { + return t.router.PreMatch(adapter.InboundContext{ + Inbound: t.Tag(), + InboundType: C.TypeNDIS, + Network: network, + Source: source, + Destination: destination, + }) +} + +func (t *Inbound) NewConnectionEx(ctx context.Context, conn net.Conn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + ctx = log.ContextWithNewID(ctx) + var metadata adapter.InboundContext + metadata.Inbound = t.Tag() + metadata.InboundType = C.TypeNDIS + metadata.Source = source + metadata.Destination = destination + t.logger.InfoContext(ctx, "inbound connection from ", metadata.Source) + t.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) + done, err := t.tracker.NewConnEx(conn) + if err != nil { + t.logger.ErrorContext(ctx, E.Cause(err, "track inbound connection")) + return + } + t.router.RouteConnectionEx(ctx, conn, metadata, N.AppendClose(onClose, done)) +} + +func (t *Inbound) NewPacketConnectionEx(ctx context.Context, conn N.PacketConn, source M.Socksaddr, destination M.Socksaddr, onClose N.CloseHandlerFunc) { + ctx = log.ContextWithNewID(ctx) + var metadata adapter.InboundContext + metadata.Inbound = t.Tag() + metadata.InboundType = C.TypeNDIS + metadata.Source = source + metadata.Destination = destination + t.logger.InfoContext(ctx, "inbound packet connection from ", metadata.Source) + t.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) + done, err := t.tracker.NewPacketConnEx(conn) + if err != nil { + t.logger.ErrorContext(ctx, E.Cause(err, "track inbound connection")) + return + } + t.router.RoutePacketConnectionEx(ctx, conn, metadata, N.AppendClose(onClose, done)) +} + +func (t *Inbound) updateRouteAddressSet(it adapter.RuleSet) { + t.stack.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet) + t.stack.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet) +} diff --git a/protocol/ndis/stack.go b/protocol/ndis/stack.go new file mode 100644 index 00000000..35c50fe0 --- /dev/null +++ b/protocol/ndis/stack.go @@ -0,0 +1,267 @@ +//go:build windows + +package ndis + +import ( + "context" + "net/netip" + "time" + + "github.com/sagernet/gvisor/pkg/buffer" + "github.com/sagernet/gvisor/pkg/tcpip" + "github.com/sagernet/gvisor/pkg/tcpip/header" + "github.com/sagernet/gvisor/pkg/tcpip/stack" + "github.com/sagernet/gvisor/pkg/tcpip/transport/tcp" + "github.com/sagernet/gvisor/pkg/tcpip/transport/udp" + "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/conntrack" + "github.com/sagernet/sing-tun" + "github.com/sagernet/sing/common/control" + "github.com/sagernet/sing/common/debug" + E "github.com/sagernet/sing/common/exceptions" + "github.com/sagernet/sing/common/logger" + + "github.com/wiresock/ndisapi-go" + "github.com/wiresock/ndisapi-go/driver" + "go4.org/netipx" + "golang.org/x/net/ipv4" + "golang.org/x/net/ipv6" +) + +type Stack struct { + ctx context.Context + logger logger.ContextLogger + network adapter.NetworkManager + trackerIn conntrack.Tracker + trackerOut conntrack.Tracker + api *ndisapi.NdisApi + handler tun.Handler + udpTimeout time.Duration + filter *driver.QueuedPacketFilter + stack *stack.Stack + endpoint *ndisEndpoint + routeAddress []netip.Prefix + routeExcludeAddress []netip.Prefix + routeAddressSet []*netipx.IPSet + routeExcludeAddressSet []*netipx.IPSet + currentInterface *control.Interface +} + +func (s *Stack) Start() error { + err := s.start(s.network.InterfaceMonitor().DefaultInterface()) + if err != nil { + return err + } + s.network.InterfaceMonitor().RegisterCallback(s.updateDefaultInterface) + return nil +} + +func (s *Stack) updateDefaultInterface(defaultInterface *control.Interface, flags int) { + if s.currentInterface.Equals(*defaultInterface) { + return + } + err := s.start(defaultInterface) + if err != nil { + s.logger.Error(E.Cause(err, "reconfigure NDIS at: ", defaultInterface.Name)) + } +} + +func (s *Stack) start(defaultInterface *control.Interface) error { + _ = s.Close() + adapters, err := s.api.GetTcpipBoundAdaptersInfo() + if err != nil { + return err + } + if defaultInterface != nil { + for index := 0; index < int(adapters.AdapterCount); index++ { + name := s.api.ConvertWindows2000AdapterName(string(adapters.AdapterNameList[index][:])) + if name != defaultInterface.Name { + continue + } + s.filter, err = driver.NewQueuedPacketFilter(s.api, adapters, nil, s.processOut) + if err != nil { + return err + } + address := tcpip.LinkAddress(adapters.CurrentAddress[index][:]) + mtu := uint32(adapters.MTU[index]) + endpoint := &ndisEndpoint{ + filter: s.filter, + mtu: mtu, + address: address, + } + s.stack, err = tun.NewGVisorStack(endpoint) + if err != nil { + s.filter = nil + return err + } + s.stack.SetTransportProtocolHandler(tcp.ProtocolNumber, tun.NewTCPForwarder(s.ctx, s.stack, s.handler).HandlePacket) + s.stack.SetTransportProtocolHandler(udp.ProtocolNumber, tun.NewUDPForwarder(s.ctx, s.stack, s.handler, s.udpTimeout).HandlePacket) + err = s.filter.StartFilter(index) + if err != nil { + s.filter = nil + s.stack.Close() + s.stack = nil + return err + } + s.endpoint = endpoint + s.logger.Info("started at ", defaultInterface.Name) + break + } + } + s.currentInterface = defaultInterface + return nil +} + +func (s *Stack) Close() error { + if s.filter != nil { + s.filter.StopFilter() + s.filter.Close() + s.filter = nil + } + if s.stack != nil { + s.stack.Close() + for _, endpoint := range s.stack.CleanupEndpoints() { + endpoint.Abort() + } + s.stack = nil + } + return nil +} + +func (s *Stack) processOut(handle ndisapi.Handle, packet *ndisapi.IntermediateBuffer) ndisapi.FilterAction { + if packet.Length < header.EthernetMinimumSize { + return ndisapi.FilterActionPass + } + if s.endpoint.dispatcher == nil || s.filterPacket(packet.Buffer[:packet.Length]) { + return ndisapi.FilterActionPass + } + packetBuffer := stack.NewPacketBuffer(stack.PacketBufferOptions{ + Payload: buffer.MakeWithData(packet.Buffer[:packet.Length]), + }) + _, ok := packetBuffer.LinkHeader().Consume(header.EthernetMinimumSize) + if !ok { + packetBuffer.DecRef() + return ndisapi.FilterActionPass + } + ethHdr := header.Ethernet(packetBuffer.LinkHeader().Slice()) + destinationAddress := ethHdr.DestinationAddress() + if destinationAddress == header.EthernetBroadcastAddress { + packetBuffer.PktType = tcpip.PacketBroadcast + } else if header.IsMulticastEthernetAddress(destinationAddress) { + packetBuffer.PktType = tcpip.PacketMulticast + } else if destinationAddress == s.endpoint.address { + packetBuffer.PktType = tcpip.PacketHost + } else { + packetBuffer.PktType = tcpip.PacketOtherHost + } + s.endpoint.dispatcher.DeliverNetworkPacket(ethHdr.Type(), packetBuffer) + packetBuffer.DecRef() + return ndisapi.FilterActionDrop +} + +func (s *Stack) filterPacket(packet []byte) bool { + var ipHdr header.Network + switch header.IPVersion(packet[header.EthernetMinimumSize:]) { + case ipv4.Version: + ipHdr = header.IPv4(packet[header.EthernetMinimumSize:]) + case ipv6.Version: + ipHdr = header.IPv6(packet[header.EthernetMinimumSize:]) + default: + return true + } + sourceAddr := tun.AddrFromAddress(ipHdr.SourceAddress()) + destinationAddr := tun.AddrFromAddress(ipHdr.DestinationAddress()) + if !destinationAddr.IsGlobalUnicast() { + return true + } + var ( + transportProtocol tcpip.TransportProtocolNumber + transportHdr header.Transport + ) + switch ipHdr.TransportProtocol() { + case tcp.ProtocolNumber: + transportProtocol = header.TCPProtocolNumber + transportHdr = header.TCP(ipHdr.Payload()) + case udp.ProtocolNumber: + transportProtocol = header.UDPProtocolNumber + transportHdr = header.UDP(ipHdr.Payload()) + default: + return false + } + source := netip.AddrPortFrom(sourceAddr, transportHdr.SourcePort()) + destination := netip.AddrPortFrom(destinationAddr, transportHdr.DestinationPort()) + if transportProtocol == header.TCPProtocolNumber { + if s.trackerIn.CheckConn(source, destination) { + if debug.Enabled { + s.logger.Trace("fall exists TCP ", source, " ", destination) + } + return false + } + } else { + if s.trackerIn.CheckPacketConn(source) { + if debug.Enabled { + s.logger.Trace("fall exists UDP ", source, " ", destination) + } + } + } + if len(s.routeAddress) > 0 { + var match bool + for _, route := range s.routeAddress { + if route.Contains(destinationAddr) { + match = true + } + } + if !match { + return true + } + } + if len(s.routeAddressSet) > 0 { + var match bool + for _, ipSet := range s.routeAddressSet { + if ipSet.Contains(destinationAddr) { + match = true + } + } + if !match { + return true + } + } + if len(s.routeExcludeAddress) > 0 { + for _, address := range s.routeExcludeAddress { + if address.Contains(destinationAddr) { + return true + } + } + } + if len(s.routeExcludeAddressSet) > 0 { + for _, ipSet := range s.routeAddressSet { + if ipSet.Contains(destinationAddr) { + return true + } + } + } + if s.trackerOut.CheckDestination(destination) { + if debug.Enabled { + s.logger.Trace("passing pending ", source, " ", destination) + } + return true + } + if transportProtocol == header.TCPProtocolNumber { + if s.trackerOut.CheckConn(source, destination) { + if debug.Enabled { + s.logger.Trace("passing TCP ", source, " ", destination) + } + return true + } + } else { + if s.trackerOut.CheckPacketConn(source) { + if debug.Enabled { + s.logger.Trace("passing UDP ", source, " ", destination) + } + } + } + if debug.Enabled { + s.logger.Trace("fall ", source, " ", destination) + } + return false +} diff --git a/protocol/tun/inbound.go b/protocol/tun/inbound.go index 51e7ca78..a6b2c451 100644 --- a/protocol/tun/inbound.go +++ b/protocol/tun/inbound.go @@ -306,7 +306,6 @@ func (t *Inbound) Start(stage adapter.StartStage) error { t.tunOptions.Name = tun.CalculateInterfaceName("") } if t.platformInterface == nil || runtime.GOOS != "android" { - t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet) for _, routeRuleSet := range t.routeRuleSet { ipSets := routeRuleSet.ExtractIPSet() if len(ipSets) == 0 { @@ -316,11 +315,10 @@ func (t *Inbound) Start(stage adapter.StartStage) error { routeRuleSet.DecRef() t.routeAddressSet = append(t.routeAddressSet, ipSets...) } - t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet) for _, routeExcludeRuleSet := range t.routeExcludeRuleSet { ipSets := routeExcludeRuleSet.ExtractIPSet() if len(ipSets) == 0 { - t.logger.Warn("route_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name()) + t.logger.Warn("route_exclude_address_set: no destination IP CIDR rules found in rule-set: ", routeExcludeRuleSet.Name()) } t.routeExcludeRuleSetCallback = append(t.routeExcludeRuleSetCallback, routeExcludeRuleSet.RegisterCallback(t.updateRouteAddressSet)) routeExcludeRuleSet.DecRef() diff --git a/route/network.go b/route/network.go index 97d165f1..c1efd509 100644 --- a/route/network.go +++ b/route/network.go @@ -35,6 +35,7 @@ var _ adapter.NetworkManager = (*NetworkManager)(nil) type NetworkManager struct { logger logger.ContextLogger + tracker conntrack.Tracker interfaceFinder *control.DefaultInterfaceFinder networkInterfaces atomic.TypedValue[[]adapter.NetworkInterface] @@ -57,6 +58,7 @@ type NetworkManager struct { func NewNetworkManager(ctx context.Context, logger logger.ContextLogger, routeOptions option.RouteOptions) (*NetworkManager, error) { nm := &NetworkManager{ logger: logger, + tracker: service.FromContext[conntrack.Tracker](ctx), interfaceFinder: control.NewDefaultInterfaceFinder(), autoDetectInterface: routeOptions.AutoDetectInterface, defaultOptions: adapter.NetworkOptions{ @@ -355,7 +357,7 @@ func (r *NetworkManager) WIFIState() adapter.WIFIState { } func (r *NetworkManager) ResetNetwork() { - conntrack.Close() + r.tracker.Close() for _, endpoint := range r.endpoint.Endpoints() { listener, isListener := endpoint.(adapter.InterfaceUpdateListener) diff --git a/route/route.go b/route/route.go index 624b2289..d8549b01 100644 --- a/route/route.go +++ b/route/route.go @@ -11,7 +11,6 @@ import ( "time" "github.com/sagernet/sing-box/adapter" - "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/common/process" "github.com/sagernet/sing-box/common/sniff" C "github.com/sagernet/sing-box/constant" @@ -72,7 +71,10 @@ func (r *Router) routeConnection(ctx context.Context, conn net.Conn, metadata ad injectable.NewConnectionEx(ctx, conn, metadata, onClose) return nil } - conntrack.KillerCheck() + err := r.connTracker.KillerCheck() + if err != nil { + return err + } metadata.Network = N.NetworkTCP switch metadata.Destination.Fqdn { case mux.Destination.Fqdn: @@ -190,7 +192,10 @@ func (r *Router) routePacketConnection(ctx context.Context, conn N.PacketConn, m injectable.NewPacketConnectionEx(ctx, conn, metadata, onClose) return nil } - conntrack.KillerCheck() + err := r.connTracker.KillerCheck() + if err != nil { + return err + } // TODO: move to UoT metadata.Network = N.NetworkUDP diff --git a/route/router.go b/route/router.go index 642340d4..3423f69a 100644 --- a/route/router.go +++ b/route/router.go @@ -10,6 +10,7 @@ import ( "time" "github.com/sagernet/sing-box/adapter" + "github.com/sagernet/sing-box/common/conntrack" "github.com/sagernet/sing-box/common/dialer" "github.com/sagernet/sing-box/common/geoip" "github.com/sagernet/sing-box/common/geosite" @@ -38,6 +39,7 @@ type Router struct { ctx context.Context logger log.ContextLogger dnsLogger log.ContextLogger + connTracker conntrack.Tracker inbound adapter.InboundManager outbound adapter.OutboundManager connection adapter.ConnectionManager @@ -75,6 +77,7 @@ func NewRouter(ctx context.Context, logFactory log.Factory, options option.Route ctx: ctx, logger: logFactory.NewLogger("router"), dnsLogger: logFactory.NewLogger("dns"), + connTracker: service.FromContext[conntrack.Tracker](ctx), inbound: service.FromContext[adapter.InboundManager](ctx), outbound: service.FromContext[adapter.OutboundManager](ctx), connection: service.FromContext[adapter.ConnectionManager](ctx),