mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-13 20:28:32 +10:00
Compare commits
54 Commits
v1.11.0-be
...
dev-ndis
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
79d3649a8b | ||
|
|
e483c909b4 | ||
|
|
d9579c26ee | ||
|
|
48d3021b2c | ||
|
|
ce0fcd5c8b | ||
|
|
d9d0a2373a | ||
|
|
0c754505f7 | ||
|
|
606ff668da | ||
|
|
f43703801b | ||
|
|
1ed8f3a8d3 | ||
|
|
60fc913dc3 | ||
|
|
be8ee370ac | ||
|
|
0a9bf97438 | ||
|
|
74de437bfb | ||
|
|
c385e7c137 | ||
|
|
01291d16e0 | ||
|
|
11a448b52d | ||
|
|
22bda86bbf | ||
|
|
04cc343b2e | ||
|
|
093e539d3d | ||
|
|
5821b974bd | ||
|
|
8ce40f77b4 | ||
|
|
b45cb0763e | ||
|
|
48d102a0ab | ||
|
|
6a5943f4ce | ||
|
|
c9f9d9ee1c | ||
|
|
f3bf440c91 | ||
|
|
292fcde876 | ||
|
|
53e227a318 | ||
|
|
65cb225a2c | ||
|
|
7819f13489 | ||
|
|
f2780d0713 | ||
|
|
72239dcbd3 | ||
|
|
daf38a84e1 | ||
|
|
f2ddc5883b | ||
|
|
0437ac512b | ||
|
|
d297ad4c56 | ||
|
|
6823670f3d | ||
|
|
4a611eddf4 | ||
|
|
f12a294fb7 | ||
|
|
040a188c66 | ||
|
|
7ed10b35d0 | ||
|
|
afd341adfd | ||
|
|
7d26bac5ac | ||
|
|
63d8f6dc1c | ||
|
|
15cc3b85eb | ||
|
|
5a1c59ca88 | ||
|
|
7686503df8 | ||
|
|
96a8de9548 | ||
|
|
578571b972 | ||
|
|
935beca45d | ||
|
|
3e246f1173 | ||
|
|
1bc27a32c2 | ||
|
|
bc2e3960e4 |
@@ -22,6 +22,16 @@ linters-settings:
|
|||||||
|
|
||||||
run:
|
run:
|
||||||
go: "1.23"
|
go: "1.23"
|
||||||
|
build-tags:
|
||||||
|
- with_gvisor
|
||||||
|
- with_quic
|
||||||
|
- with_dhcp
|
||||||
|
- with_wireguard
|
||||||
|
- with_ech
|
||||||
|
- with_utls
|
||||||
|
- with_reality_server
|
||||||
|
- with_acme
|
||||||
|
- with_clash_api
|
||||||
|
|
||||||
issues:
|
issues:
|
||||||
exclude-dirs:
|
exclude-dirs:
|
||||||
|
|||||||
@@ -51,5 +51,4 @@ type NetworkInterface struct {
|
|||||||
DNSServers []string
|
DNSServers []string
|
||||||
Expensive bool
|
Expensive bool
|
||||||
Constrained bool
|
Constrained bool
|
||||||
RawNetwork any
|
|
||||||
}
|
}
|
||||||
|
|||||||
7
box.go
7
box.go
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/sagernet/sing-box/adapter/endpoint"
|
"github.com/sagernet/sing-box/adapter/endpoint"
|
||||||
"github.com/sagernet/sing-box/adapter/inbound"
|
"github.com/sagernet/sing-box/adapter/inbound"
|
||||||
"github.com/sagernet/sing-box/adapter/outbound"
|
"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/dialer"
|
||||||
"github.com/sagernet/sing-box/common/taskmonitor"
|
"github.com/sagernet/sing-box/common/taskmonitor"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
@@ -84,7 +85,6 @@ func New(options Options) (*Box, error) {
|
|||||||
ctx = context.Background()
|
ctx = context.Background()
|
||||||
}
|
}
|
||||||
ctx = service.ContextWithDefaultRegistry(ctx)
|
ctx = service.ContextWithDefaultRegistry(ctx)
|
||||||
|
|
||||||
endpointRegistry := service.FromContext[adapter.EndpointRegistry](ctx)
|
endpointRegistry := service.FromContext[adapter.EndpointRegistry](ctx)
|
||||||
inboundRegistry := service.FromContext[adapter.InboundRegistry](ctx)
|
inboundRegistry := service.FromContext[adapter.InboundRegistry](ctx)
|
||||||
outboundRegistry := service.FromContext[adapter.OutboundRegistry](ctx)
|
outboundRegistry := service.FromContext[adapter.OutboundRegistry](ctx)
|
||||||
@@ -101,7 +101,10 @@ func New(options Options) (*Box, error) {
|
|||||||
|
|
||||||
ctx = pause.WithDefaultManager(ctx)
|
ctx = pause.WithDefaultManager(ctx)
|
||||||
experimentalOptions := common.PtrValueOrDefault(options.Experimental)
|
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 needCacheFile bool
|
||||||
var needClashAPI bool
|
var needClashAPI bool
|
||||||
var needV2RayAPI bool
|
var needV2RayAPI bool
|
||||||
|
|||||||
Submodule clients/android updated: 6533b62fa3...e1049099a0
Submodule clients/apple updated: 1ecaff4c90...3d889ae017
@@ -21,7 +21,7 @@ func initializeHTTP3Client(instance *box.Box) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
http3Client = &http.Client{
|
http3Client = &http.Client{
|
||||||
Transport: &http3.RoundTripper{
|
Transport: &http3.Transport{
|
||||||
Dial: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
Dial: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
||||||
destination := M.ParseSocksaddr(addr)
|
destination := M.ParseSocksaddr(addr)
|
||||||
udpConn, dErr := dialer.DialContext(ctx, N.NetworkUDP, destination)
|
udpConn, dErr := dialer.DialContext(ctx, N.NetworkUDP, destination)
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
14
common/conntrack/context.go
Normal file
14
common/conntrack/context.go
Normal file
@@ -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))
|
||||||
|
}
|
||||||
245
common/conntrack/default.go
Normal file
245
common/conntrack/default.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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()
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
//go:build !with_conntrack
|
|
||||||
|
|
||||||
package conntrack
|
|
||||||
|
|
||||||
const Enabled = false
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
//go:build with_conntrack
|
|
||||||
|
|
||||||
package conntrack
|
|
||||||
|
|
||||||
const Enabled = true
|
|
||||||
32
common/conntrack/tracker.go
Normal file
32
common/conntrack/tracker.go
Normal file
@@ -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()
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type DefaultDialer struct {
|
type DefaultDialer struct {
|
||||||
|
tracker conntrack.Tracker
|
||||||
dialer4 tcpDialer
|
dialer4 tcpDialer
|
||||||
dialer6 tcpDialer
|
dialer6 tcpDialer
|
||||||
udpDialer4 net.Dialer
|
udpDialer4 net.Dialer
|
||||||
@@ -46,6 +47,7 @@ type DefaultDialer struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDialer, error) {
|
func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDialer, error) {
|
||||||
|
tracker := service.FromContext[conntrack.Tracker](ctx)
|
||||||
networkManager := service.FromContext[adapter.NetworkManager](ctx)
|
networkManager := service.FromContext[adapter.NetworkManager](ctx)
|
||||||
platformInterface := service.FromContext[platform.Interface](ctx)
|
platformInterface := service.FromContext[platform.Interface](ctx)
|
||||||
|
|
||||||
@@ -197,6 +199,7 @@ func NewDefault(ctx context.Context, options option.DialerOptions) (*DefaultDial
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &DefaultDialer{
|
return &DefaultDialer{
|
||||||
|
tracker: tracker,
|
||||||
dialer4: tcpDialer4,
|
dialer4: tcpDialer4,
|
||||||
dialer6: tcpDialer6,
|
dialer6: tcpDialer6,
|
||||||
udpDialer4: udpDialer4,
|
udpDialer4: udpDialer4,
|
||||||
@@ -219,18 +222,26 @@ func (d *DefaultDialer) DialContext(ctx context.Context, network string, address
|
|||||||
return nil, E.New("invalid address")
|
return nil, E.New("invalid address")
|
||||||
}
|
}
|
||||||
if d.networkStrategy == nil {
|
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) {
|
switch N.NetworkName(network) {
|
||||||
case N.NetworkUDP:
|
case N.NetworkUDP:
|
||||||
if !address.IsIPv6() {
|
if !address.IsIPv6() {
|
||||||
return trackConn(d.udpDialer4.DialContext(ctx, network, address.String()))
|
return d.trackConn(d.udpDialer4.DialContext(ctx, network, address.String()))
|
||||||
} else {
|
} else {
|
||||||
return trackConn(d.udpDialer6.DialContext(ctx, network, address.String()))
|
return d.trackConn(d.udpDialer6.DialContext(ctx, network, address.String()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !address.IsIPv6() {
|
if !address.IsIPv6() {
|
||||||
return trackConn(DialSlowContext(&d.dialer4, ctx, network, address))
|
return d.trackConn(DialSlowContext(&d.dialer4, ctx, network, address))
|
||||||
} else {
|
} else {
|
||||||
return trackConn(DialSlowContext(&d.dialer6, ctx, network, address))
|
return d.trackConn(DialSlowContext(&d.dialer6, ctx, network, address))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return d.DialParallelInterface(ctx, network, address, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay)
|
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 {
|
if !fastFallback && !isPrimary {
|
||||||
d.networkLastFallback.Store(time.Now())
|
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) {
|
func (d *DefaultDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
if d.networkStrategy == nil {
|
if d.networkStrategy == nil {
|
||||||
if destination.IsIPv6() {
|
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() {
|
} 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 {
|
} else {
|
||||||
return trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr4))
|
return d.trackPacketConn(d.udpListener.ListenPacket(ctx, N.NetworkUDP, d.udpAddr4))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return d.ListenSerialInterfacePacket(ctx, destination, d.networkStrategy, d.networkType, d.fallbackNetworkType, d.networkFallbackDelay)
|
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 nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return trackPacketConn(packetConn, nil)
|
return d.trackPacketConn(packetConn, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DefaultDialer) ListenPacketCompat(network, address string) (net.PacketConn, error) {
|
func (d *DefaultDialer) ListenPacketCompat(network, address string) (net.PacketConn, error) {
|
||||||
return d.udpListener.ListenPacket(context.Background(), network, address)
|
return d.udpListener.ListenPacket(context.Background(), network, address)
|
||||||
}
|
}
|
||||||
|
|
||||||
func trackConn(conn net.Conn, err error) (net.Conn, error) {
|
func (d *DefaultDialer) trackConn(conn net.Conn, err error) (net.Conn, error) {
|
||||||
if !conntrack.Enabled || err != nil {
|
if d.tracker == nil || err != nil {
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
return conntrack.NewConn(conn)
|
return d.tracker.NewConn(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
func trackPacketConn(conn net.PacketConn, err error) (net.PacketConn, error) {
|
func (d *DefaultDialer) trackPacketConn(conn net.PacketConn, err error) (net.PacketConn, error) {
|
||||||
if !conntrack.Enabled || err != nil {
|
if err != nil {
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
return conntrack.NewPacketConn(conn)
|
return d.tracker.NewPacketConn(conn)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ type echConnWrapper struct {
|
|||||||
|
|
||||||
func (c *echConnWrapper) ConnectionState() tls.ConnectionState {
|
func (c *echConnWrapper) ConnectionState() tls.ConnectionState {
|
||||||
state := c.Conn.ConnectionState()
|
state := c.Conn.ConnectionState()
|
||||||
|
//nolint:staticcheck
|
||||||
return tls.ConnectionState{
|
return tls.ConnectionState{
|
||||||
Version: state.Version,
|
Version: state.Version,
|
||||||
HandshakeComplete: state.HandshakeComplete,
|
HandshakeComplete: state.HandshakeComplete,
|
||||||
|
|||||||
@@ -147,6 +147,9 @@ func echKeygen(version uint16, serverName string, conf []myECHKeyConfig, suite [
|
|||||||
pair.rawConf = b
|
pair.rawConf = b
|
||||||
|
|
||||||
secBuf, err := sec.MarshalBinary()
|
secBuf, err := sec.MarshalBinary()
|
||||||
|
if err != nil {
|
||||||
|
return nil, E.Cause(err, "serialize ECH private key")
|
||||||
|
}
|
||||||
sk := []byte{}
|
sk := []byte{}
|
||||||
sk = be.AppendUint16(sk, uint16(len(secBuf)))
|
sk = be.AppendUint16(sk, uint16(len(secBuf)))
|
||||||
sk = append(sk, secBuf...)
|
sk = append(sk, secBuf...)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func (c *echClientConfig) DialEarly(ctx context.Context, conn net.PacketConn, ad
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *echClientConfig) CreateTransport(conn net.PacketConn, quicConnPtr *quic.EarlyConnection, serverAddr M.Socksaddr, quicConfig *quic.Config) http.RoundTripper {
|
func (c *echClientConfig) CreateTransport(conn net.PacketConn, quicConnPtr *quic.EarlyConnection, serverAddr M.Socksaddr, quicConfig *quic.Config) http.RoundTripper {
|
||||||
return &http3.RoundTripper{
|
return &http3.Transport{
|
||||||
TLSClientConfig: c.config,
|
TLSClientConfig: c.config,
|
||||||
QUICConfig: quicConfig,
|
QUICConfig: quicConfig,
|
||||||
Dial: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
Dial: func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
||||||
|
|||||||
@@ -174,6 +174,7 @@ type realityConnWrapper struct {
|
|||||||
|
|
||||||
func (c *realityConnWrapper) ConnectionState() ConnectionState {
|
func (c *realityConnWrapper) ConnectionState() ConnectionState {
|
||||||
state := c.Conn.ConnectionState()
|
state := c.Conn.ConnectionState()
|
||||||
|
//nolint:staticcheck
|
||||||
return tls.ConnectionState{
|
return tls.ConnectionState{
|
||||||
Version: state.Version,
|
Version: state.Version,
|
||||||
HandshakeComplete: state.HandshakeComplete,
|
HandshakeComplete: state.HandshakeComplete,
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ type utlsConnWrapper struct {
|
|||||||
|
|
||||||
func (c *utlsConnWrapper) ConnectionState() tls.ConnectionState {
|
func (c *utlsConnWrapper) ConnectionState() tls.ConnectionState {
|
||||||
state := c.Conn.ConnectionState()
|
state := c.Conn.ConnectionState()
|
||||||
|
//nolint:staticcheck
|
||||||
return tls.ConnectionState{
|
return tls.ConnectionState{
|
||||||
Version: state.Version,
|
Version: state.Version,
|
||||||
HandshakeComplete: state.HandshakeComplete,
|
HandshakeComplete: state.HandshakeComplete,
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
//go:build android && debug
|
|
||||||
|
|
||||||
package constant
|
|
||||||
|
|
||||||
// TODO: remove after fixed
|
|
||||||
// https://github.com/golang/go/issues/68760
|
|
||||||
|
|
||||||
const FixAndroidStack = true
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
//go:build !(android && debug)
|
|
||||||
|
|
||||||
package constant
|
|
||||||
|
|
||||||
const FixAndroidStack = false
|
|
||||||
@@ -23,6 +23,7 @@ const (
|
|||||||
TypeVLESS = "vless"
|
TypeVLESS = "vless"
|
||||||
TypeTUIC = "tuic"
|
TypeTUIC = "tuic"
|
||||||
TypeHysteria2 = "hysteria2"
|
TypeHysteria2 = "hysteria2"
|
||||||
|
TypeNDIS = "ndis"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -80,6 +81,8 @@ func ProxyDisplayName(proxyType string) string {
|
|||||||
return "Selector"
|
return "Selector"
|
||||||
case TypeURLTest:
|
case TypeURLTest:
|
||||||
return "URLTest"
|
return "URLTest"
|
||||||
|
case TypeNDIS:
|
||||||
|
return "NDIS"
|
||||||
default:
|
default:
|
||||||
return "Unknown"
|
return "Unknown"
|
||||||
}
|
}
|
||||||
|
|||||||
5
debug.go
5
debug.go
@@ -3,7 +3,6 @@ package box
|
|||||||
import (
|
import (
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/common/conntrack"
|
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,9 +25,5 @@ func applyDebugOptions(options option.DebugOptions) {
|
|||||||
}
|
}
|
||||||
if options.MemoryLimit != 0 {
|
if options.MemoryLimit != 0 {
|
||||||
debug.SetMemoryLimit(int64(float64(options.MemoryLimit) / 1.5))
|
debug.SetMemoryLimit(int64(float64(options.MemoryLimit) / 1.5))
|
||||||
conntrack.MemoryLimit = uint64(options.MemoryLimit)
|
|
||||||
}
|
|
||||||
if options.OOMKiller != nil {
|
|
||||||
conntrack.KillerEnabled = *options.OOMKiller
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,26 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
|
#### 1.11.0-beta.20
|
||||||
|
|
||||||
|
* Hysteria2 `ignore_client_bandwidth` behavior update **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
When `up_mbps` and `down_mbps` are set, `ignore_client_bandwidth` instead denies clients from using BBR CC.
|
||||||
|
|
||||||
|
See [Hysteria2](/configuration/inbound/hysteria2/#ignore_client_bandwidth).
|
||||||
|
|
||||||
|
#### 1.11.0-beta.17
|
||||||
|
|
||||||
|
* Add port hopping support for Hysteria2 **1**
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
|
**1**:
|
||||||
|
|
||||||
|
See [Hysteria2](/configuration/outbound/hysteria2/).
|
||||||
|
|
||||||
#### 1.11.0-beta.14
|
#### 1.11.0-beta.14
|
||||||
|
|
||||||
* Allow adding route (exclude) address sets to routes **1**
|
* Allow adding route (exclude) address sets to routes **1**
|
||||||
@@ -24,10 +44,6 @@ See [route_address_set](/configuration/inbound/tun/#route_address_set) and
|
|||||||
* Add `rule-set merge` command
|
* Add `rule-set merge` command
|
||||||
* Fixes and improvements
|
* Fixes and improvements
|
||||||
|
|
||||||
### 1.10.5
|
|
||||||
|
|
||||||
* Fixes and improvements
|
|
||||||
|
|
||||||
#### 1.11.0-beta.3
|
#### 1.11.0-beta.3
|
||||||
|
|
||||||
* Add more masquerade options for hysteria2 **1**
|
* Add more masquerade options for hysteria2 **1**
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ icon: material/alert-decagram
|
|||||||
|
|
||||||
!!! quote "Changes in sing-box 1.11.0"
|
!!! quote "Changes in sing-box 1.11.0"
|
||||||
|
|
||||||
:material-alert: [masquerade](#masquerade)
|
:material-alert: [masquerade](#masquerade)
|
||||||
|
:material-alert: [ignore_client_bandwidth](#ignore_client_bandwidth)
|
||||||
|
|
||||||
### Structure
|
### Structure
|
||||||
|
|
||||||
@@ -75,9 +76,13 @@ Authentication password
|
|||||||
|
|
||||||
#### ignore_client_bandwidth
|
#### ignore_client_bandwidth
|
||||||
|
|
||||||
Commands the client to use the BBR flow control algorithm instead of Hysteria CC.
|
*When `up_mbps` and `down_mbps` are not set*:
|
||||||
|
|
||||||
Conflict with `up_mbps` and `down_mbps`.
|
Commands clients to use the BBR CC instead of Hysteria CC.
|
||||||
|
|
||||||
|
*When `up_mbps` and `down_mbps` are set*:
|
||||||
|
|
||||||
|
Deny clients to use the BBR CC.
|
||||||
|
|
||||||
#### tls
|
#### tls
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ icon: material/alert-decagram
|
|||||||
|
|
||||||
!!! quote "sing-box 1.11.0 中的更改"
|
!!! quote "sing-box 1.11.0 中的更改"
|
||||||
|
|
||||||
:material-alert: [masquerade](#masquerade)
|
:material-alert: [masquerade](#masquerade)
|
||||||
|
:material-alert: [ignore_client_bandwidth](#ignore_client_bandwidth)
|
||||||
|
|
||||||
### 结构
|
### 结构
|
||||||
|
|
||||||
@@ -72,9 +73,13 @@ Hysteria 用户
|
|||||||
|
|
||||||
#### ignore_client_bandwidth
|
#### ignore_client_bandwidth
|
||||||
|
|
||||||
|
*当 `up_mbps` 和 `down_mbps` 未设定时*:
|
||||||
|
|
||||||
命令客户端使用 BBR 拥塞控制算法而不是 Hysteria CC。
|
命令客户端使用 BBR 拥塞控制算法而不是 Hysteria CC。
|
||||||
|
|
||||||
与 `up_mbps` 和 `down_mbps` 冲突。
|
*当 `up_mbps` 和 `down_mbps` 已设定时*:
|
||||||
|
|
||||||
|
禁止客户端使用 BBR 拥塞控制算法。
|
||||||
|
|
||||||
#### tls
|
#### tls
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
---
|
||||||
|
icon: material/new-box
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.11.0"
|
||||||
|
|
||||||
|
:material-plus: [server_ports](#server_ports)
|
||||||
|
:material-plus: [hop_interval](#hop_interval)
|
||||||
|
|
||||||
### Structure
|
### Structure
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -7,6 +16,10 @@
|
|||||||
|
|
||||||
"server": "127.0.0.1",
|
"server": "127.0.0.1",
|
||||||
"server_port": 1080,
|
"server_port": 1080,
|
||||||
|
"server_ports": [
|
||||||
|
"2080:3000"
|
||||||
|
],
|
||||||
|
"hop_interval": "",
|
||||||
"up_mbps": 100,
|
"up_mbps": 100,
|
||||||
"down_mbps": 100,
|
"down_mbps": 100,
|
||||||
"obfs": {
|
"obfs": {
|
||||||
@@ -22,6 +35,10 @@
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!! note ""
|
||||||
|
|
||||||
|
You can ignore the JSON Array [] tag when the content is only one item
|
||||||
|
|
||||||
!!! warning "Difference from official Hysteria2"
|
!!! warning "Difference from official Hysteria2"
|
||||||
|
|
||||||
The official Hysteria2 supports an authentication method called **userpass**,
|
The official Hysteria2 supports an authentication method called **userpass**,
|
||||||
@@ -44,6 +61,24 @@ The server address.
|
|||||||
|
|
||||||
The server port.
|
The server port.
|
||||||
|
|
||||||
|
Ignored if `server_ports` is set.
|
||||||
|
|
||||||
|
#### server_ports
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.11.0"
|
||||||
|
|
||||||
|
Server port range list.
|
||||||
|
|
||||||
|
Conflicts with `server_port`.
|
||||||
|
|
||||||
|
#### hop_interval
|
||||||
|
|
||||||
|
!!! question "Since sing-box 1.11.0"
|
||||||
|
|
||||||
|
Port hopping interval.
|
||||||
|
|
||||||
|
`30s` is used by default.
|
||||||
|
|
||||||
#### up_mbps, down_mbps
|
#### up_mbps, down_mbps
|
||||||
|
|
||||||
Max bandwidth, in Mbps.
|
Max bandwidth, in Mbps.
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
---
|
||||||
|
icon: material/new-box
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.11.0 中的更改"
|
||||||
|
|
||||||
|
:material-plus: [server_ports](#server_ports)
|
||||||
|
:material-plus: [hop_interval](#hop_interval)
|
||||||
|
|
||||||
### 结构
|
### 结构
|
||||||
|
|
||||||
```json
|
```json
|
||||||
@@ -7,6 +16,10 @@
|
|||||||
|
|
||||||
"server": "127.0.0.1",
|
"server": "127.0.0.1",
|
||||||
"server_port": 1080,
|
"server_port": 1080,
|
||||||
|
"server_ports": [
|
||||||
|
"2080:3000"
|
||||||
|
],
|
||||||
|
"hop_interval": "",
|
||||||
"up_mbps": 100,
|
"up_mbps": 100,
|
||||||
"down_mbps": 100,
|
"down_mbps": 100,
|
||||||
"obfs": {
|
"obfs": {
|
||||||
@@ -22,6 +35,10 @@
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
!!! note ""
|
||||||
|
|
||||||
|
当内容只有一项时,可以忽略 JSON 数组 [] 标签
|
||||||
|
|
||||||
!!! warning "与官方 Hysteria2 的区别"
|
!!! warning "与官方 Hysteria2 的区别"
|
||||||
|
|
||||||
官方程序支持一种名为 **userpass** 的验证方式,
|
官方程序支持一种名为 **userpass** 的验证方式,
|
||||||
@@ -42,6 +59,24 @@
|
|||||||
|
|
||||||
服务器端口。
|
服务器端口。
|
||||||
|
|
||||||
|
如果设置了 `server_ports`,则忽略此项。
|
||||||
|
|
||||||
|
#### server_ports
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.11.0 起"
|
||||||
|
|
||||||
|
服务器端口范围列表。
|
||||||
|
|
||||||
|
与 `server_port` 冲突。
|
||||||
|
|
||||||
|
#### hop_interval
|
||||||
|
|
||||||
|
!!! question "自 sing-box 1.11.0 起"
|
||||||
|
|
||||||
|
端口跳跃间隔。
|
||||||
|
|
||||||
|
默认使用 `30s`。
|
||||||
|
|
||||||
#### up_mbps, down_mbps
|
#### up_mbps, down_mbps
|
||||||
|
|
||||||
最大带宽。
|
最大带宽。
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
)
|
)
|
||||||
@@ -114,7 +113,7 @@ func (c *CommandClient) Connect() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if C.FixAndroidStack {
|
if sFixAndroidStack {
|
||||||
go func() {
|
go func() {
|
||||||
c.handler.Connected()
|
c.handler.Connected()
|
||||||
c.handler.InitializeClashMode(newIterator(modeList), currentMode)
|
c.handler.InitializeClashMode(newIterator(modeList), currentMode)
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
runtimeDebug "runtime/debug"
|
runtimeDebug "runtime/debug"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/common/conntrack"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *CommandClient) CloseConnections() error {
|
func (c *CommandClient) CloseConnections() error {
|
||||||
@@ -19,7 +17,7 @@ func (c *CommandClient) CloseConnections() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleCloseConnections(conn net.Conn) error {
|
func (s *CommandServer) handleCloseConnections(conn net.Conn) error {
|
||||||
conntrack.Close()
|
tracker.Close()
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
runtimeDebug.FreeOSMemory()
|
runtimeDebug.FreeOSMemory()
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"runtime"
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/common/conntrack"
|
|
||||||
"github.com/sagernet/sing-box/experimental/clashapi"
|
"github.com/sagernet/sing-box/experimental/clashapi"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
"github.com/sagernet/sing/common/memory"
|
"github.com/sagernet/sing/common/memory"
|
||||||
@@ -28,7 +27,7 @@ func (s *CommandServer) readStatus() StatusMessage {
|
|||||||
var message StatusMessage
|
var message StatusMessage
|
||||||
message.Memory = int64(memory.Inuse())
|
message.Memory = int64(memory.Inuse())
|
||||||
message.Goroutines = int32(runtime.NumGoroutine())
|
message.Goroutines = int32(runtime.NumGoroutine())
|
||||||
message.ConnectionsOut = int32(conntrack.Count())
|
message.ConnectionsOut = int32(tracker.Count())
|
||||||
|
|
||||||
if s.service != nil {
|
if s.service != nil {
|
||||||
message.TrafficAvailable = true
|
message.TrafficAvailable = true
|
||||||
|
|||||||
@@ -82,10 +82,6 @@ func (s *platformInterfaceStub) Interfaces() ([]adapter.NetworkInterface, error)
|
|||||||
return nil, os.ErrInvalid
|
return nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *platformInterfaceStub) SetUnderlyingNetworks(networks []adapter.NetworkInterface) error {
|
|
||||||
return os.ErrInvalid
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *platformInterfaceStub) UnderNetworkExtension() bool {
|
func (s *platformInterfaceStub) UnderNetworkExtension() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,21 @@ import (
|
|||||||
"github.com/sagernet/sing-box/common/conntrack"
|
"github.com/sagernet/sing-box/common/conntrack"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var tracker *conntrack.DefaultTracker
|
||||||
|
|
||||||
func SetMemoryLimit(enabled bool) {
|
func SetMemoryLimit(enabled bool) {
|
||||||
|
if tracker != nil {
|
||||||
|
tracker.Close()
|
||||||
|
}
|
||||||
const memoryLimit = 45 * 1024 * 1024
|
const memoryLimit = 45 * 1024 * 1024
|
||||||
const memoryLimitGo = memoryLimit / 1.5
|
const memoryLimitGo = memoryLimit / 1.5
|
||||||
if enabled {
|
if enabled {
|
||||||
runtimeDebug.SetGCPercent(10)
|
runtimeDebug.SetGCPercent(10)
|
||||||
runtimeDebug.SetMemoryLimit(memoryLimitGo)
|
runtimeDebug.SetMemoryLimit(memoryLimitGo)
|
||||||
conntrack.KillerEnabled = true
|
tracker = conntrack.NewDefaultTracker(true, memoryLimit)
|
||||||
conntrack.MemoryLimit = memoryLimit
|
|
||||||
} else {
|
} else {
|
||||||
runtimeDebug.SetGCPercent(100)
|
runtimeDebug.SetGCPercent(100)
|
||||||
runtimeDebug.SetMemoryLimit(math.MaxInt64)
|
runtimeDebug.SetMemoryLimit(math.MaxInt64)
|
||||||
conntrack.KillerEnabled = false
|
tracker = conntrack.NewDefaultTracker(false, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package libbox
|
package libbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
C "github.com/sagernet/sing-box/constant"
|
|
||||||
"github.com/sagernet/sing-tun"
|
"github.com/sagernet/sing-tun"
|
||||||
"github.com/sagernet/sing/common/control"
|
"github.com/sagernet/sing/common/control"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
@@ -56,7 +55,7 @@ func (m *platformDefaultInterfaceMonitor) UnregisterCallback(element *list.Eleme
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32, isExpensive bool, isConstrained bool) {
|
func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32, isExpensive bool, isConstrained bool) {
|
||||||
if C.FixAndroidStack {
|
if sFixAndroidStack {
|
||||||
go m.updateDefaultInterface(interfaceName, interfaceIndex32, isExpensive, isConstrained)
|
go m.updateDefaultInterface(interfaceName, interfaceIndex32, isExpensive, isConstrained)
|
||||||
} else {
|
} else {
|
||||||
m.updateDefaultInterface(interfaceName, interfaceIndex32, isExpensive, isConstrained)
|
m.updateDefaultInterface(interfaceName, interfaceIndex32, isExpensive, isConstrained)
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ type PlatformInterface interface {
|
|||||||
StartDefaultInterfaceMonitor(listener InterfaceUpdateListener) error
|
StartDefaultInterfaceMonitor(listener InterfaceUpdateListener) error
|
||||||
CloseDefaultInterfaceMonitor(listener InterfaceUpdateListener) error
|
CloseDefaultInterfaceMonitor(listener InterfaceUpdateListener) error
|
||||||
GetInterfaces() (NetworkInterfaceIterator, error)
|
GetInterfaces() (NetworkInterfaceIterator, error)
|
||||||
SetUnderlyingNetworks(networks RawNetworkIterator) error
|
|
||||||
UnderNetworkExtension() bool
|
UnderNetworkExtension() bool
|
||||||
IncludeAllNetworks() bool
|
IncludeAllNetworks() bool
|
||||||
ReadWIFIState() *WIFIState
|
ReadWIFIState() *WIFIState
|
||||||
@@ -52,8 +51,6 @@ type NetworkInterface struct {
|
|||||||
Type int32
|
Type int32
|
||||||
DNSServer StringIterator
|
DNSServer StringIterator
|
||||||
Metered bool
|
Metered bool
|
||||||
|
|
||||||
RawNetwork RawNetwork
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type WIFIState struct {
|
type WIFIState struct {
|
||||||
@@ -70,11 +67,6 @@ type NetworkInterfaceIterator interface {
|
|||||||
HasNext() bool
|
HasNext() bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type RawNetworkIterator interface {
|
|
||||||
Next() RawNetwork
|
|
||||||
HasNext() bool
|
|
||||||
}
|
|
||||||
|
|
||||||
type Notification struct {
|
type Notification struct {
|
||||||
Identifier string
|
Identifier string
|
||||||
TypeName string
|
TypeName string
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ type Interface interface {
|
|||||||
UpdateRouteOptions(options *tun.Options, platformOptions option.TunPlatformOptions) error
|
UpdateRouteOptions(options *tun.Options, platformOptions option.TunPlatformOptions) error
|
||||||
CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor
|
CreateDefaultInterfaceMonitor(logger logger.Logger) tun.DefaultInterfaceMonitor
|
||||||
Interfaces() ([]adapter.NetworkInterface, error)
|
Interfaces() ([]adapter.NetworkInterface, error)
|
||||||
SetUnderlyingNetworks(networks []adapter.NetworkInterface) error
|
|
||||||
UnderNetworkExtension() bool
|
UnderNetworkExtension() bool
|
||||||
IncludeAllNetworks() bool
|
IncludeAllNetworks() bool
|
||||||
ClearDNSCache()
|
ClearDNSCache()
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
package libbox
|
|
||||||
|
|
||||||
type RawNetwork interface{}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
//go:build !android
|
|
||||||
|
|
||||||
package libbox
|
|
||||||
|
|
||||||
type RawNetwork interface {
|
|
||||||
stub()
|
|
||||||
}
|
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/sagernet/sing-box"
|
"github.com/sagernet/sing-box"
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"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/process"
|
||||||
"github.com/sagernet/sing-box/common/urltest"
|
"github.com/sagernet/sing-box/common/urltest"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
@@ -60,6 +61,7 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
|
|||||||
useProcFS: platformInterface.UseProcFS(),
|
useProcFS: platformInterface.UseProcFS(),
|
||||||
}
|
}
|
||||||
service.MustRegister[platform.Interface](ctx, platformWrapper)
|
service.MustRegister[platform.Interface](ctx, platformWrapper)
|
||||||
|
service.MustRegister[conntrack.Tracker](ctx, tracker)
|
||||||
instance, err := box.New(box.Options{
|
instance, err := box.New(box.Options{
|
||||||
Context: ctx,
|
Context: ctx,
|
||||||
Options: options,
|
Options: options,
|
||||||
@@ -81,7 +83,7 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *BoxService) Start() error {
|
func (s *BoxService) Start() error {
|
||||||
if C.FixAndroidStack {
|
if sFixAndroidStack {
|
||||||
var err error
|
var err error
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
go func() {
|
go func() {
|
||||||
@@ -220,18 +222,11 @@ func (w *platformInterfaceWrapper) Interfaces() ([]adapter.NetworkInterface, err
|
|||||||
DNSServers: iteratorToArray[string](netInterface.DNSServer),
|
DNSServers: iteratorToArray[string](netInterface.DNSServer),
|
||||||
Expensive: netInterface.Metered || isDefault && w.isExpensive,
|
Expensive: netInterface.Metered || isDefault && w.isExpensive,
|
||||||
Constrained: isDefault && w.isConstrained,
|
Constrained: isDefault && w.isConstrained,
|
||||||
RawNetwork: netInterface.RawNetwork,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return interfaces, nil
|
return interfaces, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *platformInterfaceWrapper) SetUnderlyingNetworks(networks []adapter.NetworkInterface) error {
|
|
||||||
return w.iif.SetUnderlyingNetworks(newIterator(common.Map(networks, func(it adapter.NetworkInterface) RawNetwork {
|
|
||||||
return it.RawNetwork.(RawNetwork)
|
|
||||||
})))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *platformInterfaceWrapper) UnderNetworkExtension() bool {
|
func (w *platformInterfaceWrapper) UnderNetworkExtension() bool {
|
||||||
return w.iif.UnderNetworkExtension()
|
return w.iif.UnderNetworkExtension()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,43 +14,55 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
sBasePath string
|
sBasePath string
|
||||||
sWorkingPath string
|
sWorkingPath string
|
||||||
sTempPath string
|
sTempPath string
|
||||||
sUserID int
|
sUserID int
|
||||||
sGroupID int
|
sGroupID int
|
||||||
sTVOS bool
|
sTVOS bool
|
||||||
|
sFixAndroidStack bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
debug.SetPanicOnFault(true)
|
debug.SetPanicOnFault(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setup(basePath string, workingPath string, tempPath string, isTVOS bool) {
|
type SetupOptions struct {
|
||||||
sBasePath = basePath
|
BasePath string
|
||||||
sWorkingPath = workingPath
|
WorkingPath string
|
||||||
sTempPath = tempPath
|
TempPath string
|
||||||
sUserID = os.Getuid()
|
Username string
|
||||||
sGroupID = os.Getgid()
|
IsTVOS bool
|
||||||
sTVOS = isTVOS
|
FixAndroidStack bool
|
||||||
os.MkdirAll(sWorkingPath, 0o777)
|
|
||||||
os.MkdirAll(sTempPath, 0o777)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetupWithUsername(basePath string, workingPath string, tempPath string, username string) error {
|
func Setup(options *SetupOptions) error {
|
||||||
sBasePath = basePath
|
sBasePath = options.BasePath
|
||||||
sWorkingPath = workingPath
|
sWorkingPath = options.WorkingPath
|
||||||
sTempPath = tempPath
|
sTempPath = options.TempPath
|
||||||
sUser, err := user.Lookup(username)
|
if options.Username != "" {
|
||||||
if err != nil {
|
sUser, err := user.Lookup(options.Username)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
sUserID, _ = strconv.Atoi(sUser.Uid)
|
||||||
|
sGroupID, _ = strconv.Atoi(sUser.Gid)
|
||||||
|
} else {
|
||||||
|
sUserID = os.Getuid()
|
||||||
|
sGroupID = os.Getgid()
|
||||||
}
|
}
|
||||||
sUserID, _ = strconv.Atoi(sUser.Uid)
|
sTVOS = options.IsTVOS
|
||||||
sGroupID, _ = strconv.Atoi(sUser.Gid)
|
|
||||||
|
// TODO: remove after fixed
|
||||||
|
// https://github.com/golang/go/issues/68760
|
||||||
|
sFixAndroidStack = options.FixAndroidStack
|
||||||
|
|
||||||
os.MkdirAll(sWorkingPath, 0o777)
|
os.MkdirAll(sWorkingPath, 0o777)
|
||||||
os.MkdirAll(sTempPath, 0o777)
|
os.MkdirAll(sTempPath, 0o777)
|
||||||
os.Chown(sWorkingPath, sUserID, sGroupID)
|
if options.Username != "" {
|
||||||
os.Chown(sTempPath, sUserID, sGroupID)
|
os.Chown(sWorkingPath, sUserID, sGroupID)
|
||||||
|
os.Chown(sTempPath, sUserID, sGroupID)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
209
go.mod
209
go.mod
@@ -1,104 +1,105 @@
|
|||||||
module github.com/sagernet/sing-box
|
module github.com/sagernet/sing-box
|
||||||
|
|
||||||
go 1.20
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/caddyserver/certmagic v0.20.0
|
github.com/caddyserver/certmagic v0.20.0
|
||||||
github.com/cloudflare/circl v1.3.7
|
github.com/cloudflare/circl v1.3.7
|
||||||
github.com/cretz/bine v0.2.0
|
github.com/cretz/bine v0.2.0
|
||||||
github.com/go-chi/chi/v5 v5.1.0
|
github.com/go-chi/chi/v5 v5.1.0
|
||||||
github.com/go-chi/render v1.0.3
|
github.com/go-chi/render v1.0.3
|
||||||
github.com/gofrs/uuid/v5 v5.3.0
|
github.com/gofrs/uuid/v5 v5.3.0
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
|
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
|
||||||
github.com/libdns/alidns v1.0.3
|
github.com/libdns/alidns v1.0.3
|
||||||
github.com/libdns/cloudflare v0.1.1
|
github.com/libdns/cloudflare v0.1.1
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa
|
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa
|
||||||
github.com/mholt/acmez v1.2.0
|
github.com/mholt/acmez v1.2.0
|
||||||
github.com/miekg/dns v1.1.62
|
github.com/miekg/dns v1.1.62
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0
|
github.com/oschwald/maxminddb-golang v1.12.0
|
||||||
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1
|
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1
|
||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
||||||
github.com/sagernet/cors v1.2.1
|
github.com/sagernet/cors v1.2.1
|
||||||
github.com/sagernet/fswatch v0.1.1
|
github.com/sagernet/fswatch v0.1.1
|
||||||
github.com/sagernet/gomobile v0.1.4
|
github.com/sagernet/gomobile v0.1.4
|
||||||
github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff
|
github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff
|
||||||
github.com/sagernet/quic-go v0.48.2-beta.1
|
github.com/sagernet/quic-go v0.48.2-beta.1
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||||
github.com/sagernet/sing v0.6.0-beta.8
|
github.com/sagernet/sing v0.6.0-beta.9
|
||||||
github.com/sagernet/sing-dns v0.4.0-beta.1
|
github.com/sagernet/sing-dns v0.4.0-beta.1
|
||||||
github.com/sagernet/sing-mux v0.3.0-alpha.1
|
github.com/sagernet/sing-mux v0.3.0-alpha.1
|
||||||
github.com/sagernet/sing-quic v0.4.0-alpha.4
|
github.com/sagernet/sing-quic v0.4.0-beta.3
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2
|
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2
|
||||||
github.com/sagernet/sing-tun v0.6.0-beta.7
|
github.com/sagernet/sing-tun v0.6.0-beta.7
|
||||||
github.com/sagernet/sing-vmess v0.2.0-beta.1
|
github.com/sagernet/sing-vmess v0.2.0-beta.2
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||||
github.com/sagernet/utls v1.6.7
|
github.com/sagernet/utls v1.6.7
|
||||||
github.com/sagernet/wireguard-go v0.0.1-beta.5
|
github.com/sagernet/wireguard-go v0.0.1-beta.5
|
||||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
||||||
github.com/spf13/cobra v1.8.1
|
github.com/spf13/cobra v1.8.1
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
go.uber.org/zap v1.27.0
|
github.com/wiresock/ndisapi-go v0.0.0-20241230094942-3299a7566e08
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go.uber.org/zap v1.27.0
|
||||||
golang.org/x/crypto v0.29.0
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
golang.org/x/crypto v0.31.0
|
||||||
golang.org/x/mod v0.20.0
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||||
golang.org/x/net v0.31.0
|
golang.org/x/mod v0.20.0
|
||||||
golang.org/x/sys v0.27.0
|
golang.org/x/net v0.31.0
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
golang.org/x/sys v0.28.0
|
||||||
google.golang.org/grpc v1.63.2
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||||
google.golang.org/protobuf v1.33.0
|
google.golang.org/grpc v1.63.2
|
||||||
howett.net/plist v1.0.1
|
google.golang.org/protobuf v1.33.0
|
||||||
)
|
howett.net/plist v1.0.1
|
||||||
|
)
|
||||||
//replace github.com/sagernet/sing => ../sing
|
|
||||||
|
//replace github.com/sagernet/sing => ../sing
|
||||||
require (
|
|
||||||
github.com/ajg/form v1.5.1 // indirect
|
require (
|
||||||
github.com/andybalholm/brotli v1.0.6 // indirect
|
github.com/ajg/form v1.5.1 // indirect
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
github.com/andybalholm/brotli v1.0.6 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/gobwas/httphead v0.1.0 // indirect
|
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||||
github.com/gobwas/pool v0.2.1 // indirect
|
github.com/gobwas/httphead v0.1.0 // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/gobwas/pool v0.2.1 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||||
github.com/josharian/native v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.4 // indirect
|
github.com/josharian/native v1.1.0 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
github.com/klauspost/compress v1.17.4 // indirect
|
||||||
github.com/libdns/libdns v0.2.2 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
github.com/libdns/libdns v0.2.2 // indirect
|
||||||
github.com/mdlayher/socket v0.4.1 // indirect
|
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
github.com/mdlayher/socket v0.4.1 // indirect
|
||||||
github.com/onsi/ginkgo/v2 v2.9.7 // indirect
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
github.com/onsi/ginkgo/v2 v2.9.7 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||||
github.com/quic-go/qpack v0.4.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
github.com/quic-go/qpack v0.4.0 // indirect
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||||
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/sagernet/nftables v0.3.0-beta.4 // indirect
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/vishvananda/netns v0.0.4 // indirect
|
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect
|
||||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
github.com/vishvananda/netns v0.0.4 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||||
golang.org/x/sync v0.9.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
golang.org/x/text v0.20.0 // indirect
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
golang.org/x/tools v0.24.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.org/x/tools v0.24.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
lukechampine.com/blake3 v1.3.0 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
lukechampine.com/blake3 v1.3.0 // indirect
|
||||||
|
)
|
||||||
|
|||||||
461
go.sum
461
go.sum
@@ -1,229 +1,232 @@
|
|||||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
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 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
|
||||||
github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
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 h1:bTw7LcEZAh9ucYCRXyCpIrSAGplplI0vGYJ4BpCQ/Fc=
|
||||||
github.com/caddyserver/certmagic v0.20.0/go.mod h1:N4sXgpICQUskEWpj7zVzvWD41p3NYacrNoZYiRM2jTg=
|
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 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
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 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
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/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 h1:8GiDRGlTgz+o8H9DSnsl+5MeBK4HsExxgl6WgzOCuZo=
|
||||||
github.com/cretz/bine v0.2.0/go.mod h1:WU4o9QR9wWp8AVKtTM1XD5vUHkEqnf2vVSo6dBqbetI=
|
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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:CaO/zOnF8VvUfEbhRatPcwKVWamvbYd8tQGRWacE9kU=
|
||||||
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
|
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 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
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 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||||
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
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 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
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-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 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
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 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
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 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
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 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
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 h1:m0mUMr+oVYUdxpMLgSYCZiXe7PuVPnI94+OMeVBNedk=
|
||||||
github.com/gofrs/uuid/v5 v5.3.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8=
|
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/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
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/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.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 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
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 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
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 h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
|
||||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
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 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
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 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
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 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA=
|
||||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
|
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/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.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 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA=
|
||||||
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
|
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 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
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.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 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
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/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.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
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 h1:LFHuGnbseq5+HCeGa1aW8awyX/4M2psB9962fdD2+yQ=
|
||||||
github.com/libdns/alidns v1.0.3/go.mod h1:e18uAG6GanfRhcJj6/tps2rCMzQJaYVcGKT+ELjdjGE=
|
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 h1:FVPfWwP8zZCqj268LZjmkDleXlHPlFU9KC4OJ3yn054=
|
||||||
github.com/libdns/cloudflare v0.1.1/go.mod h1:9VK91idpOjg6v7/WbjkEW49bSCxj00ALesIFDhJ8PBU=
|
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.0/go.mod h1:yQCXzk1lEZmmCPa857bnk4TsOiqYasqpyOEeSObbb40=
|
||||||
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
github.com/libdns/libdns v0.2.2 h1:O6ws7bAfRPaBsgAYt8MDe2HcNBGC29hkZ9MX2eUSX3s=
|
||||||
github.com/libdns/libdns v0.2.2/go.mod h1:4Bj9+5CQiNMVGf87wjX4CY3HQJypUHRuLvlsfsZqLWQ=
|
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 h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
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 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g=
|
||||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
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 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
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 h1:9mcjV+RGZVC3reJBNDjjNPyS8PmFG97zq56X7WNaFO4=
|
||||||
github.com/metacubex/tfo-go v0.0.0-20241006021335-daedaf0ca7aa/go.mod h1:4tLB5c8U0CxpkFM+AJJB77jEaVDbLH5XQvy42vAGsWw=
|
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 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
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 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
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 h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
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 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
|
||||||
github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
|
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/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 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
||||||
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
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 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
||||||
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
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 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
||||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
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/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 h1:qi+ijeREa0yfAaO+NOcZ81gv4uzOfALUIdhkiIFvmG4=
|
||||||
github.com/sagernet/asc-go v0.0.0-20241217030726-d563060fe4e1/go.mod h1:JULDuzTMn2gyZFcjpTVZP4/UuwAdbHJ0bum2RdjXojU=
|
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 h1:+NkI2670SQpQWvkkD2QgdTuzQG263YZ+2emfpeyGqW0=
|
||||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
|
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 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY=
|
||||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k=
|
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 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
|
||||||
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
|
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 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
|
||||||
github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
|
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 h1:WzX9ka+iHdupMgy2Vdich+OAt7TM8C2cZbIbzNjBrJY=
|
||||||
github.com/sagernet/gomobile v0.1.4/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
|
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 h1:mlohw3360Wg1BNGook/UHnISXhUx4Gd/3tVLs5T0nSs=
|
||||||
github.com/sagernet/gvisor v0.0.0-20241123041152-536d05261cff/go.mod h1:ehZwnT2UpmOWAHFL48XdBhnd4Qu4hN2O3Ji0us3ZHMw=
|
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 h1:ObwtHN2VpqE0ZNjr6sGeT00J8uU7JF4cNUdb44/Duis=
|
||||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
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 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
|
||||||
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
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 h1:W0plrLWa1XtOWDTdX3CJwxmQuxkya12nN5BRGZ87kEg=
|
||||||
github.com/sagernet/quic-go v0.48.2-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/+or9YMLaG5VeTk4k=
|
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 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
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.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||||
github.com/sagernet/sing v0.6.0-beta.8 h1:PoxDdN7y8D4oImT3cQ05Sq1ZYnYsJberkUkIEHIGwWE=
|
github.com/sagernet/sing v0.6.0-beta.9 h1:P8lKa5hN53fRNAVCIKy5cWd6/kLO5c4slhdsfehSmHs=
|
||||||
github.com/sagernet/sing v0.6.0-beta.8/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
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 h1:W1XkdhigwxDOMgMDVB+9kdomCpb7ExsZfB4acPcTZFY=
|
||||||
github.com/sagernet/sing-dns v0.4.0-beta.1/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8=
|
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 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-mux v0.3.0-alpha.1/go.mod h1:FTcImmdfW38Lz7b+HQ+mxxOth1lz4ao8uEnz+MwIJQE=
|
||||||
github.com/sagernet/sing-quic v0.4.0-alpha.4 h1:P9xAx3nIfcqb9M8jfgs0uLm+VxCcaY++FCqaBfHY3dQ=
|
github.com/sagernet/sing-quic v0.4.0-beta.3 h1:cOBjlhVdRZmBm6hIw1GleERpnTSFdBB2htgx5kQ5uqg=
|
||||||
github.com/sagernet/sing-quic v0.4.0-alpha.4/go.mod h1:h5RkKTmUhudJKzK7c87FPXD5w1bJjVyxMN9+opZcctA=
|
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 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
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 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
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 h1:RPrpgAdkP5td0vLfS5ldvYosFjSsZtRPxiyLV6jyKg0=
|
||||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2/go.mod h1:0j5XlzKxaWRIEjc1uiSKmVoWb0k+L9QgZVb876+thZA=
|
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 h1:FCSX8oGBqb0H57AAvfGeeH/jMGYWCOg6XWkN/oeES+0=
|
||||||
github.com/sagernet/sing-tun v0.6.0-beta.7/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
github.com/sagernet/sing-tun v0.6.0-beta.7/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||||
github.com/sagernet/sing-vmess v0.2.0-beta.1 h1:5sXQ23uwNlZuDvygzi0dFtnG0Csm/SNqTjAHXJkpuj4=
|
github.com/sagernet/sing-vmess v0.2.0-beta.2 h1:obAkAL35X7ql4RnGzDg4dBYIRpGXRKqcN4LyLZpZGSs=
|
||||||
github.com/sagernet/sing-vmess v0.2.0-beta.1/go.mod h1:fLyE1emIcvQ5DV8reFWnufquZ7MkCSYM5ThodsR9NrQ=
|
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 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
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 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8=
|
||||||
github.com/sagernet/utls v1.6.7/go.mod h1:Uua1TKO/FFuAhLr9rkaVnnrTmmiItzDjv1BUb2+ERwM=
|
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 h1:aBEsxJUMEONwOZqKPIkuAcv4zJV5p6XlzEN04CF0FXc=
|
||||||
github.com/sagernet/wireguard-go v0.0.1-beta.5/go.mod h1:jGXij2Gn2wbrWuYNUmmNhf1dwcZtvyAvQoe8Xd8MbUo=
|
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 h1:6uUiZcDRnZSAegryaUGwPC/Fj13JSHwiTftrXhMmYOc=
|
||||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854/go.mod h1:LtfoSK3+NG57tvnVEHgcuBW9ujgE8enPSgzgwStwCAA=
|
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 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
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 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
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/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.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.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 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
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 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA=
|
||||||
github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
|
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 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||||
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
github.com/wiresock/ndisapi-go v0.0.0-20241230094942-3299a7566e08 h1:is+7xN6CAKtgxt3mDSl9OQNvjfi6LggugSP07QhDtws=
|
||||||
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
github.com/wiresock/ndisapi-go v0.0.0-20241230094942-3299a7566e08/go.mod h1:lFE7JYt3LC2UYJ31mRDwl/K35pbtxDnkSDlXrYzgyqg=
|
||||||
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
github.com/zeebo/assert v1.1.0 h1:hU1L1vLTHsnO8x8c9KAR5GmM5QscxHg5RNU5z5qbUWY=
|
||||||
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
github.com/zeebo/assert v1.1.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||||
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
github.com/zeebo/blake3 v0.2.3 h1:TFoLXsjeXqRNFxSbk35Dk4YtszE/MQQGK10BH4ptoTg=
|
||||||
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
github.com/zeebo/blake3 v0.2.3/go.mod h1:mjJjZpnsyIVtVgTOSpJ9vmRE4wgDeyt2HU3qXvvKCaQ=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
github.com/zeebo/pcg v1.0.1 h1:lyqfGeWiv4ahac6ttHs+I5hwtH/+1mrhlCtVNQM2kHo=
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
github.com/zeebo/pcg v1.0.1/go.mod h1:09F0S9iiKrwn9rlI5yjLkmrug154/YRW6KnnXVDM/l4=
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||||
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo=
|
||||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
golang.org/x/time v0.7.0 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6 h1:CawjfCvYQH2OU3/TnxLx97WDSUDRABfT18pCOYwc2GE=
|
||||||
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6/go.mod h1:3rxYc4HtVcSG9gVaTs2GEBdehh+sYPOwKtyUWEOTb80=
|
||||||
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
|
||||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
|
||||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||||
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
|
||||||
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
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=
|
||||||
|
|||||||
12
include/ndis.go
Normal file
12
include/ndis.go
Normal file
@@ -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)
|
||||||
|
}
|
||||||
20
include/ndis_nongvisor_stub.go
Normal file
20
include/ndis_nongvisor_stub.go
Normal file
@@ -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
|
||||||
|
})
|
||||||
|
}
|
||||||
20
include/ndis_nonwindows_stub.go
Normal file
20
include/ndis_nonwindows_stub.go
Normal file
@@ -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")
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -51,6 +51,7 @@ func InboundRegistry() *inbound.Registry {
|
|||||||
|
|
||||||
registerQUICInbounds(registry)
|
registerQUICInbounds(registry)
|
||||||
registerStubForRemovedInbounds(registry)
|
registerStubForRemovedInbounds(registry)
|
||||||
|
registerNDISInbound(registry)
|
||||||
|
|
||||||
return registry
|
return registry
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type DebugOptions struct {
|
|||||||
PanicOnFault *bool `json:"panic_on_fault,omitempty"`
|
PanicOnFault *bool `json:"panic_on_fault,omitempty"`
|
||||||
TraceBack string `json:"trace_back,omitempty"`
|
TraceBack string `json:"trace_back,omitempty"`
|
||||||
MemoryLimit MemoryBytes `json:"memory_limit,omitempty"`
|
MemoryLimit MemoryBytes `json:"memory_limit,omitempty"`
|
||||||
OOMKiller *bool `json:"oom_killer,omitempty"`
|
OOMKiller bool `json:"oom_killer,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type MemoryBytes uint64
|
type MemoryBytes uint64
|
||||||
|
|||||||
@@ -111,11 +111,13 @@ type Hysteria2MasqueradeString struct {
|
|||||||
type Hysteria2OutboundOptions struct {
|
type Hysteria2OutboundOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
ServerOptions
|
ServerOptions
|
||||||
UpMbps int `json:"up_mbps,omitempty"`
|
ServerPorts badoption.Listable[string] `json:"server_ports,omitempty"`
|
||||||
DownMbps int `json:"down_mbps,omitempty"`
|
HopInterval badoption.Duration `json:"hop_interval,omitempty"`
|
||||||
Obfs *Hysteria2Obfs `json:"obfs,omitempty"`
|
UpMbps int `json:"up_mbps,omitempty"`
|
||||||
Password string `json:"password,omitempty"`
|
DownMbps int `json:"down_mbps,omitempty"`
|
||||||
Network NetworkList `json:"network,omitempty"`
|
Obfs *Hysteria2Obfs `json:"obfs,omitempty"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
Network NetworkList `json:"network,omitempty"`
|
||||||
OutboundTLSOptionsContainer
|
OutboundTLSOptionsContainer
|
||||||
BrutalDebug bool `json:"brutal_debug,omitempty"`
|
BrutalDebug bool `json:"brutal_debug,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
17
option/ndis.go
Normal file
17
option/ndis.go
Normal file
@@ -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"`
|
||||||
|
}
|
||||||
@@ -67,7 +67,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
|||||||
if len(options.Down) > 0 {
|
if len(options.Down) > 0 {
|
||||||
receiveBps, err = humanize.ParseBytes(options.Down)
|
receiveBps, err = humanize.ParseBytes(options.Down)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, E.New("invalid down speed format: ", options.Down)
|
return nil, E.Cause(err, "invalid down speed format: ", options.Down)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
receiveBps = uint64(options.DownMbps) * hysteria.MbpsToBps
|
receiveBps = uint64(options.DownMbps) * hysteria.MbpsToBps
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/adapter/outbound"
|
"github.com/sagernet/sing-box/adapter/outbound"
|
||||||
@@ -70,6 +71,8 @@ func NewOutbound(ctx context.Context, router adapter.Router, logger log.ContextL
|
|||||||
Logger: logger,
|
Logger: logger,
|
||||||
BrutalDebug: options.BrutalDebug,
|
BrutalDebug: options.BrutalDebug,
|
||||||
ServerAddress: options.ServerOptions.Build(),
|
ServerAddress: options.ServerOptions.Build(),
|
||||||
|
ServerPorts: options.ServerPorts,
|
||||||
|
HopInterval: time.Duration(options.HopInterval),
|
||||||
SendBPS: uint64(options.UpMbps * hysteria.MbpsToBps),
|
SendBPS: uint64(options.UpMbps * hysteria.MbpsToBps),
|
||||||
ReceiveBPS: uint64(options.DownMbps * hysteria.MbpsToBps),
|
ReceiveBPS: uint64(options.DownMbps * hysteria.MbpsToBps),
|
||||||
SalamanderPassword: salamanderPassword,
|
SalamanderPassword: salamanderPassword,
|
||||||
|
|||||||
110
protocol/ndis/endpoint.go
Normal file
110
protocol/ndis/endpoint.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
203
protocol/ndis/inbound.go
Normal file
203
protocol/ndis/inbound.go
Normal file
@@ -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)
|
||||||
|
}
|
||||||
267
protocol/ndis/stack.go
Normal file
267
protocol/ndis/stack.go
Normal file
@@ -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
|
||||||
|
}
|
||||||
@@ -306,7 +306,6 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
|
|||||||
t.tunOptions.Name = tun.CalculateInterfaceName("")
|
t.tunOptions.Name = tun.CalculateInterfaceName("")
|
||||||
}
|
}
|
||||||
if t.platformInterface == nil || runtime.GOOS != "android" {
|
if t.platformInterface == nil || runtime.GOOS != "android" {
|
||||||
t.routeAddressSet = common.FlatMap(t.routeRuleSet, adapter.RuleSet.ExtractIPSet)
|
|
||||||
for _, routeRuleSet := range t.routeRuleSet {
|
for _, routeRuleSet := range t.routeRuleSet {
|
||||||
ipSets := routeRuleSet.ExtractIPSet()
|
ipSets := routeRuleSet.ExtractIPSet()
|
||||||
if len(ipSets) == 0 {
|
if len(ipSets) == 0 {
|
||||||
@@ -316,11 +315,10 @@ func (t *Inbound) Start(stage adapter.StartStage) error {
|
|||||||
routeRuleSet.DecRef()
|
routeRuleSet.DecRef()
|
||||||
t.routeAddressSet = append(t.routeAddressSet, ipSets...)
|
t.routeAddressSet = append(t.routeAddressSet, ipSets...)
|
||||||
}
|
}
|
||||||
t.routeExcludeAddressSet = common.FlatMap(t.routeExcludeRuleSet, adapter.RuleSet.ExtractIPSet)
|
|
||||||
for _, routeExcludeRuleSet := range t.routeExcludeRuleSet {
|
for _, routeExcludeRuleSet := range t.routeExcludeRuleSet {
|
||||||
ipSets := routeExcludeRuleSet.ExtractIPSet()
|
ipSets := routeExcludeRuleSet.ExtractIPSet()
|
||||||
if len(ipSets) == 0 {
|
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))
|
t.routeExcludeRuleSetCallback = append(t.routeExcludeRuleSetCallback, routeExcludeRuleSet.RegisterCallback(t.updateRouteAddressSet))
|
||||||
routeExcludeRuleSet.DecRef()
|
routeExcludeRuleSet.DecRef()
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ var _ adapter.NetworkManager = (*NetworkManager)(nil)
|
|||||||
|
|
||||||
type NetworkManager struct {
|
type NetworkManager struct {
|
||||||
logger logger.ContextLogger
|
logger logger.ContextLogger
|
||||||
|
tracker conntrack.Tracker
|
||||||
interfaceFinder *control.DefaultInterfaceFinder
|
interfaceFinder *control.DefaultInterfaceFinder
|
||||||
networkInterfaces atomic.TypedValue[[]adapter.NetworkInterface]
|
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) {
|
func NewNetworkManager(ctx context.Context, logger logger.ContextLogger, routeOptions option.RouteOptions) (*NetworkManager, error) {
|
||||||
nm := &NetworkManager{
|
nm := &NetworkManager{
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
tracker: service.FromContext[conntrack.Tracker](ctx),
|
||||||
interfaceFinder: control.NewDefaultInterfaceFinder(),
|
interfaceFinder: control.NewDefaultInterfaceFinder(),
|
||||||
autoDetectInterface: routeOptions.AutoDetectInterface,
|
autoDetectInterface: routeOptions.AutoDetectInterface,
|
||||||
defaultOptions: adapter.NetworkOptions{
|
defaultOptions: adapter.NetworkOptions{
|
||||||
@@ -90,9 +92,6 @@ func NewNetworkManager(ctx context.Context, logger logger.ContextLogger, routeOp
|
|||||||
return nil, E.Cause(err, "create network monitor")
|
return nil, E.Cause(err, "create network monitor")
|
||||||
}
|
}
|
||||||
nm.networkMonitor = networkMonitor
|
nm.networkMonitor = networkMonitor
|
||||||
networkMonitor.RegisterCallback(func() {
|
|
||||||
_ = nm.interfaceFinder.Update()
|
|
||||||
})
|
|
||||||
interfaceMonitor, err := tun.NewDefaultInterfaceMonitor(nm.networkMonitor, logger, tun.DefaultInterfaceMonitorOptions{
|
interfaceMonitor, err := tun.NewDefaultInterfaceMonitor(nm.networkMonitor, logger, tun.DefaultInterfaceMonitorOptions{
|
||||||
InterfaceFinder: nm.interfaceFinder,
|
InterfaceFinder: nm.interfaceFinder,
|
||||||
OverrideAndroidVPN: routeOptions.OverrideAndroidVPN,
|
OverrideAndroidVPN: routeOptions.OverrideAndroidVPN,
|
||||||
@@ -240,9 +239,6 @@ func (r *NetworkManager) UpdateInterfaces() error {
|
|||||||
newInterfaces := common.Filter(interfaces, func(it adapter.NetworkInterface) bool {
|
newInterfaces := common.Filter(interfaces, func(it adapter.NetworkInterface) bool {
|
||||||
return it.Flags&net.FlagUp != 0
|
return it.Flags&net.FlagUp != 0
|
||||||
})
|
})
|
||||||
for _, networkInterface := range newInterfaces {
|
|
||||||
networkInterface.RawNetwork = nil
|
|
||||||
}
|
|
||||||
r.networkInterfaces.Store(newInterfaces)
|
r.networkInterfaces.Store(newInterfaces)
|
||||||
if len(newInterfaces) > 0 && !slices.EqualFunc(oldInterfaces, newInterfaces, func(oldInterface adapter.NetworkInterface, newInterface adapter.NetworkInterface) bool {
|
if len(newInterfaces) > 0 && !slices.EqualFunc(oldInterfaces, newInterfaces, func(oldInterface adapter.NetworkInterface, newInterface adapter.NetworkInterface) bool {
|
||||||
return oldInterface.Interface.Index == newInterface.Interface.Index &&
|
return oldInterface.Interface.Index == newInterface.Interface.Index &&
|
||||||
@@ -263,15 +259,6 @@ func (r *NetworkManager) UpdateInterfaces() error {
|
|||||||
}
|
}
|
||||||
return F.ToString(it.Name, " (", strings.Join(options, ", "), ")")
|
return F.ToString(it.Name, " (", strings.Join(options, ", "), ")")
|
||||||
}), ", "))
|
}), ", "))
|
||||||
if C.IsAndroid {
|
|
||||||
err = r.platformInterface.SetUnderlyingNetworks(newInterfaces)
|
|
||||||
if err != nil {
|
|
||||||
r.logger.Error("set underlying networks: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, networkInterface := range interfaces {
|
|
||||||
networkInterface.RawNetwork = nil
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -370,7 +357,7 @@ func (r *NetworkManager) WIFIState() adapter.WIFIState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *NetworkManager) ResetNetwork() {
|
func (r *NetworkManager) ResetNetwork() {
|
||||||
conntrack.Close()
|
r.tracker.Close()
|
||||||
|
|
||||||
for _, endpoint := range r.endpoint.Endpoints() {
|
for _, endpoint := range r.endpoint.Endpoints() {
|
||||||
listener, isListener := endpoint.(adapter.InterfaceUpdateListener)
|
listener, isListener := endpoint.(adapter.InterfaceUpdateListener)
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"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/process"
|
||||||
"github.com/sagernet/sing-box/common/sniff"
|
"github.com/sagernet/sing-box/common/sniff"
|
||||||
C "github.com/sagernet/sing-box/constant"
|
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)
|
injectable.NewConnectionEx(ctx, conn, metadata, onClose)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
conntrack.KillerCheck()
|
err := r.connTracker.KillerCheck()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
metadata.Network = N.NetworkTCP
|
metadata.Network = N.NetworkTCP
|
||||||
switch metadata.Destination.Fqdn {
|
switch metadata.Destination.Fqdn {
|
||||||
case mux.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)
|
injectable.NewPacketConnectionEx(ctx, conn, metadata, onClose)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
conntrack.KillerCheck()
|
err := r.connTracker.KillerCheck()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: move to UoT
|
// TODO: move to UoT
|
||||||
metadata.Network = N.NetworkUDP
|
metadata.Network = N.NetworkUDP
|
||||||
@@ -473,7 +478,7 @@ match:
|
|||||||
}
|
}
|
||||||
if !preMatch && inputPacketConn != nil && !metadata.Destination.IsFqdn() && !metadata.Destination.Addr.IsGlobalUnicast() {
|
if !preMatch && inputPacketConn != nil && !metadata.Destination.IsFqdn() && !metadata.Destination.Addr.IsGlobalUnicast() {
|
||||||
var timeout time.Duration
|
var timeout time.Duration
|
||||||
if metadata.InboundType == C.TypeSOCKS {
|
if metadata.InboundType == C.TypeSOCKS || metadata.InboundType == C.TypeMixed {
|
||||||
timeout = C.TCPTimeout
|
timeout = C.TCPTimeout
|
||||||
}
|
}
|
||||||
newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, &rule.RuleActionSniff{Timeout: timeout}, inputConn, inputPacketConn)
|
newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, &rule.RuleActionSniff{Timeout: timeout}, inputConn, inputPacketConn)
|
||||||
@@ -572,7 +577,7 @@ func (r *Router) actionSniff(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !metadata.Destination.Addr.IsGlobalUnicast() {
|
if !metadata.Destination.IsFqdn() && !metadata.Destination.Addr.IsGlobalUnicast() {
|
||||||
metadata.Destination = destination
|
metadata.Destination = destination
|
||||||
}
|
}
|
||||||
if len(packetBuffers) > 0 {
|
if len(packetBuffers) > 0 {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"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/dialer"
|
||||||
"github.com/sagernet/sing-box/common/geoip"
|
"github.com/sagernet/sing-box/common/geoip"
|
||||||
"github.com/sagernet/sing-box/common/geosite"
|
"github.com/sagernet/sing-box/common/geosite"
|
||||||
@@ -38,6 +39,7 @@ type Router struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
logger log.ContextLogger
|
logger log.ContextLogger
|
||||||
dnsLogger log.ContextLogger
|
dnsLogger log.ContextLogger
|
||||||
|
connTracker conntrack.Tracker
|
||||||
inbound adapter.InboundManager
|
inbound adapter.InboundManager
|
||||||
outbound adapter.OutboundManager
|
outbound adapter.OutboundManager
|
||||||
connection adapter.ConnectionManager
|
connection adapter.ConnectionManager
|
||||||
@@ -75,6 +77,7 @@ func NewRouter(ctx context.Context, logFactory log.Factory, options option.Route
|
|||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
logger: logFactory.NewLogger("router"),
|
logger: logFactory.NewLogger("router"),
|
||||||
dnsLogger: logFactory.NewLogger("dns"),
|
dnsLogger: logFactory.NewLogger("dns"),
|
||||||
|
connTracker: service.FromContext[conntrack.Tracker](ctx),
|
||||||
inbound: service.FromContext[adapter.InboundManager](ctx),
|
inbound: service.FromContext[adapter.InboundManager](ctx),
|
||||||
outbound: service.FromContext[adapter.OutboundManager](ctx),
|
outbound: service.FromContext[adapter.OutboundManager](ctx),
|
||||||
connection: service.FromContext[adapter.ConnectionManager](ctx),
|
connection: service.FromContext[adapter.ConnectionManager](ctx),
|
||||||
|
|||||||
16
test/go.mod
16
test/go.mod
@@ -13,9 +13,9 @@ require (
|
|||||||
github.com/docker/go-connections v0.5.0
|
github.com/docker/go-connections v0.5.0
|
||||||
github.com/gofrs/uuid/v5 v5.3.0
|
github.com/gofrs/uuid/v5 v5.3.0
|
||||||
github.com/sagernet/quic-go v0.48.2-beta.1
|
github.com/sagernet/quic-go v0.48.2-beta.1
|
||||||
github.com/sagernet/sing v0.6.0-beta.5
|
github.com/sagernet/sing v0.6.0-beta.9
|
||||||
github.com/sagernet/sing-dns v0.4.0-beta.1
|
github.com/sagernet/sing-dns v0.4.0-beta.1
|
||||||
github.com/sagernet/sing-quic v0.4.0-alpha.4
|
github.com/sagernet/sing-quic v0.4.0-beta.3
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||||
github.com/spyzhov/ajson v0.9.4
|
github.com/spyzhov/ajson v0.9.4
|
||||||
@@ -85,8 +85,8 @@ require (
|
|||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 // indirect
|
||||||
github.com/sagernet/sing-mux v0.3.0-alpha.1 // indirect
|
github.com/sagernet/sing-mux v0.3.0-alpha.1 // indirect
|
||||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 // indirect
|
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2 // indirect
|
||||||
github.com/sagernet/sing-tun v0.6.0-beta.2 // indirect
|
github.com/sagernet/sing-tun v0.6.0-beta.7 // indirect
|
||||||
github.com/sagernet/sing-vmess v0.2.0-beta.1 // indirect
|
github.com/sagernet/sing-vmess v0.2.0-beta.2 // indirect
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 // indirect
|
||||||
github.com/sagernet/utls v1.6.7 // indirect
|
github.com/sagernet/utls v1.6.7 // indirect
|
||||||
github.com/sagernet/wireguard-go v0.0.1-beta.5 // indirect
|
github.com/sagernet/wireguard-go v0.0.1-beta.5 // indirect
|
||||||
@@ -103,12 +103,12 @@ require (
|
|||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba // indirect
|
||||||
golang.org/x/crypto v0.29.0 // indirect
|
golang.org/x/crypto v0.31.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||||
golang.org/x/mod v0.20.0 // indirect
|
golang.org/x/mod v0.20.0 // indirect
|
||||||
golang.org/x/sync v0.9.0 // indirect
|
golang.org/x/sync v0.10.0 // indirect
|
||||||
golang.org/x/sys v0.27.0 // indirect
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
golang.org/x/text v0.20.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
golang.org/x/time v0.7.0 // indirect
|
golang.org/x/time v0.7.0 // indirect
|
||||||
golang.org/x/tools v0.24.0 // indirect
|
golang.org/x/tools v0.24.0 // indirect
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
|
||||||
|
|||||||
36
test/go.sum
36
test/go.sum
@@ -146,24 +146,24 @@ github.com/sagernet/quic-go v0.48.2-beta.1/go.mod h1:1WgdDIVD1Gybp40JTWketeSfKA/
|
|||||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
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/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.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||||
github.com/sagernet/sing v0.6.0-beta.5 h1:RD2j8WmJsvAbbBkAlJWaiYmnd+v/JohBiweoew7kMwo=
|
github.com/sagernet/sing v0.6.0-beta.9 h1:P8lKa5hN53fRNAVCIKy5cWd6/kLO5c4slhdsfehSmHs=
|
||||||
github.com/sagernet/sing v0.6.0-beta.5/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
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 h1:W1XkdhigwxDOMgMDVB+9kdomCpb7ExsZfB4acPcTZFY=
|
||||||
github.com/sagernet/sing-dns v0.4.0-beta.1/go.mod h1:8wuFcoFkWM4vJuQyg8e97LyvDwe0/Vl7G839WLcKDs8=
|
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 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-mux v0.3.0-alpha.1/go.mod h1:FTcImmdfW38Lz7b+HQ+mxxOth1lz4ao8uEnz+MwIJQE=
|
||||||
github.com/sagernet/sing-quic v0.4.0-alpha.4 h1:P9xAx3nIfcqb9M8jfgs0uLm+VxCcaY++FCqaBfHY3dQ=
|
github.com/sagernet/sing-quic v0.4.0-beta.3 h1:cOBjlhVdRZmBm6hIw1GleERpnTSFdBB2htgx5kQ5uqg=
|
||||||
github.com/sagernet/sing-quic v0.4.0-alpha.4/go.mod h1:h5RkKTmUhudJKzK7c87FPXD5w1bJjVyxMN9+opZcctA=
|
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 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
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 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||||
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
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 h1:RPrpgAdkP5td0vLfS5ldvYosFjSsZtRPxiyLV6jyKg0=
|
||||||
github.com/sagernet/sing-shadowtls v0.2.0-alpha.2/go.mod h1:0j5XlzKxaWRIEjc1uiSKmVoWb0k+L9QgZVb876+thZA=
|
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.2 h1:GK7r2jWKm7RhlJGTq4QadgFcebQia1c3BO3OlYMcQJ0=
|
github.com/sagernet/sing-tun v0.6.0-beta.7 h1:FCSX8oGBqb0H57AAvfGeeH/jMGYWCOg6XWkN/oeES+0=
|
||||||
github.com/sagernet/sing-tun v0.6.0-beta.2/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
github.com/sagernet/sing-tun v0.6.0-beta.7/go.mod h1:fisFCbC4Vfb6HqQNcwPJi2CDK2bf0Xapyz3j3t4cnHE=
|
||||||
github.com/sagernet/sing-vmess v0.2.0-beta.1 h1:5sXQ23uwNlZuDvygzi0dFtnG0Csm/SNqTjAHXJkpuj4=
|
github.com/sagernet/sing-vmess v0.2.0-beta.2 h1:obAkAL35X7ql4RnGzDg4dBYIRpGXRKqcN4LyLZpZGSs=
|
||||||
github.com/sagernet/sing-vmess v0.2.0-beta.1/go.mod h1:fLyE1emIcvQ5DV8reFWnufquZ7MkCSYM5ThodsR9NrQ=
|
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 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
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 h1:Ep3+aJ8FUGGta+II2IEVNUc3EDhaRCZINWkj/LloIA8=
|
||||||
@@ -221,8 +221,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ=
|
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||||
golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg=
|
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 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
@@ -240,8 +240,8 @@ golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM=
|
|||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
|
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -252,16 +252,16 @@ 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.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.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.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
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.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU=
|
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||||
golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E=
|
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
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.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
|
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 h1:ntUhktv3OPE6TgYxXWv9vKvUSJyIFJlyohwbkEwPrKQ=
|
||||||
golang.org/x/time v0.7.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
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.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
|
|||||||
@@ -3,24 +3,36 @@ package main
|
|||||||
import (
|
import (
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
"github.com/sagernet/sing-quic/hysteria2"
|
"github.com/sagernet/sing-quic/hysteria2"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
|
F "github.com/sagernet/sing/common/format"
|
||||||
"github.com/sagernet/sing/common/json/badoption"
|
"github.com/sagernet/sing/common/json/badoption"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestHysteria2Self(t *testing.T) {
|
func TestHysteria2Self(t *testing.T) {
|
||||||
t.Run("self", func(t *testing.T) {
|
t.Run("self", func(t *testing.T) {
|
||||||
testHysteria2Self(t, "")
|
testHysteria2Self(t, "", false)
|
||||||
})
|
})
|
||||||
t.Run("self-salamander", func(t *testing.T) {
|
t.Run("self-salamander", func(t *testing.T) {
|
||||||
testHysteria2Self(t, "password")
|
testHysteria2Self(t, "password", false)
|
||||||
|
})
|
||||||
|
t.Run("self-hop", func(t *testing.T) {
|
||||||
|
testHysteria2Self(t, "", true)
|
||||||
|
})
|
||||||
|
t.Run("self-hop-salamander", func(t *testing.T) {
|
||||||
|
testHysteria2Self(t, "password", true)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testHysteria2Self(t *testing.T, salamanderPassword string) {
|
func TestHysteria2Hop(t *testing.T) {
|
||||||
|
testHysteria2Self(t, "password", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testHysteria2Self(t *testing.T, salamanderPassword string, portHop bool) {
|
||||||
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
_, certPem, keyPem := createSelfSignedCertificate(t, "example.org")
|
||||||
var obfs *option.Hysteria2Obfs
|
var obfs *option.Hysteria2Obfs
|
||||||
if salamanderPassword != "" {
|
if salamanderPassword != "" {
|
||||||
@@ -29,6 +41,14 @@ func testHysteria2Self(t *testing.T, salamanderPassword string) {
|
|||||||
Password: salamanderPassword,
|
Password: salamanderPassword,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var (
|
||||||
|
serverPorts []string
|
||||||
|
hopInterval time.Duration
|
||||||
|
)
|
||||||
|
if portHop {
|
||||||
|
serverPorts = []string{F.ToString(serverPort, ":", serverPort)}
|
||||||
|
hopInterval = 5 * time.Second
|
||||||
|
}
|
||||||
startInstance(t, option.Options{
|
startInstance(t, option.Options{
|
||||||
Inbounds: []option.Inbound{
|
Inbounds: []option.Inbound{
|
||||||
{
|
{
|
||||||
@@ -77,10 +97,12 @@ func testHysteria2Self(t *testing.T, salamanderPassword string) {
|
|||||||
Server: "127.0.0.1",
|
Server: "127.0.0.1",
|
||||||
ServerPort: serverPort,
|
ServerPort: serverPort,
|
||||||
},
|
},
|
||||||
UpMbps: 100,
|
ServerPorts: serverPorts,
|
||||||
DownMbps: 100,
|
HopInterval: badoption.Duration(hopInterval),
|
||||||
Obfs: obfs,
|
UpMbps: 100,
|
||||||
Password: "password",
|
DownMbps: 100,
|
||||||
|
Obfs: obfs,
|
||||||
|
Password: "password",
|
||||||
OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{
|
OutboundTLSOptionsContainer: option.OutboundTLSOptionsContainer{
|
||||||
TLS: &option.OutboundTLSOptions{
|
TLS: &option.OutboundTLSOptions{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
@@ -112,6 +134,10 @@ func testHysteria2Self(t *testing.T, salamanderPassword string) {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
testSuitLargeUDP(t, clientPort, testPort)
|
testSuitLargeUDP(t, clientPort, testPort)
|
||||||
|
if portHop {
|
||||||
|
time.Sleep(5 * time.Second)
|
||||||
|
testSuitLargeUDP(t, clientPort, testPort)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHysteria2Inbound(t *testing.T) {
|
func TestHysteria2Inbound(t *testing.T) {
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/netip"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
C "github.com/sagernet/sing-box/constant"
|
|
||||||
"github.com/sagernet/sing-box/option"
|
|
||||||
"github.com/sagernet/sing/common"
|
|
||||||
"github.com/sagernet/sing/common/json/badoption"
|
|
||||||
)
|
|
||||||
|
|
||||||
func _TestWireGuard(t *testing.T) {
|
|
||||||
startDockerContainer(t, DockerOptions{
|
|
||||||
Image: ImageBoringTun,
|
|
||||||
Cap: []string{"MKNOD", "NET_ADMIN", "NET_RAW"},
|
|
||||||
Ports: []uint16{serverPort, testPort},
|
|
||||||
Bind: map[string]string{
|
|
||||||
"wireguard.conf": "/etc/wireguard/wg0.conf",
|
|
||||||
},
|
|
||||||
Cmd: []string{"wg0"},
|
|
||||||
})
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
startInstance(t, option.Options{
|
|
||||||
Inbounds: []option.Inbound{
|
|
||||||
{
|
|
||||||
Type: C.TypeMixed,
|
|
||||||
Options: &option.HTTPMixedInboundOptions{
|
|
||||||
ListenOptions: option.ListenOptions{
|
|
||||||
Listen: common.Ptr(badoption.Addr(netip.IPv4Unspecified())),
|
|
||||||
ListenPort: clientPort,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Outbounds: []option.Outbound{
|
|
||||||
{
|
|
||||||
Type: C.TypeWireGuard,
|
|
||||||
Options: &option.WireGuardEndpointOptions{
|
|
||||||
ServerOptions: option.ServerOptions{
|
|
||||||
Server: "127.0.0.1",
|
|
||||||
ServerPort: serverPort,
|
|
||||||
},
|
|
||||||
Address: []netip.Prefix{netip.MustParsePrefix("10.0.0.2/32")},
|
|
||||||
PrivateKey: "qGnwlkZljMxeECW8fbwAWdvgntnbK7B8UmMFl3zM0mk=",
|
|
||||||
PeerPublicKey: "QsdcBm+oJw2oNv0cIFXLIq1E850lgTBonup4qnKEQBg=",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
testSuitWg(t, clientPort, testPort)
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user