diff --git a/.golangci.yaml b/.golangci.yaml index a0764585..f5b67397 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -8,9 +8,10 @@ linters: linters-settings: gci: + custom-order: true sections: - standard - prefix(github.com/Dreamacro/clash) - default staticcheck: - go: '1.18' + go: '1.19' diff --git a/adapter/outbound/http.go b/adapter/outbound/http.go index ae4fd75b..67cafd7e 100644 --- a/adapter/outbound/http.go +++ b/adapter/outbound/http.go @@ -44,7 +44,9 @@ type HttpOption struct { func (h *Http) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { if h.tlsConfig != nil { cc := tls.Client(c, h.tlsConfig) - err := cc.Handshake() + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) + defer cancel() + err := cc.HandshakeContext(ctx) c = cc if err != nil { return nil, fmt.Errorf("%s connect error: %w", h.addr, err) diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index cb0ea4fc..f8f9de48 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -13,6 +13,7 @@ import ( obfs "github.com/Dreamacro/clash/transport/simple-obfs" "github.com/Dreamacro/clash/transport/socks5" v2rayObfs "github.com/Dreamacro/clash/transport/v2ray-plugin" + "github.com/sagernet/sing-shadowsocks" "github.com/sagernet/sing-shadowsocks/shadowimpl" "github.com/sagernet/sing/common/bufio" diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index 915e192e..63b76dd3 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -41,7 +41,9 @@ type Socks5Option struct { func (ss *Socks5) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { if ss.tls { cc := tls.Client(c, ss.tlsConfig) - err := cc.Handshake() + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) + defer cancel() + err := cc.HandshakeContext(ctx) c = cc if err != nil { return nil, fmt.Errorf("%s connect error: %w", ss.addr, err) @@ -89,7 +91,9 @@ func (ss *Socks5) ListenPacketContext(ctx context.Context, metadata *C.Metadata, if ss.tls { cc := tls.Client(c, ss.tlsConfig) - err = cc.Handshake() + ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) + defer cancel() + err = cc.HandshakeContext(ctx) c = cc } diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index a8777bf7..aea3bd6a 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -18,6 +18,7 @@ import ( C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/transport/gun" clashVMess "github.com/Dreamacro/clash/transport/vmess" + "github.com/sagernet/sing-vmess/packetaddr" M "github.com/sagernet/sing/common/metadata" ) diff --git a/adapter/outboundgroup/loadbalance.go b/adapter/outboundgroup/loadbalance.go index a396f420..7f875451 100644 --- a/adapter/outboundgroup/loadbalance.go +++ b/adapter/outboundgroup/loadbalance.go @@ -157,7 +157,7 @@ func strategyConsistentHashing() strategyFn { func strategyStickySessions() strategyFn { ttl := time.Minute * 10 maxRetry := 5 - lruCache := cache.NewLRUCache[uint64, int]( + lruCache := cache.New[uint64, int]( cache.WithAge[uint64, int](int64(ttl.Seconds())), cache.WithSize[uint64, int](1000)) return func(proxies []C.Proxy, metadata *C.Metadata) C.Proxy { diff --git a/adapter/provider/provider.go b/adapter/provider/provider.go index 6f16a813..51f536fe 100644 --- a/adapter/provider/provider.go +++ b/adapter/provider/provider.go @@ -5,21 +5,20 @@ import ( "encoding/json" "errors" "fmt" - "github.com/Dreamacro/clash/common/convert" - clashHttp "github.com/Dreamacro/clash/component/http" - "github.com/Dreamacro/clash/component/resource" - "github.com/Dreamacro/clash/log" "github.com/dlclark/regexp2" + "gopkg.in/yaml.v3" "net/http" "runtime" "strings" "time" "github.com/Dreamacro/clash/adapter" + "github.com/Dreamacro/clash/common/convert" + clashHttp "github.com/Dreamacro/clash/component/http" + "github.com/Dreamacro/clash/component/resource" C "github.com/Dreamacro/clash/constant" types "github.com/Dreamacro/clash/constant/provider" - - "gopkg.in/yaml.v3" + "github.com/Dreamacro/clash/log" ) const ( diff --git a/common/cache/cache.go b/common/cache/cache.go deleted file mode 100644 index b87392b4..00000000 --- a/common/cache/cache.go +++ /dev/null @@ -1,106 +0,0 @@ -package cache - -import ( - "runtime" - "sync" - "time" -) - -// Cache store element with a expired time -type Cache[K comparable, V any] struct { - *cache[K, V] -} - -type cache[K comparable, V any] struct { - mapping sync.Map - janitor *janitor[K, V] -} - -type element[V any] struct { - Expired time.Time - Payload V -} - -// Put element in Cache with its ttl -func (c *cache[K, V]) Put(key K, payload V, ttl time.Duration) { - c.mapping.Store(key, &element[V]{ - Payload: payload, - Expired: time.Now().Add(ttl), - }) -} - -// Get element in Cache, and drop when it expired -func (c *cache[K, V]) Get(key K) V { - item, exist := c.mapping.Load(key) - if !exist { - return getZero[V]() - } - elm := item.(*element[V]) - // expired - if time.Since(elm.Expired) > 0 { - c.mapping.Delete(key) - return getZero[V]() - } - return elm.Payload -} - -// GetWithExpire element in Cache with Expire Time -func (c *cache[K, V]) GetWithExpire(key K) (payload V, expired time.Time) { - item, exist := c.mapping.Load(key) - if !exist { - return - } - elm := item.(*element[V]) - // expired - if time.Since(elm.Expired) > 0 { - c.mapping.Delete(key) - return - } - return elm.Payload, elm.Expired -} - -func (c *cache[K, V]) cleanup() { - c.mapping.Range(func(k, v any) bool { - key := k.(string) - elm := v.(*element[V]) - if time.Since(elm.Expired) > 0 { - c.mapping.Delete(key) - } - return true - }) -} - -type janitor[K comparable, V any] struct { - interval time.Duration - stop chan struct{} -} - -func (j *janitor[K, V]) process(c *cache[K, V]) { - ticker := time.NewTicker(j.interval) - for { - select { - case <-ticker.C: - c.cleanup() - case <-j.stop: - ticker.Stop() - return - } - } -} - -func stopJanitor[K comparable, V any](c *Cache[K, V]) { - c.janitor.stop <- struct{}{} -} - -// New return *Cache -func New[K comparable, V any](interval time.Duration) *Cache[K, V] { - j := &janitor[K, V]{ - interval: interval, - stop: make(chan struct{}), - } - c := &cache[K, V]{janitor: j} - go j.process(c) - C := &Cache[K, V]{c} - runtime.SetFinalizer(C, stopJanitor[K, V]) - return C -} diff --git a/common/cache/cache_test.go b/common/cache/cache_test.go deleted file mode 100644 index 0945d905..00000000 --- a/common/cache/cache_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package cache - -import ( - "runtime" - "testing" - "time" - - "github.com/stretchr/testify/assert" -) - -func TestCache_Basic(t *testing.T) { - interval := 200 * time.Millisecond - ttl := 20 * time.Millisecond - c := New[string, int](interval) - c.Put("int", 1, ttl) - - d := New[string, string](interval) - d.Put("string", "a", ttl) - - i := c.Get("int") - assert.Equal(t, i, 1, "should recv 1") - - s := d.Get("string") - assert.Equal(t, s, "a", "should recv 'a'") -} - -func TestCache_TTL(t *testing.T) { - interval := 200 * time.Millisecond - ttl := 20 * time.Millisecond - now := time.Now() - c := New[string, int](interval) - c.Put("int", 1, ttl) - c.Put("int2", 2, ttl) - - i := c.Get("int") - _, expired := c.GetWithExpire("int2") - assert.Equal(t, i, 1, "should recv 1") - assert.True(t, now.Before(expired)) - - time.Sleep(ttl * 2) - i = c.Get("int") - j, _ := c.GetWithExpire("int2") - assert.True(t, i == 0, "should recv 0") - assert.True(t, j == 0, "should recv 0") -} - -func TestCache_AutoCleanup(t *testing.T) { - interval := 10 * time.Millisecond - ttl := 15 * time.Millisecond - c := New[string, int](interval) - c.Put("int", 1, ttl) - - time.Sleep(ttl * 2) - i := c.Get("int") - j, _ := c.GetWithExpire("int") - assert.True(t, i == 0, "should recv 0") - assert.True(t, j == 0, "should recv 0") -} - -func TestCache_AutoGC(t *testing.T) { - sign := make(chan struct{}) - go func() { - interval := 10 * time.Millisecond - ttl := 15 * time.Millisecond - c := New[string, int](interval) - c.Put("int", 1, ttl) - sign <- struct{}{} - }() - - <-sign - runtime.GC() -} diff --git a/common/cache/lrucache.go b/common/cache/lrucache.go index 5fef9445..73600e71 100644 --- a/common/cache/lrucache.go +++ b/common/cache/lrucache.go @@ -65,8 +65,8 @@ type LruCache[K comparable, V any] struct { onEvict EvictCallback[K, V] } -// NewLRUCache creates an LruCache -func NewLRUCache[K comparable, V any](options ...Option[K, V]) *LruCache[K, V] { +// New creates an LruCache +func New[K comparable, V any](options ...Option[K, V]) *LruCache[K, V] { lc := &LruCache[K, V]{ lru: list.New[*entry[K, V]](), cache: make(map[K]*list.Element[*entry[K, V]]), diff --git a/common/cache/lrucache_test.go b/common/cache/lrucache_test.go index 1a4c68ae..4cbc1ff8 100644 --- a/common/cache/lrucache_test.go +++ b/common/cache/lrucache_test.go @@ -19,7 +19,7 @@ var entries = []struct { } func TestLRUCache(t *testing.T) { - c := NewLRUCache[string, string]() + c := New[string, string]() for _, e := range entries { c.Set(e.key, e.value) @@ -45,7 +45,7 @@ func TestLRUCache(t *testing.T) { } func TestLRUMaxAge(t *testing.T) { - c := NewLRUCache[string, string](WithAge[string, string](86400)) + c := New[string, string](WithAge[string, string](86400)) now := time.Now().Unix() expected := now + 86400 @@ -88,7 +88,7 @@ func TestLRUMaxAge(t *testing.T) { } func TestLRUpdateOnGet(t *testing.T) { - c := NewLRUCache[string, string](WithAge[string, string](86400), WithUpdateAgeOnGet[string, string]()) + c := New[string, string](WithAge[string, string](86400), WithUpdateAgeOnGet[string, string]()) now := time.Now().Unix() expires := now + 86400/2 @@ -103,7 +103,7 @@ func TestLRUpdateOnGet(t *testing.T) { } func TestMaxSize(t *testing.T) { - c := NewLRUCache[string, string](WithSize[string, string](2)) + c := New[string, string](WithSize[string, string](2)) // Add one expired entry c.Set("foo", "bar") _, ok := c.Get("foo") @@ -117,7 +117,7 @@ func TestMaxSize(t *testing.T) { } func TestExist(t *testing.T) { - c := NewLRUCache[int, int](WithSize[int, int](1)) + c := New[int, int](WithSize[int, int](1)) c.Set(1, 2) assert.True(t, c.Exist(1)) c.Set(2, 3) @@ -130,7 +130,7 @@ func TestEvict(t *testing.T) { temp = key + value } - c := NewLRUCache[int, int](WithEvict[int, int](evict), WithSize[int, int](1)) + c := New[int, int](WithEvict[int, int](evict), WithSize[int, int](1)) c.Set(1, 2) c.Set(2, 3) @@ -138,7 +138,7 @@ func TestEvict(t *testing.T) { } func TestSetWithExpire(t *testing.T) { - c := NewLRUCache[int, *struct{}](WithAge[int, *struct{}](1)) + c := New[int, *struct{}](WithAge[int, *struct{}](1)) now := time.Now().Unix() tenSecBefore := time.Unix(now-10, 0) @@ -153,7 +153,7 @@ func TestSetWithExpire(t *testing.T) { } func TestStale(t *testing.T) { - c := NewLRUCache[int, int](WithAge[int, int](1), WithStale[int, int](true)) + c := New[int, int](WithAge[int, int](1), WithStale[int, int](true)) now := time.Now().Unix() tenSecBefore := time.Unix(now-10, 0) @@ -166,11 +166,11 @@ func TestStale(t *testing.T) { } func TestCloneTo(t *testing.T) { - o := NewLRUCache[string, int](WithSize[string, int](10)) + o := New[string, int](WithSize[string, int](10)) o.Set("1", 1) o.Set("2", 2) - n := NewLRUCache[string, int](WithSize[string, int](2)) + n := New[string, int](WithSize[string, int](2)) n.Set("3", 3) n.Set("4", 4) diff --git a/common/structure/structure_test.go b/common/structure/structure_test.go index b3bc52a6..9f31d3d1 100644 --- a/common/structure/structure_test.go +++ b/common/structure/structure_test.go @@ -137,3 +137,45 @@ func TestStructure_Nest(t *testing.T) { assert.Nil(t, err) assert.Equal(t, s.BazOptional, goal) } + +func TestStructure_SliceNilValue(t *testing.T) { + rawMap := map[string]any{ + "foo": 1, + "bar": []any{"bar", nil}, + } + + goal := &BazSlice{ + Foo: 1, + Bar: []string{"bar", ""}, + } + + s := &BazSlice{} + err := weakTypeDecoder.Decode(rawMap, s) + assert.Nil(t, err) + assert.Equal(t, goal.Bar, s.Bar) + + s = &BazSlice{} + err = decoder.Decode(rawMap, s) + assert.NotNil(t, err) +} + +func TestStructure_SliceNilValueComplex(t *testing.T) { + rawMap := map[string]any{ + "bar": []any{map[string]any{"bar": "foo"}, nil}, + } + + s := &struct { + Bar []map[string]any `test:"bar"` + }{} + + err := decoder.Decode(rawMap, s) + assert.Nil(t, err) + assert.Nil(t, s.Bar[1]) + + ss := &struct { + Bar []Baz `test:"bar"` + }{} + + err = decoder.Decode(rawMap, ss) + assert.NotNil(t, err) +} diff --git a/component/dialer/mark_linux.go b/component/dialer/mark_linux.go index 41b61863..eaba5cf7 100644 --- a/component/dialer/mark_linux.go +++ b/component/dialer/mark_linux.go @@ -29,13 +29,13 @@ func bindMarkToControl(mark int, chain controlFn) controlFn { return } - return c.Control(func(fd uintptr) { - switch network { - case "tcp4", "udp4": - _ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark) - case "tcp6", "udp6": - _ = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark) - } + var innerErr error + err = c.Control(func(fd uintptr) { + innerErr = syscall.SetsockoptInt(int(fd), syscall.SOL_SOCKET, syscall.SO_MARK, mark) }) + if innerErr != nil { + err = innerErr + } + return } } diff --git a/component/fakeip/memory.go b/component/fakeip/memory.go index 5566ce48..249c5e2a 100644 --- a/component/fakeip/memory.go +++ b/component/fakeip/memory.go @@ -73,7 +73,7 @@ func (m *memoryStore) FlushFakeIP() error { func newMemoryStore(size int) *memoryStore { return &memoryStore{ - cacheIP: cache.NewLRUCache[string, netip.Addr](cache.WithSize[string, netip.Addr](size)), - cacheHost: cache.NewLRUCache[netip.Addr, string](cache.WithSize[netip.Addr, string](size)), + cacheIP: cache.New[string, netip.Addr](cache.WithSize[string, netip.Addr](size)), + cacheHost: cache.New[netip.Addr, string](cache.WithSize[netip.Addr, string](size)), } } diff --git a/component/fakeip/pool.go b/component/fakeip/pool.go index 1ef50d95..ee11fedd 100644 --- a/component/fakeip/pool.go +++ b/component/fakeip/pool.go @@ -3,6 +3,7 @@ package fakeip import ( "errors" "net/netip" + "strings" "sync" "github.com/Dreamacro/clash/common/nnip" @@ -26,7 +27,7 @@ type store interface { FlushFakeIP() error } -// Pool is a implementation about fake ip generator without storage +// Pool is an implementation about fake ip generator without storage type Pool struct { gateway netip.Addr first netip.Addr @@ -43,6 +44,9 @@ type Pool struct { func (p *Pool) Lookup(host string) netip.Addr { p.mux.Lock() defer p.mux.Unlock() + + // RFC4343: DNS Case Insensitive, we SHOULD return result with all cases. + host = strings.ToLower(host) if ip, exist := p.store.GetByHost(host); exist { return ip } diff --git a/component/fakeip/pool_test.go b/component/fakeip/pool_test.go index 7919675b..ae343f96 100644 --- a/component/fakeip/pool_test.go +++ b/component/fakeip/pool_test.go @@ -104,6 +104,27 @@ func TestPool_BasicV6(t *testing.T) { } } +func TestPool_Case_Insensitive(t *testing.T) { + ipnet := netip.MustParsePrefix("192.168.0.1/29") + pools, tempfile, err := createPools(Options{ + IPNet: &ipnet, + Size: 10, + }) + assert.Nil(t, err) + defer os.Remove(tempfile) + + for _, pool := range pools { + first := pool.Lookup("foo.com") + last := pool.Lookup("Foo.Com") + foo, exist := pool.LookBack(last) + + assert.Equal(t, first, pool.Lookup("Foo.Com")) + assert.Equal(t, pool.Lookup("fOo.cOM"), first) + assert.True(t, exist) + assert.Equal(t, foo, "foo.com") + } +} + func TestPool_CycleUsed(t *testing.T) { ipnet := netip.MustParsePrefix("192.168.0.16/28") pools, tempfile, err := createPools(Options{ diff --git a/component/process/process.go b/component/process/process.go index a44af6c0..fe4c5d2a 100644 --- a/component/process/process.go +++ b/component/process/process.go @@ -16,14 +16,14 @@ const ( UDP = "udp" ) -func FindProcessName(network string, srcIP netip.Addr, srcPort int) (int32, string, error) { +func FindProcessName(network string, srcIP netip.Addr, srcPort int) (*uint32, string, error) { return findProcessName(network, srcIP, srcPort) } -func FindUid(network string, srcIP netip.Addr, srcPort int) (int32, error) { +func FindUid(network string, srcIP netip.Addr, srcPort int) (*uint32, error) { _, uid, err := resolveSocketByNetlink(network, srcIP, srcPort) if err != nil { - return -1, err + return nil, err } - return uid, nil + return &uid, nil } diff --git a/component/process/process_darwin.go b/component/process/process_darwin.go index c27aed04..39e56dd2 100644 --- a/component/process/process_darwin.go +++ b/component/process/process_darwin.go @@ -33,11 +33,11 @@ var structSize = func() int { } }() -func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) { +func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (uint32, uint32, error) { return 0, 0, ErrPlatformNotSupport } -func findProcessName(network string, ip netip.Addr, port int) (int32, string, error) { +func findProcessName(network string, ip netip.Addr, port int) (*uint32, string, error) { var spath string switch network { case TCP: @@ -45,14 +45,14 @@ func findProcessName(network string, ip netip.Addr, port int) (int32, string, er case UDP: spath = "net.inet.udp.pcblist_n" default: - return -1, "", ErrInvalidNetwork + return nil, "", ErrInvalidNetwork } isIPv4 := ip.Is4() value, err := syscall.Sysctl(spath) if err != nil { - return -1, "", err + return nil, "", err } buf := []byte(value) @@ -96,7 +96,7 @@ func findProcessName(network string, ip netip.Addr, port int) (int32, string, er // xsocket_n.so_last_pid pid := readNativeUint32(buf[so+68 : so+72]) pp, err := getExecPathFromPID(pid) - return -1, pp, err + return nil, pp, err } // udp packet connection may be not equal with srcIP @@ -106,10 +106,10 @@ func findProcessName(network string, ip netip.Addr, port int) (int32, string, er } if network == UDP && fallbackUDPProcess != "" { - return -1, fallbackUDPProcess, nil + return nil, fallbackUDPProcess, nil } - return -1, "", ErrNotFound + return nil, "", ErrNotFound } func getExecPathFromPID(pid uint32) (string, error) { diff --git a/component/process/process_freebsd_amd64.go b/component/process/process_freebsd_amd64.go index 6b5f51f7..ffbe1515 100644 --- a/component/process/process_freebsd_amd64.go +++ b/component/process/process_freebsd_amd64.go @@ -21,11 +21,11 @@ var ( once sync.Once ) -func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) { +func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (uint32, uint32, error) { return 0, 0, ErrPlatformNotSupport } -func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, error) { +func findProcessName(network string, ip netip.Addr, srcPort int) (*uint32, string, error) { once.Do(func() { if err := initSearcher(); err != nil { log.Errorln("Initialize PROCESS-NAME failed: %s", err.Error()) @@ -35,7 +35,7 @@ func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, }) if defaultSearcher == nil { - return -1, "", ErrPlatformNotSupport + return nil, "", ErrPlatformNotSupport } var spath string @@ -46,22 +46,22 @@ func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, case UDP: spath = "net.inet.udp.pcblist" default: - return -1, "", ErrInvalidNetwork + return nil, "", ErrInvalidNetwork } value, err := syscall.Sysctl(spath) if err != nil { - return -1, "", err + return nil, "", err } buf := []byte(value) pid, err := defaultSearcher.Search(buf, ip, uint16(srcPort), isTCP) if err != nil { - return -1, "", err + return nil, "", err } pp, err := getExecPathFromPID(pid) - return -1, pp, err + return nil, pp, err } func getExecPathFromPID(pid uint32) (string, error) { diff --git a/component/process/process_linux.go b/component/process/process_linux.go index 01da1d33..d0853be9 100644 --- a/component/process/process_linux.go +++ b/component/process/process_linux.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/binary" "fmt" - "net" "net/netip" "os" "path" @@ -15,162 +14,125 @@ import ( "unicode" "unsafe" - "github.com/Dreamacro/clash/common/pool" + "github.com/mdlayher/netlink" + "golang.org/x/sys/unix" ) -// from https://github.com/vishvananda/netlink/blob/bca67dfc8220b44ef582c9da4e9172bf1c9ec973/nl/nl_linux.go#L52-L62 -var nativeEndian = func() binary.ByteOrder { - var x uint32 = 0x01020304 - if *(*byte)(unsafe.Pointer(&x)) == 0x01 { - return binary.BigEndian - } - - return binary.LittleEndian -}() - const ( - sizeOfSocketDiagRequest = syscall.SizeofNlMsghdr + 8 + 48 - socketDiagByFamily = 20 - pathProc = "/proc" + SOCK_DIAG_BY_FAMILY = 20 + inetDiagRequestSize = int(unsafe.Sizeof(inetDiagRequest{})) + inetDiagResponseSize = int(unsafe.Sizeof(inetDiagResponse{})) ) -func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, error) { +type inetDiagRequest struct { + Family byte + Protocol byte + Ext byte + Pad byte + States uint32 + + SrcPort [2]byte + DstPort [2]byte + Src [16]byte + Dst [16]byte + If uint32 + Cookie [2]uint32 +} + +type inetDiagResponse struct { + Family byte + State byte + Timer byte + ReTrans byte + + SrcPort [2]byte + DstPort [2]byte + Src [16]byte + Dst [16]byte + If uint32 + Cookie [2]uint32 + + Expires uint32 + RQueue uint32 + WQueue uint32 + UID uint32 + INode uint32 +} + +func findProcessName(network string, ip netip.Addr, srcPort int) (*uint32, string, error) { inode, uid, err := resolveSocketByNetlink(network, ip, srcPort) if err != nil { - return -1, "", err + return nil, "", err } pp, err := resolveProcessNameByProcSearch(inode, uid) - return uid, pp, err + return &uid, pp, err } -func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) { - var family byte - var protocol byte - - switch network { - case TCP: - protocol = syscall.IPPROTO_TCP - case UDP: - protocol = syscall.IPPROTO_UDP - default: - return 0, 0, ErrInvalidNetwork +func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (uint32, uint32, error) { + request := &inetDiagRequest{ + States: 0xffffffff, + Cookie: [2]uint32{0xffffffff, 0xffffffff}, } if ip.Is4() { - family = syscall.AF_INET + request.Family = unix.AF_INET } else { - family = syscall.AF_INET6 + request.Family = unix.AF_INET6 } - req := packSocketDiagRequest(family, protocol, ip, uint16(srcPort)) + if strings.HasPrefix(network, "tcp") { + request.Protocol = unix.IPPROTO_TCP + } else if strings.HasPrefix(network, "udp") { + request.Protocol = unix.IPPROTO_UDP + } else { + return 0, 0, ErrInvalidNetwork + } - socket, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_DGRAM, syscall.NETLINK_INET_DIAG) + copy(request.Src[:], ip.AsSlice()) + + binary.BigEndian.PutUint16(request.SrcPort[:], uint16(srcPort)) + + conn, err := netlink.Dial(unix.NETLINK_INET_DIAG, nil) if err != nil { - return 0, 0, fmt.Errorf("dial netlink: %w", err) + return 0, 0, err } - defer func() { - _ = syscall.Close(socket) - }() + defer conn.Close() - _ = syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_SNDTIMEO, &syscall.Timeval{Usec: 100}) - _ = syscall.SetsockoptTimeval(socket, syscall.SOL_SOCKET, syscall.SO_RCVTIMEO, &syscall.Timeval{Usec: 100}) + message := netlink.Message{ + Header: netlink.Header{ + Type: SOCK_DIAG_BY_FAMILY, + Flags: netlink.Request | netlink.Dump, + }, + Data: (*(*[inetDiagRequestSize]byte)(unsafe.Pointer(request)))[:], + } - if err := syscall.Connect(socket, &syscall.SockaddrNetlink{ - Family: syscall.AF_NETLINK, - Pad: 0, - Pid: 0, - Groups: 0, - }); err != nil { + messages, err := conn.Execute(message) + if err != nil { return 0, 0, err } - if _, err := syscall.Write(socket, req); err != nil { - return 0, 0, fmt.Errorf("write request: %w", err) + for _, msg := range messages { + if len(msg.Data) < inetDiagResponseSize { + continue + } + + response := (*inetDiagResponse)(unsafe.Pointer(&msg.Data[0])) + + return response.INode, response.UID, nil } - rb := pool.Get(pool.RelayBufferSize) - defer func() { - _ = pool.Put(rb) - }() - - n, err := syscall.Read(socket, rb) - if err != nil { - return 0, 0, fmt.Errorf("read response: %w", err) - } - - messages, err := syscall.ParseNetlinkMessage(rb[:n]) - if err != nil { - return 0, 0, fmt.Errorf("parse netlink message: %w", err) - } else if len(messages) == 0 { - return 0, 0, fmt.Errorf("unexcepted netlink response") - } - - message := messages[0] - if message.Header.Type&syscall.NLMSG_ERROR != 0 { - return 0, 0, fmt.Errorf("netlink message: NLMSG_ERROR") - } - - inode, uid := unpackSocketDiagResponse(&messages[0]) - if inode < 0 || uid < 0 { - return 0, 0, fmt.Errorf("invalid inode(%d) or uid(%d)", inode, uid) - } - - return inode, uid, nil + return 0, 0, ErrNotFound } -func packSocketDiagRequest(family, protocol byte, source netip.Addr, sourcePort uint16) []byte { - s := make([]byte, 16) - - copy(s, source.AsSlice()) - - buf := make([]byte, sizeOfSocketDiagRequest) - - nativeEndian.PutUint32(buf[0:4], sizeOfSocketDiagRequest) - nativeEndian.PutUint16(buf[4:6], socketDiagByFamily) - nativeEndian.PutUint16(buf[6:8], syscall.NLM_F_REQUEST|syscall.NLM_F_DUMP) - nativeEndian.PutUint32(buf[8:12], 0) - nativeEndian.PutUint32(buf[12:16], 0) - - buf[16] = family - buf[17] = protocol - buf[18] = 0 - buf[19] = 0 - nativeEndian.PutUint32(buf[20:24], 0xFFFFFFFF) - - binary.BigEndian.PutUint16(buf[24:26], sourcePort) - binary.BigEndian.PutUint16(buf[26:28], 0) - - copy(buf[28:44], s) - copy(buf[44:60], net.IPv6zero) - - nativeEndian.PutUint32(buf[60:64], 0) - nativeEndian.PutUint64(buf[64:72], 0xFFFFFFFFFFFFFFFF) - - return buf -} - -func unpackSocketDiagResponse(msg *syscall.NetlinkMessage) (inode, uid int32) { - if len(msg.Data) < 72 { - return 0, 0 - } - - data := msg.Data - - uid = int32(nativeEndian.Uint32(data[64:68])) - inode = int32(nativeEndian.Uint32(data[68:72])) - - return -} - -func resolveProcessNameByProcSearch(inode, uid int32) (string, error) { - files, err := os.ReadDir(pathProc) +func resolveProcessNameByProcSearch(inode, uid uint32) (string, error) { + files, err := os.ReadDir("/proc") if err != nil { return "", err } - buffer := make([]byte, syscall.PathMax) - socket := []byte(fmt.Sprintf("socket:[%d]", inode)) + buffer := make([]byte, unix.PathMax) + socket := fmt.Appendf(nil, "socket:[%d]", inode) for _, f := range files { if !f.IsDir() || !isPid(f.Name()) { @@ -181,12 +143,12 @@ func resolveProcessNameByProcSearch(inode, uid int32) (string, error) { if err != nil { return "", err } - if info.Sys().(*syscall.Stat_t).Uid != uint32(uid) { + if info.Sys().(*syscall.Stat_t).Uid != uid { continue } - processPath := path.Join(pathProc, f.Name()) - fdPath := path.Join(processPath, "fd") + processPath := filepath.Join("/proc", f.Name()) + fdPath := filepath.Join(processPath, "fd") fds, err := os.ReadDir(fdPath) if err != nil { @@ -194,7 +156,7 @@ func resolveProcessNameByProcSearch(inode, uid int32) (string, error) { } for _, fd := range fds { - n, err := syscall.Readlink(path.Join(fdPath, fd.Name()), buffer) + n, err := unix.Readlink(filepath.Join(fdPath, fd.Name()), buffer) if err != nil { continue } @@ -209,9 +171,10 @@ func resolveProcessNameByProcSearch(inode, uid int32) (string, error) { } } else { if bytes.Equal(buffer[:n], socket) { - return os.Readlink(path.Join(processPath, "exe")) + return os.Readlink(filepath.Join(processPath, "exe")) } } + } } diff --git a/component/process/process_other.go b/component/process/process_other.go index 77dad250..32614b26 100644 --- a/component/process/process_other.go +++ b/component/process/process_other.go @@ -4,10 +4,10 @@ package process import "net/netip" -func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, error) { - return -1, "", ErrPlatformNotSupport +func findProcessName(network string, ip netip.Addr, srcPort int) (*uint32, string, error) { + return nil, "", ErrPlatformNotSupport } -func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) { +func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (uint32, uint32, error) { return 0, 0, ErrPlatformNotSupport } diff --git a/component/process/process_windows.go b/component/process/process_windows.go index 03935c37..7e073c8e 100644 --- a/component/process/process_windows.go +++ b/component/process/process_windows.go @@ -29,7 +29,7 @@ var ( once sync.Once ) -func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (int32, int32, error) { +func resolveSocketByNetlink(network string, ip netip.Addr, srcPort int) (uint32, uint32, error) { return 0, 0, ErrPlatformNotSupport } @@ -62,7 +62,7 @@ func initWin32API() error { return nil } -func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, error) { +func findProcessName(network string, ip netip.Addr, srcPort int) (*uint32, string, error) { once.Do(func() { err := initWin32API() if err != nil { @@ -86,22 +86,22 @@ func findProcessName(network string, ip netip.Addr, srcPort int) (int32, string, fn = getExUDPTable class = udpTablePid default: - return -1, "", ErrInvalidNetwork + return nil, "", ErrInvalidNetwork } buf, err := getTransportTable(fn, family, class) if err != nil { - return -1, "", err + return nil, "", err } s := newSearcher(family == windows.AF_INET, network == TCP) pid, err := s.Search(buf, ip, uint16(srcPort)) if err != nil { - return -1, "", err + return nil, "", err } pp, err := getExecPathFromPID(pid) - return -1, pp, err + return nil, pp, err } type searcher struct { @@ -220,7 +220,8 @@ func getExecPathFromPID(pid uint32) (string, error) { uintptr(h), uintptr(1), uintptr(unsafe.Pointer(&buf[0])), - uintptr(unsafe.Pointer(&size))) + uintptr(unsafe.Pointer(&size)), + ) if r1 == 0 { return "", err } diff --git a/component/resolver/resolver.go b/component/resolver/resolver.go index 0c09d23c..dfe47000 100644 --- a/component/resolver/resolver.go +++ b/component/resolver/resolver.go @@ -3,12 +3,13 @@ package resolver import ( "context" "errors" + "fmt" "math/rand" "net" "net/netip" + "strings" "time" - "github.com/Dreamacro/clash/common/nnip" "github.com/Dreamacro/clash/component/trie" ) @@ -45,39 +46,164 @@ type Resolver interface { ResolveIPv6(ctx context.Context, host string) (ip netip.Addr, err error) } +// LookupIPv4WithResolver same as LookupIPv4, but with a resolver +func LookupIPv4WithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) { + if node := DefaultHosts.Search(host); node != nil { + if ip := node.Data(); ip.Is4() { + return []netip.Addr{node.Data()}, nil + } + } + + ip, err := netip.ParseAddr(host) + if err == nil { + if ip.Is4() || ip.Is4In6() { + return []netip.Addr{ip}, nil + } + return []netip.Addr{}, ErrIPVersion + } + + if r != nil { + return r.LookupIPv4(ctx, host) + } + + if DefaultResolver != nil { + return DefaultResolver.LookupIPv4(ctx, host) + } + + ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout) + defer cancel() + ipAddrs, err := net.DefaultResolver.LookupNetIP(ctx, "ip4", host) + if err != nil { + return nil, err + } else if len(ipAddrs) == 0 { + return nil, ErrIPNotFound + } + + return ipAddrs, nil +} + +// LookupIPv4 with a host, return ipv4 list +func LookupIPv4(ctx context.Context, host string) ([]netip.Addr, error) { + return LookupIPv4WithResolver(ctx, host, DefaultResolver) +} + +// ResolveIPv4WithResolver same as ResolveIPv4, but with a resolver +func ResolveIPv4WithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) { + ips, err := LookupIPv4WithResolver(ctx, host, r) + if err != nil { + return netip.Addr{}, err + } else if len(ips) == 0 { + return netip.Addr{}, fmt.Errorf("%w: %s", ErrIPNotFound, host) + } + return ips[rand.Intn(len(ips))], nil +} + // ResolveIPv4 with a host, return ipv4 func ResolveIPv4(ctx context.Context, host string) (netip.Addr, error) { return ResolveIPv4WithResolver(ctx, host, DefaultResolver) } -func ResolveIPv4WithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) { - if ips, err := LookupIPv4WithResolver(ctx, host, r); err == nil { - return ips[rand.Intn(len(ips))], nil - } else { - return netip.Addr{}, err +// LookupIPv6WithResolver same as LookupIPv6, but with a resolver +func LookupIPv6WithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) { + if DisableIPv6 { + return nil, ErrIPv6Disabled } + + if node := DefaultHosts.Search(host); node != nil { + if ip := node.Data(); ip.Is6() { + return []netip.Addr{ip}, nil + } + } + + if ip, err := netip.ParseAddr(host); err == nil { + if strings.Contains(host, ":") { + return []netip.Addr{ip}, nil + } + return nil, ErrIPVersion + } + + if r != nil { + return r.LookupIPv6(ctx, host) + } + if DefaultResolver != nil { + return DefaultResolver.LookupIPv6(ctx, host) + } + + ctx, cancel := context.WithTimeout(context.Background(), DefaultDNSTimeout) + defer cancel() + ipAddrs, err := net.DefaultResolver.LookupNetIP(ctx, "ip6", host) + if err != nil { + return nil, err + } else if len(ipAddrs) == 0 { + return nil, ErrIPNotFound + } + + return ipAddrs, nil +} + +// LookupIPv6 with a host, return ipv6 list +func LookupIPv6(ctx context.Context, host string) ([]netip.Addr, error) { + return LookupIPv6WithResolver(ctx, host, DefaultResolver) +} + +// ResolveIPv6WithResolver same as ResolveIPv6, but with a resolver +func ResolveIPv6WithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) { + ips, err := LookupIPv6WithResolver(ctx, host, r) + if err != nil { + return netip.Addr{}, err + } else if len(ips) == 0 { + return netip.Addr{}, fmt.Errorf("%w: %s", ErrIPNotFound, host) + } + return ips[rand.Intn(len(ips))], nil } -// ResolveIPv6 with a host, return ipv6 func ResolveIPv6(ctx context.Context, host string) (netip.Addr, error) { return ResolveIPv6WithResolver(ctx, host, DefaultResolver) } -func ResolveIPv6WithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) { - if ips, err := LookupIPv6WithResolver(ctx, host, r); err == nil { - return ips[rand.Intn(len(ips))], nil - } else { - return netip.Addr{}, err +// LookupIPWithResolver same as LookupIP, but with a resolver +func LookupIPWithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) { + if node := DefaultHosts.Search(host); node != nil { + return []netip.Addr{node.Data()}, nil } + + if r != nil { + if DisableIPv6 { + return r.LookupIPv4(ctx, host) + } + return r.LookupIP(ctx, host) + } else if DisableIPv6 { + return LookupIPv4(ctx, host) + } + + if ip, err := netip.ParseAddr(host); err == nil { + return []netip.Addr{ip}, nil + } + + ips, err := net.DefaultResolver.LookupNetIP(ctx, "ip", host) + if err != nil { + return nil, err + } else if len(ips) == 0 { + return nil, ErrIPNotFound + } + + return ips, nil +} + +// LookupIP with a host, return ip +func LookupIP(ctx context.Context, host string) ([]netip.Addr, error) { + return LookupIPWithResolver(ctx, host, DefaultResolver) } // ResolveIPWithResolver same as ResolveIP, but with a resolver func ResolveIPWithResolver(ctx context.Context, host string, r Resolver) (netip.Addr, error) { - if ip, err := ResolveIPv4WithResolver(ctx, host, r); err == nil { - return ip, nil - } else { - return ResolveIPv6WithResolver(ctx, host, r) + ips, err := LookupIPWithResolver(ctx, host, r) + if err != nil { + return netip.Addr{}, err + } else if len(ips) == 0 { + return netip.Addr{}, fmt.Errorf("%w: %s", ErrIPNotFound, host) } + return ips[rand.Intn(len(ips))], nil } // ResolveIP with a host, return ip @@ -121,142 +247,6 @@ func ResolveProxyServerHost(ctx context.Context, host string) (netip.Addr, error return ResolveIP(ctx, host) } -func LookupIPv6WithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) { - if DisableIPv6 { - return []netip.Addr{}, ErrIPv6Disabled - } - - if node := DefaultHosts.Search(host); node != nil { - if ip := node.Data(); ip.Is6() { - return []netip.Addr{ip}, nil - } - } - - ip, err := netip.ParseAddr(host) - if err == nil { - if ip.Is6() { - return []netip.Addr{ip}, nil - } - return []netip.Addr{}, ErrIPVersion - } - - if r != nil { - return r.LookupIPv6(ctx, host) - } - - if DefaultResolver == nil { - ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip6", host) - if err != nil { - return []netip.Addr{}, err - } else if len(ipAddrs) == 0 { - return []netip.Addr{}, ErrIPNotFound - } - - addrs := make([]netip.Addr, 0, len(ipAddrs)) - for _, ipAddr := range ipAddrs { - addrs = append(addrs, nnip.IpToAddr(ipAddr)) - } - - rand.Shuffle(len(addrs), func(i, j int) { - addrs[i], addrs[j] = addrs[j], addrs[i] - }) - return addrs, nil - } - return []netip.Addr{}, ErrIPNotFound -} - -func LookupIPv4WithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) { - if node := DefaultHosts.Search(host); node != nil { - if ip := node.Data(); ip.Is4() { - return []netip.Addr{node.Data()}, nil - } - } - - ip, err := netip.ParseAddr(host) - if err == nil { - if ip.Is4() || ip.Is4In6() { - return []netip.Addr{ip}, nil - } - return []netip.Addr{}, ErrIPVersion - } - - if r != nil { - return r.LookupIPv4(ctx, host) - } - - if DefaultResolver == nil { - ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip4", host) - if err != nil { - return []netip.Addr{}, err - } else if len(ipAddrs) == 0 { - return []netip.Addr{}, ErrIPNotFound - } - - addrs := make([]netip.Addr, 0, len(ipAddrs)) - for _, ipAddr := range ipAddrs { - addrs = append(addrs, nnip.IpToAddr(ipAddr)) - } - - rand.Shuffle(len(addrs), func(i, j int) { - addrs[i], addrs[j] = addrs[j], addrs[i] - }) - return addrs, nil - } - return []netip.Addr{}, ErrIPNotFound -} - -func LookupIPWithResolver(ctx context.Context, host string, r Resolver) ([]netip.Addr, error) { - if node := DefaultHosts.Search(host); node != nil { - return []netip.Addr{node.Data()}, nil - } - - ip, err := netip.ParseAddr(host) - if err == nil { - return []netip.Addr{ip}, nil - } - - if r != nil { - if DisableIPv6 { - return r.LookupIPv4(ctx, host) - } - - return r.LookupIP(ctx, host) - } else if DisableIPv6 { - return LookupIPv4(ctx, host) - } - - if DefaultResolver == nil { - ipAddrs, err := net.DefaultResolver.LookupIP(ctx, "ip", host) - if err != nil { - return []netip.Addr{}, err - } else if len(ipAddrs) == 0 { - return []netip.Addr{}, ErrIPNotFound - } - addrs := make([]netip.Addr, 0, len(ipAddrs)) - for _, ipAddr := range ipAddrs { - addrs = append(addrs, nnip.IpToAddr(ipAddr)) - } - - rand.Shuffle(len(addrs), func(i, j int) { - addrs[i], addrs[j] = addrs[j], addrs[i] - }) - return addrs, nil - } - return []netip.Addr{}, ErrIPNotFound -} - -func LookupIP(ctx context.Context, host string) ([]netip.Addr, error) { - return LookupIPWithResolver(ctx, host, DefaultResolver) -} - -func LookupIPv4(ctx context.Context, host string) ([]netip.Addr, error) { - return LookupIPv4WithResolver(ctx, host, DefaultResolver) -} - -func LookupIPv6(ctx context.Context, host string) ([]netip.Addr, error) { - return LookupIPv6WithResolver(ctx, host, DefaultResolver) -} - func LookupIPv6ProxyServerHost(ctx context.Context, host string) ([]netip.Addr, error) { if ProxyServerHostResolver != nil { return LookupIPv6WithResolver(ctx, host, ProxyServerHostResolver) diff --git a/component/sniffer/dispatcher.go b/component/sniffer/dispatcher.go index ef586d45..fd4fe98e 100644 --- a/component/sniffer/dispatcher.go +++ b/component/sniffer/dispatcher.go @@ -190,7 +190,7 @@ func NewSnifferDispatcher(needSniffer []sniffer.Type, forceDomain *trie.DomainTr forceDomain: forceDomain, skipSNI: skipSNI, portRanges: ports, - skipList: cache.NewLRUCache[string, uint8](cache.WithSize[string, uint8](128), cache.WithAge[string, uint8](600)), + skipList: cache.New[string, uint8](cache.WithSize[string, uint8](128), cache.WithAge[string, uint8](600)), forceDnsMapping: forceDnsMapping, parsePureIp: parsePureIp, } diff --git a/constant/metadata.go b/constant/metadata.go index dcddcd8b..67a42186 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -119,7 +119,7 @@ type Metadata struct { InPort string `json:"inboundPort"` Host string `json:"host"` DNSMode DNSMode `json:"dnsMode"` - Uid *int32 `json:"uid"` + Uid *uint32 `json:"uid"` Process string `json:"process"` ProcessPath string `json:"processPath"` RemoteDst string `json:"remoteDestination"` diff --git a/constant/mime/mime.go b/constant/mime/mime.go deleted file mode 100644 index 431457be..00000000 --- a/constant/mime/mime.go +++ /dev/null @@ -1,16 +0,0 @@ -package mime - -import ( - "mime" -) - -var consensusMimes = map[string]string{ - // rfc4329: text/javascript is obsolete, so we need to overwrite mime's builtin - ".js": "application/javascript; charset=utf-8", -} - -func init() { - for ext, typ := range consensusMimes { - mime.AddExtensionType(ext, typ) - } -} diff --git a/constant/provider/interface.go b/constant/provider/interface.go index a56bc0a3..8bc3c0fe 100644 --- a/constant/provider/interface.go +++ b/constant/provider/interface.go @@ -1,7 +1,7 @@ package provider import ( - C "github.com/Dreamacro/clash/constant" + "github.com/Dreamacro/clash/constant" ) // Vehicle Type @@ -65,7 +65,9 @@ type Provider interface { // ProxyProvider interface type ProxyProvider interface { Provider - Proxies() []C.Proxy + Proxies() []constant.Proxy + // Touch is used to inform the provider that the proxy is actually being used while getting the list of proxies. + // Commonly used in DialContext and DialPacketConn Touch() HealthCheck() Version() uint32 @@ -98,7 +100,7 @@ func (rt RuleType) String() string { type RuleProvider interface { Provider Behavior() RuleType - Match(*C.Metadata) bool + Match(*constant.Metadata) bool ShouldResolveIP() bool - AsRule(adaptor string) C.Rule + AsRule(adaptor string) constant.Rule } diff --git a/dns/client.go b/dns/client.go index 13b01422..0a13469c 100644 --- a/dns/client.go +++ b/dns/client.go @@ -6,6 +6,7 @@ import ( "fmt" tlsC "github.com/Dreamacro/clash/component/tls" "go.uber.org/atomic" + "math/rand" "net" "net/netip" "strings" @@ -34,15 +35,19 @@ func (c *client) ExchangeContext(ctx context.Context, m *D.Msg) (*D.Msg, error) ip netip.Addr err error ) - if ip, err = netip.ParseAddr(c.host); err != nil { - if c.r == nil { + if c.r == nil { + // a default ip dns + if ip, err = netip.ParseAddr(c.host); err != nil { return nil, fmt.Errorf("dns %s not a valid ip", c.host) - } else { - if ip, err = resolver.ResolveIPWithResolver(ctx, c.host, c.r); err != nil { - return nil, fmt.Errorf("use default dns resolve failed: %w", err) - } - c.host = ip.String() } + } else { + ips, err := resolver.LookupIPWithResolver(ctx, c.host, c.r) + if err != nil { + return nil, fmt.Errorf("use default dns resolve failed: %w", err) + } else if len(ips) == 0 { + return nil, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, c.host) + } + ip = ips[rand.Intn(len(ips))] } network := "udp" diff --git a/dns/dhcp.go b/dns/dhcp.go index a4ad70a5..1efa3bd1 100644 --- a/dns/dhcp.go +++ b/dns/dhcp.go @@ -30,7 +30,7 @@ type dhcpClient struct { ifaceAddr *netip.Prefix done chan struct{} - resolver *Resolver + clients []dnsClient err error } @@ -42,15 +42,15 @@ func (d *dhcpClient) Exchange(m *D.Msg) (msg *D.Msg, err error) { } func (d *dhcpClient) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, err error) { - res, err := d.resolve(ctx) + clients, err := d.resolve(ctx) if err != nil { return nil, err } - return res.ExchangeContext(ctx, m) + return batchExchange(ctx, clients, m) } -func (d *dhcpClient) resolve(ctx context.Context) (*Resolver, error) { +func (d *dhcpClient) resolve(ctx context.Context) ([]dnsClient, error) { d.lock.Lock() invalidated, err := d.invalidate() @@ -65,8 +65,9 @@ func (d *dhcpClient) resolve(ctx context.Context) (*Resolver, error) { ctx, cancel := context.WithTimeout(context.Background(), DHCPTimeout) defer cancel() - var res *Resolver + var res []dnsClient dns, err := dhcp.ResolveDNSFromDHCP(ctx, d.ifaceName) + // dns never empty if err is nil if err == nil { nameserver := make([]NameServer, 0, len(dns)) for _, item := range dns { @@ -76,9 +77,7 @@ func (d *dhcpClient) resolve(ctx context.Context) (*Resolver, error) { }) } - res = NewResolver(Config{ - Main: nameserver, - }) + res = transform(nameserver, nil) } d.lock.Lock() @@ -87,7 +86,7 @@ func (d *dhcpClient) resolve(ctx context.Context) (*Resolver, error) { close(done) d.done = nil - d.resolver = res + d.clients = res d.err = err }() } @@ -97,7 +96,7 @@ func (d *dhcpClient) resolve(ctx context.Context) (*Resolver, error) { for { d.lock.Lock() - res, err, done := d.resolver, d.err, d.done + res, err, done := d.clients, d.err, d.done d.lock.Unlock() diff --git a/dns/enhancer.go b/dns/enhancer.go index 6e1d03ac..8b3ce282 100644 --- a/dns/enhancer.go +++ b/dns/enhancer.go @@ -109,7 +109,7 @@ func NewEnhancer(cfg Config) *ResolverEnhancer { if cfg.EnhancedMode != C.DNSNormal { fakePool = cfg.Pool - mapping = cache.NewLRUCache[netip.Addr, string](cache.WithSize[netip.Addr, string](4096), cache.WithStale[netip.Addr, string](true)) + mapping = cache.New[netip.Addr, string](cache.WithSize[netip.Addr, string](4096), cache.WithStale[netip.Addr, string](true)) } return &ResolverEnhancer{ diff --git a/dns/resolver.go b/dns/resolver.go index eacb7dc4..a0623dc2 100644 --- a/dns/resolver.go +++ b/dns/resolver.go @@ -10,7 +10,6 @@ import ( "time" "github.com/Dreamacro/clash/common/cache" - "github.com/Dreamacro/clash/common/picker" "github.com/Dreamacro/clash/component/fakeip" "github.com/Dreamacro/clash/component/geodata/router" "github.com/Dreamacro/clash/component/resolver" @@ -48,14 +47,14 @@ func (r *Resolver) LookupIPPrimaryIPv4(ctx context.Context, host string) (ips [] ch := make(chan []netip.Addr, 1) go func() { defer close(ch) - ip, err := r.resolveIP(ctx, host, D.TypeAAAA) + ip, err := r.lookupIP(ctx, host, D.TypeAAAA) if err != nil { return } ch <- ip }() - ips, err = r.resolveIP(ctx, host, D.TypeA) + ips, err = r.lookupIP(ctx, host, D.TypeA) if err == nil { return } @@ -72,7 +71,7 @@ func (r *Resolver) LookupIP(ctx context.Context, host string) (ips []netip.Addr, ch := make(chan []netip.Addr, 1) go func() { defer close(ch) - ip, err := r.resolveIP(ctx, host, D.TypeAAAA) + ip, err := r.lookupIP(ctx, host, D.TypeAAAA) if err != nil { return } @@ -80,7 +79,7 @@ func (r *Resolver) LookupIP(ctx context.Context, host string) (ips []netip.Addr, ch <- ip }() - ips, err = r.resolveIP(ctx, host, D.TypeA) + ips, err = r.lookupIP(ctx, host, D.TypeA) select { case ipv6s, open := <-ch: @@ -95,39 +94,47 @@ func (r *Resolver) LookupIP(ctx context.Context, host string) (ips []netip.Addr, return ips, nil } -func (r *Resolver) LookupIPv4(ctx context.Context, host string) (ips []netip.Addr, err error) { - return r.resolveIP(ctx, host, D.TypeA) -} - -func (r *Resolver) LookupIPv6(ctx context.Context, host string) (ips []netip.Addr, err error) { - return r.resolveIP(ctx, host, D.TypeAAAA) -} - // ResolveIP request with TypeA and TypeAAAA, priority return TypeA func (r *Resolver) ResolveIP(ctx context.Context, host string) (ip netip.Addr, err error) { - if ips, err := r.LookupIPPrimaryIPv4(ctx, host); err == nil { - return ips[rand.Intn(len(ips))], nil - } else { + ips, err := r.LookupIPPrimaryIPv4(ctx, host) + if err != nil { return netip.Addr{}, err + } else if len(ips) == 0 { + return netip.Addr{}, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, host) } + return ips[rand.Intn(len(ips))], nil +} + +// LookupIPv4 request with TypeA +func (r *Resolver) LookupIPv4(ctx context.Context, host string) ([]netip.Addr, error) { + return r.lookupIP(ctx, host, D.TypeA) } // ResolveIPv4 request with TypeA func (r *Resolver) ResolveIPv4(ctx context.Context, host string) (ip netip.Addr, err error) { - if ips, err := r.LookupIPv4(ctx, host); err == nil { - return ips[rand.Intn(len(ips))], nil - } else { + ips, err := r.lookupIP(ctx, host, D.TypeA) + if err != nil { return netip.Addr{}, err + } else if len(ips) == 0 { + return netip.Addr{}, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, host) } + return ips[rand.Intn(len(ips))], nil +} + +// LookupIPv6 request with TypeAAAA +func (r *Resolver) LookupIPv6(ctx context.Context, host string) ([]netip.Addr, error) { + return r.lookupIP(ctx, host, D.TypeAAAA) } // ResolveIPv6 request with TypeAAAA func (r *Resolver) ResolveIPv6(ctx context.Context, host string) (ip netip.Addr, err error) { - if ips, err := r.LookupIPv6(ctx, host); err == nil { - return ips[rand.Intn(len(ips))], nil - } else { + ips, err := r.lookupIP(ctx, host, D.TypeAAAA) + if err != nil { return netip.Addr{}, err + } else if len(ips) == 0 { + return netip.Addr{}, fmt.Errorf("%w: %s", resolver.ErrIPNotFound, host) } + return ips[rand.Intn(len(ips))], nil } func (r *Resolver) shouldIPFallback(ip netip.Addr) bool { @@ -149,6 +156,16 @@ func (r *Resolver) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, e if len(m.Question) == 0 { return nil, errors.New("should have one question at least") } + continueFetch := false + defer func() { + if continueFetch || errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) { + ctx, cancel := context.WithTimeout(context.Background(), resolver.DefaultDNSTimeout) + defer cancel() + go func() { + _, _ = r.exchangeWithoutCache(ctx, m) // ignore result, just for putMsgToCache + }() + } + }() q := m.Question[0] cacheM, expireTime, hit := r.lruCache.GetWithExpire(q.String()) @@ -157,7 +174,7 @@ func (r *Resolver) ExchangeContext(ctx context.Context, m *D.Msg) (msg *D.Msg, e msg = cacheM.Copy() if expireTime.Before(now) { setMsgTTL(msg, uint32(1)) // Continue fetch - go r.exchangeWithoutCache(ctx, m) + continueFetch = true } else { setMsgTTL(msg, uint32(time.Until(expireTime).Seconds())) } @@ -203,31 +220,10 @@ func (r *Resolver) exchangeWithoutCache(ctx context.Context, m *D.Msg) (msg *D.M } func (r *Resolver) batchExchange(ctx context.Context, clients []dnsClient, m *D.Msg) (msg *D.Msg, err error) { - fast, ctx := picker.WithTimeout[*D.Msg](ctx, resolver.DefaultDNSTimeout) - for _, client := range clients { - r := client - fast.Go(func() (*D.Msg, error) { - m, err := r.ExchangeContext(ctx, m) - if err != nil { - return nil, err - } else if m.Rcode == D.RcodeServerFailure || m.Rcode == D.RcodeRefused { - return nil, errors.New("server failure") - } - return m, nil - }) - } + ctx, cancel := context.WithTimeout(ctx, resolver.DefaultDNSTimeout) + defer cancel() - elm := fast.Wait() - if elm == nil { - err := errors.New("all DNS requests failed") - if fErr := fast.Error(); fErr != nil { - err = fmt.Errorf("%w, first error: %s", err, fErr.Error()) - } - return nil, err - } - - msg = elm - return + return batchExchange(ctx, clients, m) } func (r *Resolver) matchPolicy(m *D.Msg) []dnsClient { @@ -305,7 +301,7 @@ func (r *Resolver) ipExchange(ctx context.Context, m *D.Msg) (msg *D.Msg, err er return } -func (r *Resolver) resolveIP(ctx context.Context, host string, dnsType uint16) (ips []netip.Addr, err error) { +func (r *Resolver) lookupIP(ctx context.Context, host string, dnsType uint16) (ips []netip.Addr, err error) { ip, err := netip.ParseAddr(host) if err == nil { isIPv4 := ip.Is4() @@ -381,13 +377,13 @@ type Config struct { func NewResolver(config Config) *Resolver { defaultResolver := &Resolver{ main: transform(config.Default, nil), - lruCache: cache.NewLRUCache[string, *D.Msg](cache.WithSize[string, *D.Msg](4096), cache.WithStale[string, *D.Msg](true)), + lruCache: cache.New[string, *D.Msg](cache.WithSize[string, *D.Msg](4096), cache.WithStale[string, *D.Msg](true)), } r := &Resolver{ ipv6: config.IPv6, main: transform(config.Main, defaultResolver), - lruCache: cache.NewLRUCache[string, *D.Msg](cache.WithSize[string, *D.Msg](4096), cache.WithStale[string, *D.Msg](true)), + lruCache: cache.New[string, *D.Msg](cache.WithSize[string, *D.Msg](4096), cache.WithStale[string, *D.Msg](true)), hosts: config.Hosts, } diff --git a/dns/util.go b/dns/util.go index 3e726f3a..5bf09b8f 100644 --- a/dns/util.go +++ b/dns/util.go @@ -3,6 +3,7 @@ package dns import ( "context" "crypto/tls" + "errors" "fmt" "net" "net/netip" @@ -11,7 +12,9 @@ import ( "github.com/Dreamacro/clash/common/cache" "github.com/Dreamacro/clash/common/nnip" + "github.com/Dreamacro/clash/common/picker" "github.com/Dreamacro/clash/component/dialer" + "github.com/Dreamacro/clash/component/resolver" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/tunnel" @@ -71,8 +74,8 @@ func transform(servers []NameServer, resolver *Resolver) []dnsClient { case "quic": if doq, err := newDoQ(resolver, s.Addr, s.ProxyAdapter); err == nil { ret = append(ret, doq) - }else{ - log.Fatalln("DoQ format error: %v",err) + } else { + log.Fatalln("DoQ format error: %v", err) } continue } @@ -208,3 +211,31 @@ func dialContextExtra(ctx context.Context, adapterName string, network string, d return adapter.DialContext(ctx, metadata, opts...) } + +func batchExchange(ctx context.Context, clients []dnsClient, m *D.Msg) (msg *D.Msg, err error) { + fast, ctx := picker.WithTimeout[*D.Msg](ctx, resolver.DefaultDNSTimeout) + for _, client := range clients { + r := client + fast.Go(func() (*D.Msg, error) { + m, err := r.ExchangeContext(ctx, m) + if err != nil { + return nil, err + } else if m.Rcode == D.RcodeServerFailure || m.Rcode == D.RcodeRefused { + return nil, errors.New("server failure") + } + return m, nil + }) + } + + elm := fast.Wait() + if elm == nil { + err := errors.New("all DNS requests failed") + if fErr := fast.Error(); fErr != nil { + err = fmt.Errorf("%w, first error: %s", err, fErr.Error()) + } + return nil, err + } + + msg = elm + return +} diff --git a/go.mod b/go.mod index 03cd4821..57cc35de 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/insomniacslk/dhcp v0.0.0-20221001123530-5308ebe5334c github.com/lucas-clemente/quic-go v0.29.1 github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 + github.com/mdlayher/netlink v1.1.1 github.com/metacubex/sing-wireguard v0.0.0-20221109114053-16c22adda03c github.com/miekg/dns v1.1.50 github.com/oschwald/geoip2-golang v1.8.0 @@ -27,16 +28,16 @@ require ( github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0 github.com/sagernet/wireguard-go v0.0.0-20221108054404-7c2acadba17c github.com/sirupsen/logrus v1.9.0 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.1 github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 go.etcd.io/bbolt v1.3.6 go.uber.org/atomic v1.10.0 go.uber.org/automaxprocs v1.5.1 - golang.org/x/crypto v0.1.0 + golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077 golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 - golang.org/x/net v0.1.0 - golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 - golang.org/x/sys v0.1.0 + golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0 + golang.org/x/sync v0.1.0 + golang.org/x/sys v0.1.1-0.20221102194838-fc697a31fa06 google.golang.org/protobuf v1.28.1 gopkg.in/yaml.v3 v3.0.1 @@ -52,9 +53,9 @@ require ( github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/golang/mock v1.6.0 // indirect - github.com/google/btree v1.1.2 // indirect + github.com/google/btree v1.0.1 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect - github.com/klauspost/cpuid/v2 v2.1.1 // indirect + github.com/klauspost/cpuid/v2 v2.0.12 // indirect github.com/marten-seemann/qpack v0.3.0 // indirect github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect @@ -63,13 +64,12 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e // indirect github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect - github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect - github.com/vishvananda/netns v0.0.0-20220913150850-18c4f4234207 // indirect + github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect + github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/text v0.4.0 // indirect - golang.org/x/time v0.0.0-20220922220347-f3bd1da661af // indirect + golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect golang.org/x/tools v0.1.12 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/go.sum b/go.sum index 9a5d0133..06551cdc 100644 --- a/go.sum +++ b/go.sum @@ -36,8 +36,8 @@ github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= -github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -61,11 +61,12 @@ github.com/insomniacslk/dhcp v0.0.0-20221001123530-5308ebe5334c/go.mod h1:h+MxyH github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= +github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c h1:7cpGGTQO6+OuYQWkueqeXuErSjs1NZtpALpv1x7Mq4g= github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.1.1 h1:t0wUqjowdm8ezddV5k0tLWVklVuvLJpoHeb4WBdydm0= -github.com/klauspost/cpuid/v2 v2.1.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= +github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= @@ -80,6 +81,7 @@ github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQob github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= +github.com/mdlayher/netlink v1.1.1 h1:VqG+Voq9V4uZ+04vjIrcSCWDpf91B1xxbP4QBUmUJE8= github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= @@ -119,17 +121,18 @@ github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1 github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 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.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA= github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= -github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME= -github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= -github.com/vishvananda/netns v0.0.0-20220913150850-18c4f4234207 h1:nn7SOQy8xCu3iXNv7oiBhhEQtbWdnEOMnuKBlHvrqIM= -github.com/vishvananda/netns v0.0.0-20220913150850-18c4f4234207/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= +github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 h1:AHhUwwFJGl27E46OpdJHplZkK09m7aETNBNzhT6t15M= github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -142,8 +145,8 @@ go.uber.org/automaxprocs v1.5.1/go.mod h1:BF4eumQw0P9GtnuxxovUd06vwm1o18oMzFtK66 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077 h1:t5bjOfJPQfaG9NV1imLZM5E2uzaLGs5/NtyMtRNVjQ4= +golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 h1:RjggHMcaTVp0LOVZcW0bo8alwHrOaCrGUDgfWUHhnN4= golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= @@ -163,12 +166,12 @@ golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0 h1:vZ44Ys50wUISbPd+jC8cRLSvhyfX9Ii/ZmDnn/aiJtM= +golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0 h1:cu5kTvlzcw1Q5S9f5ip1/cpiB4nXvw1XYzFPGgzLUOY= -golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190411185658-b44545bcd369/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -191,19 +194,18 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.1-0.20221102194838-fc697a31fa06 h1:E1pm64FqQa4v8dHd/bAneyMkR4hk8LTJhoSlc5mc1cM= +golang.org/x/sys v0.1.1-0.20221102194838-fc697a31fa06/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y= -golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -220,8 +222,7 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/hub/route/server.go b/hub/route/server.go index 7ebc4ceb..62a8c95a 100644 --- a/hub/route/server.go +++ b/hub/route/server.go @@ -9,7 +9,6 @@ import ( "time" C "github.com/Dreamacro/clash/constant" - _ "github.com/Dreamacro/clash/constant/mime" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/tunnel/statistic" @@ -211,16 +210,26 @@ func getLogs(w http.ResponseWriter, r *http.Request) { render.Status(r, http.StatusOK) } + ch := make(chan log.Event, 1024) sub := log.Subscribe() defer log.UnSubscribe(sub) buf := &bytes.Buffer{} - var err error - for elm := range sub { - buf.Reset() - logM := elm + + go func() { + for logM := range sub { + select { + case ch <- logM: + default: + } + } + close(ch) + }() + + for logM := range ch { if logM.LogLevel < level { continue } + buf.Reset() if err := json.NewEncoder(buf).Encode(Log{ Type: logM.Type(), @@ -229,6 +238,7 @@ func getLogs(w http.ResponseWriter, r *http.Request) { break } + var err error if wsConn == nil { _, err = w.Write(buf.Bytes()) w.(http.Flusher).Flush() diff --git a/listener/http/proxy.go b/listener/http/proxy.go index b57ff4f3..1c10732b 100644 --- a/listener/http/proxy.go +++ b/listener/http/proxy.go @@ -5,7 +5,6 @@ import ( "net" "net/http" "strings" - "time" "github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/common/cache" @@ -15,7 +14,7 @@ import ( "github.com/Dreamacro/clash/log" ) -func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache[string, bool]) { +func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.LruCache[string, bool]) { client := newClient(c.RemoteAddr(), in) defer client.CloseIdleConnections() @@ -62,9 +61,9 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache[string, request.RequestURI = "" if isUpgradeRequest(request) { - if resp = handleUpgrade(conn, conn.RemoteAddr(), request, in); resp == nil { - return // hijack connection - } + handleUpgrade(conn, request, in) + + return // hijack connection } removeHopByHopHeaders(request.Header) @@ -99,7 +98,7 @@ func HandleConn(c net.Conn, in chan<- C.ConnContext, cache *cache.Cache[string, _ = conn.Close() } -func authenticate(request *http.Request, cache *cache.Cache[string, bool]) *http.Response { +func authenticate(request *http.Request, cache *cache.LruCache[string, bool]) *http.Response { authenticator := authStore.Authenticator() if authenticator != nil { credential := parseBasicProxyAuthorization(request) @@ -109,11 +108,11 @@ func authenticate(request *http.Request, cache *cache.Cache[string, bool]) *http return resp } - var authed bool - if authed = cache.Get(credential); !authed { + authed, exist := cache.Get(credential) + if !exist { user, pass, err := decodeBasicProxyAuthorization(credential) authed = err == nil && authenticator.Verify(user, pass) - cache.Put(credential, authed, time.Minute) + cache.Set(credential, authed) } if !authed { log.Infoln("Auth failed from %s", request.RemoteAddr) diff --git a/listener/http/server.go b/listener/http/server.go index edbca1b2..bd3a198d 100644 --- a/listener/http/server.go +++ b/listener/http/server.go @@ -4,7 +4,6 @@ import ( "context" "github.com/database64128/tfo-go" "net" - "time" "github.com/Dreamacro/clash/common/cache" C "github.com/Dreamacro/clash/constant" @@ -46,9 +45,9 @@ func NewWithAuthenticate(addr string, in chan<- C.ConnContext, authenticate bool return nil, err } - var c *cache.Cache[string, bool] + var c *cache.LruCache[string, bool] if authenticate { - c = cache.New[string, bool](time.Second * 30) + c = cache.New[string, bool](cache.WithAge[string, bool](30)) } hl := &Listener{ diff --git a/listener/http/upgrade.go b/listener/http/upgrade.go index 251c842a..9032166c 100644 --- a/listener/http/upgrade.go +++ b/listener/http/upgrade.go @@ -6,7 +6,6 @@ import ( "net" "net/http" "strings" - "time" "github.com/Dreamacro/clash/adapter/inbound" N "github.com/Dreamacro/clash/common/net" @@ -26,17 +25,15 @@ func isUpgradeRequest(req *http.Request) bool { return false } -func handleUpgrade(localConn net.Conn, source net.Addr, request *http.Request, in chan<- C.ConnContext) (resp *http.Response) { +func handleUpgrade(conn net.Conn, request *http.Request, in chan<- C.ConnContext) { + defer conn.Close() + removeProxyHeaders(request.Header) removeExtraHTTPHostPort(request) address := request.Host if _, _, err := net.SplitHostPort(address); err != nil { - port := "80" - if request.TLS != nil { - port = "443" - } - address = net.JoinHostPort(address, port) + address = net.JoinHostPort(address, "80") } dstAddr := socks5.ParseAddr(address) @@ -46,9 +43,9 @@ func handleUpgrade(localConn net.Conn, source net.Addr, request *http.Request, i left, right := net.Pipe() - in <- inbound.NewHTTP(dstAddr, source, right) + in <- inbound.NewHTTP(dstAddr, conn.RemoteAddr(), right) - var remoteServer *N.BufferedConn + var bufferedLeft *N.BufferedConn if request.TLS != nil { tlsConn := tls.Client(left, &tls.Config{ ServerName: request.URL.Hostname(), @@ -57,47 +54,36 @@ func handleUpgrade(localConn net.Conn, source net.Addr, request *http.Request, i ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) defer cancel() if tlsConn.HandshakeContext(ctx) != nil { - _ = localConn.Close() _ = left.Close() return } - remoteServer = N.NewBufferedConn(tlsConn) + bufferedLeft = N.NewBufferedConn(tlsConn) } else { - remoteServer = N.NewBufferedConn(left) + bufferedLeft = N.NewBufferedConn(left) } defer func() { - _ = remoteServer.Close() + _ = bufferedLeft.Close() }() - err := request.Write(remoteServer) + err := request.Write(bufferedLeft) if err != nil { - _ = localConn.Close() return } - resp, err = http.ReadResponse(remoteServer.Reader(), request) + resp, err := http.ReadResponse(bufferedLeft.Reader(), request) + if err != nil { + return + } + + removeProxyHeaders(resp.Header) + + err = resp.Write(conn) if err != nil { - _ = localConn.Close() return } if resp.StatusCode == http.StatusSwitchingProtocols { - removeProxyHeaders(resp.Header) - - err = localConn.SetReadDeadline(time.Time{}) // set to not time out - if err != nil { - return - } - - err = resp.Write(localConn) - if err != nil { - return - } - - N.Relay(remoteServer, localConn) // blocking here - _ = localConn.Close() - resp = nil + N.Relay(bufferedLeft, conn) } - return } diff --git a/listener/mixed/mixed.go b/listener/mixed/mixed.go index feaf73aa..acdcff33 100644 --- a/listener/mixed/mixed.go +++ b/listener/mixed/mixed.go @@ -4,7 +4,6 @@ import ( "context" "github.com/database64128/tfo-go" "net" - "time" "github.com/Dreamacro/clash/common/cache" N "github.com/Dreamacro/clash/common/net" @@ -18,8 +17,9 @@ import ( type Listener struct { listener net.Listener addr string - cache *cache.Cache[string, bool] - closed bool + + cache *cache.LruCache[string, bool] + closed bool } // RawAddress implements C.Listener @@ -50,7 +50,7 @@ func New(addr string, inboundTfo bool, in chan<- C.ConnContext) (*Listener, erro ml := &Listener{ listener: l, addr: addr, - cache: cache.New[string, bool](30 * time.Second), + cache: cache.New[string, bool](cache.WithAge[string, bool](30)), } go func() { for { @@ -68,7 +68,7 @@ func New(addr string, inboundTfo bool, in chan<- C.ConnContext) (*Listener, erro return ml, nil } -func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.Cache[string, bool]) { +func handleConn(conn net.Conn, in chan<- C.ConnContext, cache *cache.LruCache[string, bool]) { conn.(*net.TCPConn).SetKeepAlive(true) bufConn := N.NewBufferedConn(conn) diff --git a/listener/tproxy/packet.go b/listener/tproxy/packet.go index d60f0ac2..e86a11ca 100644 --- a/listener/tproxy/packet.go +++ b/listener/tproxy/packet.go @@ -2,13 +2,14 @@ package tproxy import ( "net" + "net/netip" "github.com/Dreamacro/clash/common/pool" ) type packet struct { pc net.PacketConn - lAddr *net.UDPAddr + lAddr netip.AddrPort buf []byte } @@ -18,7 +19,7 @@ func (c *packet) Data() []byte { // WriteBack opens a new socket binding `addr` to write UDP packet back func (c *packet) WriteBack(b []byte, addr net.Addr) (n int, err error) { - tc, err := dialUDP("udp", addr.(*net.UDPAddr), c.lAddr) + tc, err := dialUDP("udp", addr.(*net.UDPAddr).AddrPort(), c.lAddr) if err != nil { n = 0 return @@ -30,7 +31,7 @@ func (c *packet) WriteBack(b []byte, addr net.Addr) (n int, err error) { // LocalAddr returns the source IP/Port of UDP Packet func (c *packet) LocalAddr() net.Addr { - return c.lAddr + return &net.UDPAddr{IP: c.lAddr.Addr().AsSlice(), Port: int(c.lAddr.Port()), Zone: c.lAddr.Addr().Zone()} } func (c *packet) Drop() { diff --git a/listener/tproxy/udp.go b/listener/tproxy/udp.go index 57120785..90d0a97d 100644 --- a/listener/tproxy/udp.go +++ b/listener/tproxy/udp.go @@ -2,6 +2,7 @@ package tproxy import ( "net" + "net/netip" "github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/common/pool" @@ -58,7 +59,7 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) oob := make([]byte, 1024) for { buf := pool.Get(pool.UDPBufferSize) - n, oobn, _, lAddr, err := c.ReadMsgUDP(buf, oob) + n, oobn, _, lAddr, err := c.ReadMsgUDPAddrPort(buf, oob) if err != nil { pool.Put(buf) if rl.closed { @@ -67,10 +68,15 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) continue } - rAddr, err := getOrigDst(oob, oobn) + rAddr, err := getOrigDst(oob[:oobn]) if err != nil { continue } + + if rAddr.Addr().Is4() { + // try to unmap 4in6 address + lAddr = netip.AddrPortFrom(lAddr.Addr().Unmap(), lAddr.Port()) + } handlePacketConn(l, in, buf[:n], lAddr, rAddr) } }() @@ -78,8 +84,8 @@ func NewUDP(addr string, in chan<- *inbound.PacketAdapter) (*UDPListener, error) return rl, nil } -func handlePacketConn(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []byte, lAddr *net.UDPAddr, rAddr *net.UDPAddr) { - target := socks5.ParseAddrToSocksAddr(rAddr) +func handlePacketConn(pc net.PacketConn, in chan<- *inbound.PacketAdapter, buf []byte, lAddr, rAddr netip.AddrPort) { + target := socks5.AddrFromStdAddrPort(rAddr) pkt := &packet{ pc: pc, lAddr: lAddr, diff --git a/listener/tproxy/udp_linux.go b/listener/tproxy/udp_linux.go index 8cda96fd..472a23d3 100644 --- a/listener/tproxy/udp_linux.go +++ b/listener/tproxy/udp_linux.go @@ -3,13 +3,14 @@ package tproxy import ( - "encoding/binary" - "errors" "fmt" "net" + "net/netip" "os" "strconv" "syscall" + + "golang.org/x/sys/unix" ) const ( @@ -19,7 +20,7 @@ const ( // dialUDP acts like net.DialUDP for transparent proxy. // It binds to a non-local address(`lAddr`). -func dialUDP(network string, lAddr *net.UDPAddr, rAddr *net.UDPAddr) (*net.UDPConn, error) { +func dialUDP(network string, lAddr, rAddr netip.AddrPort) (uc *net.UDPConn, err error) { rSockAddr, err := udpAddrToSockAddr(rAddr) if err != nil { return nil, err @@ -35,23 +36,25 @@ func dialUDP(network string, lAddr *net.UDPAddr, rAddr *net.UDPAddr) (*net.UDPCo return nil, err } + defer func() { + if err != nil { + syscall.Close(fd) + } + }() + if err = syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_REUSEADDR, 1); err != nil { - syscall.Close(fd) return nil, err } if err = syscall.SetsockoptInt(fd, syscall.SOL_IP, syscall.IP_TRANSPARENT, 1); err != nil { - syscall.Close(fd) return nil, err } if err = syscall.Bind(fd, lSockAddr); err != nil { - syscall.Close(fd) return nil, err } if err = syscall.Connect(fd, rSockAddr); err != nil { - syscall.Close(fd) return nil, err } @@ -60,35 +63,26 @@ func dialUDP(network string, lAddr *net.UDPAddr, rAddr *net.UDPAddr) (*net.UDPCo c, err := net.FileConn(fdFile) if err != nil { - syscall.Close(fd) return nil, err } return c.(*net.UDPConn), nil } -func udpAddrToSockAddr(addr *net.UDPAddr) (syscall.Sockaddr, error) { - switch { - case addr.IP.To4() != nil: - ip := [4]byte{} - copy(ip[:], addr.IP.To4()) - - return &syscall.SockaddrInet4{Addr: ip, Port: addr.Port}, nil - - default: - ip := [16]byte{} - copy(ip[:], addr.IP.To16()) - - zoneID, err := strconv.ParseUint(addr.Zone, 10, 32) - if err != nil { - zoneID = 0 - } - - return &syscall.SockaddrInet6{Addr: ip, Port: addr.Port, ZoneId: uint32(zoneID)}, nil +func udpAddrToSockAddr(addr netip.AddrPort) (syscall.Sockaddr, error) { + if addr.Addr().Is4() { + return &syscall.SockaddrInet4{Addr: addr.Addr().As4(), Port: int(addr.Port())}, nil } + + zoneID, err := strconv.ParseUint(addr.Addr().Zone(), 10, 32) + if err != nil { + zoneID = 0 + } + + return &syscall.SockaddrInet6{Addr: addr.Addr().As16(), Port: int(addr.Port()), ZoneId: uint32(zoneID)}, nil } -func udpAddrFamily(net string, lAddr, rAddr *net.UDPAddr) int { +func udpAddrFamily(net string, lAddr, rAddr netip.AddrPort) int { switch net[len(net)-1] { case '4': return syscall.AF_INET @@ -96,29 +90,35 @@ func udpAddrFamily(net string, lAddr, rAddr *net.UDPAddr) int { return syscall.AF_INET6 } - if (lAddr == nil || lAddr.IP.To4() != nil) && (rAddr == nil || lAddr.IP.To4() != nil) { + if lAddr.Addr().Is4() && rAddr.Addr().Is4() { return syscall.AF_INET } return syscall.AF_INET6 } -func getOrigDst(oob []byte, oobn int) (*net.UDPAddr, error) { - msgs, err := syscall.ParseSocketControlMessage(oob[:oobn]) +func getOrigDst(oob []byte) (netip.AddrPort, error) { + // oob contains socket control messages which we need to parse. + scms, err := unix.ParseSocketControlMessage(oob) if err != nil { - return nil, err + return netip.AddrPort{}, fmt.Errorf("parse control message: %w", err) } - for _, msg := range msgs { - if msg.Header.Level == syscall.SOL_IP && msg.Header.Type == syscall.IP_RECVORIGDSTADDR { - ip := net.IP(msg.Data[4:8]) - port := binary.BigEndian.Uint16(msg.Data[2:4]) - return &net.UDPAddr{IP: ip, Port: int(port)}, nil - } else if msg.Header.Level == syscall.SOL_IPV6 && msg.Header.Type == IPV6_RECVORIGDSTADDR { - ip := net.IP(msg.Data[8:24]) - port := binary.BigEndian.Uint16(msg.Data[2:4]) - return &net.UDPAddr{IP: ip, Port: int(port)}, nil - } + // retrieve the destination address from the SCM. + sa, err := unix.ParseOrigDstAddr(&scms[0]) + if err != nil { + return netip.AddrPort{}, fmt.Errorf("retrieve destination: %w", err) } - return nil, errors.New("cannot find origDst") + // encode the destination address into a cmsg. + var rAddr netip.AddrPort + switch v := sa.(type) { + case *unix.SockaddrInet4: + rAddr = netip.AddrPortFrom(netip.AddrFrom4(v.Addr), uint16(v.Port)) + case *unix.SockaddrInet6: + rAddr = netip.AddrPortFrom(netip.AddrFrom16(v.Addr), uint16(v.Port)) + default: + return netip.AddrPort{}, fmt.Errorf("unsupported address type: %T", v) + } + + return rAddr, nil } diff --git a/listener/tproxy/udp_other.go b/listener/tproxy/udp_other.go index db4a1409..b35b07dd 100644 --- a/listener/tproxy/udp_other.go +++ b/listener/tproxy/udp_other.go @@ -5,12 +5,13 @@ package tproxy import ( "errors" "net" + "net/netip" ) -func getOrigDst(oob []byte, oobn int) (*net.UDPAddr, error) { - return nil, errors.New("UDP redir not supported on current platform") +func getOrigDst(oob []byte) (netip.AddrPort, error) { + return netip.AddrPort{}, errors.New("UDP redir not supported on current platform") } -func dialUDP(network string, lAddr *net.UDPAddr, rAddr *net.UDPAddr) (*net.UDPConn, error) { +func dialUDP(network string, lAddr, rAddr netip.AddrPort) (*net.UDPConn, error) { return nil, errors.New("UDP redir not supported on current platform") } diff --git a/rules/common/process.go b/rules/common/process.go index 9263c32d..e972d2bc 100644 --- a/rules/common/process.go +++ b/rules/common/process.go @@ -14,7 +14,11 @@ type Process struct { } func (ps *Process) RuleType() C.RuleType { - return C.Process + if ps.nameOnly { + return C.Process + } + + return C.ProcessPath } func (ps *Process) Match(metadata *C.Metadata) (bool, string) { diff --git a/rules/common/uid.go b/rules/common/uid.go index 5a989f67..1457a3d0 100644 --- a/rules/common/uid.go +++ b/rules/common/uid.go @@ -13,7 +13,7 @@ import ( type Uid struct { *Base - uids []utils.Range[int32] + uids []utils.Range[uint32] oUid string adapter string } @@ -26,7 +26,7 @@ func NewUid(oUid, adapter string) (*Uid, error) { return nil, fmt.Errorf("uid rule not support this platform") } - var uidRange []utils.Range[int32] + var uidRange []utils.Range[uint32] for _, u := range strings.Split(oUid, "/") { if u == "" { continue @@ -45,14 +45,14 @@ func NewUid(oUid, adapter string) (*Uid, error) { switch subUidsLen { case 1: - uidRange = append(uidRange, *utils.NewRange(int32(uidStart), int32(uidStart))) + uidRange = append(uidRange, *utils.NewRange(uint32(uidStart), uint32(uidStart))) case 2: uidEnd, err := strconv.ParseUint(strings.Trim(subUids[1], "[ ]"), 10, 32) if err != nil { return nil, errPayload } - uidRange = append(uidRange, *utils.NewRange(int32(uidStart), int32(uidEnd))) + uidRange = append(uidRange, *utils.NewRange(uint32(uidStart), uint32(uidEnd))) } } @@ -76,19 +76,21 @@ func (u *Uid) Match(metadata *C.Metadata) (bool, string) { if err != nil { return false, "" } - var uid int32 + var uid *uint32 if metadata.Uid != nil { - uid = *metadata.Uid + uid = metadata.Uid } else if uid, err = process.FindUid(metadata.NetWork.String(), metadata.SrcIP, int(srcPort)); err == nil { - metadata.Uid = &uid + metadata.Uid = uid } else { log.Warnln("[UID] could not get uid from %s", metadata.String()) return false, "" } - for _, _uid := range u.uids { - if _uid.Contains(uid) { - return true, u.adapter + if uid != nil { + for _, _uid := range u.uids { + if _uid.Contains(*uid) { + return true, u.adapter + } } } return false, "" diff --git a/test/.golangci.yaml b/test/.golangci.yaml index cfaed770..b65afc5e 100644 --- a/test/.golangci.yaml +++ b/test/.golangci.yaml @@ -13,4 +13,4 @@ linters-settings: - prefix(github.com/Dreamacro/clash) - default staticcheck: - go: '1.18' + go: '1.19' diff --git a/test/go.mod b/test/go.mod index d5f6c29e..cc9432da 100644 --- a/test/go.mod +++ b/test/go.mod @@ -4,11 +4,11 @@ go 1.19 require ( github.com/Dreamacro/clash v0.0.0 - github.com/docker/docker v20.10.16+incompatible + github.com/docker/docker v20.10.17+incompatible github.com/docker/go-connections v0.4.0 - github.com/miekg/dns v1.1.49 - github.com/stretchr/testify v1.7.2 - golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e + github.com/miekg/dns v1.1.50 + github.com/stretchr/testify v1.8.1 + golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0 ) replace github.com/Dreamacro/clash => ../ @@ -20,65 +20,66 @@ replace github.com/lucas-clemente/quic-go => github.com/tobyxdd/quic-go v0.27.1- require ( github.com/Microsoft/go-winio v0.5.1 // indirect github.com/cheekybits/genny v1.0.0 // indirect - github.com/cilium/ebpf v0.9.1 // indirect + github.com/cilium/ebpf v0.9.3 // indirect github.com/coreos/go-iptables v0.6.0 // indirect - github.com/database64128/tfo-go v1.1.0 // indirect + github.com/database64128/tfo-go v1.1.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dlclark/regexp2 v1.4.0 // indirect + github.com/dlclark/regexp2 v1.7.0 // indirect github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/go-units v0.4.0 // indirect github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/gofrs/uuid v4.2.0+incompatible // indirect + github.com/gofrs/uuid v4.3.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/google/btree v1.0.1 // indirect github.com/google/gopacket v1.1.19 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/insomniacslk/dhcp v0.0.0-20220504074936-1ca156eafb9f // indirect + github.com/insomniacslk/dhcp v0.0.0-20221001123530-5308ebe5334c // indirect github.com/klauspost/cpuid/v2 v2.0.12 // indirect - github.com/lucas-clemente/quic-go v0.27.2 // indirect + github.com/lucas-clemente/quic-go v0.29.1 // indirect github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // indirect - github.com/marten-seemann/qpack v0.2.1 // indirect + github.com/marten-seemann/qpack v0.3.0 // indirect github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect - github.com/marten-seemann/qtls-go1-17 v0.1.2 // indirect - github.com/marten-seemann/qtls-go1-18 v0.1.2 // indirect - github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect + github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect + github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect + github.com/mdlayher/netlink v1.1.1 // indirect + github.com/metacubex/sing-wireguard v0.0.0-20221109114053-16c22adda03c // indirect + github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c // indirect github.com/morikuni/aec v1.0.0 // indirect github.com/nxadm/tail v1.4.8 // indirect - github.com/onsi/ginkgo v1.16.5 // indirect + github.com/onsi/ginkgo v1.16.4 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.0.2 // indirect - github.com/oschwald/geoip2-golang v1.7.0 // indirect - github.com/oschwald/maxminddb-golang v1.9.0 // indirect + github.com/oschwald/geoip2-golang v1.8.0 // indirect + github.com/oschwald/maxminddb-golang v1.10.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/sagernet/sing v0.0.0-20220627234642-a817f7084d9c // indirect - github.com/sagernet/sing-shadowsocks v0.0.0-20220627234717-689e0165ef2c // indirect - github.com/sagernet/sing-vmess v0.0.0-20220616051646-3d3fc5d01eec // indirect - github.com/sirupsen/logrus v1.8.1 // indirect - github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 // indirect - github.com/vishvananda/netlink v1.2.1-beta.2 // indirect + github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e // indirect + github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect + github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 // indirect + github.com/sagernet/sing v0.0.0-20221008120626-60a9910eefe4 // indirect + github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 // indirect + github.com/sagernet/sing-tun v0.0.0-20221012082254-488c3b75f6fd // indirect + github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0 // indirect + github.com/sagernet/wireguard-go v0.0.0-20221108054404-7c2acadba17c // indirect + github.com/sirupsen/logrus v1.9.0 // indirect + github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect - github.com/xtls/go v0.0.0-20210920065950-d4af136d3672 // indirect + github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 // indirect go.etcd.io/bbolt v1.3.6 // indirect - go.uber.org/atomic v1.9.0 // indirect - golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect - golang.org/x/exp v0.0.0-20220608143224-64259d1afd70 // indirect - golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect - golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect - golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e // indirect - golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab // indirect - golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect - golang.org/x/tools v0.1.10 // indirect - golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df // indirect - golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect - golang.zx2c4.com/wireguard v0.0.0-20220601130007-6a08d81f6bc4 // indirect - golang.zx2c4.com/wireguard/windows v0.5.4-0.20220328111914-004c22c5647e // indirect - google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + go.uber.org/atomic v1.10.0 // indirect + golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077 // indirect + golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 // indirect + golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/sys v0.1.1-0.20221102194838-fc697a31fa06 // indirect + golang.org/x/text v0.4.0 // indirect + golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect + golang.org/x/tools v0.1.12 // indirect + google.golang.org/protobuf v1.28.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - gotest.tools/v3 v3.1.0 // indirect - gvisor.dev/gvisor v0.0.0-20220810234332-45096a971e66 // indirect + gotest.tools/v3 v3.4.0 // indirect + gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c // indirect lukechampine.com/blake3 v1.1.7 // indirect ) diff --git a/test/go.sum b/test/go.sum index adec0f55..4a057a02 100644 --- a/test/go.sum +++ b/test/go.sum @@ -8,10 +8,7 @@ dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1 dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/MetaCubeX/netlink v1.2.0-beta.0.20220529072258-d6853f887820 h1:fGKWZ25VApYnuPZoNeqdH/nZtHa2XMajwH6Yj/OgoVc= -github.com/MetaCubeX/netlink v1.2.0-beta.0.20220529072258-d6853f887820/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= @@ -20,24 +17,23 @@ github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBT github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE= github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ= -github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= -github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= +github.com/cilium/ebpf v0.9.3 h1:5KtxXZU+scyERvkJMEm16TbScVvuuMrlhPly78ZMbSc= +github.com/cilium/ebpf v0.9.3/go.mod h1:w27N4UjpaQ9X/DGrSugxUG+H+NhgntDuPb5lCzxCn8A= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/coreos/go-iptables v0.6.0 h1:is9qnZMPYjLd8LYqmm/qlE+wwEgJIkTYdhV3rfZo4jk= github.com/coreos/go-iptables v0.6.0/go.mod h1:Qe8Bv2Xik5FyTXwgIbLAnv2sWSBmvWdFETJConOQ//Q= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/database64128/tfo-go v1.1.0 h1:VO0polyGNSAmr99nYw9GQeMz7ZOcQ/QbjlTwniHwfTQ= -github.com/database64128/tfo-go v1.1.0/go.mod h1:95pOT8bnV3P2Lmu9upHNWFHz6dYGJ9cr7pnb0tGQAG8= +github.com/database64128/tfo-go v1.1.2 h1:GwxtJp09BdUTVEoeT421t231eNZoGOCRkklbl4WI1kU= +github.com/database64128/tfo-go v1.1.2/go.mod h1:jgrSUPyOvTGQyn6irCOpk7L2W/q/0VLZZcovQiMi+bI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= -github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= +github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68= github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v20.10.16+incompatible h1:2Db6ZR/+FUR3hqPMwnogOPHFn405crbpxvWzKovETOQ= -github.com/docker/docker v20.10.16+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE= +github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= @@ -56,8 +52,8 @@ github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= -github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= +github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -88,7 +84,7 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.4.0/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.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= @@ -104,12 +100,13 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:Fecb github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= -github.com/insomniacslk/dhcp v0.0.0-20220504074936-1ca156eafb9f h1:l1QCwn715k8nYkj4Ql50rzEog3WnMdrd4YYMMwemxEo= -github.com/insomniacslk/dhcp v0.0.0-20220504074936-1ca156eafb9f/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= +github.com/insomniacslk/dhcp v0.0.0-20221001123530-5308ebe5334c h1:OCFM4+DXTWfNlyeoddrTwdup/ztkGSyAMR2UGcPckNQ= +github.com/insomniacslk/dhcp v0.0.0-20221001123530-5308ebe5334c/go.mod h1:h+MxyHxRg9NH3terB1nfRIUaQEcI0XOVkdR9LNBlp8E= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw= github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ= github.com/jsimonetti/rtnetlink v0.0.0-20201009170750-9c6f07d100c1/go.mod h1:hqoO/u39cqLeBLebZ8fWdE96O7FxrAsRYhnVOdgHxok= +github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c h1:7cpGGTQO6+OuYQWkueqeXuErSjs1NZtpALpv1x7Mq4g= github.com/jsimonetti/rtnetlink v0.0.0-20201110080708-d2c240429e6c/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -120,7 +117,6 @@ github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa02 github.com/klauspost/cpuid/v2 v2.0.12 h1:p9dKCg8i4gmOxtv35DvrYoWqYzQrvEVdjQ762Y0OqZE= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -130,29 +126,32 @@ github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0 github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= +github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE= +github.com/marten-seemann/qpack v0.3.0/go.mod h1:cGfKPBiP4a9EQdxCwEwI/GEeWAsjSekBvx/X8mh58+g= github.com/marten-seemann/qtls-go1-16 v0.1.5 h1:o9JrYPPco/Nukd/HpOHMHZoBDXQqoNtUCmny98/1uqQ= github.com/marten-seemann/qtls-go1-16 v0.1.5/go.mod h1:gNpI2Ol+lRS3WwSOtIUUtRwZEQMXjYK+dQSBFbethAk= +github.com/marten-seemann/qtls-go1-17 v0.1.1 h1:DQjHPq+aOzUeh9/lixAGunn6rIOQyWChPSI4+hgW7jc= github.com/marten-seemann/qtls-go1-17 v0.1.1/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= -github.com/marten-seemann/qtls-go1-17 v0.1.2 h1:JADBlm0LYiVbuSySCHeY863dNkcpMmDR7s0bLKJeYlQ= -github.com/marten-seemann/qtls-go1-17 v0.1.2/go.mod h1:C2ekUKcDdz9SDWxec1N/MvcXBpaX9l3Nx67XaR84L5s= github.com/marten-seemann/qtls-go1-18 v0.1.1/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= -github.com/marten-seemann/qtls-go1-18 v0.1.2 h1:JH6jmzbduz0ITVQ7ShevK10Av5+jBEKAHMntXmIV7kM= -github.com/marten-seemann/qtls-go1-18 v0.1.2/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= +github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI= +github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/mdlayher/ethernet v0.0.0-20190606142754-0394541c37b7/go.mod h1:U6ZQobyTjI/tJyq2HG+i/dfSoFUt8/aZCM+GKtmFk/Y= github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA= github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M= github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY= +github.com/mdlayher/netlink v1.1.1 h1:VqG+Voq9V4uZ+04vjIrcSCWDpf91B1xxbP4QBUmUJE8= github.com/mdlayher/netlink v1.1.1/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= github.com/mdlayher/raw v0.0.0-20190606142536-fef19f00fc18/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= github.com/mdlayher/raw v0.0.0-20191009151244-50f2db8cc065/go.mod h1:7EpbotpCmVZcu+KCX4g9WaRNuu11uyhiW7+Le1dKawg= +github.com/metacubex/sing-wireguard v0.0.0-20221109114053-16c22adda03c h1:VHtXDny/TNOF7YDT9d9Qkr+x6K1O4cejXLlyPUXDeXQ= +github.com/metacubex/sing-wireguard v0.0.0-20221109114053-16c22adda03c/go.mod h1:fULJ451x1/XlpIhl+Oo+EPGKla9tFZaqT5dKLrZ+NvM= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= -github.com/miekg/dns v1.1.49 h1:qe0mQU3Z/XpFeE+AEBo2rqaS1IPBJ3anmqZ4XiZJVG8= -github.com/miekg/dns v1.1.49/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc= -github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw= +github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= +github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c h1:RC8WMpjonrBfyAh6VN/POIPtYD5tRAq0qMqCRjQNK+g= +github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c/go.mod h1:9OcmHNQQUTbk4XCffrLgN1NEKc2mh5u++biHVrvHsSU= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= @@ -166,22 +165,22 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= +github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= +github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= +github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= -github.com/oschwald/geoip2-golang v1.7.0 h1:JW1r5AKi+vv2ujSxjKthySK3jo8w8oKWPyXsw+Qs/S8= -github.com/oschwald/geoip2-golang v1.7.0/go.mod h1:mdI/C7iK7NVMcIDDtf4bCKMJ7r0o7UwGeCo9eiitCMQ= -github.com/oschwald/maxminddb-golang v1.9.0 h1:tIk4nv6VT9OiPyrnDAfJS1s1xKDQMZOsGojab6EjC1Y= -github.com/oschwald/maxminddb-golang v1.9.0/go.mod h1:TK+s/Z2oZq0rSl4PSeAEoP0bgm82Cp5HyvYbt8K3zLY= +github.com/oschwald/geoip2-golang v1.8.0 h1:KfjYB8ojCEn/QLqsDU0AzrJ3R5Qa9vFlx3z6SLNcKTs= +github.com/oschwald/geoip2-golang v1.8.0/go.mod h1:R7bRvYjOeaoenAp9sKRS8GX5bJWcZ0laWO5+DauEktw= +github.com/oschwald/maxminddb-golang v1.10.0 h1:Xp1u0ZhqkSuopaKmk1WwHtjF0H9Hd9181uj2MQ5Vndg= +github.com/oschwald/maxminddb-golang v1.10.0/go.mod h1:Y2ELenReaLAZ0b400URyGwvYxHV1dLIxBuyOsyYjHK0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -193,12 +192,23 @@ github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7q github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/sagernet/sing v0.0.0-20220627234642-a817f7084d9c h1:98QC0wtaD648MFPw82KaT1O9LloQgR4ZyIDtNtsno8Y= -github.com/sagernet/sing v0.0.0-20220627234642-a817f7084d9c/go.mod h1:I67R/q5f67xDExL2kL3RLIP7kGJBOPkYXkpRAykgC+E= -github.com/sagernet/sing-shadowsocks v0.0.0-20220627234717-689e0165ef2c h1:Jhgjyb2jXL4GtwJec6/kgeTqaQXsvMiNX2wAkGOSD3I= -github.com/sagernet/sing-shadowsocks v0.0.0-20220627234717-689e0165ef2c/go.mod h1:ng5pxdNnKZWlxzZTXRqWeY0ftzhScPZmjgJGJeRuPYY= -github.com/sagernet/sing-vmess v0.0.0-20220616051646-3d3fc5d01eec h1:jUSfKmyL6K9O2TvIvcVacZ4eNXHYbNSfdph+DRPyVlU= -github.com/sagernet/sing-vmess v0.0.0-20220616051646-3d3fc5d01eec/go.mod h1:jDZ8fJgOea7Y7MMHWgfqwLBVLnhtW2zuxS5wjtDaB84= +github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e h1:5CFRo8FJbCuf5s/eTBdZpmMbn8Fe2eSMLNAYfKanA34= +github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e/go.mod h1:qbt0dWObotCfcjAJJ9AxtFPNSDUfZF+6dCpgKEOBn/g= +github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c6AkmAylhauulqN/c5dnh8/KssrE9c93TQrXldA= +github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61/go.mod h1:QUQ4RRHD6hGGHdFMEtR8T2P6GS6R3D/CXKdaYHKKXms= +github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= +github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= +github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= +github.com/sagernet/sing v0.0.0-20221008120626-60a9910eefe4 h1:LO7xMvMGhYmjQg2vjhTzsODyzs9/WLYu5Per+/8jIeo= +github.com/sagernet/sing v0.0.0-20221008120626-60a9910eefe4/go.mod h1:zvgDYKI+vCAW9RyfyrKTgleI+DOa8lzHMPC7VZo3OL4= +github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4= +github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM= +github.com/sagernet/sing-tun v0.0.0-20221012082254-488c3b75f6fd h1:TtoZDwg09Cpqi+gCmCtL6w4oEUZ5lHz+vHIjdr1UBNY= +github.com/sagernet/sing-tun v0.0.0-20221012082254-488c3b75f6fd/go.mod h1:1u3pjXA9HmH7kRiBJqM3C/zPxrxnCLd3svmqtub/RFU= +github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0 h1:z3kuD3hPNdEq7/wVy5lwE21f+8ZTazBtR81qswxJoCc= +github.com/sagernet/sing-vmess v0.0.0-20221109021549-b446d5bdddf0/go.mod h1:bwhAdSNET1X+j9DOXGj9NIQR39xgcWIk1rOQ9lLD+gM= +github.com/sagernet/wireguard-go v0.0.0-20221108054404-7c2acadba17c h1:qP3ZOHnjZalvqbjundbXiv/YrNlo3HOgrKc+S1QGs0U= +github.com/sagernet/wireguard-go v0.0.0-20221108054404-7c2acadba17c/go.mod h1:euOmN6O5kk9dQmgSS8Df4psAl3TCjxOz0NW60EWkSaI= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= @@ -223,41 +233,42 @@ github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go. github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= -github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s= -github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tobyxdd/quic-go v0.27.1-0.20220512040129-ed2a645d9218 h1:0DEghzcIfYe+7HTuI+zEd/5M+5c/gcepjJWGdcPPIrc= github.com/tobyxdd/quic-go v0.27.1-0.20220512040129-ed2a645d9218/go.mod h1:AzgQoPda7N+3IqMMMkywBKggIFo2KT6pfnlrQ2QieeI= +github.com/u-root/uio v0.0.0-20210528114334-82958018845c h1:BFvcl34IGnw8yvJi8hlqLFo9EshRInwWBs2M5fGWzQA= github.com/u-root/uio v0.0.0-20210528114334-82958018845c/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= -github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4 h1:hl6sK6aFgTLISijk6xIzeqnPzQcsLqqvL6vEfTPinME= -github.com/u-root/uio v0.0.0-20220204230159-dac05f7d2cb4/go.mod h1:LpEX5FO/cB+WF4TYGY1V5qktpaZLkKkSegbr0V4eYXA= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= -github.com/xtls/go v0.0.0-20210920065950-d4af136d3672 h1:4mkzGhKqt3JO1BWYjtD3iRFyAx4ow67hmSqOcGjuxqQ= -github.com/xtls/go v0.0.0-20210920065950-d4af136d3672/go.mod h1:YGGVbz9cOxyKFUmhW7LGaLZaMA0cPlHJinvAmVxEMSU= +github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 h1:AHhUwwFJGl27E46OpdJHplZkK09m7aETNBNzhT6t15M= +github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= +go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -266,11 +277,11 @@ golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/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-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM= -golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077 h1:t5bjOfJPQfaG9NV1imLZM5E2uzaLGs5/NtyMtRNVjQ4= +golang.org/x/crypto v0.1.1-0.20221024173537-a3485e174077/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20220608143224-64259d1afd70 h1:8uGxpY2cLF9H/NSHUiEWUIBZqIcsMzMWIMPCCUkyYgc= -golang.org/x/exp v0.0.0-20220608143224-64259d1afd70/go.mod h1:yh0Ynu2b5ZUe3MQfp2nM0ecK7wsgouWTDN0FNeJuIys= +golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9 h1:RjggHMcaTVp0LOVZcW0bo8alwHrOaCrGUDgfWUHhnN4= +golang.org/x/exp v0.0.0-20220930202632-ec3f01382ef9/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -279,8 +290,8 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -306,8 +317,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ= -golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0 h1:vZ44Ys50wUISbPd+jC8cRLSvhyfX9Ii/ZmDnn/aiJtM= +golang.org/x/net v0.1.1-0.20221102181756-a1278a7f7ee0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -321,8 +332,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ 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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -344,7 +355,6 @@ golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -358,23 +368,24 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e h1:NHvCuwuS43lGnYhten69ZWqi2QOj/CiDNcKbVqwVoew= -golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.1-0.20221102194838-fc697a31fa06 h1:E1pm64FqQa4v8dHd/bAneyMkR4hk8LTJhoSlc5mc1cM= +golang.org/x/sys v0.1.1-0.20221102194838-fc697a31fa06/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 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.8-0.20220124021120-d1c84af989ab h1:eHo2TTVBaAPw9lDGK2Gb9GyPMXT6g7O63W6sx3ylbzU= -golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w= -golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -382,7 +393,6 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -391,20 +401,12 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df h1:5Pf6pFKu98ODmgnpvkJ3kFUOQGGLIzLIkbzUHp47618= -golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= -golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY= -golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= -golang.zx2c4.com/wireguard v0.0.0-20220601130007-6a08d81f6bc4 h1:QlbNZ9SwDAepRQwgeWHLi3rfEMo/kVEU4SmgsNM7HmQ= -golang.zx2c4.com/wireguard v0.0.0-20220601130007-6a08d81f6bc4/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U= -golang.zx2c4.com/wireguard/windows v0.5.4-0.20220328111914-004c22c5647e h1:yV04h6Tx19uDR6LvuEbR19cDU+3QrB9LuGjtF7F5G0w= -golang.zx2c4.com/wireguard/windows v0.5.4-0.20220328111914-004c22c5647e/go.mod h1:1CeiatTZwcwSFA3cAtMm8CQoroviTldnxd7DOgM/vI4= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= @@ -429,12 +431,11 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= @@ -443,17 +444,15 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= -gotest.tools/v3 v3.1.0 h1:rVV8Tcg/8jHUkPUorwjaMTtemIMVXfIPKiOqnhEhakk= -gotest.tools/v3 v3.1.0/go.mod h1:fHy7eyTmJFO5bQbUsEGQ1v4m2J3Jz9eWL54TP2/ZuYQ= +gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= -gvisor.dev/gvisor v0.0.0-20220810234332-45096a971e66 h1:GrHxpIMY0lHZ3Q8rp3m4iOb0pJsnCQ/5AHaN9SXE69E= -gvisor.dev/gvisor v0.0.0-20220810234332-45096a971e66/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM= +gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4= +gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/transport/gun/gun.go b/transport/gun/gun.go index f65a1929..66b95517 100644 --- a/transport/gun/gun.go +++ b/transport/gun/gun.go @@ -18,7 +18,6 @@ import ( "time" "github.com/Dreamacro/clash/common/pool" - C "github.com/Dreamacro/clash/constant" "go.uber.org/atomic" "golang.org/x/net/http2" @@ -168,7 +167,7 @@ func (g *Conn) SetDeadline(t time.Time) error { func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config) *TransportWrap { wrap := TransportWrap{} - dialFunc := func(network, addr string, cfg *tls.Config) (net.Conn, error) { + dialFunc := func(ctx context.Context, network, addr string, cfg *tls.Config) (net.Conn, error) { pconn, err := dialFn(network, addr) if err != nil { return nil, err @@ -176,10 +175,6 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config) *TransportWrap { wrap.remoteAddr = pconn.RemoteAddr() cn := tls.Client(pconn, cfg) - - // fix tls handshake not timeout - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) - defer cancel() if err := cn.HandshakeContext(ctx); err != nil { pconn.Close() return nil, err @@ -193,7 +188,7 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config) *TransportWrap { } wrap.Transport = &http2.Transport{ - DialTLS: dialFunc, + DialTLSContext: dialFunc, TLSClientConfig: tlsConfig, AllowHTTP: false, DisableCompression: true, diff --git a/transport/socks5/socks5.go b/transport/socks5/socks5.go index 2950819a..7d4f11ae 100644 --- a/transport/socks5/socks5.go +++ b/transport/socks5/socks5.go @@ -6,6 +6,7 @@ import ( "errors" "io" "net" + "net/netip" "strconv" "github.com/Dreamacro/clash/component/auth" @@ -398,6 +399,21 @@ func ParseAddrToSocksAddr(addr net.Addr) Addr { return parsed } +func AddrFromStdAddrPort(addrPort netip.AddrPort) Addr { + addr := addrPort.Addr() + if addr.Is4() { + ip4 := addr.As4() + return []byte{AtypIPv4, ip4[0], ip4[1], ip4[2], ip4[3], byte(addrPort.Port() >> 8), byte(addrPort.Port())} + } + + buf := make([]byte, 1+net.IPv6len+2) + buf[0] = AtypIPv6 + copy(buf[1:], addr.AsSlice()) + buf[1+net.IPv6len] = byte(addrPort.Port() >> 8) + buf[1+net.IPv6len+1] = byte(addrPort.Port()) + return buf +} + // DecodeUDPPacket split `packet` to addr payload, and this function is mutable with `packet` func DecodeUDPPacket(packet []byte) (addr Addr, payload []byte, err error) { if len(packet) < 5 { diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index f769dcce..b7b369fd 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -256,10 +256,16 @@ func streamWebsocketConn(conn net.Conn, c *WebsocketConfig, earlyData *bytes.Buf dialer.TLSClientConfig = c.TLSConfig } + u, err := url.Parse(c.Path) + if err != nil { + return nil, fmt.Errorf("parse url %s error: %w", c.Path, err) + } + uri := url.URL{ - Scheme: scheme, - Host: net.JoinHostPort(c.Host, c.Port), - Path: c.Path, + Scheme: scheme, + Host: net.JoinHostPort(c.Host, c.Port), + Path: u.Path, + RawQuery: u.RawQuery, } headers := http.Header{} diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index bdac6cce..2e38da40 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -3,7 +3,6 @@ package tunnel import ( "context" "fmt" - P "github.com/Dreamacro/clash/component/process" "net" "net/netip" "path/filepath" @@ -14,6 +13,7 @@ import ( "github.com/Dreamacro/clash/adapter/inbound" "github.com/Dreamacro/clash/component/nat" + P "github.com/Dreamacro/clash/component/process" "github.com/Dreamacro/clash/component/resolver" "github.com/Dreamacro/clash/component/sniffer" C "github.com/Dreamacro/clash/constant" @@ -276,9 +276,15 @@ func handleUDPConn(packet *inbound.PacketAdapter) { rawPc, err := proxy.ListenPacketContext(ctx, metadata.Pure()) if err != nil { if rule == nil { - log.Warnln("[UDP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error()) + log.Warnln( + "[UDP] dial %s %s --> %s error: %s", + proxy.Name(), + metadata.SourceAddress(), + metadata.RemoteAddress(), + err.Error(), + ) } else { - log.Warnln("[UDP] dial %s (match %s/%s) to %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.RemoteAddress(), err.Error()) + log.Warnln("[UDP] dial %s (match %s/%s) %s --> %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.SourceAddress(), metadata.RemoteAddress(), err.Error()) } return } @@ -351,9 +357,15 @@ func handleTCPConn(connCtx C.ConnContext) { remoteConn, err := proxy.DialContext(ctx, dialMetadata) if err != nil { if rule == nil { - log.Warnln("[TCP] dial %s to %s error: %s", proxy.Name(), metadata.RemoteAddress(), err.Error()) + log.Warnln( + "[TCP] dial %s %s --> %s error: %s", + proxy.Name(), + metadata.SourceAddress(), + metadata.RemoteAddress(), + err.Error(), + ) } else { - log.Warnln("[TCP] dial %s (match %s(%s)) to %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.RemoteAddress(), err.Error()) + log.Warnln("[TCP] dial %s (match %s/%s) %s --> %s error: %s", proxy.Name(), rule.RuleType().String(), rule.Payload(), metadata.SourceAddress(), metadata.RemoteAddress(), err.Error()) } return } @@ -375,7 +387,11 @@ func handleTCPConn(connCtx C.ConnContext) { case mode == Direct: log.Infoln("[TCP] %s --> %s using DIRECT", metadata.SourceDetail(), metadata.RemoteAddress()) default: - log.Infoln("[TCP] %s --> %s doesn't match any rule using DIRECT", metadata.SourceAddress(), metadata.RemoteAddress()) + log.Infoln( + "[TCP] %s --> %s doesn't match any rule using DIRECT", + metadata.SourceAddress(), + metadata.RemoteAddress(), + ) } handleSocket(connCtx, remoteConn) @@ -422,9 +438,7 @@ func match(metadata *C.Metadata) (C.Proxy, C.Rule, error) { } else { metadata.Process = filepath.Base(path) metadata.ProcessPath = path - if uid != -1 { - metadata.Uid = &uid - } + metadata.Uid = uid processFound = true } }