From a7233f603620d0e31ef3651d8eb5c3501d892e57 Mon Sep 17 00:00:00 2001 From: Skyxim Date: Fri, 28 Apr 2023 16:55:35 +0000 Subject: [PATCH 01/62] fix: wildcard matching problem --- component/trie/domain_set.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/component/trie/domain_set.go b/component/trie/domain_set.go index be793ad3..41ca2161 100644 --- a/component/trie/domain_set.go +++ b/component/trie/domain_set.go @@ -104,8 +104,8 @@ func (ss *DomainSet) Has(key string) bool { goto RESTART } } - for ; ; nextBmIdx++ { - if nextBmIdx-nextNodeId < len(ss.labels) && ss.labels[nextBmIdx-nextNodeId] == domainStepByte { + for ; nextBmIdx-nextNodeId < len(ss.labels); nextBmIdx++ { + if ss.labels[nextBmIdx-nextNodeId] == domainStepByte { bmIdx = nextBmIdx nodeId = nextNodeId i = j From 6ecd1c31e5ae292cd891421cdec7153c0b2e2a91 Mon Sep 17 00:00:00 2001 From: Skyxim Date: Sat, 29 Apr 2023 15:44:07 +0000 Subject: [PATCH 02/62] fix: tuic connection error using fast_open --- transport/tuic/client.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/transport/tuic/client.go b/transport/tuic/client.go index af00da03..583eaba7 100644 --- a/transport/tuic/client.go +++ b/transport/tuic/client.go @@ -307,6 +307,10 @@ type earlyConn struct { RequestTimeout time.Duration } +func (conn *earlyConn) ReaderReplaceable() bool { + return false +} + func (conn *earlyConn) response() error { if conn.RequestTimeout > 0 { _ = conn.SetReadDeadline(time.Now().Add(conn.RequestTimeout)) From 19b403da866b00a372760aeae74cd4d0dc507f02 Mon Sep 17 00:00:00 2001 From: H1JK Date: Sun, 30 Apr 2023 18:57:16 +0800 Subject: [PATCH 03/62] refactor: Switch to sing-shadowsocks2 client --- adapter/outbound/shadowsocks.go | 8 +- go.mod | 1 + go.sum | 2 + test/go.mod | 95 ++++++++---- test/go.sum | 263 ++++++++++++++++++-------------- 5 files changed, 214 insertions(+), 155 deletions(-) diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index e2ed24c2..01b0bd46 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -6,7 +6,6 @@ import ( "fmt" "net" "strconv" - "time" N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/structure" @@ -21,8 +20,7 @@ import ( v2rayObfs "github.com/Dreamacro/clash/transport/v2ray-plugin" restlsC "github.com/3andne/restls-client-go" - shadowsocks "github.com/metacubex/sing-shadowsocks" - "github.com/metacubex/sing-shadowsocks/shadowimpl" + "github.com/sagernet/sing-shadowsocks2" "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" "github.com/sagernet/sing/common/uot" @@ -234,7 +232,9 @@ func (ss *ShadowSocks) SupportUOT() bool { func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) { addr := net.JoinHostPort(option.Server, strconv.Itoa(option.Port)) - method, err := shadowimpl.FetchMethod(option.Cipher, option.Password, time.Now) + method, err := shadowsocks.CreateMethod(context.Background(), option.Cipher, shadowsocks.MethodOptions{ + Password: option.Password, + }) if err != nil { return nil, fmt.Errorf("ss %s initialize error: %w", addr, err) } diff --git a/go.mod b/go.mod index 0d4a638e..baad3ea3 100644 --- a/go.mod +++ b/go.mod @@ -30,6 +30,7 @@ require ( github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9 github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e + github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 diff --git a/go.sum b/go.sum index 37cc84b1..08ca5915 100644 --- a/go.sum +++ b/go.sum @@ -149,6 +149,8 @@ github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9 h1:kpgKJbhesj6BBLT github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzlnPxOpuv64jhjz3teIvccu3YMFX4fJI= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc h1:Jvm/7wtYYRP4mrZtUpWJxNxwnntqK+n8e/xgMHkOyP0= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI= github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U= diff --git a/test/go.mod b/test/go.mod index 6cbf50e8..e2e164b7 100644 --- a/test/go.mod +++ b/test/go.mod @@ -6,26 +6,34 @@ require ( github.com/Dreamacro/clash v0.0.0 github.com/docker/docker v20.10.21+incompatible github.com/docker/go-connections v0.4.0 - github.com/miekg/dns v1.1.50 - github.com/stretchr/testify v1.8.1 - golang.org/x/net v0.2.1-0.20221117215542-ecf7fda6a59e + github.com/miekg/dns v1.1.53 + github.com/stretchr/testify v1.8.2 + golang.org/x/net v0.9.0 ) replace github.com/Dreamacro/clash => ../ require ( - github.com/Microsoft/go-winio v0.5.1 // indirect + github.com/3andne/restls-client-go v0.1.4 // indirect + github.com/Microsoft/go-winio v0.6.0 // indirect + github.com/RyuaNerin/go-krypto v1.0.2 // indirect + github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 // indirect github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da // indirect + github.com/andybalholm/brotli v1.0.5 // indirect github.com/cilium/ebpf v0.9.3 // indirect github.com/coreos/go-iptables v0.6.0 // indirect - github.com/database64128/tfo-go/v2 v2.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // 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/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 // indirect + github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 // indirect + github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 // indirect + github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/gofrs/uuid v4.3.1+incompatible // indirect + github.com/gofrs/uuid/v5 v5.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/mock v1.6.0 // indirect github.com/google/btree v1.0.1 // indirect @@ -33,53 +41,74 @@ require ( github.com/google/gopacket v1.1.19 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/gorilla/websocket v1.5.0 // indirect - github.com/insomniacslk/dhcp v0.0.0-20221001123530-5308ebe5334c // indirect - github.com/josharian/native v1.0.0 // indirect + github.com/hashicorp/yamux v0.1.1 // indirect + github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 // indirect + github.com/josharian/native v1.1.0 // indirect github.com/jpillora/backoff v1.0.0 // indirect + github.com/klauspost/compress v1.15.15 // indirect github.com/klauspost/cpuid/v2 v2.0.12 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 // 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 - github.com/mdlayher/netlink v1.7.0 // indirect + github.com/mdlayher/netlink v1.7.2-0.20221213171556-9881fafed8c7 // indirect github.com/mdlayher/socket v0.4.0 // indirect - github.com/metacubex/quic-go v0.31.1-0.20221127023445-9f0ce65a734e // indirect - github.com/metacubex/sing-shadowsocks v0.1.0 // indirect - github.com/metacubex/sing-tun v0.1.0 // indirect - github.com/metacubex/sing-wireguard v0.0.0-20221109114053-16c22adda03c // indirect + github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c // indirect + github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594 // indirect + github.com/metacubex/sing-shadowsocks v0.2.2-0.20230422111054-f54786eee8ba // indirect + github.com/metacubex/sing-tun v0.1.4 // indirect + github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a // indirect github.com/moby/term v0.0.0-20221105221325-4eb28fa6025c // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/mroth/weightedrand/v2 v2.0.0 // indirect + github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect github.com/onsi/ginkgo/v2 v2.2.0 // indirect + github.com/openacid/low v0.1.21 // 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.8.0 // indirect github.com/oschwald/maxminddb-golang v1.10.0 // indirect + github.com/pierrec/lz4/v4 v4.1.14 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/sagernet/abx-go v0.0.0-20220819185957-dba1257d738e // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/quic-go/qpack v0.4.0 // indirect + github.com/quic-go/qtls-go1-19 v0.2.1 // indirect + github.com/quic-go/qtls-go1-20 v0.1.1 // 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.1.0 // indirect - github.com/sagernet/sing-vmess v0.1.0 // indirect - github.com/sagernet/wireguard-go v0.0.0-20221108054404-7c2acadba17c // indirect - github.com/samber/lo v1.35.0 // indirect + github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9 // indirect + github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e // indirect + github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc // indirect + github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b // indirect + github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 // indirect + github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect + github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 // indirect + github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect + github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 // indirect + github.com/samber/lo v1.38.1 // indirect + github.com/shirou/gopsutil/v3 v3.23.3 // indirect + github.com/shoenig/go-m1cpu v0.1.5 // indirect + github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect + github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect + github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e // indirect github.com/sirupsen/logrus v1.9.0 // indirect - github.com/u-root/uio v0.0.0-20210528114334-82958018845c // indirect + github.com/tklauser/go-sysconf v0.3.11 // indirect + github.com/tklauser/numcpus v0.6.0 // indirect + github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 // indirect + github.com/yusufpapurcu/wmi v1.2.2 // indirect + github.com/zhangyunhao116/fastrand v0.3.0 // indirect + gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect go.etcd.io/bbolt v1.3.6 // indirect - go.uber.org/atomic v1.10.0 // indirect - golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a // 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/crypto v0.8.0 // indirect + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect + golang.org/x/mod v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.2.1-0.20221110211117-d684c6f88669 // 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 + golang.org/x/sys v0.7.0 // indirect + golang.org/x/text v0.9.0 // indirect + golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + golang.org/x/tools v0.6.0 // indirect + google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d // indirect gopkg.in/yaml.v3 v3.0.1 // 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 22e24a16..bc4c6a7b 100644 --- a/test/go.sum +++ b/test/go.sum @@ -1,8 +1,17 @@ +github.com/3andne/restls-client-go v0.1.4 h1:kLNC2aSRHPlEVYmTj6EOqJoorCpobEe2toMRSfBF7FU= +github.com/3andne/restls-client-go v0.1.4/go.mod h1:04CGbRk1BwBiEDles8b5mlKgTqIwE5MqF7JDloJV47I= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= -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/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= +github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE= +github.com/RyuaNerin/go-krypto v1.0.2 h1:9KiZrrBs+tDrQ66dNy4nrX6SzntKtSKdm0wKHhdB4WM= +github.com/RyuaNerin/go-krypto v1.0.2/go.mod h1:17LzMeJCgzGTkPH3TmfzRnEJ/yA7ErhTPp9sxIqONtA= +github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344 h1:cDVUiFo+npB0ZASqnw4q90ylaVAbnYyx0JYqK4YcGok= +github.com/Yawning/aez v0.0.0-20211027044916-e49e68abd344/go.mod h1:9pIqrY6SXNL8vjRQE5Hd/OL5GyK/9MrGUWs87z/eFfk= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -10,8 +19,6 @@ 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/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/database64128/tfo-go/v2 v2.0.2 h1:5rGgkJeLEKlNaqredfrPQNLnctn1b+1fq/8tdKdOzJg= -github.com/database64128/tfo-go/v2 v2.0.2/go.mod h1:FDdt4JaAsRU66wsYHxSVytYimPkKIHupVsxM+5DhvjY= 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= @@ -25,94 +32,100 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/fanliao/go-promise v0.0.0-20141029170127-1890db352a72/go.mod h1:PjfxuH4FZdUyfMdtBio2lsRr1AKEaVPwelzuHuh8Lqc= +github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8= +github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I= +github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g= +github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391/go.mod h1:K2R7GhgxrlJzHw2qiPWsCZXf/kXEJN9PLnQK73Ll0po= +github.com/ericlagergren/saferand v0.0.0-20220206064634-960a4dd2bc5c h1:RUzBDdZ+e/HEe2Nh8lYsduiPAZygUfVXJn0Ncj5sHMg= +github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 h1:tlDMEdcPRQKBEz5nGDMvswiajqh7k8ogWRlhRwKy5mY= +github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4= +github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA= +github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010/go.mod h1:JtBcj7sBuTTRupn7c2bFspMDIObMJsVK8TeUvpShPok= github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= 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.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= -github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M= +github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 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.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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.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= -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/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714/go.mod h1:2Goc3h8EklBH5mspfHFxBnEoURQCGzQQH1ga9Myjvis= +github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= +github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -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/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk= -github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 h1:+aAGyK41KRn8jbF2Q7PLL0Sxwg6dShGcQSeCC7nZQ8E= +github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16/go.mod h1:IKrnDWs3/Mqq5n0lI+RxA2sB7MvN/vbMBP3ehXg65UI= +github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= +github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtLA= +github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -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/go.mod h1:huN4d1phzjhlOsNIjFsw2SVRbwIHj3fJDMEU2SDPTmg= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= +github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 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/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= -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-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI= -github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4= -github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE= -github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI= -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/go.mod h1:WTYpFb/WTvlRJAyKhZL5/uy69TDDpHHu2VZmb2XgV7o= -github.com/mdlayher/netlink v1.7.0 h1:ZNGI4V7i1fJ94DPYtWhI/R85i/Q7ZxnuhUJQcJMoodI= -github.com/mdlayher/netlink v1.7.0/go.mod h1:nKO5CSjE/DJjVhk/TNp6vCE1ktVxEA8VEh8drhZzxsQ= -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/mdlayher/netlink v1.7.2-0.20221213171556-9881fafed8c7 h1:HSkXG1bE/qcRuuPlZ2Jyf0Od8HLxOowi7CzKQqNtWn4= +github.com/mdlayher/netlink v1.7.2-0.20221213171556-9881fafed8c7/go.mod h1:1ztDZHGbU5MjN5lNZpkpG8ygndjjWzcojp/H7r6l6QQ= github.com/mdlayher/socket v0.4.0 h1:280wsy40IC9M9q1uPGcLBwXpcTQDtoGwVt+BNoITxIw= github.com/mdlayher/socket v0.4.0/go.mod h1:xxFqz5GRCUN3UEOm9CZqEJsAbe1C8OwSK46NlmWuVoc= -github.com/metacubex/quic-go v0.31.1-0.20221127023445-9f0ce65a734e h1:RnfC6+sShJ3biU2Q2wuh4FxZ8/3fp1QG+1zAfswVehA= -github.com/metacubex/quic-go v0.31.1-0.20221127023445-9f0ce65a734e/go.mod h1:7NPWVTLiX2Ss9q9gBNZaNHsPqZ3Tg/ApyrXxxUYbl78= -github.com/metacubex/sing-shadowsocks v0.1.0 h1:uGBtNkpy4QFlofaNkJf+iFegeLU11VzTUlkC46FHF8A= -github.com/metacubex/sing-shadowsocks v0.1.0/go.mod h1:8pBSYDKVxTtqUtGZyEh4ZpFJXwP6wBVVKrs6oQiOwmQ= -github.com/metacubex/sing-tun v0.1.0 h1:iQj0+0WjJynSKAtfv87wOZlVKWl3w9RvkOSkVe9zuMg= -github.com/metacubex/sing-tun v0.1.0/go.mod h1:l4JyI6RTrlHLQz5vSakg+wxA+LwGVI0Mz5ZtlOv67dA= -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/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= -github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c h1:D62872jiuzC6b+3aI8tqfeyc6YgbfarYKywTnnvXwEM= +github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c/go.mod h1:wqEuzdImyqD2MCGE8CYRJXbB77oSEJeoSSXXdwKjnsE= +github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594 h1:KD96JPdTIayTGGgRl6PuVqo2Bpo6+x3LqDDyqrYDDXw= +github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= +github.com/metacubex/sing-shadowsocks v0.2.2-0.20230422111054-f54786eee8ba h1:He8YwyK600lHAS1xxNsP4k/jnZ8zqQ34XjCGn925+Yk= +github.com/metacubex/sing-shadowsocks v0.2.2-0.20230422111054-f54786eee8ba/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= +github.com/metacubex/sing-tun v0.1.4 h1:OQDBNHjuPKrOprCiK+sLt97YQ0K6b9ZWmJB6z51ibZQ= +github.com/metacubex/sing-tun v0.1.4/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= +github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= +github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a/go.mod h1:Bsw2BvKMMMY0FhZPseDI50ZOalvoUPMKYyGpyqvIIqY= +github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw= +github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= 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/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/mroth/weightedrand/v2 v2.0.0 h1:ADehnByWbliEDIazDAKFdBHoqgHSXAkgyKqM/9YsPoo= +github.com/mroth/weightedrand/v2 v2.0.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 h1:1102pQc2SEPp5+xrS26wEaeb26sZy6k9/ZXlZN+eXE4= +github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7/go.mod h1:UqoUn6cHESlliMhOnKLWr+CBH+e3bazUPvFj1XZwAjs= github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI= github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q= +github.com/openacid/errors v0.8.1/go.mod h1:GUQEJJOJE3W9skHm8E8Y4phdl2LLEN8iD7c5gcGgdx0= +github.com/openacid/low v0.1.21 h1:Tr2GNu4N/+rGRYdOsEHOE89cxUIaDViZbVmKz29uKGo= +github.com/openacid/low v0.1.21/go.mod h1:q+MsKI6Pz2xsCkzV4BLj7NR5M4EX0sGz5AqotpZDVh0= +github.com/openacid/must v0.1.3/go.mod h1:luPiXCuJlEo3UUFQngVQokV0MPGryeYvtCbQPs3U1+I= +github.com/openacid/testkeys v0.1.6/go.mod h1:MfA7cACzBpbiwekivj8StqX0WIRmqlMsci1c37CA3Do= 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= @@ -121,45 +134,79 @@ github.com/oschwald/geoip2-golang v1.8.0 h1:KfjYB8ojCEn/QLqsDU0AzrJ3R5Qa9vFlx3z6 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/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE= +github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo= +github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A= +github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A= +github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= +github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= +github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -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.1.0 h1:FGmaP2BVPYO2IyC/3R1DaQa/zr+kOKHRgWqrmOF+Gu8= -github.com/sagernet/sing v0.1.0/go.mod h1:zvgDYKI+vCAW9RyfyrKTgleI+DOa8lzHMPC7VZo3OL4= -github.com/sagernet/sing-vmess v0.1.0 h1:x0tYBJRbVi7zVXpMEW45eApGpXIDs9ub3raglouAKMo= -github.com/sagernet/sing-vmess v0.1.0/go.mod h1:4lwj6EHrUlgRnKhbmtboGbt+wtl5+tHMv96Ez8LZArw= -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/samber/lo v1.35.0 h1:GlT8CV1GE+v97Y7MLF1wXvX6mjoxZ+hi61tj/ZcQwY0= -github.com/samber/lo v1.35.0/go.mod h1:HLeWcJRRyLKp3+/XBJvOrerCQn9mhdKMHyd7IRlgeQ8= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= +github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9 h1:kpgKJbhesj6BBLTKIfBCJGQPm2ww7pNxn566C6TrHdA= +github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzlnPxOpuv64jhjz3teIvccu3YMFX4fJI= +github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc h1:Jvm/7wtYYRP4mrZtUpWJxNxwnntqK+n8e/xgMHkOyP0= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= +github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= +github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI= +github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U= +github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3/go.mod h1:yKrAr+dqZd64DxBXCHWrYicp+n4qbqO73mtwv3dck8U= +github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as= +github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0= +github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE= +github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9/go.mod h1:FUyTEc5ye5NjKnDTDMuiLF2M6T4BE6y6KZuax//UCEg= +github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 h1:kDUqhc9Vsk5HJuhfIATJ8oQwBmpOZJuozQG7Vk88lL4= +github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2/go.mod h1:JKQMZq/O2qnZjdrt+B57olmfgEmLtY9iiSIEYtWvoSM= +github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2dKX7EQP++1JLNtw4C2TNxd4/ov8YUpOPOSo= +github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0= +github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= +github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE= +github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU= +github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= +github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ= +github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= +github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c= +github.com/shoenig/test v0.6.3/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b h1:rXHg9GrUEtWZhEkrykicdND3VPjlVbYiLdX9J7gimS8= +github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b/go.mod h1:X7qrxNQViEaAN9LNZOPl9PfvQtp3V3c7LTo0dvGi0fM= +github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c h1:DjKMC30y6yjG3IxDaeAj3PCoRr+IsO+bzyT+Se2m2Hk= +github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c/go.mod h1:NV/a66PhhWYVmUMaotlXJ8fIEFB98u+c8l/CQIEFLrU= +github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e h1:ur8uMsPIFG3i4Gi093BQITvwH9znsz2VUZmnmwHvpIo= +github.com/sina-ghaderi/rabbitio v0.0.0-20220730151941-9ce26f4f872e/go.mod h1:+e5fBW3bpPyo+3uLo513gIUblc03egGjMM0+5GKbzK8= 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/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.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/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M= -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/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= +github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= +github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= +github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= +github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA= +github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= github.com/vishvananda/netns v0.0.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= @@ -167,40 +214,35 @@ github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837/go.mod h1:YJTRELIWrGxR1s8x 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= +github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= +github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +github.com/zhangyunhao116/fastrand v0.3.0 h1:7bwe124xcckPulX6fxtr2lFdO2KQqaefdtbk+mqO/Ig= +github.com/zhangyunhao116/fastrand v0.3.0/go.mod h1:0v5KgHho0VE6HU192HnY15de/oDS8UrbBChIFjIhBtc= +gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec h1:FpfFs4EhNehiVfzQttTuxanPIT43FtkkCFypIod8LHo= +gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec/go.mod h1:BZ1RAoRPbCxum9Grlv5aeksu2H8BiKehBYooU2LFiOQ= 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.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ= -go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= 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.3.1-0.20221117191849-2c476679df9a h1:diz9pEYuTIuLMJLs3rGDkeaTsNyRs6duYdFyPAxzE/U= -golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -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/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= +golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 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.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-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190419010253-1f3472d942ba/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -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.2.1-0.20221117215542-ecf7fda6a59e h1:IVOjWZQH/57UDcpX19vSmMz8w3ohroOMWohn8qWpRkg= -golang.org/x/net v0.2.1-0.20221117215542-ecf7fda6a59e/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -208,60 +250,48 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ 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= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190418153312-f0ce4c0180be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606122018-79a91cf218c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/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= -golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.1-0.20221110211117-d684c6f88669 h1:pvmSpBoSG0gD2LLPAX15QHPig8xsbU0tu1sSAmResqk= -golang.org/x/sys v0.2.1-0.20221110211117-d684c6f88669/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= +golang.org/x/sys v0.7.0/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-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= +golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/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= 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= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -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.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 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= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d h1:qp0AnQCvRCMlu9jBjtdbTaaEmThIgZOrbVyDEOcmKhQ= +google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d/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-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -269,8 +299,5 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C 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.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= -gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= -gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c h1:m5lcgWnL3OElQNVyp3qcncItJ2c0sQlSGjYK2+nJTA4= -gvisor.dev/gvisor v0.0.0-20220901235040-6ca97ef2ce1c/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM= lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0= lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA= From d6931ec491dfad55d2043caddcef242939f536dc Mon Sep 17 00:00:00 2001 From: sleshep <9625413+sleshep@users.noreply.github.com> Date: Wed, 26 Apr 2023 15:57:55 +0800 Subject: [PATCH 04/62] feat: support system dns --- config/config.go | 4 +++- dns/system.go | 39 +++++++++++++++++++++++++++++++++++++++ dns/system_windows.go | 7 +++++++ dns/util.go | 8 ++++++++ 4 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 dns/system.go create mode 100644 dns/system_windows.go diff --git a/config/config.go b/config/config.go index 71f4087e..35929849 100644 --- a/config/config.go +++ b/config/config.go @@ -841,7 +841,7 @@ func parseHosts(cfg *RawConfig) (*trie.DomainTrie[resolver.HostValue], error) { } else { ips := make([]netip.Addr, 0) for _, addr := range addrs { - if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback()&&!ipnet.IP.IsLinkLocalUnicast() { + if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && !ipnet.IP.IsLinkLocalUnicast() { if ip, err := netip.ParseAddr(ipnet.IP.String()); err == nil { ips = append(ips, ip) } @@ -938,6 +938,8 @@ func parseNameServer(servers []string, preferH3 bool) ([]dns.NameServer, error) case "quic": addr, err = hostWithDefaultPort(u.Host, "853") dnsNetType = "quic" // DNS over QUIC + case "system": + dnsNetType = "system" // System DNS default: return nil, fmt.Errorf("DNS NameServer[%d] unsupport scheme: %s", idx, u.Scheme) } diff --git a/dns/system.go b/dns/system.go new file mode 100644 index 00000000..2e52f90f --- /dev/null +++ b/dns/system.go @@ -0,0 +1,39 @@ +//go:build !windows + +package dns + +import ( + "fmt" + "os" + "regexp" +) + +var ( + // nameserver xxx.xxx.xxx.xxx + nameserverPattern = regexp.MustCompile(`nameserver\s+(?P\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})`) +) + +func loadSystemResolver() (clients []dnsClient, err error) { + content, err := os.ReadFile("/etc/resolv.conf") + if err != nil { + err = fmt.Errorf("failed to read /etc/resolv.conf: %w", err) + return + } + nameservers := make([]string, 0) + for _, line := range nameserverPattern.FindAllStringSubmatch(string(content), -1) { + addr := line[1] + nameservers = append(nameservers, addr) + } + if len(nameservers) == 0 { + err = fmt.Errorf("no nameserver found in /etc/resolv.conf") + return + } + servers := make([]NameServer, 0, len(nameservers)) + for _, addr := range nameservers { + servers = append(servers, NameServer{ + Addr: fmt.Sprintf("%s:%d", addr, 53), + Net: "udp", + }) + } + return transform(servers, nil), nil +} diff --git a/dns/system_windows.go b/dns/system_windows.go new file mode 100644 index 00000000..3334af96 --- /dev/null +++ b/dns/system_windows.go @@ -0,0 +1,7 @@ +//go:build windows + +package dns + +func loadSystemResolver() (clients []dnsClient, err error) { + return nil, errors.New("system resolver is not yet supported on Windows") +} diff --git a/dns/util.go b/dns/util.go index bfd2e9ed..948687ac 100644 --- a/dns/util.go +++ b/dns/util.go @@ -79,6 +79,14 @@ func transform(servers []NameServer, resolver *Resolver) []dnsClient { case "dhcp": ret = append(ret, newDHCPClient(s.Addr)) continue + case "system": + clients, err := loadSystemResolver() + if err != nil { + log.Warnln("[DNS:system] load system resolver failed: %s", err.Error()) + continue + } + ret = append(ret, clients...) + continue case "quic": if doq, err := newDoQ(resolver, s.Addr, s.ProxyAdapter, s.ProxyName); err == nil { ret = append(ret, doq) From 94f990da31ad7231763afa1b6d74d23b9fa92dd9 Mon Sep 17 00:00:00 2001 From: Larvan2 <78135608+Larvan2@users.noreply.github.com> Date: Mon, 1 May 2023 00:30:47 +0800 Subject: [PATCH 05/62] feat: support system dns for windows --- dns/system_windows.go | 109 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) diff --git a/dns/system_windows.go b/dns/system_windows.go index 3334af96..3e9736d0 100644 --- a/dns/system_windows.go +++ b/dns/system_windows.go @@ -2,6 +2,111 @@ package dns -func loadSystemResolver() (clients []dnsClient, err error) { - return nil, errors.New("system resolver is not yet supported on Windows") +import ( + "fmt" + "net" + "os" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var ( + defaultNS = []string{"114.114.114.114:53"} +) + +type dnsConfig struct { + servers []string // server addresses (in host:port form) to use +} + +func loadSystemResolver() (clients []dnsClient, err error) { + content, err := dnsReadConfig() + if err != nil { + err = fmt.Errorf("failed to read system DNS: %w", err) + } + nameservers := content.servers + if len(nameservers) == 0 { + err = fmt.Errorf("no nameserver found in windows system") + return + } + servers := make([]NameServer, 0, len(nameservers)) + for _, addr := range nameservers { + servers = append(servers, NameServer{ + Addr: addr, + Net: "udp", + }) + } + return transform(servers, nil), nil +} + +func dnsReadConfig() (conf *dnsConfig, err error) { + conf = &dnsConfig{} + defer func() { + if len(conf.servers) == 0 { + conf.servers = defaultNS + } + }() + aas, err := adapterAddresses() + if err != nil { + return conf, err + } + for _, aa := range aas { + for dns := aa.FirstDnsServerAddress; dns != nil; dns = dns.Next { + sa, err := dns.Address.Sockaddr.Sockaddr() + if err != nil { + continue + } + var ip net.IP + switch sa := sa.(type) { + case *syscall.SockaddrInet4: + ip = net.IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3]) + case *syscall.SockaddrInet6: + //ip = make(net.IP, net.IPv6len) + //copy(ip, sa.Addr[:]) + //if ip[0] == 0xfe && ip[1] == 0xc0 { + // // Ignore these fec0/10 ones. Windows seems to + // // populate them as defaults on its misc rando + // // interfaces. + // continue + //} + continue + default: + // Unexpected type. + continue + } + conf.servers = append(conf.servers, net.JoinHostPort(ip.String(), "53")) + } + } + return conf, nil +} + +// adapterAddresses returns a list of IP adapter and address +// structures. The structure contains an IP adapter and flattened +// multiple IP addresses including unicast, anycast and multicast +// addresses. +func adapterAddresses() ([]*windows.IpAdapterAddresses, error) { + var b []byte + l := uint32(15000) // recommended initial size + for { + b = make([]byte, l) + err := windows.GetAdaptersAddresses(syscall.AF_UNSPEC, windows.GAA_FLAG_INCLUDE_PREFIX, 0, (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])), &l) + if err == nil { + if l == 0 { + return nil, nil + } + break + } + if err.(syscall.Errno) != syscall.ERROR_BUFFER_OVERFLOW { + return nil, os.NewSyscallError("getadaptersaddresses", err) + } + if l <= uint32(len(b)) { + return nil, os.NewSyscallError("getadaptersaddresses", err) + } + } + var aas []*windows.IpAdapterAddresses + for aa := (*windows.IpAdapterAddresses)(unsafe.Pointer(&b[0])); aa != nil; aa = aa.Next { + aas = append(aas, aa) + } + return aas, nil } From f35ff24d0c909d3e7a1a549b42ef058541f3b0dc Mon Sep 17 00:00:00 2001 From: Larvan2 <78135608+Larvan2@users.noreply.github.com> Date: Sun, 30 Apr 2023 17:10:57 +0000 Subject: [PATCH 06/62] docs: update config.yaml --- docs/config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/config.yaml b/docs/config.yaml index 97bd40ec..2be8be37 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -177,6 +177,7 @@ dns: - 8.8.8.8 - tls://1.12.12.12:853 - tls://223.5.5.5:853 + - system:// # get DNS server from system's configuration enhanced-mode: fake-ip # or redir-host fake-ip-range: 198.18.0.1/16 # fake-ip 池设置 From 969c235490bcfe5cd14a743a9e624d01ac8f8e1c Mon Sep 17 00:00:00 2001 From: H1JK Date: Mon, 1 May 2023 12:41:36 +0800 Subject: [PATCH 07/62] chore: Remove default DNS in system resolver --- config/config.go | 3 +++ dns/system_windows.go | 10 ---------- dns/util.go | 6 +++++- docs/config.yaml | 2 +- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/config/config.go b/config/config.go index 35929849..6425934e 100644 --- a/config/config.go +++ b/config/config.go @@ -1144,6 +1144,9 @@ func parseDNS(rawCfg *RawConfig, hosts *trie.DomainTrie[resolver.HostValue], rul } // check default nameserver is pure ip addr for _, ns := range dnsCfg.DefaultNameserver { + if ns.Net == "system" { + continue + } host, _, err := net.SplitHostPort(ns.Addr) if err != nil || net.ParseIP(host) == nil { u, err := url.Parse(ns.Addr) diff --git a/dns/system_windows.go b/dns/system_windows.go index 3e9736d0..2e0aa237 100644 --- a/dns/system_windows.go +++ b/dns/system_windows.go @@ -12,10 +12,6 @@ import ( "golang.org/x/sys/windows" ) -var ( - defaultNS = []string{"114.114.114.114:53"} -) - type dnsConfig struct { servers []string // server addresses (in host:port form) to use } @@ -27,7 +23,6 @@ func loadSystemResolver() (clients []dnsClient, err error) { } nameservers := content.servers if len(nameservers) == 0 { - err = fmt.Errorf("no nameserver found in windows system") return } servers := make([]NameServer, 0, len(nameservers)) @@ -42,11 +37,6 @@ func loadSystemResolver() (clients []dnsClient, err error) { func dnsReadConfig() (conf *dnsConfig, err error) { conf = &dnsConfig{} - defer func() { - if len(conf.servers) == 0 { - conf.servers = defaultNS - } - }() aas, err := adapterAddresses() if err != nil { return conf, err diff --git a/dns/util.go b/dns/util.go index 948687ac..d85deb17 100644 --- a/dns/util.go +++ b/dns/util.go @@ -82,7 +82,11 @@ func transform(servers []NameServer, resolver *Resolver) []dnsClient { case "system": clients, err := loadSystemResolver() if err != nil { - log.Warnln("[DNS:system] load system resolver failed: %s", err.Error()) + log.Errorln("[DNS:system] load system resolver failed: %s", err.Error()) + continue + } + if len(clients) == 0 { + log.Errorln("[DNS:system] no nameserver found in system") continue } ret = append(ret, clients...) diff --git a/docs/config.yaml b/docs/config.yaml index 2be8be37..66cab25c 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -177,7 +177,7 @@ dns: - 8.8.8.8 - tls://1.12.12.12:853 - tls://223.5.5.5:853 - - system:// # get DNS server from system's configuration + - system:// # append DNS server from system configuration. If not found, it would print an error log and skip. enhanced-mode: fake-ip # or redir-host fake-ip-range: 198.18.0.1/16 # fake-ip 池设置 From 1eefa71e1f4db3920d40ba209b4e45d92c84fe36 Mon Sep 17 00:00:00 2001 From: H1JK Date: Mon, 1 May 2023 12:58:02 +0800 Subject: [PATCH 08/62] chore: Make slash optional for system resolver --- config/config.go | 4 ++++ docs/config.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/config/config.go b/config/config.go index 6425934e..ff16ac11 100644 --- a/config/config.go +++ b/config/config.go @@ -974,6 +974,10 @@ func parsePureDNSServer(server string) string { return "udp://" + server } + if server == "system" { + return "system://" + } + if ip, err := netip.ParseAddr(server); err != nil { if strings.Contains(server, "://") { return server diff --git a/docs/config.yaml b/docs/config.yaml index 66cab25c..8721340f 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -177,7 +177,7 @@ dns: - 8.8.8.8 - tls://1.12.12.12:853 - tls://223.5.5.5:853 - - system:// # append DNS server from system configuration. If not found, it would print an error log and skip. + - system # append DNS server from system configuration. If not found, it would print an error log and skip. enhanced-mode: fake-ip # or redir-host fake-ip-range: 198.18.0.1/16 # fake-ip 池设置 From 463da578ddae85c6b6c03657377daad490286550 Mon Sep 17 00:00:00 2001 From: sleshep <9625413+sleshep@users.noreply.github.com> Date: Mon, 1 May 2023 21:27:55 +0800 Subject: [PATCH 09/62] fixes #512: geo download failed when startup (#538) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fixes #512: geo download failed when startup - 启动阶段,executor还未初始化tunnel,tcpIn==nil导致geo下载失败,阻塞在 tcpIn <- context * chore: handled by the upper layer * chore: remove useless parameters --------- Co-authored-by: Skyxim --- adapter/inbound/socket.go | 15 ++++++--------- component/http/http.go | 8 ++++++-- listener/inner/tcp.go | 14 ++++++++++---- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/adapter/inbound/socket.go b/adapter/inbound/socket.go index a6b1288c..e41ee925 100644 --- a/adapter/inbound/socket.go +++ b/adapter/inbound/socket.go @@ -30,21 +30,18 @@ func NewSocket(target socks5.Addr, conn net.Conn, source C.Type, additions ...Ad return context.NewConnContext(conn, metadata) } -func NewInner(conn net.Conn, dst string, host string) *context.ConnContext { +func NewInner(conn net.Conn, address string) *context.ConnContext { metadata := &C.Metadata{} metadata.NetWork = C.TCP metadata.Type = C.INNER metadata.DNSMode = C.DNSNormal - metadata.Host = host metadata.Process = C.ClashName - if h, port, err := net.SplitHostPort(dst); err == nil { + if h, port, err := net.SplitHostPort(address); err == nil { metadata.DstPort = port - if host == "" { - if ip, err := netip.ParseAddr(h); err == nil { - metadata.DstIP = ip - } else { - metadata.Host = h - } + if ip, err := netip.ParseAddr(h); err == nil { + metadata.DstIP = ip + } else { + metadata.Host = h } } diff --git a/component/http/http.go b/component/http/http.go index ece7b442..bcede09f 100644 --- a/component/http/http.go +++ b/component/http/http.go @@ -53,8 +53,12 @@ func HttpRequest(ctx context.Context, url, method string, header map[string][]st TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, DialContext: func(ctx context.Context, network, address string) (net.Conn, error) { - conn := inner.HandleTcp(address, "") - return conn, nil + if conn, err := inner.HandleTcp(address); err == nil { + return conn, nil + } else { + d := net.Dialer{} + return d.DialContext(ctx, network, address) + } }, TLSClientConfig: tls.GetDefaultTLSConfig(), } diff --git a/listener/inner/tcp.go b/listener/inner/tcp.go index a7e38588..9ba87e2f 100644 --- a/listener/inner/tcp.go +++ b/listener/inner/tcp.go @@ -1,9 +1,11 @@ package inner import ( + "errors" + "net" + "github.com/Dreamacro/clash/adapter/inbound" C "github.com/Dreamacro/clash/constant" - "net" ) var tcpIn chan<- C.ConnContext @@ -12,9 +14,13 @@ func New(in chan<- C.ConnContext) { tcpIn = in } -func HandleTcp(dst string, host string) net.Conn { +func HandleTcp(address string) (conn net.Conn, err error) { + if tcpIn == nil { + return nil, errors.New("tcp uninitialized") + } + // executor Parsed conn1, conn2 := net.Pipe() - context := inbound.NewInner(conn2, dst, host) + context := inbound.NewInner(conn2, address) tcpIn <- context - return conn1 + return conn1, nil } From f90066f286e02b2349988f838b8b29b0da82f4c9 Mon Sep 17 00:00:00 2001 From: H1JK Date: Mon, 1 May 2023 23:38:02 +0800 Subject: [PATCH 10/62] chore: Update dependencies --- go.mod | 6 +++--- go.sum | 14 ++++++-------- test/go.mod | 6 +++--- test/go.sum | 14 ++++++-------- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/go.mod b/go.mod index baad3ea3..0639de6a 100644 --- a/go.mod +++ b/go.mod @@ -28,16 +28,16 @@ require ( github.com/openacid/low v0.1.21 github.com/oschwald/geoip2-golang v1.8.0 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9 + github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e - github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc + github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9 github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 github.com/samber/lo v1.38.1 - github.com/shirou/gopsutil/v3 v3.23.3 + github.com/shirou/gopsutil/v3 v3.23.4 github.com/sirupsen/logrus v1.9.0 github.com/stretchr/testify v1.8.2 github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 diff --git a/go.sum b/go.sum index 08ca5915..548e19f6 100644 --- a/go.sum +++ b/go.sum @@ -145,12 +145,12 @@ github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6E 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.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9 h1:kpgKJbhesj6BBLTKIfBCJGQPm2ww7pNxn566C6TrHdA= -github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a h1:s2kkd/eR3mWGkYioknxhgQzG8uft4VRx9skhqxxeyVQ= +github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzlnPxOpuv64jhjz3teIvccu3YMFX4fJI= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= -github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc h1:Jvm/7wtYYRP4mrZtUpWJxNxwnntqK+n8e/xgMHkOyP0= -github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9 h1:0Dc1t9ao9EyvRil6l/950PLwND1qO1rgnxwbcctE8KE= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI= github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U= @@ -165,9 +165,8 @@ github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2d github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE= -github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU= -github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= +github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o= +github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8= github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ= github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c= @@ -249,7 +248,6 @@ golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/test/go.mod b/test/go.mod index e2e164b7..1327f84f 100644 --- a/test/go.mod +++ b/test/go.mod @@ -75,9 +75,9 @@ require ( github.com/quic-go/qtls-go1-20 v0.1.1 // 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.2.5-0.20230425211221-a23ffbaeb5b9 // indirect + github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a // indirect github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e // indirect - github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc // indirect + github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9 // indirect github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b // indirect github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 // indirect github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect @@ -85,7 +85,7 @@ require ( github.com/sagernet/utls v0.0.0-20230309024959-6732c2ab36f2 // indirect github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 // indirect github.com/samber/lo v1.38.1 // indirect - github.com/shirou/gopsutil/v3 v3.23.3 // indirect + github.com/shirou/gopsutil/v3 v3.23.4 // indirect github.com/shoenig/go-m1cpu v0.1.5 // indirect github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect diff --git a/test/go.sum b/test/go.sum index bc4c6a7b..b6f03871 100644 --- a/test/go.sum +++ b/test/go.sum @@ -155,12 +155,12 @@ github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6E 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.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9 h1:kpgKJbhesj6BBLTKIfBCJGQPm2ww7pNxn566C6TrHdA= -github.com/sagernet/sing v0.2.5-0.20230425211221-a23ffbaeb5b9/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a h1:s2kkd/eR3mWGkYioknxhgQzG8uft4VRx9skhqxxeyVQ= +github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzlnPxOpuv64jhjz3teIvccu3YMFX4fJI= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= -github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc h1:Jvm/7wtYYRP4mrZtUpWJxNxwnntqK+n8e/xgMHkOyP0= -github.com/sagernet/sing-shadowsocks2 v0.0.0-20230430083720-38321e1355cc/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9 h1:0Dc1t9ao9EyvRil6l/950PLwND1qO1rgnxwbcctE8KE= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI= github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U= @@ -175,9 +175,8 @@ github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2d github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE= -github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU= -github.com/shoenig/go-m1cpu v0.1.4/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= +github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o= +github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8= github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ= github.com/shoenig/go-m1cpu v0.1.5/go.mod h1:Wwvst4LR89UxjeFtLRMrpgRiyY4xPsejnVZym39dbAQ= github.com/shoenig/test v0.6.3 h1:GVXWJFk9PiOjN0KoJ7VrJGH6uLPnqxR7/fe3HUPfE0c= @@ -267,7 +266,6 @@ golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= From d61a5af3351a7c4392bc5fe2b747906952b579ef Mon Sep 17 00:00:00 2001 From: Larvan2 <78135608+Larvan2@users.noreply.github.com> Date: Tue, 2 May 2023 21:35:40 +0800 Subject: [PATCH 11/62] chore: update release note --- .github/workflows/build.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 86352a15..ccbe3dc6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -246,11 +246,8 @@ jobs: Release created at ${{ env.BUILDTIME }} Synchronize ${{ github.ref_name }} branch code updates, keeping only the latest version
- ### release version - `default(not specified in file name)`: compiled with GOAMD64=v3 - `cgo`: support lwip tun stack, compiled with GOAMD64=v1 - `compatible`: compiled with GOAMD64=v1 - Check details between different architectural levels [here](https://github.com/golang/go/wiki/MinimumRequirements#amd64). + [我应该下载哪个文件? / Which file should I download?](https://github.com/MetaCubeX/Clash.Meta/wiki/FAQ) + [查看文档 / Docs](https://metacubex.github.io/Meta-Docs/) EOF - name: Upload Prerelease From 7ae3e78b15ddce72079d3aaa53bacf84bb5f754f Mon Sep 17 00:00:00 2001 From: PuerNya Date: Tue, 2 May 2023 20:55:25 +0800 Subject: [PATCH 12/62] Feat: rewrite http outbound --- adapter/outbound/http.go | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/adapter/outbound/http.go b/adapter/outbound/http.go index 2d5fd899..82fff5bb 100644 --- a/adapter/outbound/http.go +++ b/adapter/outbound/http.go @@ -10,7 +10,6 @@ import ( "io" "net" "net/http" - "net/url" "strconv" "github.com/Dreamacro/clash/component/dialer" @@ -98,34 +97,36 @@ func (h *Http) SupportWithDialer() C.NetWork { func (h *Http) shakeHand(metadata *C.Metadata, rw io.ReadWriter) error { addr := metadata.RemoteAddress() - req := &http.Request{ - Method: http.MethodConnect, - URL: &url.URL{ - Host: addr, - }, - Host: addr, - Header: http.Header{ - "Proxy-Connection": []string{"Keep-Alive"}, - }, + HeaderString := "CONNECT " + addr + " HTTP/1.1\r\n" + tempHeaders := map[string]string{ + "Host": addr, + "User-Agent": "Go-http-client/1.1", + "Proxy-Connection": "Keep-Alive", } - //增加headers - if len(h.option.Headers) != 0 { - for key, value := range h.option.Headers { - req.Header.Add(key, value) - } + for key, value := range h.option.Headers { + tempHeaders[key] = value } if h.user != "" && h.pass != "" { auth := h.user + ":" + h.pass - req.Header.Add("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth))) + tempHeaders["Proxy-Authorization"] = "Basic " + base64.StdEncoding.EncodeToString([]byte(auth)) } - if err := req.Write(rw); err != nil { + for key, value := range tempHeaders { + HeaderString += key + ": " + value + "\r\n" + } + + HeaderString += "\r\n" + + _, err := rw.Write([]byte(HeaderString)) + + if err != nil { return err } - resp, err := http.ReadResponse(bufio.NewReader(rw), req) + resp, err := http.ReadResponse(bufio.NewReader(rw), nil) + if err != nil { return err } From 8c0168d3a8e8a038ee08cf3fba4fda2f1b91c0ae Mon Sep 17 00:00:00 2001 From: Skyxim Date: Fri, 5 May 2023 07:27:36 +0000 Subject: [PATCH 13/62] chore: upgrade dependencies --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 0639de6a..52a7ad10 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e - github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9 + github.com/sagernet/sing-shadowsocks2 v0.0.0-20230503144228-9896afb7d1ba github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 diff --git a/go.sum b/go.sum index 548e19f6..074cfed6 100644 --- a/go.sum +++ b/go.sum @@ -151,6 +151,8 @@ github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzl github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9 h1:0Dc1t9ao9EyvRil6l/950PLwND1qO1rgnxwbcctE8KE= github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230503144228-9896afb7d1ba h1:IyAM9hOexorIEtKWufGZ+YoJWGdTqfJv0iaLb6crY8Q= +github.com/sagernet/sing-shadowsocks2 v0.0.0-20230503144228-9896afb7d1ba/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI= github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U= From bd431fbf49e01819d625c4b6758ea59539c99661 Mon Sep 17 00:00:00 2001 From: H1JK Date: Sat, 6 May 2023 15:49:10 +0800 Subject: [PATCH 14/62] fix: Update unsafe pointer add usage --- component/geodata/strmatcher/mph_matcher.go | 26 +++++++++------------ component/tls/reality.go | 2 +- transport/vless/conn.go | 12 +++++----- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/component/geodata/strmatcher/mph_matcher.go b/component/geodata/strmatcher/mph_matcher.go index 3c10cb49..8d8b0508 100644 --- a/component/geodata/strmatcher/mph_matcher.go +++ b/component/geodata/strmatcher/mph_matcher.go @@ -234,26 +234,26 @@ tail: case s == 0: case s < 4: h ^= uint64(*(*byte)(p)) - h ^= uint64(*(*byte)(add(p, s>>1))) << 8 - h ^= uint64(*(*byte)(add(p, s-1))) << 16 + h ^= uint64(*(*byte)(unsafe.Add(p, s>>1))) << 8 + h ^= uint64(*(*byte)(unsafe.Add(p, s-1))) << 16 h = rotl31(h*m1) * m2 case s <= 8: h ^= uint64(readUnaligned32(p)) - h ^= uint64(readUnaligned32(add(p, s-4))) << 32 + h ^= uint64(readUnaligned32(unsafe.Add(p, s-4))) << 32 h = rotl31(h*m1) * m2 case s <= 16: h ^= readUnaligned64(p) h = rotl31(h*m1) * m2 - h ^= readUnaligned64(add(p, s-8)) + h ^= readUnaligned64(unsafe.Add(p, s-8)) h = rotl31(h*m1) * m2 case s <= 32: h ^= readUnaligned64(p) h = rotl31(h*m1) * m2 - h ^= readUnaligned64(add(p, 8)) + h ^= readUnaligned64(unsafe.Add(p, 8)) h = rotl31(h*m1) * m2 - h ^= readUnaligned64(add(p, s-16)) + h ^= readUnaligned64(unsafe.Add(p, s-16)) h = rotl31(h*m1) * m2 - h ^= readUnaligned64(add(p, s-8)) + h ^= readUnaligned64(unsafe.Add(p, s-8)) h = rotl31(h*m1) * m2 default: v1 := h @@ -263,16 +263,16 @@ tail: for s >= 32 { v1 ^= readUnaligned64(p) v1 = rotl31(v1*m1) * m2 - p = add(p, 8) + p = unsafe.Add(p, 8) v2 ^= readUnaligned64(p) v2 = rotl31(v2*m2) * m3 - p = add(p, 8) + p = unsafe.Add(p, 8) v3 ^= readUnaligned64(p) v3 = rotl31(v3*m3) * m4 - p = add(p, 8) + p = unsafe.Add(p, 8) v4 ^= readUnaligned64(p) v4 = rotl31(v4*m4) * m1 - p = add(p, 8) + p = unsafe.Add(p, 8) s -= 32 } h = v1 ^ v2 ^ v3 ^ v4 @@ -285,10 +285,6 @@ tail: return uintptr(h) } -func add(p unsafe.Pointer, x uintptr) unsafe.Pointer { - return unsafe.Pointer(uintptr(p) + x) -} - func readUnaligned32(p unsafe.Pointer) uint32 { q := (*[4]byte)(p) return uint32(q[0]) | uint32(q[1])<<8 | uint32(q[2])<<16 | uint32(q[3])<<24 diff --git a/component/tls/reality.go b/component/tls/reality.go index dd4f3af8..b8a7fa3a 100644 --- a/component/tls/reality.go +++ b/component/tls/reality.go @@ -141,7 +141,7 @@ var pOffset = utils.MustOK(reflect.TypeOf((*utls.UConn)(nil)).Elem().FieldByName func (c *realityVerifier) VerifyPeerCertificate(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error { //p, _ := reflect.TypeOf(c.Conn).Elem().FieldByName("peerCertificates") - certs := *(*[]*x509.Certificate)(unsafe.Pointer(uintptr(unsafe.Pointer(c.Conn)) + pOffset)) + certs := *(*[]*x509.Certificate)(unsafe.Add(unsafe.Pointer(c.Conn), pOffset)) if pub, ok := certs[0].PublicKey.(ed25519.PublicKey); ok { h := hmac.New(sha512.New, c.authKey) h.Write(pub) diff --git a/transport/vless/conn.go b/transport/vless/conn.go index 6c3714e0..9289afcf 100644 --- a/transport/vless/conn.go +++ b/transport/vless/conn.go @@ -474,34 +474,34 @@ func newConn(conn net.Conn, client *Client, dst *DstAddr) (*Conn, error) { c.writeFilterApplicationData = true c.addons = client.Addons var t reflect.Type - var p uintptr + var p unsafe.Pointer switch underlying := conn.(type) { case *gotls.Conn: //log.Debugln("type tls") c.Conn = underlying.NetConn() c.tlsConn = underlying t = reflect.TypeOf(underlying).Elem() - p = uintptr(unsafe.Pointer(underlying)) + p = unsafe.Pointer(underlying) case *utls.UConn: //log.Debugln("type *utls.UConn") c.Conn = underlying.NetConn() c.tlsConn = underlying t = reflect.TypeOf(underlying.Conn).Elem() - p = uintptr(unsafe.Pointer(underlying.Conn)) + p = unsafe.Pointer(underlying.Conn) case *tlsC.UConn: //log.Debugln("type *tlsC.UConn") c.Conn = underlying.NetConn() c.tlsConn = underlying.UConn t = reflect.TypeOf(underlying.Conn).Elem() //log.Debugln("t:%v", t) - p = uintptr(unsafe.Pointer(underlying.Conn)) + p = unsafe.Pointer(underlying.Conn) default: return nil, fmt.Errorf(`failed to use %s, maybe "security" is not "tls" or "utls"`, client.Addons.Flow) } i, _ := t.FieldByName("input") r, _ := t.FieldByName("rawInput") - c.input = (*bytes.Reader)(unsafe.Pointer(p + i.Offset)) - c.rawInput = (*bytes.Buffer)(unsafe.Pointer(p + r.Offset)) + c.input = (*bytes.Reader)(unsafe.Add(p, i.Offset)) + c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset)) //if _, ok := c.Conn.(*net.TCPConn); !ok { // log.Debugln("XTLS underlying conn is not *net.TCPConn, got %T", c.Conn) //} From 0cb594dd5d481defafb1e8612ad3b37f39413c06 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Wed, 10 May 2023 07:23:49 +0800 Subject: [PATCH 15/62] chore: upgrade dependencies --- adapter/outbound/shadowsocks.go | 2 +- go.mod | 38 +++++++------- go.sum | 87 +++++++++++++++------------------ 3 files changed, 59 insertions(+), 68 deletions(-) diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 01b0bd46..7ee9e634 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -20,7 +20,7 @@ import ( v2rayObfs "github.com/Dreamacro/clash/transport/v2ray-plugin" restlsC "github.com/3andne/restls-client-go" - "github.com/sagernet/sing-shadowsocks2" + "github.com/metacubex/sing-shadowsocks2" "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" "github.com/sagernet/sing/common/uot" diff --git a/go.mod b/go.mod index 52a7ad10..531eeefe 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,9 @@ go 1.19 require ( github.com/3andne/restls-client-go v0.1.4 github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da - github.com/cilium/ebpf v0.9.3 + github.com/cilium/ebpf v0.10.0 github.com/coreos/go-iptables v0.6.0 - github.com/dlclark/regexp2 v1.7.0 + github.com/dlclark/regexp2 v1.9.0 github.com/go-chi/chi/v5 v5.0.8 github.com/go-chi/cors v1.2.1 github.com/go-chi/render v1.0.2 @@ -18,19 +18,19 @@ require ( github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 github.com/jpillora/backoff v1.0.0 github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 - github.com/mdlayher/netlink v1.7.2-0.20221213171556-9881fafed8c7 + github.com/mdlayher/netlink v1.7.2 github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594 - github.com/metacubex/sing-shadowsocks v0.2.2-0.20230422111054-f54786eee8ba - github.com/metacubex/sing-tun v0.1.4 + github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c + github.com/metacubex/sing-shadowsocks2 v0.0.0-20230509232051-858c32776907 + github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a - github.com/miekg/dns v1.1.53 - github.com/mroth/weightedrand/v2 v2.0.0 + github.com/miekg/dns v1.1.54 + github.com/mroth/weightedrand/v2 v2.0.1 github.com/openacid/low v0.1.21 github.com/oschwald/geoip2-golang v1.8.0 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a + github.com/sagernet/sing v0.2.5-0.20230509045155-f60c80c56f21 github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e - github.com/sagernet/sing-shadowsocks2 v0.0.0-20230503144228-9896afb7d1ba github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 @@ -40,16 +40,16 @@ require ( github.com/shirou/gopsutil/v3 v3.23.4 github.com/sirupsen/logrus v1.9.0 github.com/stretchr/testify v1.8.2 - github.com/xtls/go v0.0.0-20220914232946-0441cf4cf837 + github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3 github.com/zhangyunhao116/fastrand v0.3.0 - go.etcd.io/bbolt v1.3.6 + go.etcd.io/bbolt v1.3.7 go.uber.org/automaxprocs v1.5.2 - golang.org/x/crypto v0.8.0 - golang.org/x/exp v0.0.0-20230321023759-10a507213a29 - golang.org/x/net v0.9.0 - golang.org/x/sync v0.1.0 - golang.org/x/sys v0.7.0 - google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d + golang.org/x/crypto v0.9.0 + golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 + golang.org/x/net v0.10.0 + golang.org/x/sync v0.2.0 + golang.org/x/sys v0.8.0 + google.golang.org/protobuf v1.30.0 gopkg.in/yaml.v3 v3.0.1 lukechampine.com/blake3 v1.1.7 ) @@ -76,9 +76,8 @@ require ( github.com/klauspost/compress v1.15.15 // indirect github.com/klauspost/cpuid/v2 v2.0.12 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect - github.com/mdlayher/socket v0.4.0 // indirect + github.com/mdlayher/socket v0.4.1 // indirect github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c // indirect - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 // indirect github.com/onsi/ginkgo/v2 v2.2.0 // indirect github.com/oschwald/maxminddb-golang v1.10.0 // indirect @@ -104,5 +103,4 @@ require ( golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect golang.org/x/tools v0.6.0 // indirect - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect ) diff --git a/go.sum b/go.sum index 074cfed6..ccbc7238 100644 --- a/go.sum +++ b/go.sum @@ -14,15 +14,15 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -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/cilium/ebpf v0.10.0 h1:nk5HPMeoBXtOzbkZBWym+ZWq1GIiHUsBFXxwewXAHLQ= +github.com/cilium/ebpf v0.10.0/go.mod h1:DPiVdY/kT534dgc9ERmvP8mWA+9gvwgKfRvk4nNWnoE= 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/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.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= -github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/dlclark/regexp2 v1.9.0 h1:pTK/l/3qYIKaRXuHnEnIf7Y5NxfRPfpb7dis6/gdlVI= +github.com/dlclark/regexp2 v1.9.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9 h1:/5RkVc9Rc81XmMyVqawCiDyrBHZbLAZgTTCqou4mwj8= github.com/ericlagergren/aegis v0.0.0-20230312195928-b4ce538b56f9/go.mod h1:hkIFzoiIPZYxdFOOLyDho59b7SrDfo+w3h+yWdlg45I= github.com/ericlagergren/polyval v0.0.0-20220411101811-e25bc10ba391 h1:8j2RH289RJplhA6WfdaPqzg1MjH2K8wX5e0uhAxrw2g= @@ -32,7 +32,7 @@ github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1 h1:tlDMEdcPRQKBE github.com/ericlagergren/siv v0.0.0-20220507050439-0b757b3aa5f1/go.mod h1:4RfsapbGx2j/vU5xC/5/9qB3kn9Awp1YDiEnN43QrJ4= github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010 h1:fuGucgPk5dN6wzfnxl3D0D3rVLw4v2SbBT9jb4VnxzA= github.com/ericlagergren/subtle v0.0.0-20220507045147-890d697da010/go.mod h1:JtBcj7sBuTTRupn7c2bFspMDIObMJsVK8TeUvpShPok= -github.com/frankban/quicktest v1.14.0 h1:+cqqvzZV87b4adx/5ayVOaYZ2CrvM4ejQvUdBzPPUss= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= @@ -82,34 +82,32 @@ github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9 github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= -github.com/mdlayher/netlink v1.7.2-0.20221213171556-9881fafed8c7 h1:HSkXG1bE/qcRuuPlZ2Jyf0Od8HLxOowi7CzKQqNtWn4= -github.com/mdlayher/netlink v1.7.2-0.20221213171556-9881fafed8c7/go.mod h1:1ztDZHGbU5MjN5lNZpkpG8ygndjjWzcojp/H7r6l6QQ= -github.com/mdlayher/socket v0.4.0 h1:280wsy40IC9M9q1uPGcLBwXpcTQDtoGwVt+BNoITxIw= -github.com/mdlayher/socket v0.4.0/go.mod h1:xxFqz5GRCUN3UEOm9CZqEJsAbe1C8OwSK46NlmWuVoc= +github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/g= +github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw= +github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U= +github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c h1:D62872jiuzC6b+3aI8tqfeyc6YgbfarYKywTnnvXwEM= github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c/go.mod h1:wqEuzdImyqD2MCGE8CYRJXbB77oSEJeoSSXXdwKjnsE= github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594 h1:KD96JPdTIayTGGgRl6PuVqo2Bpo6+x3LqDDyqrYDDXw= github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= -github.com/metacubex/sing-shadowsocks v0.2.2-0.20230422111054-f54786eee8ba h1:He8YwyK600lHAS1xxNsP4k/jnZ8zqQ34XjCGn925+Yk= -github.com/metacubex/sing-shadowsocks v0.2.2-0.20230422111054-f54786eee8ba/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= -github.com/metacubex/sing-tun v0.1.4 h1:OQDBNHjuPKrOprCiK+sLt97YQ0K6b9ZWmJB6z51ibZQ= -github.com/metacubex/sing-tun v0.1.4/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= +github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= +github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230509232051-858c32776907 h1:GbsWXKtzgn+QvYrdhP3TL/FJPmoxWIs4VjUP53BTaQ0= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230509232051-858c32776907/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= +github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= +github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a/go.mod h1:Bsw2BvKMMMY0FhZPseDI50ZOalvoUPMKYyGpyqvIIqY= -github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw= -github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= -github.com/mroth/weightedrand/v2 v2.0.0 h1:ADehnByWbliEDIazDAKFdBHoqgHSXAkgyKqM/9YsPoo= -github.com/mroth/weightedrand/v2 v2.0.0/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= +github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY= +github.com/mroth/weightedrand/v2 v2.0.1 h1:zrEVDIaau/E4QLOKu02kpg8T8myweFlMGikIgbIdrRA= +github.com/mroth/weightedrand/v2 v2.0.1/go.mod h1:f2faGsfOGOwc1p94wzHKKZyTpcJUW7OJ/9U4yfiNAOU= github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7 h1:1102pQc2SEPp5+xrS26wEaeb26sZy6k9/ZXlZN+eXE4= github.com/oasisprotocol/deoxysii v0.0.0-20220228165953-2091330c22b7/go.mod h1:UqoUn6cHESlliMhOnKLWr+CBH+e3bazUPvFj1XZwAjs= github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI= @@ -138,21 +136,17 @@ github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1T github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI= github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk= github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= 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.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a h1:s2kkd/eR3mWGkYioknxhgQzG8uft4VRx9skhqxxeyVQ= -github.com/sagernet/sing v0.2.5-0.20230501044132-8365dd48a17a/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/sagernet/sing v0.2.5-0.20230509045155-f60c80c56f21 h1:voT2nOCvukNfRLn9KxQYEYSu9/OZsCqEmD6tEFJAnBw= +github.com/sagernet/sing v0.2.5-0.20230509045155-f60c80c56f21/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzlnPxOpuv64jhjz3teIvccu3YMFX4fJI= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= -github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9 h1:0Dc1t9ao9EyvRil6l/950PLwND1qO1rgnxwbcctE8KE= -github.com/sagernet/sing-shadowsocks2 v0.0.0-20230501032827-681c9c4ee0e9/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= -github.com/sagernet/sing-shadowsocks2 v0.0.0-20230503144228-9896afb7d1ba h1:IyAM9hOexorIEtKWufGZ+YoJWGdTqfJv0iaLb6crY8Q= -github.com/sagernet/sing-shadowsocks2 v0.0.0-20230503144228-9896afb7d1ba/go.mod h1:Dpib342FFR68SZ3CSRYxk/zWbanAqRBrCxoLuda5I0A= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI= github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U= @@ -200,8 +194,8 @@ github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gV github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= 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/xtls/go v0.0.0-20230107031059-4610f88d00f3 h1:a3Y4WVjCxwoyO4E2xdNvq577tW8lkSBgyrA8E9+2NtM= +github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg= github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= @@ -209,16 +203,16 @@ github.com/zhangyunhao116/fastrand v0.3.0 h1:7bwe124xcckPulX6fxtr2lFdO2KQqaefdtb github.com/zhangyunhao116/fastrand v0.3.0/go.mod h1:0v5KgHho0VE6HU192HnY15de/oDS8UrbBChIFjIhBtc= gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec h1:FpfFs4EhNehiVfzQttTuxanPIT43FtkkCFypIod8LHo= gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec/go.mod h1:BZ1RAoRPbCxum9Grlv5aeksu2H8BiKehBYooU2LFiOQ= -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.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ= +go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= 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.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= -golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29 h1:ooxPy7fPvB4kwsA2h+iBNHkAbp/4JxTSwCmvdjEYmug= -golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53 h1:5llv2sWeaMSnA3w2kS57ouQQ4pudlXrR0dCgw51QK9o= +golang.org/x/exp v0.0.0-20230425010034-47ecfdc1ba53/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -227,19 +221,18 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 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.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI= +golang.org/x/sync v0.2.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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -250,8 +243,9 @@ golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/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= @@ -270,11 +264,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T 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= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d h1:qp0AnQCvRCMlu9jBjtdbTaaEmThIgZOrbVyDEOcmKhQ= -google.golang.org/protobuf v1.28.2-0.20230118093459-a9481185b34d/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/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-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/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= From 99f7c4f8210978e6a5795ae3d2b365359c4bf82d Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Wed, 10 May 2023 08:31:16 +0800 Subject: [PATCH 16/62] fix: ss aead udp problem --- component/proxydialer/proxydialer.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/component/proxydialer/proxydialer.go b/component/proxydialer/proxydialer.go index fc5cb294..83010f96 100644 --- a/component/proxydialer/proxydialer.go +++ b/component/proxydialer/proxydialer.go @@ -71,7 +71,7 @@ func (p proxyDialer) DialContext(ctx context.Context, network, address string) ( func (p proxyDialer) ListenPacket(ctx context.Context, network, address string, rAddrPort netip.AddrPort) (net.PacketConn, error) { currentMeta := &C.Metadata{Type: C.INNER} - if err := currentMeta.SetRemoteAddress(address); err != nil { + if err := currentMeta.SetRemoteAddress(rAddrPort.String()); err != nil { return nil, err } return p.listenPacket(ctx, currentMeta) diff --git a/go.mod b/go.mod index 531eeefe..26ccf70d 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/mdlayher/netlink v1.7.2 github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594 github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c - github.com/metacubex/sing-shadowsocks2 v0.0.0-20230509232051-858c32776907 + github.com/metacubex/sing-shadowsocks2 v0.0.0-20230510002911-25e95d677383 github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a github.com/miekg/dns v1.1.54 diff --git a/go.sum b/go.sum index ccbc7238..9a3499e3 100644 --- a/go.sum +++ b/go.sum @@ -98,8 +98,8 @@ github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594 h1:KD96JPdTIa github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230509232051-858c32776907 h1:GbsWXKtzgn+QvYrdhP3TL/FJPmoxWIs4VjUP53BTaQ0= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230509232051-858c32776907/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230510002911-25e95d677383 h1:YdLeRuENJZ9QL58Kf/qtMp1wZv9VGQJYMqZ2WEF6/FM= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230510002911-25e95d677383/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= From 67b9314693dad67c9ad0df8345dcbd67aa870989 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Wed, 10 May 2023 09:03:49 +0800 Subject: [PATCH 17/62] fix: tuic can't work with proxy-dialer --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 26ccf70d..f590f382 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/jpillora/backoff v1.0.0 github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 github.com/mdlayher/netlink v1.7.2 - github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594 + github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c github.com/metacubex/sing-shadowsocks2 v0.0.0-20230510002911-25e95d677383 github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 diff --git a/go.sum b/go.sum index 9a3499e3..5054c691 100644 --- a/go.sum +++ b/go.sum @@ -94,8 +94,8 @@ github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA= github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c h1:D62872jiuzC6b+3aI8tqfeyc6YgbfarYKywTnnvXwEM= github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c/go.mod h1:wqEuzdImyqD2MCGE8CYRJXbB77oSEJeoSSXXdwKjnsE= -github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594 h1:KD96JPdTIayTGGgRl6PuVqo2Bpo6+x3LqDDyqrYDDXw= -github.com/metacubex/quic-go v0.33.3-0.20230322045857-901b636b4594/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= +github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 h1:E/sNW9tugFjoBjAkth89MHlKHRaMdo43tGQ3MOPVayQ= +github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= github.com/metacubex/sing-shadowsocks2 v0.0.0-20230510002911-25e95d677383 h1:YdLeRuENJZ9QL58Kf/qtMp1wZv9VGQJYMqZ2WEF6/FM= From 15a8d7c4730abb941961672651216cff81c75383 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Wed, 10 May 2023 09:36:06 +0800 Subject: [PATCH 18/62] chore: better tuic earlyConn impl --- transport/tuic/client.go | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/transport/tuic/client.go b/transport/tuic/client.go index 583eaba7..c18a9049 100644 --- a/transport/tuic/client.go +++ b/transport/tuic/client.go @@ -11,6 +11,7 @@ import ( "sync" "sync/atomic" "time" + "unsafe" "github.com/Dreamacro/clash/common/buf" N "github.com/Dreamacro/clash/common/net" @@ -289,7 +290,8 @@ func (t *clientImpl) DialContextWithDialer(ctx context.Context, metadata *C.Meta return nil, err } - conn := &earlyConn{BufferedConn: N.NewBufferedConn(stream), RequestTimeout: t.RequestTimeout} + bufConn := N.NewBufferedConn(stream) + conn := &earlyConn{ExtendedConn: bufConn, bufConn: bufConn, RequestTimeout: t.RequestTimeout} if !t.FastOpen { err = conn.Response() if err != nil { @@ -300,22 +302,19 @@ func (t *clientImpl) DialContextWithDialer(ctx context.Context, metadata *C.Meta } type earlyConn struct { - *N.BufferedConn - resOnce sync.Once - resErr error + N.ExtendedConn // only expose standard N.ExtendedConn function to outside + bufConn *N.BufferedConn + resOnce sync.Once + resErr error RequestTimeout time.Duration } -func (conn *earlyConn) ReaderReplaceable() bool { - return false -} - func (conn *earlyConn) response() error { if conn.RequestTimeout > 0 { _ = conn.SetReadDeadline(time.Now().Add(conn.RequestTimeout)) } - response, err := ReadResponse(conn) + response, err := ReadResponse(conn.bufConn) if err != nil { _ = conn.Close() return err @@ -340,7 +339,7 @@ func (conn *earlyConn) Read(b []byte) (n int, err error) { if err != nil { return 0, err } - return conn.BufferedConn.Read(b) + return conn.bufConn.Read(b) } func (conn *earlyConn) ReadBuffer(buffer *buf.Buffer) (err error) { @@ -348,7 +347,19 @@ func (conn *earlyConn) ReadBuffer(buffer *buf.Buffer) (err error) { if err != nil { return err } - return conn.BufferedConn.ReadBuffer(buffer) + return conn.bufConn.ReadBuffer(buffer) +} + +func (conn *earlyConn) Upstream() any { + return conn.bufConn +} + +func (conn *earlyConn) ReaderReplaceable() bool { + return atomic.LoadUint32((*uint32)(unsafe.Pointer(&conn.resOnce))) == 1 && conn.resErr == nil +} + +func (conn *earlyConn) WriterReplaceable() bool { + return true } func (t *clientImpl) ListenPacketWithDialer(ctx context.Context, metadata *C.Metadata, dialer C.Dialer, dialFn DialFunc) (net.PacketConn, error) { From 3b291d3fbfd92536c68165efae7728f594759f40 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Wed, 10 May 2023 16:03:28 +0800 Subject: [PATCH 19/62] fix: sing inbound should check needAdditionReadDeadline on udp too --- common/net/sing.go | 2 +- listener/sing/sing.go | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/common/net/sing.go b/common/net/sing.go index 7eb92f03..aa6f6917 100644 --- a/common/net/sing.go +++ b/common/net/sing.go @@ -23,7 +23,7 @@ func NewDeadlineConn(conn net.Conn) ExtendedConn { return deadline.NewFallbackConn(conn) } -func NewDeadlinePacketConn(pc net.PacketConn) net.PacketConn { +func NewDeadlinePacketConn(pc net.PacketConn) network.NetPacketConn { return deadline.NewFallbackPacketConn(bufio.NewPacketConn(pc)) } diff --git a/listener/sing/sing.go b/listener/sing/sing.go index 2ccdfe2d..4a86dc82 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -18,6 +18,7 @@ import ( mux "github.com/sagernet/sing-mux" vmess "github.com/sagernet/sing-vmess" "github.com/sagernet/sing/common/buf" + "github.com/sagernet/sing/common/bufio" "github.com/sagernet/sing/common/bufio/deadline" E "github.com/sagernet/sing/common/exceptions" M "github.com/sagernet/sing/common/metadata" @@ -104,6 +105,9 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. additions = slices.Clone(additions) additions = append(additions, ctxAdditions...) } + if deadline.NeedAdditionalReadDeadline(conn) { + conn = N.NewDeadlinePacketConn(bufio.NewNetPacketConn(conn)) // conn from sing should check NeedAdditionalReadDeadline + } defer func() { _ = conn.Close() }() mutex := sync.Mutex{} conn2 := conn // a new interface to set nil in defer From c58400572ce2c93e523fbc55c7f2f469c3180be0 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Wed, 10 May 2023 22:35:50 +0800 Subject: [PATCH 20/62] chore: sing inbound support WaitReadPacket --- listener/shadowsocks/udp.go | 2 +- listener/sing/sing.go | 21 ++++++++++++++++--- listener/sing_shadowsocks/server.go | 31 +++++++++++++++++++++-------- listener/sing_tun/dns.go | 26 +++++++++++++++++++----- 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/listener/shadowsocks/udp.go b/listener/shadowsocks/udp.go index 3f058406..ef67d4e8 100644 --- a/listener/shadowsocks/udp.go +++ b/listener/shadowsocks/udp.go @@ -32,7 +32,7 @@ func NewUDP(addr string, pickCipher core.Cipher, in chan<- C.PacketAdapter) (*UD conn := pickCipher.PacketConn(l) go func() { for { - buf := pool.Get(pool.RelayBufferSize) + buf := pool.Get(pool.UDPBufferSize) n, remoteAddr, err := conn.ReadFrom(buf) if err != nil { pool.Put(buf) diff --git a/listener/sing/sing.go b/listener/sing/sing.go index 4a86dc82..7292df33 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -116,11 +116,26 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. defer mutex.Unlock() conn2 = nil }() + readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) for { - buff := buf.NewPacket() // do not use stack buffer - dest, err := conn.ReadPacket(buff) + var ( + buff *buf.Buffer + dest M.Socksaddr + err error + ) + newBuffer := func() *buf.Buffer { + buff = buf.NewPacket() // do not use stack buffer + return buff + } + if isReadWaiter { + dest, err = readWaiter.WaitReadPacket(newBuffer) + } else { + dest, err = conn.ReadPacket(newBuffer()) + } if err != nil { - buff.Release() + if buff != nil { + buff.Release() + } if ShouldIgnorePacketError(err) { break } diff --git a/listener/sing_shadowsocks/server.go b/listener/sing_shadowsocks/server.go index c7e05bb5..31b342e8 100644 --- a/listener/sing_shadowsocks/server.go +++ b/listener/sing_shadowsocks/server.go @@ -21,7 +21,7 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/bufio" - "github.com/sagernet/sing/common/metadata" + M "github.com/sagernet/sing/common/metadata" ) type Listener struct { @@ -92,19 +92,34 @@ func New(config LC.ShadowsocksServer, tcpIn chan<- C.ConnContext, udpIn chan<- C go func() { conn := bufio.NewPacketConn(ul) + readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) for { - buff := buf.NewPacket() - remoteAddr, err := conn.ReadPacket(buff) + var ( + buff *buf.Buffer + dest M.Socksaddr + err error + ) + newBuffer := func() *buf.Buffer { + buff = buf.NewPacket() // do not use stack buffer + return buff + } + if isReadWaiter { + dest, err = readWaiter.WaitReadPacket(newBuffer) + } else { + dest, err = conn.ReadPacket(newBuffer()) + } if err != nil { - buff.Release() + if buff != nil { + buff.Release() + } if sl.closed { break } continue } - _ = sl.service.NewPacket(context.TODO(), conn, buff, metadata.Metadata{ + _ = sl.service.NewPacket(context.TODO(), conn, buff, M.Metadata{ Protocol: "shadowsocks", - Source: remoteAddr, + Source: dest, }) } }() @@ -170,9 +185,9 @@ func (l *Listener) AddrList() (addrList []net.Addr) { func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext, additions ...inbound.Addition) { ctx := sing.WithAdditions(context.TODO(), additions...) - err := l.service.NewConnection(ctx, conn, metadata.Metadata{ + err := l.service.NewConnection(ctx, conn, M.Metadata{ Protocol: "shadowsocks", - Source: metadata.ParseSocksaddr(conn.RemoteAddr().String()), + Source: M.ParseSocksaddr(conn.RemoteAddr().String()), }) if err != nil { _ = conn.Close() diff --git a/listener/sing_tun/dns.go b/listener/sing_tun/dns.go index dc33be91..fcf0cc9c 100644 --- a/listener/sing_tun/dns.go +++ b/listener/sing_tun/dns.go @@ -17,6 +17,7 @@ import ( D "github.com/miekg/dns" "github.com/sagernet/sing/common/buf" + "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" "github.com/sagernet/sing/common/network" ) @@ -108,14 +109,29 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. defer mutex.Unlock() conn2 = nil }() + readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) for { - // safe size which is 1232 from https://dnsflagday.net/2020/. - // so 2048 is enough - buff := buf.NewSize(2 * 1024) + var ( + buff *buf.Buffer + dest M.Socksaddr + err error + ) + newBuffer := func() *buf.Buffer { + // safe size which is 1232 from https://dnsflagday.net/2020/. + // so 2048 is enough + buff = buf.NewSize(2 * 1024) + return buff + } _ = conn.SetReadDeadline(time.Now().Add(DefaultDnsReadTimeout)) - dest, err := conn.ReadPacket(buff) + if isReadWaiter { + dest, err = readWaiter.WaitReadPacket(newBuffer) + } else { + dest, err = conn.ReadPacket(newBuffer()) + } if err != nil { - buff.Release() + if buff != nil { + buff.Release() + } if sing.ShouldIgnorePacketError(err) { break } From 98394095e452ab971ff6fa541f6f8844765f910d Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 11 May 2023 00:03:40 +0800 Subject: [PATCH 21/62] fix: udp can't auto close --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f590f382..b51e646a 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/openacid/low v0.1.21 github.com/oschwald/geoip2-golang v1.8.0 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.2.5-0.20230509045155-f60c80c56f21 + github.com/sagernet/sing v0.2.5-0.20230510160026-237a991b46d0 github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 diff --git a/go.sum b/go.sum index 5054c691..abb18231 100644 --- a/go.sum +++ b/go.sum @@ -143,8 +143,8 @@ github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6E 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.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.5-0.20230509045155-f60c80c56f21 h1:voT2nOCvukNfRLn9KxQYEYSu9/OZsCqEmD6tEFJAnBw= -github.com/sagernet/sing v0.2.5-0.20230509045155-f60c80c56f21/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/sagernet/sing v0.2.5-0.20230510160026-237a991b46d0 h1:NS4U+yQ4ToyRqFvCS91BM1D6fQbriW1qvioxSj5PvI4= +github.com/sagernet/sing v0.2.5-0.20230510160026-237a991b46d0/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzlnPxOpuv64jhjz3teIvccu3YMFX4fJI= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= From d9fa051dd8dd47a948bb2eb74b0f17040a1b08c4 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 11 May 2023 11:30:20 +0800 Subject: [PATCH 22/62] chore: drop bufio.Reader in BufferedConn to let gc can clean up its internal buf --- common/net/bufconn.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/net/bufconn.go b/common/net/bufconn.go index 2ff73c82..6da2d9d1 100644 --- a/common/net/bufconn.go +++ b/common/net/bufconn.go @@ -62,7 +62,7 @@ func (c *BufferedConn) Buffered() int { } func (c *BufferedConn) ReadBuffer(buffer *buf.Buffer) (err error) { - if c.r.Buffered() > 0 { + if c.r != nil && c.r.Buffered() > 0 { _, err = buffer.ReadOnceFrom(c.r) return } @@ -70,10 +70,11 @@ func (c *BufferedConn) ReadBuffer(buffer *buf.Buffer) (err error) { } func (c *BufferedConn) ReadCached() *buf.Buffer { // call in sing/common/bufio.Copy - if c.r.Buffered() > 0 { + if c.r != nil && c.r.Buffered() > 0 { length := c.r.Buffered() b, _ := c.r.Peek(length) _, _ = c.r.Discard(length) + c.r = nil // drop bufio.Reader to let gc can clean up its internal buf return buf.As(b) } return nil @@ -84,7 +85,7 @@ func (c *BufferedConn) Upstream() any { } func (c *BufferedConn) ReaderReplaceable() bool { - if c.r.Buffered() > 0 { + if c.r != nil && c.r.Buffered() > 0 { return false } return true From 75cd72385ab67b6d60388c790e8f0ff3b539cbc4 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 11 May 2023 13:47:51 +0800 Subject: [PATCH 23/62] chore: decrease direct udp read memory used for no-windows platform --- adapter/outbound/base.go | 18 ++++++++-- adapter/outbound/direct.go | 8 +---- common/net/packet.go | 68 ++++++++++++++++++++++++++++++++++++ common/net/packet_posix.go | 64 +++++++++++++++++++++++++++++++++ common/net/packet_windows.go | 15 ++++++++ constant/adapters.go | 2 +- tunnel/connection.go | 10 +++--- tunnel/statistic/tracker.go | 10 ++++++ 8 files changed, 178 insertions(+), 17 deletions(-) create mode 100644 common/net/packet.go create mode 100644 common/net/packet_posix.go create mode 100644 common/net/packet_windows.go diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index 367638b8..e4a553b9 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -220,7 +220,7 @@ func NewConn(c net.Conn, a C.ProxyAdapter) C.Conn { } type packetConn struct { - net.PacketConn + N.EnhancePacketConn chain C.Chain adapterName string connID string @@ -242,15 +242,27 @@ func (c *packetConn) AppendToChains(a C.ProxyAdapter) { } func (c *packetConn) LocalAddr() net.Addr { - lAddr := c.PacketConn.LocalAddr() + lAddr := c.EnhancePacketConn.LocalAddr() return N.NewCustomAddr(c.adapterName, c.connID, lAddr) // make quic-go's connMultiplexer happy } +func (c *packetConn) Upstream() any { + return c.EnhancePacketConn +} + +func (c *packetConn) WriterReplaceable() bool { + return true +} + +func (c *packetConn) ReaderReplaceable() bool { + return true +} + func newPacketConn(pc net.PacketConn, a C.ProxyAdapter) C.PacketConn { if _, ok := pc.(syscall.Conn); !ok { // exclusion system conn like *net.UDPConn pc = N.NewDeadlinePacketConn(pc) // most conn from outbound can't handle readDeadline correctly } - return &packetConn{pc, []string{a.Name()}, a.Name(), utils.NewUUIDV4().String(), parseRemoteDestination(a.Addr())} + return &packetConn{N.NewEnhancePacketConn(pc), []string{a.Name()}, a.Name(), utils.NewUUIDV4().String(), parseRemoteDestination(a.Addr())} } func parseRemoteDestination(addr string) string { diff --git a/adapter/outbound/direct.go b/adapter/outbound/direct.go index eae37d7a..94b59cd0 100644 --- a/adapter/outbound/direct.go +++ b/adapter/outbound/direct.go @@ -3,8 +3,6 @@ package outbound import ( "context" "errors" - "net" - "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/resolver" C "github.com/Dreamacro/clash/constant" @@ -39,11 +37,7 @@ func (d *Direct) ListenPacketContext(ctx context.Context, metadata *C.Metadata, if err != nil { return nil, err } - return newPacketConn(&directPacketConn{pc}, d), nil -} - -type directPacketConn struct { - net.PacketConn + return newPacketConn(pc, d), nil } func NewDirect() *Direct { diff --git a/common/net/packet.go b/common/net/packet.go new file mode 100644 index 00000000..30f1104a --- /dev/null +++ b/common/net/packet.go @@ -0,0 +1,68 @@ +package net + +import ( + "net" + + "github.com/Dreamacro/clash/common/pool" +) + +type EnhancePacketConn interface { + net.PacketConn + WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) + Upstream() any +} + +func NewEnhancePacketConn(pc net.PacketConn) EnhancePacketConn { + if udpConn, isUDPConn := pc.(*net.UDPConn); isUDPConn { + return &enhanceUDPConn{UDPConn: udpConn} + } + return &enhancePacketConn{PacketConn: pc} +} + +type enhancePacketConn struct { + net.PacketConn +} + +func (c *enhancePacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + return waitReadFrom(c.PacketConn) +} + +func (c *enhancePacketConn) Upstream() any { + return c.PacketConn +} + +func (c *enhancePacketConn) WriterReplaceable() bool { + return true +} + +func (c *enhancePacketConn) ReaderReplaceable() bool { + return true +} + +func (c *enhanceUDPConn) Upstream() any { + return c.UDPConn +} + +func (c *enhanceUDPConn) WriterReplaceable() bool { + return true +} + +func (c *enhanceUDPConn) ReaderReplaceable() bool { + return true +} + +func waitReadFrom(pc net.PacketConn) (data []byte, put func(), addr net.Addr, err error) { + readBuf := pool.Get(pool.UDPBufferSize) + put = func() { + _ = pool.Put(readBuf) + } + var readN int + readN, addr, err = pc.ReadFrom(readBuf) + if readN > 0 { + data = readBuf[:readN] + } else { + put() + put = nil + } + return +} diff --git a/common/net/packet_posix.go b/common/net/packet_posix.go new file mode 100644 index 00000000..18c72a1c --- /dev/null +++ b/common/net/packet_posix.go @@ -0,0 +1,64 @@ +//go:build !windows + +package net + +import ( + "io" + "net" + "strconv" + "syscall" + + "github.com/Dreamacro/clash/common/pool" +) + +type enhanceUDPConn struct { + *net.UDPConn + rawConn syscall.RawConn +} + +func (c *enhanceUDPConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + if c.rawConn == nil { + c.rawConn, _ = c.UDPConn.SyscallConn() + } + var readErr error + err = c.rawConn.Read(func(fd uintptr) (done bool) { + readBuf := pool.Get(pool.UDPBufferSize) + put = func() { + _ = pool.Put(readBuf) + } + var readFrom syscall.Sockaddr + var readN int + readN, _, _, readFrom, readErr = syscall.Recvmsg(int(fd), readBuf, nil, 0) + if readN > 0 { + data = readBuf[:readN] + } else { + put() + put = nil + } + if readErr == syscall.EAGAIN { + return false + } + if readFrom != nil { + switch from := readFrom.(type) { + case *syscall.SockaddrInet4: + ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 4 bytes + addr = &net.UDPAddr{IP: ip[:], Port: from.Port} + case *syscall.SockaddrInet6: + ip := from.Addr // copy from.Addr; ip escapes, so this line allocates 16 bytes + addr = &net.UDPAddr{IP: ip[:], Port: from.Port, Zone: strconv.FormatInt(int64(from.ZoneId), 10)} + } + } + if readN == 0 { + readErr = io.EOF + } + return true + }) + if err != nil { + return + } + if readErr != nil { + err = readErr + return + } + return +} diff --git a/common/net/packet_windows.go b/common/net/packet_windows.go new file mode 100644 index 00000000..a5bf75aa --- /dev/null +++ b/common/net/packet_windows.go @@ -0,0 +1,15 @@ +//go:build windows + +package net + +import ( + "net" +) + +type enhanceUDPConn struct { + *net.UDPConn +} + +func (c *enhanceUDPConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + return waitReadFrom(c.UDPConn) +} diff --git a/constant/adapters.go b/constant/adapters.go index 2a2c68c1..73877dec 100644 --- a/constant/adapters.go +++ b/constant/adapters.go @@ -81,7 +81,7 @@ type Conn interface { } type PacketConn interface { - net.PacketConn + N.EnhancePacketConn Connection // Deprecate WriteWithMetadata because of remote resolve DNS cause TURN failed // WriteWithMetadata(p []byte, metadata *Metadata) (n int, err error) diff --git a/tunnel/connection.go b/tunnel/connection.go index c64a5266..c95e33f2 100644 --- a/tunnel/connection.go +++ b/tunnel/connection.go @@ -7,7 +7,6 @@ import ( "time" N "github.com/Dreamacro/clash/common/net" - "github.com/Dreamacro/clash/common/pool" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" ) @@ -27,18 +26,16 @@ func handleUDPToRemote(packet C.UDPPacket, pc C.PacketConn, metadata *C.Metadata return nil } -func handleUDPToLocal(packet C.UDPPacket, pc net.PacketConn, key string, oAddr, fAddr netip.Addr) { - buf := pool.Get(pool.UDPBufferSize) +func handleUDPToLocal(packet C.UDPPacket, pc N.EnhancePacketConn, key string, oAddr, fAddr netip.Addr) { defer func() { _ = pc.Close() closeAllLocalCoon(key) natTable.Delete(key) - _ = pool.Put(buf) }() for { _ = pc.SetReadDeadline(time.Now().Add(udpTimeout)) - n, from, err := pc.ReadFrom(buf) + data, put, from, err := pc.WaitReadFrom() if err != nil { return } @@ -54,7 +51,8 @@ func handleUDPToLocal(packet C.UDPPacket, pc net.PacketConn, key string, oAddr, } } - _, err = packet.WriteBack(buf[:n], fromUDPAddr) + _, err = packet.WriteBack(data, fromUDPAddr) + put() if err != nil { return } diff --git a/tunnel/statistic/tracker.go b/tunnel/statistic/tracker.go index 170cbc99..685b5e90 100644 --- a/tunnel/statistic/tracker.go +++ b/tunnel/statistic/tracker.go @@ -186,6 +186,16 @@ func (ut *udpTracker) ReadFrom(b []byte) (int, net.Addr, error) { return n, addr, err } +func (ut *udpTracker) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + data, put, addr, err = ut.PacketConn.WaitReadFrom() + download := int64(len(data)) + if ut.pushToManager { + ut.manager.PushDownloaded(download) + } + ut.DownloadTotal.Add(download) + return +} + func (ut *udpTracker) WriteTo(b []byte, addr net.Addr) (int, error) { n, err := ut.PacketConn.WriteTo(b, addr) upload := int64(n) From e404695a0de07a338161829d87262c76d4827a03 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 11 May 2023 15:34:28 +0800 Subject: [PATCH 24/62] fix: mux's udp should add write lock --- adapter/outbound/singmux.go | 2 +- adapter/outbound/vless.go | 13 +++++++------ adapter/outbound/vmess.go | 13 +------------ common/net/packet.go | 20 ++++++++++++++++++++ 4 files changed, 29 insertions(+), 19 deletions(-) diff --git a/adapter/outbound/singmux.go b/adapter/outbound/singmux.go index acfdfe99..555a0ecb 100644 --- a/adapter/outbound/singmux.go +++ b/adapter/outbound/singmux.go @@ -92,7 +92,7 @@ func (s *SingMux) ListenPacketContext(ctx context.Context, metadata *C.Metadata, if pc == nil { return nil, E.New("packetConn is nil") } - return newPacketConn(CN.NewRefPacketConn(pc, s), s.ProxyAdapter), nil + return newPacketConn(CN.NewRefPacketConn(CN.NewThreadSafePacketConn(pc), s), s.ProxyAdapter), nil } func (s *SingMux) SupportUDP() bool { diff --git a/adapter/outbound/vless.go b/adapter/outbound/vless.go index d7db27d5..82ecf927 100644 --- a/adapter/outbound/vless.go +++ b/adapter/outbound/vless.go @@ -13,6 +13,7 @@ import ( "sync" "github.com/Dreamacro/clash/common/convert" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/proxydialer" "github.com/Dreamacro/clash/component/resolver" @@ -372,15 +373,15 @@ func (v *Vless) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metada } if v.option.XUDP { - return newPacketConn(&threadSafePacketConn{ - PacketConn: vmessSing.NewXUDPConn(c, M.SocksaddrFromNet(metadata.UDPAddr())), - }, v), nil + return newPacketConn(N.NewThreadSafePacketConn( + vmessSing.NewXUDPConn(c, M.SocksaddrFromNet(metadata.UDPAddr())), + ), v), nil } else if v.option.PacketAddr { - return newPacketConn(&threadSafePacketConn{ - PacketConn: packetaddr.NewConn(&vlessPacketConn{ + return newPacketConn(N.NewThreadSafePacketConn( + packetaddr.NewConn(&vlessPacketConn{ Conn: c, rAddr: metadata.UDPAddr(), }, M.SocksaddrFromNet(metadata.UDPAddr())), - }, v), nil + ), v), nil } return newPacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil } diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index 8901f3d5..91e509d7 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -379,7 +379,7 @@ func (v *Vmess) ListenPacketOnStreamConn(ctx context.Context, c net.Conn, metada } if pc, ok := c.(net.PacketConn); ok { - return newPacketConn(&threadSafePacketConn{PacketConn: pc}, v), nil + return newPacketConn(N.NewThreadSafePacketConn(pc), v), nil } return newPacketConn(&vmessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil } @@ -489,17 +489,6 @@ func NewVmess(option VmessOption) (*Vmess, error) { return v, nil } -type threadSafePacketConn struct { - net.PacketConn - access sync.Mutex -} - -func (c *threadSafePacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { - c.access.Lock() - defer c.access.Unlock() - return c.PacketConn.WriteTo(b, addr) -} - type vmessPacketConn struct { net.Conn rAddr net.Addr diff --git a/common/net/packet.go b/common/net/packet.go index 30f1104a..43a2bc9c 100644 --- a/common/net/packet.go +++ b/common/net/packet.go @@ -2,6 +2,7 @@ package net import ( "net" + "sync" "github.com/Dreamacro/clash/common/pool" ) @@ -66,3 +67,22 @@ func waitReadFrom(pc net.PacketConn) (data []byte, put func(), addr net.Addr, er } return } + +type threadSafePacketConn struct { + net.PacketConn + access sync.Mutex +} + +func (c *threadSafePacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { + c.access.Lock() + defer c.access.Unlock() + return c.PacketConn.WriteTo(b, addr) +} + +func (c *threadSafePacketConn) Upstream() any { + return c.PacketConn +} + +func NewThreadSafePacketConn(pc net.PacketConn) net.PacketConn { + return &threadSafePacketConn{PacketConn: pc} +} From 234f7dbd3b13c96918977da7c0018098d569cde5 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 11 May 2023 19:01:41 +0800 Subject: [PATCH 25/62] chore: decrease shadowsocks udp read memory used for no-windows platform --- adapter/outbound/shadowsocks.go | 3 +- common/net/bind.go | 35 +++-- common/net/deadline/packet.go | 172 ++++++++++++++++++++++ common/net/deadline/pipe.go | 84 +++++++++++ common/net/packet.go | 65 +------- common/net/packet/packet.go | 70 +++++++++ common/net/{ => packet}/packet_posix.go | 2 +- common/net/{ => packet}/packet_windows.go | 2 +- common/net/sing.go | 4 - go.mod | 4 +- go.sum | 4 +- listener/sing/sing.go | 2 +- 12 files changed, 361 insertions(+), 86 deletions(-) create mode 100644 common/net/deadline/packet.go create mode 100644 common/net/deadline/pipe.go create mode 100644 common/net/packet/packet.go rename common/net/{ => packet}/packet_posix.go (98%) rename common/net/{ => packet}/packet_windows.go (93%) diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 7ee9e634..44bfe64f 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -21,7 +21,6 @@ import ( restlsC "github.com/3andne/restls-client-go" "github.com/metacubex/sing-shadowsocks2" - "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" "github.com/sagernet/sing/common/uot" ) @@ -194,7 +193,7 @@ func (ss *ShadowSocks) ListenPacketWithDialer(ctx context.Context, dialer C.Dial if err != nil { return nil, err } - pc = ss.method.DialPacketConn(bufio.NewBindPacketConn(pc, addr)) + pc = ss.method.DialPacketConn(N.NewBindPacketConn(N.NewEnhancePacketConn(pc), addr)) return newPacketConn(pc, ss), nil } diff --git a/common/net/bind.go b/common/net/bind.go index 1e20a8c0..edf51ccb 100644 --- a/common/net/bind.go +++ b/common/net/bind.go @@ -3,34 +3,43 @@ package net import "net" type bindPacketConn struct { - net.PacketConn + EnhancePacketConn rAddr net.Addr } -func (wpc *bindPacketConn) Read(b []byte) (n int, err error) { - n, _, err = wpc.PacketConn.ReadFrom(b) +func (c *bindPacketConn) Read(b []byte) (n int, err error) { + n, _, err = c.EnhancePacketConn.ReadFrom(b) return n, err } -func (wpc *bindPacketConn) Write(b []byte) (n int, err error) { - return wpc.PacketConn.WriteTo(b, wpc.rAddr) +func (c *bindPacketConn) WaitRead() (data []byte, put func(), err error) { + data, put, _, err = c.EnhancePacketConn.WaitReadFrom() + return } -func (wpc *bindPacketConn) RemoteAddr() net.Addr { - return wpc.rAddr +func (c *bindPacketConn) Write(b []byte) (n int, err error) { + return c.EnhancePacketConn.WriteTo(b, c.rAddr) } -func (wpc *bindPacketConn) LocalAddr() net.Addr { - if wpc.PacketConn.LocalAddr() == nil { +func (c *bindPacketConn) RemoteAddr() net.Addr { + return c.rAddr +} + +func (c *bindPacketConn) LocalAddr() net.Addr { + if c.EnhancePacketConn.LocalAddr() == nil { return &net.UDPAddr{IP: net.IPv4zero, Port: 0} } else { - return wpc.PacketConn.LocalAddr() + return c.EnhancePacketConn.LocalAddr() } } -func NewBindPacketConn(pc net.PacketConn, rAddr net.Addr) net.Conn { +func (c *bindPacketConn) Upstream() any { + return c.EnhancePacketConn +} + +func NewBindPacketConn(pc EnhancePacketConn, rAddr net.Addr) net.Conn { return &bindPacketConn{ - PacketConn: pc, - rAddr: rAddr, + EnhancePacketConn: pc, + rAddr: rAddr, } } diff --git a/common/net/deadline/packet.go b/common/net/deadline/packet.go new file mode 100644 index 00000000..4f2e9111 --- /dev/null +++ b/common/net/deadline/packet.go @@ -0,0 +1,172 @@ +package deadline + +import ( + "net" + "os" + "time" + + "github.com/Dreamacro/clash/common/atomic" + "github.com/Dreamacro/clash/common/net/packet" +) + +type readResult struct { + data []byte + put func() + addr net.Addr + err error +} + +type PacketConn struct { + net.PacketConn + deadline atomic.TypedValue[time.Time] + pipeDeadline pipeDeadline + disablePipe atomic.Bool + inRead atomic.Bool + resultCh chan *readResult +} + +func NewPacketConn(pc net.PacketConn) net.PacketConn { + c := &PacketConn{ + PacketConn: pc, + pipeDeadline: makePipeDeadline(), + resultCh: make(chan *readResult, 1), + } + c.resultCh <- nil + if enhancePacketConn, isEnhance := pc.(packet.EnhancePacketConn); isEnhance { + return &EnhancePacketConn{ + PacketConn: c, + enhancePacketConn: enhancePacketConn, + } + } + return c +} + +func (c *PacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { + select { + case result := <-c.resultCh: + if result != nil { + n = copy(p, result.data) + addr = result.addr + err = result.err + c.resultCh <- nil // finish cache read + return + } else { + c.resultCh <- nil + break + } + case <-c.pipeDeadline.wait(): + return 0, nil, os.ErrDeadlineExceeded + } + + if c.disablePipe.Load() { + return c.PacketConn.ReadFrom(p) + } else if c.deadline.Load().IsZero() { + c.inRead.Store(true) + defer c.inRead.Store(false) + n, addr, err = c.PacketConn.ReadFrom(p) + return + } + + <-c.resultCh + go c.pipeReadFrom(len(p)) + + return c.ReadFrom(p) +} + +func (c *PacketConn) pipeReadFrom(size int) { + buffer := make([]byte, size) + n, addr, err := c.PacketConn.ReadFrom(buffer) + buffer = buffer[:n] + c.resultCh <- &readResult{ + data: buffer, + addr: addr, + err: err, + } +} + +func (c *PacketConn) SetReadDeadline(t time.Time) error { + if c.disablePipe.Load() { + return c.PacketConn.SetReadDeadline(t) + } else if c.inRead.Load() { + c.disablePipe.Store(true) + return c.PacketConn.SetReadDeadline(t) + } + c.deadline.Store(t) + c.pipeDeadline.set(t) + return nil +} + +func (c *PacketConn) ReaderReplaceable() bool { + select { + case result := <-c.resultCh: + c.resultCh <- result + if result != nil { + return false // cache reading + } else { + break + } + default: + return false // pipe reading + } + return c.disablePipe.Load() || c.deadline.Load().IsZero() +} + +func (c *PacketConn) WriterReplaceable() bool { + return true +} + +func (c *PacketConn) Upstream() any { + return c.PacketConn +} + +func (c *PacketConn) NeedAdditionalReadDeadline() bool { + return false +} + +type EnhancePacketConn struct { + *PacketConn + enhancePacketConn packet.EnhancePacketConn +} + +func (c *EnhancePacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + select { + case result := <-c.resultCh: + if result != nil { + data = result.data + put = result.put + addr = result.addr + err = result.err + c.resultCh <- nil // finish cache read + return + } else { + c.resultCh <- nil + break + } + case <-c.pipeDeadline.wait(): + return nil, nil, nil, os.ErrDeadlineExceeded + } + + if c.disablePipe.Load() { + return c.enhancePacketConn.WaitReadFrom() + } else if c.deadline.Load().IsZero() { + c.inRead.Store(true) + defer c.inRead.Store(false) + data, put, addr, err = c.enhancePacketConn.WaitReadFrom() + return + } + + <-c.resultCh + go c.pipeWaitReadFrom() + + return c.WaitReadFrom() +} + +func (c *EnhancePacketConn) pipeWaitReadFrom() { + data, put, addr, err := c.enhancePacketConn.WaitReadFrom() + c.resultCh <- &readResult{ + data: data, + put: put, + addr: addr, + err: err, + } +} diff --git a/common/net/deadline/pipe.go b/common/net/deadline/pipe.go new file mode 100644 index 00000000..2cccfb42 --- /dev/null +++ b/common/net/deadline/pipe.go @@ -0,0 +1,84 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package deadline + +import ( + "sync" + "time" +) + +// pipeDeadline is an abstraction for handling timeouts. +type pipeDeadline struct { + mu sync.Mutex // Guards timer and cancel + timer *time.Timer + cancel chan struct{} // Must be non-nil +} + +func makePipeDeadline() pipeDeadline { + return pipeDeadline{cancel: make(chan struct{})} +} + +// set sets the point in time when the deadline will time out. +// A timeout event is signaled by closing the channel returned by waiter. +// Once a timeout has occurred, the deadline can be refreshed by specifying a +// t value in the future. +// +// A zero value for t prevents timeout. +func (d *pipeDeadline) set(t time.Time) { + d.mu.Lock() + defer d.mu.Unlock() + + if d.timer != nil && !d.timer.Stop() { + <-d.cancel // Wait for the timer callback to finish and close cancel + } + d.timer = nil + + // Time is zero, then there is no deadline. + closed := isClosedChan(d.cancel) + if t.IsZero() { + if closed { + d.cancel = make(chan struct{}) + } + return + } + + // Time in the future, setup a timer to cancel in the future. + if dur := time.Until(t); dur > 0 { + if closed { + d.cancel = make(chan struct{}) + } + d.timer = time.AfterFunc(dur, func() { + close(d.cancel) + }) + return + } + + // Time in the past, so close immediately. + if !closed { + close(d.cancel) + } +} + +// wait returns a channel that is closed when the deadline is exceeded. +func (d *pipeDeadline) wait() chan struct{} { + d.mu.Lock() + defer d.mu.Unlock() + return d.cancel +} + +func isClosedChan(c <-chan struct{}) bool { + select { + case <-c: + return true + default: + return false + } +} + +func makeFilledChan() chan struct{} { + ch := make(chan struct{}, 1) + ch <- struct{}{} + return ch +} diff --git a/common/net/packet.go b/common/net/packet.go index 43a2bc9c..2895b537 100644 --- a/common/net/packet.go +++ b/common/net/packet.go @@ -4,69 +4,14 @@ import ( "net" "sync" - "github.com/Dreamacro/clash/common/pool" + "github.com/Dreamacro/clash/common/net/deadline" + "github.com/Dreamacro/clash/common/net/packet" ) -type EnhancePacketConn interface { - net.PacketConn - WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) - Upstream() any -} +type EnhancePacketConn = packet.EnhancePacketConn -func NewEnhancePacketConn(pc net.PacketConn) EnhancePacketConn { - if udpConn, isUDPConn := pc.(*net.UDPConn); isUDPConn { - return &enhanceUDPConn{UDPConn: udpConn} - } - return &enhancePacketConn{PacketConn: pc} -} - -type enhancePacketConn struct { - net.PacketConn -} - -func (c *enhancePacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { - return waitReadFrom(c.PacketConn) -} - -func (c *enhancePacketConn) Upstream() any { - return c.PacketConn -} - -func (c *enhancePacketConn) WriterReplaceable() bool { - return true -} - -func (c *enhancePacketConn) ReaderReplaceable() bool { - return true -} - -func (c *enhanceUDPConn) Upstream() any { - return c.UDPConn -} - -func (c *enhanceUDPConn) WriterReplaceable() bool { - return true -} - -func (c *enhanceUDPConn) ReaderReplaceable() bool { - return true -} - -func waitReadFrom(pc net.PacketConn) (data []byte, put func(), addr net.Addr, err error) { - readBuf := pool.Get(pool.UDPBufferSize) - put = func() { - _ = pool.Put(readBuf) - } - var readN int - readN, addr, err = pc.ReadFrom(readBuf) - if readN > 0 { - data = readBuf[:readN] - } else { - put() - put = nil - } - return -} +var NewEnhancePacketConn = packet.NewEnhancePacketConn +var NewDeadlinePacketConn = deadline.NewPacketConn type threadSafePacketConn struct { net.PacketConn diff --git a/common/net/packet/packet.go b/common/net/packet/packet.go new file mode 100644 index 00000000..d823334e --- /dev/null +++ b/common/net/packet/packet.go @@ -0,0 +1,70 @@ +package packet + +import ( + "net" + + "github.com/Dreamacro/clash/common/pool" +) + +type EnhancePacketConn interface { + net.PacketConn + WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) +} + +func NewEnhancePacketConn(pc net.PacketConn) EnhancePacketConn { + if udpConn, isUDPConn := pc.(*net.UDPConn); isUDPConn { + return &enhanceUDPConn{UDPConn: udpConn} + } + if enhancePC, isEnhancePC := pc.(EnhancePacketConn); isEnhancePC { + return enhancePC + } + return &enhancePacketConn{PacketConn: pc} +} + +type enhancePacketConn struct { + net.PacketConn +} + +func (c *enhancePacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + return waitReadFrom(c.PacketConn) +} + +func (c *enhancePacketConn) Upstream() any { + return c.PacketConn +} + +func (c *enhancePacketConn) WriterReplaceable() bool { + return true +} + +func (c *enhancePacketConn) ReaderReplaceable() bool { + return true +} + +func (c *enhanceUDPConn) Upstream() any { + return c.UDPConn +} + +func (c *enhanceUDPConn) WriterReplaceable() bool { + return true +} + +func (c *enhanceUDPConn) ReaderReplaceable() bool { + return true +} + +func waitReadFrom(pc net.PacketConn) (data []byte, put func(), addr net.Addr, err error) { + readBuf := pool.Get(pool.UDPBufferSize) + put = func() { + _ = pool.Put(readBuf) + } + var readN int + readN, addr, err = pc.ReadFrom(readBuf) + if readN > 0 { + data = readBuf[:readN] + } else { + put() + put = nil + } + return +} diff --git a/common/net/packet_posix.go b/common/net/packet/packet_posix.go similarity index 98% rename from common/net/packet_posix.go rename to common/net/packet/packet_posix.go index 18c72a1c..3c5d23a6 100644 --- a/common/net/packet_posix.go +++ b/common/net/packet/packet_posix.go @@ -1,6 +1,6 @@ //go:build !windows -package net +package packet import ( "io" diff --git a/common/net/packet_windows.go b/common/net/packet/packet_windows.go similarity index 93% rename from common/net/packet_windows.go rename to common/net/packet/packet_windows.go index a5bf75aa..cb4c518b 100644 --- a/common/net/packet_windows.go +++ b/common/net/packet/packet_windows.go @@ -1,6 +1,6 @@ //go:build windows -package net +package packet import ( "net" diff --git a/common/net/sing.go b/common/net/sing.go index aa6f6917..c92008ba 100644 --- a/common/net/sing.go +++ b/common/net/sing.go @@ -23,10 +23,6 @@ func NewDeadlineConn(conn net.Conn) ExtendedConn { return deadline.NewFallbackConn(conn) } -func NewDeadlinePacketConn(pc net.PacketConn) network.NetPacketConn { - return deadline.NewFallbackPacketConn(bufio.NewPacketConn(pc)) -} - func NeedHandshake(conn any) bool { if earlyConn, isEarlyConn := common.Cast[network.EarlyConn](conn); isEarlyConn && earlyConn.NeedHandshake() { return true diff --git a/go.mod b/go.mod index b51e646a..ffa071ae 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/mdlayher/netlink v1.7.2 github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c - github.com/metacubex/sing-shadowsocks2 v0.0.0-20230510002911-25e95d677383 + github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511095725-1d6e98507d8c github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a github.com/miekg/dns v1.1.54 @@ -103,4 +103,4 @@ require ( golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect golang.org/x/tools v0.6.0 // indirect -) +) \ No newline at end of file diff --git a/go.sum b/go.sum index abb18231..9bad1a3a 100644 --- a/go.sum +++ b/go.sum @@ -98,8 +98,8 @@ github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 h1:E/sNW9tugF github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230510002911-25e95d677383 h1:YdLeRuENJZ9QL58Kf/qtMp1wZv9VGQJYMqZ2WEF6/FM= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230510002911-25e95d677383/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511095725-1d6e98507d8c h1:LlKpVuMuccNe3JfKJ+G+JMxiqw4FBSVsK/jQYatSsnY= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511095725-1d6e98507d8c/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= diff --git a/listener/sing/sing.go b/listener/sing/sing.go index 7292df33..fe806e0f 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -106,7 +106,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. additions = append(additions, ctxAdditions...) } if deadline.NeedAdditionalReadDeadline(conn) { - conn = N.NewDeadlinePacketConn(bufio.NewNetPacketConn(conn)) // conn from sing should check NeedAdditionalReadDeadline + conn = deadline.NewFallbackPacketConn(bufio.NewNetPacketConn(conn)) // conn from sing should check NeedAdditionalReadDeadline } defer func() { _ = conn.Close() }() mutex := sync.Mutex{} From 76caab19bf1401f2eb9caa45922e155e9f3bbbed Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 11 May 2023 19:58:50 +0800 Subject: [PATCH 26/62] fix: Deadline not apply on EnhancePacketConn --- adapter/outbound/base.go | 5 +++-- common/net/deadline/packet.go | 4 ++++ common/net/packet.go | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index e4a553b9..c5901d7f 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -259,10 +259,11 @@ func (c *packetConn) ReaderReplaceable() bool { } func newPacketConn(pc net.PacketConn, a C.ProxyAdapter) C.PacketConn { + epc := N.NewEnhancePacketConn(pc) if _, ok := pc.(syscall.Conn); !ok { // exclusion system conn like *net.UDPConn - pc = N.NewDeadlinePacketConn(pc) // most conn from outbound can't handle readDeadline correctly + epc = N.NewDeadlineEnhancePacketConn(epc) // most conn from outbound can't handle readDeadline correctly } - return &packetConn{N.NewEnhancePacketConn(pc), []string{a.Name()}, a.Name(), utils.NewUUIDV4().String(), parseRemoteDestination(a.Addr())} + return &packetConn{epc, []string{a.Name()}, a.Name(), utils.NewUUIDV4().String(), parseRemoteDestination(a.Addr())} } func parseRemoteDestination(addr string) string { diff --git a/common/net/deadline/packet.go b/common/net/deadline/packet.go index 4f2e9111..38b5f579 100644 --- a/common/net/deadline/packet.go +++ b/common/net/deadline/packet.go @@ -128,6 +128,10 @@ type EnhancePacketConn struct { enhancePacketConn packet.EnhancePacketConn } +func NewEnhancePacketConn(pc packet.EnhancePacketConn) packet.EnhancePacketConn { + return NewPacketConn(pc).(packet.EnhancePacketConn) +} + func (c *EnhancePacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { select { case result := <-c.resultCh: diff --git a/common/net/packet.go b/common/net/packet.go index 2895b537..261c721c 100644 --- a/common/net/packet.go +++ b/common/net/packet.go @@ -12,6 +12,7 @@ type EnhancePacketConn = packet.EnhancePacketConn var NewEnhancePacketConn = packet.NewEnhancePacketConn var NewDeadlinePacketConn = deadline.NewPacketConn +var NewDeadlineEnhancePacketConn = deadline.NewEnhancePacketConn type threadSafePacketConn struct { net.PacketConn From 51e9f3598ed43164db03cfb5e8c621249407f2a6 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 11 May 2023 20:42:36 +0800 Subject: [PATCH 27/62] fix: shadowsocks rc4-md5 not working --- go.mod | 4 ++-- go.sum | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index ffa071ae..a0a19311 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/mdlayher/netlink v1.7.2 github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c - github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511095725-1d6e98507d8c + github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511124108-b20f64384bdd github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a github.com/miekg/dns v1.1.54 @@ -103,4 +103,4 @@ require ( golang.org/x/text v0.9.0 // indirect golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect golang.org/x/tools v0.6.0 // indirect -) \ No newline at end of file +) diff --git a/go.sum b/go.sum index 9bad1a3a..53f730b8 100644 --- a/go.sum +++ b/go.sum @@ -98,8 +98,8 @@ github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 h1:E/sNW9tugF github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511095725-1d6e98507d8c h1:LlKpVuMuccNe3JfKJ+G+JMxiqw4FBSVsK/jQYatSsnY= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511095725-1d6e98507d8c/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511124108-b20f64384bdd h1:RXdD763CbvqaJOyFLAh6xa8xg7BZTkOJ0p8fBc7kB+w= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511124108-b20f64384bdd/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= From 8dd7632d0a7e84c26d69a0c87e7c287b03de914d Mon Sep 17 00:00:00 2001 From: cubemaze <117334465+cubemaze@users.noreply.github.com> Date: Thu, 11 May 2023 21:24:38 +0800 Subject: [PATCH 28/62] chore: update docs --- docs/config.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/docs/config.yaml b/docs/config.yaml index 8721340f..4239abcf 100644 --- a/docs/config.yaml +++ b/docs/config.yaml @@ -77,32 +77,32 @@ tun: # auto-detect-interface: true # 自动识别出口网卡 # auto-route: true # 配置路由表 # mtu: 9000 # 最大传输单元 - # strict_route: true # 将所有连接路由到tun来防止泄漏,但你的设备将无法其他设备被访问 - inet4_route_address: # 启用 auto_route 时使用自定义路由而不是默认路由 + # strict-route: true # 将所有连接路由到tun来防止泄漏,但你的设备将无法其他设备被访问 + inet4-route-address: # 启用 auto_route 时使用自定义路由而不是默认路由 - 0.0.0.0/1 - 128.0.0.0/1 - inet6_route_address: # 启用 auto_route 时使用自定义路由而不是默认路由 + inet6-route-address: # 启用 auto_route 时使用自定义路由而不是默认路由 - "::/1" - "8000::/1" - # endpoint_independent_nat: false # 启用独立于端点的 NAT - # include_uid: # UID 规则仅在 Linux 下被支持,并且需要 auto_route + # endpoint-independent-nat: false # 启用独立于端点的 NAT + # include-uid: # UID 规则仅在 Linux 下被支持,并且需要 auto_route # - 0 - # include_uid_range: # 限制被路由的的用户范围 + # include-uid-range: # 限制被路由的的用户范围 # - 1000-99999 - # exclude_uid: # 排除路由的的用户 + # exclude-uid: # 排除路由的的用户 #- 1000 - # exclude_uid_range: # 排除路由的的用户范围 + # exclude-uid-range: # 排除路由的的用户范围 # - 1000-99999 # Android 用户和应用规则仅在 Android 下被支持 - # 并且需要 auto_route + # 并且需要 auto-route - # include_android_user: # 限制被路由的 Android 用户 + # include-android-user: # 限制被路由的 Android 用户 # - 0 # - 10 - # include_package: # 限制被路由的 Android 应用包名 + # include-package: # 限制被路由的 Android 应用包名 # - com.android.chrome - # exclude_package: # 排除被路由的 Android 应用包名 + # exclude-package: # 排除被路由的 Android 应用包名 # - com.android.captiveportallogin #ebpf配置 From 534282839ca7cb886203807714d7427aa38128a4 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 11 May 2023 21:31:29 +0800 Subject: [PATCH 29/62] chore: better tproxy error logging --- listener/tproxy/packet.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/listener/tproxy/packet.go b/listener/tproxy/packet.go index 2a274f61..4967adc6 100644 --- a/listener/tproxy/packet.go +++ b/listener/tproxy/packet.go @@ -78,7 +78,7 @@ func createOrGetLocalConn(rAddr, lAddr net.Addr, in chan<- C.PacketAdapter, natT }() conn, err := listenLocalConn(rAddr, lAddr, in, natTable) if err != nil { - log.Errorln("listenLocalConn failed with error: %s, packet loss", err.Error()) + log.Errorln("listenLocalConn failed with error: %s, packet loss (rAddr[%T]=%s lAddr[%T]=%s)", err.Error(), rAddr, remote, lAddr, local) return nil, err } natTable.AddLocalConn(local, remote, conn) From f1be9b3f4aee53be5fe9438ed9c452cb6456e6f8 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 11 May 2023 22:45:27 +0800 Subject: [PATCH 30/62] fix: tuic server return error udp address --- transport/tuic/protocol.go | 5 +++++ tunnel/connection.go | 11 +++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/transport/tuic/protocol.go b/transport/tuic/protocol.go index a460eecc..472bb980 100644 --- a/transport/tuic/protocol.go +++ b/transport/tuic/protocol.go @@ -465,6 +465,11 @@ func NewAddress(metadata *C.Metadata) Address { } func NewAddressNetAddr(addr net.Addr) (Address, error) { + if addr, ok := addr.(interface{ AddrPort() netip.AddrPort }); ok { + if addrPort := addr.AddrPort(); addrPort.IsValid() { // sing's M.Socksaddr maybe return an invalid AddrPort if it's a DomainName + return NewAddressAddrPort(addrPort), nil + } + } addrStr := addr.String() if addrPort, err := netip.ParseAddrPort(addrStr); err == nil { return NewAddressAddrPort(addrPort), nil diff --git a/tunnel/connection.go b/tunnel/connection.go index c95e33f2..73c3e499 100644 --- a/tunnel/connection.go +++ b/tunnel/connection.go @@ -44,10 +44,13 @@ func handleUDPToLocal(packet C.UDPPacket, pc N.EnhancePacketConn, key string, oA _fromUDPAddr := *fromUDPAddr fromUDPAddr = &_fromUDPAddr // make a copy if fromAddr, ok := netip.AddrFromSlice(fromUDPAddr.IP); ok { - if fAddr.IsValid() && (oAddr.Unmap() == fromAddr.Unmap()) { - fromUDPAddr.IP = fAddr.Unmap().AsSlice() - } else { - fromUDPAddr.IP = fromAddr.Unmap().AsSlice() + fromAddr = fromAddr.Unmap() + if fAddr.IsValid() && (oAddr.Unmap() == fromAddr) { + fromAddr = fAddr.Unmap() + } + fromUDPAddr.IP = fromAddr.AsSlice() + if fromAddr.Is4() { + fromUDPAddr.Zone = "" // only ipv6 can have the zone } } From a22b1cd69e37b6739512079ca517eb748bf59e63 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Fri, 12 May 2023 09:14:27 +0800 Subject: [PATCH 31/62] fix: sing-based listener panic --- adapter/outbound/shadowsocks.go | 2 +- common/net/bind.go | 4 ++-- common/net/packet.go | 12 ++++++++---- common/net/refconn.go | 23 ++++++++++++++++++++--- listener/sing/sing.go | 14 ++++++++++++-- listener/sing_shadowsocks/server.go | 7 +++++-- listener/sing_tun/dns.go | 7 +++++-- tunnel/statistic/tracker.go | 4 ++++ 8 files changed, 57 insertions(+), 16 deletions(-) diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 44bfe64f..02e975ef 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -193,7 +193,7 @@ func (ss *ShadowSocks) ListenPacketWithDialer(ctx context.Context, dialer C.Dial if err != nil { return nil, err } - pc = ss.method.DialPacketConn(N.NewBindPacketConn(N.NewEnhancePacketConn(pc), addr)) + pc = ss.method.DialPacketConn(N.NewBindPacketConn(pc, addr)) return newPacketConn(pc, ss), nil } diff --git a/common/net/bind.go b/common/net/bind.go index edf51ccb..231c24c2 100644 --- a/common/net/bind.go +++ b/common/net/bind.go @@ -37,9 +37,9 @@ func (c *bindPacketConn) Upstream() any { return c.EnhancePacketConn } -func NewBindPacketConn(pc EnhancePacketConn, rAddr net.Addr) net.Conn { +func NewBindPacketConn(pc net.PacketConn, rAddr net.Addr) net.Conn { return &bindPacketConn{ - EnhancePacketConn: pc, + EnhancePacketConn: NewEnhancePacketConn(pc), rAddr: rAddr, } } diff --git a/common/net/packet.go b/common/net/packet.go index 261c721c..d01c9efe 100644 --- a/common/net/packet.go +++ b/common/net/packet.go @@ -15,20 +15,24 @@ var NewDeadlinePacketConn = deadline.NewPacketConn var NewDeadlineEnhancePacketConn = deadline.NewEnhancePacketConn type threadSafePacketConn struct { - net.PacketConn + EnhancePacketConn access sync.Mutex } func (c *threadSafePacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { c.access.Lock() defer c.access.Unlock() - return c.PacketConn.WriteTo(b, addr) + return c.EnhancePacketConn.WriteTo(b, addr) } func (c *threadSafePacketConn) Upstream() any { - return c.PacketConn + return c.EnhancePacketConn +} + +func (c *threadSafePacketConn) ReaderReplaceable() bool { + return true } func NewThreadSafePacketConn(pc net.PacketConn) net.PacketConn { - return &threadSafePacketConn{PacketConn: pc} + return &threadSafePacketConn{EnhancePacketConn: NewEnhancePacketConn(pc)} } diff --git a/common/net/refconn.go b/common/net/refconn.go index 537cb839..0f32ebc1 100644 --- a/common/net/refconn.go +++ b/common/net/refconn.go @@ -82,10 +82,15 @@ func NewRefConn(conn net.Conn, ref any) net.Conn { } type refPacketConn struct { - pc net.PacketConn + pc EnhancePacketConn ref any } +func (pc *refPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + defer runtime.KeepAlive(pc.ref) + return pc.pc.WaitReadFrom() +} + func (pc *refPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { defer runtime.KeepAlive(pc.ref) return pc.pc.ReadFrom(p) @@ -121,6 +126,18 @@ func (pc *refPacketConn) SetWriteDeadline(t time.Time) error { return pc.pc.SetWriteDeadline(t) } -func NewRefPacketConn(pc net.PacketConn, ref any) net.PacketConn { - return &refPacketConn{pc: pc, ref: ref} +func (pc *refPacketConn) Upstream() any { + return pc.pc +} + +func (pc *refPacketConn) ReaderReplaceable() bool { // Relay() will handle reference + return true +} + +func (pc *refPacketConn) WriterReplaceable() bool { // Relay() will handle reference + return true +} + +func NewRefPacketConn(pc net.PacketConn, ref any) net.PacketConn { + return &refPacketConn{pc: NewEnhancePacketConn(pc), ref: ref} } diff --git a/listener/sing/sing.go b/listener/sing/sing.go index fe806e0f..2a2d8474 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -58,6 +58,14 @@ func (c *waitCloseConn) Upstream() any { return c.ExtendedConn } +func (c *waitCloseConn) ReaderReplaceable() bool { + return true +} + +func (c *waitCloseConn) WriterReplaceable() bool { + return true +} + func UpstreamMetadata(metadata M.Metadata) M.Metadata { return M.Metadata{ Source: metadata.Source, @@ -116,7 +124,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. defer mutex.Unlock() conn2 = nil }() - readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) + connReader := network.UnwrapPacketReader(conn) // decrease runtime cost for bufio.CreatePacketReadWaiter for { var ( buff *buf.Buffer @@ -127,7 +135,9 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. buff = buf.NewPacket() // do not use stack buffer return buff } - if isReadWaiter { + // syscallPacketReadWaiter.WaitReadPacket will cache newBuffer function + // so create new PacketReadWaiter in each loop + if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(connReader); isReadWaiter { dest, err = readWaiter.WaitReadPacket(newBuffer) } else { dest, err = conn.ReadPacket(newBuffer()) diff --git a/listener/sing_shadowsocks/server.go b/listener/sing_shadowsocks/server.go index 31b342e8..b35e1238 100644 --- a/listener/sing_shadowsocks/server.go +++ b/listener/sing_shadowsocks/server.go @@ -22,6 +22,7 @@ import ( "github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" + "github.com/sagernet/sing/common/network" ) type Listener struct { @@ -92,7 +93,7 @@ func New(config LC.ShadowsocksServer, tcpIn chan<- C.ConnContext, udpIn chan<- C go func() { conn := bufio.NewPacketConn(ul) - readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) + connReader := network.UnwrapPacketReader(conn) // decrease runtime cost for bufio.CreatePacketReadWaiter for { var ( buff *buf.Buffer @@ -103,7 +104,9 @@ func New(config LC.ShadowsocksServer, tcpIn chan<- C.ConnContext, udpIn chan<- C buff = buf.NewPacket() // do not use stack buffer return buff } - if isReadWaiter { + // syscallPacketReadWaiter.WaitReadPacket will cache newBuffer function + // so create new PacketReadWaiter in each loop + if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(connReader); isReadWaiter { dest, err = readWaiter.WaitReadPacket(newBuffer) } else { dest, err = conn.ReadPacket(newBuffer()) diff --git a/listener/sing_tun/dns.go b/listener/sing_tun/dns.go index fcf0cc9c..5ec6d96b 100644 --- a/listener/sing_tun/dns.go +++ b/listener/sing_tun/dns.go @@ -109,7 +109,8 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. defer mutex.Unlock() conn2 = nil }() - readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) + + connReader := network.UnwrapPacketReader(conn) // decrease runtime cost for bufio.CreatePacketReadWaiter for { var ( buff *buf.Buffer @@ -123,7 +124,9 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. return buff } _ = conn.SetReadDeadline(time.Now().Add(DefaultDnsReadTimeout)) - if isReadWaiter { + // syscallPacketReadWaiter.WaitReadPacket will cache newBuffer function + // so create new PacketReadWaiter in each loop + if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(connReader); isReadWaiter { dest, err = readWaiter.WaitReadPacket(newBuffer) } else { dest, err = conn.ReadPacket(newBuffer()) diff --git a/tunnel/statistic/tracker.go b/tunnel/statistic/tracker.go index 685b5e90..a2a921ac 100644 --- a/tunnel/statistic/tracker.go +++ b/tunnel/statistic/tracker.go @@ -211,6 +211,10 @@ func (ut *udpTracker) Close() error { return ut.PacketConn.Close() } +func (ut *udpTracker) Upstream() any { + return ut.PacketConn +} + func NewUDPTracker(conn C.PacketConn, manager *Manager, metadata *C.Metadata, rule C.Rule, uploadTotal int64, downloadTotal int64, pushToManager bool) *udpTracker { metadata.RemoteDst = parseRemoteDestination(nil, conn) From b6749830345bb9b6e82bf06f2099a10d05da0f53 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Fri, 12 May 2023 12:12:22 +0800 Subject: [PATCH 32/62] chore: improve read waiter interface --- go.mod | 2 +- go.sum | 4 ++-- listener/sing/sing.go | 22 +++++++++++---------- listener/sing_shadowsocks/server.go | 23 +++++++++++----------- listener/sing_tun/dns.go | 30 +++++++++++++++-------------- 5 files changed, 43 insertions(+), 38 deletions(-) diff --git a/go.mod b/go.mod index a0a19311..9b1e2dbd 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/openacid/low v0.1.21 github.com/oschwald/geoip2-golang v1.8.0 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.2.5-0.20230510160026-237a991b46d0 + github.com/sagernet/sing v0.2.5-0.20230512033628-9be7806bab51 github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 diff --git a/go.sum b/go.sum index 53f730b8..d38293a3 100644 --- a/go.sum +++ b/go.sum @@ -143,8 +143,8 @@ github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6E 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.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.5-0.20230510160026-237a991b46d0 h1:NS4U+yQ4ToyRqFvCS91BM1D6fQbriW1qvioxSj5PvI4= -github.com/sagernet/sing v0.2.5-0.20230510160026-237a991b46d0/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/sagernet/sing v0.2.5-0.20230512033628-9be7806bab51 h1:ySJuouhl890pBZly51Hkb2mbDnz+qSQCLF5j+4IFHis= +github.com/sagernet/sing v0.2.5-0.20230512033628-9be7806bab51/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzlnPxOpuv64jhjz3teIvccu3YMFX4fJI= github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= diff --git a/listener/sing/sing.go b/listener/sing/sing.go index 2a2d8474..9bf52e9c 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -124,21 +124,23 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. defer mutex.Unlock() conn2 = nil }() - connReader := network.UnwrapPacketReader(conn) // decrease runtime cost for bufio.CreatePacketReadWaiter + var buff *buf.Buffer + newBuffer := func() *buf.Buffer { + buff = buf.NewPacket() // do not use stack buffer + return buff + } + readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) + if isReadWaiter { + readWaiter.InitializeReadWaiter(newBuffer) + } for { var ( - buff *buf.Buffer dest M.Socksaddr err error ) - newBuffer := func() *buf.Buffer { - buff = buf.NewPacket() // do not use stack buffer - return buff - } - // syscallPacketReadWaiter.WaitReadPacket will cache newBuffer function - // so create new PacketReadWaiter in each loop - if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(connReader); isReadWaiter { - dest, err = readWaiter.WaitReadPacket(newBuffer) + buff = nil // clear last loop status, avoid repeat release + if isReadWaiter { + dest, err = readWaiter.WaitReadPacket() } else { dest, err = conn.ReadPacket(newBuffer()) } diff --git a/listener/sing_shadowsocks/server.go b/listener/sing_shadowsocks/server.go index b35e1238..1fa9a3ba 100644 --- a/listener/sing_shadowsocks/server.go +++ b/listener/sing_shadowsocks/server.go @@ -22,7 +22,6 @@ import ( "github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" - "github.com/sagernet/sing/common/network" ) type Listener struct { @@ -93,21 +92,23 @@ func New(config LC.ShadowsocksServer, tcpIn chan<- C.ConnContext, udpIn chan<- C go func() { conn := bufio.NewPacketConn(ul) - connReader := network.UnwrapPacketReader(conn) // decrease runtime cost for bufio.CreatePacketReadWaiter + var buff *buf.Buffer + newBuffer := func() *buf.Buffer { + buff = buf.NewPacket() // do not use stack buffer + return buff + } + readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) + if isReadWaiter { + readWaiter.InitializeReadWaiter(newBuffer) + } for { var ( - buff *buf.Buffer dest M.Socksaddr err error ) - newBuffer := func() *buf.Buffer { - buff = buf.NewPacket() // do not use stack buffer - return buff - } - // syscallPacketReadWaiter.WaitReadPacket will cache newBuffer function - // so create new PacketReadWaiter in each loop - if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(connReader); isReadWaiter { - dest, err = readWaiter.WaitReadPacket(newBuffer) + buff = nil // clear last loop status, avoid repeat release + if isReadWaiter { + dest, err = readWaiter.WaitReadPacket() } else { dest, err = conn.ReadPacket(newBuffer()) } diff --git a/listener/sing_tun/dns.go b/listener/sing_tun/dns.go index 5ec6d96b..88e3f6d6 100644 --- a/listener/sing_tun/dns.go +++ b/listener/sing_tun/dns.go @@ -110,24 +110,26 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. conn2 = nil }() - connReader := network.UnwrapPacketReader(conn) // decrease runtime cost for bufio.CreatePacketReadWaiter + var buff *buf.Buffer + newBuffer := func() *buf.Buffer { + // safe size which is 1232 from https://dnsflagday.net/2020/. + // so 2048 is enough + buff = buf.NewSize(2 * 1024) + return buff + } + readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn) + if isReadWaiter { + readWaiter.InitializeReadWaiter(newBuffer) + } for { var ( - buff *buf.Buffer dest M.Socksaddr err error ) - newBuffer := func() *buf.Buffer { - // safe size which is 1232 from https://dnsflagday.net/2020/. - // so 2048 is enough - buff = buf.NewSize(2 * 1024) - return buff - } _ = conn.SetReadDeadline(time.Now().Add(DefaultDnsReadTimeout)) - // syscallPacketReadWaiter.WaitReadPacket will cache newBuffer function - // so create new PacketReadWaiter in each loop - if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(connReader); isReadWaiter { - dest, err = readWaiter.WaitReadPacket(newBuffer) + buff = nil // clear last loop status, avoid repeat release + if isReadWaiter { + dest, err = readWaiter.WaitReadPacket() } else { dest, err = conn.ReadPacket(newBuffer()) } @@ -140,7 +142,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. } return err } - go func() { + go func(buff *buf.Buffer) { ctx, cancel := context.WithTimeout(ctx, DefaultDnsRelayTimeout) defer cancel() inData := buff.Bytes() @@ -165,7 +167,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. if err != nil { return } - }() + }(buff) // catch buff at goroutine create, avoid next loop change buff } return nil } From ed174789619ecaa20838f8c91bb3573052870675 Mon Sep 17 00:00:00 2001 From: H1JK Date: Sat, 13 May 2023 09:38:14 +0800 Subject: [PATCH 33/62] feat: Support insecure gRPC --- adapter/outbound/vless.go | 22 +++++++++++++--------- adapter/outbound/vmess.go | 27 ++++++++++++--------------- transport/gun/gun.go | 5 ++++- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/adapter/outbound/vless.go b/adapter/outbound/vless.go index 82ecf927..048350e9 100644 --- a/adapter/outbound/vless.go +++ b/adapter/outbound/vless.go @@ -596,15 +596,19 @@ func NewVless(option VlessOption) (*Vless, error) { Host: v.option.ServerName, ClientFingerprint: v.option.ClientFingerprint, } - tlsConfig := tlsC.GetGlobalTLSConfig(&tls.Config{ - InsecureSkipVerify: v.option.SkipCertVerify, - ServerName: v.option.ServerName, - }) - - if v.option.ServerName == "" { - host, _, _ := net.SplitHostPort(v.addr) - tlsConfig.ServerName = host - gunConfig.Host = host + if option.ServerName == "" { + gunConfig.Host = v.addr + } + var tlsConfig *tls.Config + if option.TLS { + tlsConfig = tlsC.GetGlobalTLSConfig(&tls.Config{ + InsecureSkipVerify: v.option.SkipCertVerify, + ServerName: v.option.ServerName, + }) + if option.ServerName == "" { + host, _, _ := net.SplitHostPort(v.addr) + tlsConfig.ServerName = host + } } v.gunTLSConfig = tlsConfig diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index 91e509d7..c0063b3e 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -413,13 +413,6 @@ func NewVmess(option VmessOption) (*Vmess, error) { option.PacketAddr = false } - switch option.Network { - case "h2", "grpc": - if !option.TLS { - option.TLS = true - } - } - v := &Vmess{ Base: &Base{ name: option.Name, @@ -464,15 +457,19 @@ func NewVmess(option VmessOption) (*Vmess, error) { Host: v.option.ServerName, ClientFingerprint: v.option.ClientFingerprint, } - tlsConfig := &tls.Config{ - InsecureSkipVerify: v.option.SkipCertVerify, - ServerName: v.option.ServerName, + if option.ServerName == "" { + gunConfig.Host = v.addr } - - if v.option.ServerName == "" { - host, _, _ := net.SplitHostPort(v.addr) - tlsConfig.ServerName = host - gunConfig.Host = host + var tlsConfig *tls.Config + if option.TLS { + tlsConfig = tlsC.GetGlobalTLSConfig(&tls.Config{ + InsecureSkipVerify: v.option.SkipCertVerify, + ServerName: v.option.ServerName, + }) + if option.ServerName == "" { + host, _, _ := net.SplitHostPort(v.addr) + tlsConfig.ServerName = host + } } v.gunTLSConfig = tlsConfig diff --git a/transport/gun/gun.go b/transport/gun/gun.go index 36cf68f8..e98f7fb5 100644 --- a/transport/gun/gun.go +++ b/transport/gun/gun.go @@ -199,9 +199,12 @@ func NewHTTP2Client(dialFn DialFn, tlsConfig *tls.Config, Fingerprint string, re if err != nil { return nil, err } - wrap.remoteAddr = pconn.RemoteAddr() + if tlsConfig == nil { + return pconn, nil + } + if len(Fingerprint) != 0 { if realityConfig == nil { if fingerprint, exists := tlsC.GetFingerprint(Fingerprint); exists { From c6fed3e97f3e86d474dd9700817082cc5bab1f22 Mon Sep 17 00:00:00 2001 From: H1JK Date: Sun, 14 May 2023 00:21:59 +0800 Subject: [PATCH 34/62] fix: TLS certificate pool initialize Co-authored-by: Skyxim --- component/tls/config.go | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/component/tls/config.go b/component/tls/config.go index b5b56591..6f808248 100644 --- a/component/tls/config.go +++ b/component/tls/config.go @@ -33,10 +33,22 @@ func AddCertificate(certificate string) error { } } +func initializeCertPool() { + var err error + certPool, err = x509.SystemCertPool() + if err != nil { + certPool = x509.NewCertPool() + } + for _, cert := range trustCerts { + certPool.AddCert(cert) + } +} + func ResetCertificate() { mutex.Lock() defer mutex.Unlock() trustCerts = nil + initializeCertPool() } func getCertPool() *x509.CertPool { @@ -49,12 +61,7 @@ func getCertPool() *x509.CertPool { if certPool != nil { return certPool } - certPool, err := x509.SystemCertPool() - if err == nil { - for _, cert := range trustCerts { - certPool.AddCert(cert) - } - } + initializeCertPool() } return certPool } From c7557b8e483c823f5298ef98d91cf7c29005c6c6 Mon Sep 17 00:00:00 2001 From: H1JK Date: Sun, 14 May 2023 12:34:47 +0800 Subject: [PATCH 35/62] feat: Updater detect and download AMD64v3 artifact Co-authored-by: Larvan2 <78135608+larvan2@users.noreply.github.com> --- hub/updater/updater.go | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/hub/updater/updater.go b/hub/updater/updater.go index 3d80707a..9762f3f3 100644 --- a/hub/updater/updater.go +++ b/hub/updater/updater.go @@ -17,15 +17,16 @@ import ( clashHttp "github.com/Dreamacro/clash/component/http" "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" + + "github.com/klauspost/cpuid/v2" ) // modify from https://github.com/AdguardTeam/AdGuardHome/blob/595484e0b3fb4c457f9bb727a6b94faa78a66c5f/internal/updater/updater.go // Updater is the Clash.Meta updater. var ( - goarch string - goos string - goarm string - gomips string + goarm string + gomips string + amd64Compatible string workDir string @@ -45,6 +46,12 @@ var ( latestVersion string ) +func init() { + if runtime.GOARCH == "amd64" && cpuid.CPU.X64Level() < 3 { + amd64Compatible = "-compatible" + } +} + type updateError struct { Message string } @@ -59,8 +66,6 @@ func Update(execPath string) (err error) { mu.Lock() defer mu.Unlock() - goos = runtime.GOOS - goarch = runtime.GOARCH latestVersion, err = getLatestVersion() if err != nil { return err @@ -128,12 +133,10 @@ func prepare(exePath string) (err error) { //log.Infoln(packageName) backupDir = filepath.Join(workDir, "meta-backup") - if goos == "windows" && goarch == "amd64" { - updateExeName = "clash.meta" + "-" + goos + "-" + goarch + "-compatible.exe" - } else if goos == "linux" && goarch == "amd64" { - updateExeName = "clash.meta" + "-" + goos + "-" + goarch + "-compatible" + if runtime.GOOS == "windows" { + updateExeName = "clash.meta" + "-" + runtime.GOOS + "-" + runtime.GOARCH + amd64Compatible + ".exe" } else { - updateExeName = "clash.meta" + "-" + goos + "-" + goarch + updateExeName = "clash.meta" + "-" + runtime.GOOS + "-" + runtime.GOARCH + amd64Compatible } log.Infoln("updateExeName: %s ", updateExeName) @@ -198,7 +201,7 @@ func replace() error { var err error log.Infoln("replacing: %s to %s", updateExeName, currentExeName) - if goos == "windows" { + if runtime.GOOS == "windows" { // rename fails with "File in use" error err = copyFile(updateExeName, currentExeName) } else { @@ -430,17 +433,15 @@ func getLatestVersion() (version string, err error) { func updateDownloadURL() { var middle string - if goarch == "arm" && goarm != "" { - middle = fmt.Sprintf("-%s-%sv%s-%s", goos, goarch, goarm, latestVersion) - } else if isMIPS(goarch) && gomips != "" { - middle = fmt.Sprintf("-%s-%s-%s-%s", goos, goarch, gomips, latestVersion) - } else if goarch == "amd64" && (goos == "windows" || goos == "linux") { - middle = fmt.Sprintf("-%s-%s-compatible-%s", goos, goarch, latestVersion) + if runtime.GOARCH == "arm" && goarm != "" { + middle = fmt.Sprintf("-%s-%sv%s-%s", runtime.GOOS, runtime.GOARCH, goarm, latestVersion) + } else if isMIPS(runtime.GOARCH) && gomips != "" { + middle = fmt.Sprintf("-%s-%s-%s-%s", runtime.GOOS, runtime.GOARCH, gomips, latestVersion) } else { - middle = fmt.Sprintf("-%s-%s-%s", goos, goarch, latestVersion) + middle = fmt.Sprintf("-%s-%s%s-%s", runtime.GOOS, runtime.GOARCH, amd64Compatible, latestVersion) } - if goos == "windows" { + if runtime.GOOS == "windows" { middle += ".zip" } else { middle += ".gz" From 872a28a5eb4a4593d2f3f11db63aff04abfb4744 Mon Sep 17 00:00:00 2001 From: H1JK Date: Sun, 14 May 2023 13:43:25 +0800 Subject: [PATCH 36/62] Fix: deprecated action commands (#556) Co-authored-by: 8Mi_Yile --- .github/workflows/build.yml | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ccbe3dc6..ecc9c8a5 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -126,7 +126,7 @@ jobs: shell: bash - name: Setup Go - uses: actions/setup-go@v3 + uses: actions/setup-go@v4 with: go-version: "1.20" check-latest: true @@ -254,7 +254,6 @@ jobs: uses: softprops/action-gh-release@v1 if: ${{ success() }} with: - tag: ${{ github.ref_name }} tag_name: Prerelease-${{ github.ref_name }} files: | bin/* @@ -281,7 +280,6 @@ jobs: uses: softprops/action-gh-release@v1 if: ${{ success() }} with: - tag: ${{ github.ref_name }} tag_name: ${{ github.ref_name }} files: bin/* generate_release_notes: true @@ -306,10 +304,10 @@ jobs: working-directory: bin - name: Set up QEMU - uses: docker/setup-qemu-action@v1 + uses: docker/setup-qemu-action@v2 - name: Setup Docker buildx - uses: docker/setup-buildx-action@v1 + uses: docker/setup-buildx-action@v2 with: version: latest @@ -317,7 +315,7 @@ jobs: # https://github.com/docker/metadata-action - name: Extract Docker metadata id: meta - uses: docker/metadata-action@v3 + uses: docker/metadata-action@v4 with: images: ${{ env.REGISTRY }}/${{ secrets.DOCKERHUB_ACCOUNT }}/${{secrets.DOCKERHUB_REPO}} - name: Show files @@ -326,7 +324,7 @@ jobs: ls bin/ - name: Log into registry if: github.event_name != 'pull_request' - uses: docker/login-action@v1 + uses: docker/login-action@v2 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.DOCKER_HUB_USER }} @@ -336,7 +334,7 @@ jobs: # https://github.com/docker/build-push-action - name: Build and push Docker image id: build-and-push - uses: docker/build-push-action@v2 + uses: docker/build-push-action@v4 with: context: . file: ./Dockerfile From 1a9104c003707e23dc2612f23a2ef73792a97b77 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Mon, 15 May 2023 19:06:58 +0800 Subject: [PATCH 37/62] fix: UDP packet should not return io.EOF --- common/net/packet/packet_posix.go | 9 +++++---- go.mod | 2 +- go.sum | 4 ++-- tunnel/connection.go | 4 +++- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/common/net/packet/packet_posix.go b/common/net/packet/packet_posix.go index 3c5d23a6..2861482f 100644 --- a/common/net/packet/packet_posix.go +++ b/common/net/packet/packet_posix.go @@ -3,7 +3,6 @@ package packet import ( - "io" "net" "strconv" "syscall" @@ -34,6 +33,7 @@ func (c *enhanceUDPConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, } else { put() put = nil + data = nil } if readErr == syscall.EAGAIN { return false @@ -48,9 +48,10 @@ func (c *enhanceUDPConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, addr = &net.UDPAddr{IP: ip[:], Port: from.Port, Zone: strconv.FormatInt(int64(from.ZoneId), 10)} } } - if readN == 0 { - readErr = io.EOF - } + // udp should not convert readN == 0 to io.EOF + //if readN == 0 { + // readErr = io.EOF + //} return true }) if err != nil { diff --git a/go.mod b/go.mod index 9b1e2dbd..3ecee7a1 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( github.com/mdlayher/netlink v1.7.2 github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c - github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511124108-b20f64384bdd + github.com/metacubex/sing-shadowsocks2 v0.0.0-20230515071211-0c3604faef69 github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a github.com/miekg/dns v1.1.54 diff --git a/go.sum b/go.sum index d38293a3..80d18133 100644 --- a/go.sum +++ b/go.sum @@ -98,8 +98,8 @@ github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 h1:E/sNW9tugF github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511124108-b20f64384bdd h1:RXdD763CbvqaJOyFLAh6xa8xg7BZTkOJ0p8fBc7kB+w= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230511124108-b20f64384bdd/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230515071211-0c3604faef69 h1:6mwe6TyQUqjpqu8QwRlY5xR5VjENzXtM3LVRhjq00nw= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230515071211-0c3604faef69/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= diff --git a/tunnel/connection.go b/tunnel/connection.go index 73c3e499..321c7d06 100644 --- a/tunnel/connection.go +++ b/tunnel/connection.go @@ -55,7 +55,9 @@ func handleUDPToLocal(packet C.UDPPacket, pc N.EnhancePacketConn, key string, oA } _, err = packet.WriteBack(data, fromUDPAddr) - put() + if put != nil { + put() + } if err != nil { return } From 8b631f11b86994c370ed5e35d14d2882ae21f9e7 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Mon, 15 May 2023 22:45:08 +0800 Subject: [PATCH 38/62] chore: better sing's udp api support --- common/net/packet/packet.go | 3 ++ common/net/packet/packet_sing.go | 74 ++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 common/net/packet/packet_sing.go diff --git a/common/net/packet/packet.go b/common/net/packet/packet.go index d823334e..6329803b 100644 --- a/common/net/packet/packet.go +++ b/common/net/packet/packet.go @@ -18,6 +18,9 @@ func NewEnhancePacketConn(pc net.PacketConn) EnhancePacketConn { if enhancePC, isEnhancePC := pc.(EnhancePacketConn); isEnhancePC { return enhancePC } + if singPC, isSingPC := pc.(SingPacketConn); isSingPC { + return newEnhanceSingPacketConn(singPC) + } return &enhancePacketConn{PacketConn: pc} } diff --git a/common/net/packet/packet_sing.go b/common/net/packet/packet_sing.go new file mode 100644 index 00000000..9be1a4a1 --- /dev/null +++ b/common/net/packet/packet_sing.go @@ -0,0 +1,74 @@ +package packet + +import ( + "net" + + "github.com/sagernet/sing/common/buf" + "github.com/sagernet/sing/common/bufio" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" +) + +type SingPacketConn = N.NetPacketConn + +type enhanceSingPacketConn struct { + N.NetPacketConn + readWaiter N.PacketReadWaiter +} + +func (c *enhanceSingPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + var buff *buf.Buffer + var dest M.Socksaddr + newBuffer := func() *buf.Buffer { + buff = buf.NewPacket() // do not use stack buffer + return buff + } + if c.readWaiter != nil { + c.readWaiter.InitializeReadWaiter(newBuffer) + defer c.readWaiter.InitializeReadWaiter(nil) + dest, err = c.readWaiter.WaitReadPacket() + } else { + dest, err = c.NetPacketConn.ReadPacket(newBuffer()) + } + if dest.IsFqdn() { + addr = dest + } else { + addr = dest.UDPAddr() + } + if err != nil { + if buff != nil { + buff.Release() + } + return + } + if buff == nil { + return + } + if buff.IsEmpty() { + buff.Release() + return + } + data = buff.Bytes() + put = buff.Release + return +} + +func (c *enhanceSingPacketConn) Upstream() any { + return c.NetPacketConn +} + +func (c *enhanceSingPacketConn) WriterReplaceable() bool { + return true +} + +func (c *enhanceSingPacketConn) ReaderReplaceable() bool { + return true +} + +func newEnhanceSingPacketConn(conn N.NetPacketConn) *enhanceSingPacketConn { + epc := &enhanceSingPacketConn{NetPacketConn: conn} + if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn); isReadWaiter { + epc.readWaiter = readWaiter + } + return epc +} From e552b5475fef42f12ce23db9b5ae76fd110b6e6c Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Tue, 16 May 2023 14:55:50 +0800 Subject: [PATCH 39/62] fix: tfoConn panic --- component/dialer/tfo.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/component/dialer/tfo.go b/component/dialer/tfo.go index 09d5cced..4863d6ae 100644 --- a/component/dialer/tfo.go +++ b/component/dialer/tfo.go @@ -18,10 +18,11 @@ type tfoConn struct { } func (c *tfoConn) Dial(earlyData []byte) (err error) { - c.Conn, err = c.dialFn(c.ctx, earlyData) + conn, err := c.dialFn(c.ctx, earlyData) if err != nil { return } + c.Conn = conn c.dialed <- true return err } From 6b1a4385b298251099f25189833234bbd5feb65f Mon Sep 17 00:00:00 2001 From: Larvan2 <78135608+Larvan2@users.noreply.github.com> Date: Wed, 17 May 2023 00:17:23 +0800 Subject: [PATCH 40/62] chore: better updater --- hub/route/upgrade.go | 3 ++- hub/updater/updater.go | 30 +++++++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/hub/route/upgrade.go b/hub/route/upgrade.go index 0a7c54f9..a58f224c 100644 --- a/hub/route/upgrade.go +++ b/hub/route/upgrade.go @@ -30,8 +30,9 @@ func upgrade(w http.ResponseWriter, r *http.Request) { err = updater.Update(execPath) if err != nil { + log.Warnln("%s", err) render.Status(r, http.StatusInternalServerError) - render.JSON(w, r, newError(fmt.Sprintf("Upgrade: %s", err))) + render.JSON(w, r, newError(fmt.Sprintf("%s", err))) return } diff --git a/hub/updater/updater.go b/hub/updater/updater.go index 9762f3f3..90b14c27 100644 --- a/hub/updater/updater.go +++ b/hub/updater/updater.go @@ -8,6 +8,7 @@ import ( "io" "net/http" "os" + "os/exec" "path/filepath" "runtime" "strings" @@ -74,7 +75,7 @@ func Update(execPath string) (err error) { log.Infoln("current version %s, latest version %s", constant.Version, latestVersion) if latestVersion == constant.Version { - err := &updateError{Message: "Already using latest version"} + err := &updateError{Message: "already using latest version"} return err } @@ -433,8 +434,12 @@ func getLatestVersion() (version string, err error) { func updateDownloadURL() { var middle string - if runtime.GOARCH == "arm" && goarm != "" { - middle = fmt.Sprintf("-%s-%sv%s-%s", runtime.GOOS, runtime.GOARCH, goarm, latestVersion) + if runtime.GOARCH == "arm" && probeGoARM() { + //-linux-armv7-alpha-e552b54.gz + middle = fmt.Sprintf("-%s-%s%s-%s", runtime.GOOS, runtime.GOARCH, goarm, latestVersion) + } else if runtime.GOARCH == "arm64" { + //-linux-arm64-alpha-e552b54.gz + middle = fmt.Sprintf("-%s-%s-%s", runtime.GOOS, runtime.GOARCH, latestVersion) } else if isMIPS(runtime.GOARCH) && gomips != "" { middle = fmt.Sprintf("-%s-%s-%s-%s", runtime.GOOS, runtime.GOARCH, gomips, latestVersion) } else { @@ -463,3 +468,22 @@ func isMIPS(arch string) (ok bool) { return false } } + +// linux only +func probeGoARM() (ok bool) { + cmd := exec.Command("cat", "/proc/cpuinfo") + output, err := cmd.Output() + if err != nil { + log.Errorln("probe goarm error:%s", err) + return false + } + cpuInfo := string(output) + if strings.Contains(cpuInfo, "vfpv3") || strings.Contains(cpuInfo, "vfpv4") { + goarm = "v7" + } else if strings.Contains(cpuInfo, "vfp") { + goarm = "v6" + } else { + goarm = "v5" + } + return true +} From 033f902ace8662e5b5da0019cefb9c739847935b Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 18 May 2023 13:15:08 +0800 Subject: [PATCH 41/62] chore: more context passing in outbounds --- adapter/outbound/base.go | 4 ++-- adapter/outbound/http.go | 8 +++----- adapter/outbound/shadowsocks.go | 11 ++--------- adapter/outbound/shadowsocksr.go | 6 +++--- adapter/outbound/snell.go | 6 +++--- adapter/outbound/socks5.go | 8 +++----- adapter/outbound/trojan.go | 16 ++++++++-------- adapter/outbound/vless.go | 20 ++++++++++---------- adapter/outbound/vmess.go | 16 ++++++++-------- adapter/outbound/wireguard.go | 4 ++-- constant/adapters.go | 4 ++-- transport/trojan/trojan.go | 6 +++--- transport/v2ray-plugin/websocket.go | 5 +++-- transport/vless/xtls.go | 6 +----- transport/vmess/tls.go | 11 +---------- transport/vmess/websocket.go | 22 +++++++++++----------- 16 files changed, 65 insertions(+), 88 deletions(-) diff --git a/adapter/outbound/base.go b/adapter/outbound/base.go index c5901d7f..f2ce56c9 100644 --- a/adapter/outbound/base.go +++ b/adapter/outbound/base.go @@ -45,8 +45,8 @@ func (b *Base) Type() C.AdapterType { return b.tp } -// StreamConn implements C.ProxyAdapter -func (b *Base) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { +// StreamConnContext implements C.ProxyAdapter +func (b *Base) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { return c, C.ErrNotSupport } diff --git a/adapter/outbound/http.go b/adapter/outbound/http.go index 82fff5bb..78735b2d 100644 --- a/adapter/outbound/http.go +++ b/adapter/outbound/http.go @@ -40,12 +40,10 @@ type HttpOption struct { Headers map[string]string `proxy:"headers,omitempty"` } -// StreamConn implements C.ProxyAdapter -func (h *Http) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { +// StreamConnContext implements C.ProxyAdapter +func (h *Http) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { if h.tlsConfig != nil { cc := tls.Client(c, h.tlsConfig) - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) - defer cancel() err := cc.HandshakeContext(ctx) c = cc if err != nil { @@ -82,7 +80,7 @@ func (h *Http) DialContextWithDialer(ctx context.Context, dialer C.Dialer, metad safeConnClose(c, err) }(c) - c, err = h.StreamConn(c, metadata) + c, err = h.StreamConnContext(ctx, c, metadata) if err != nil { return nil, err } diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 02e975ef..e6c74592 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -84,14 +84,7 @@ type restlsOption struct { RestlsScript string `obfs:"restls-script,omitempty"` } -// StreamConn implements C.ProxyAdapter -func (ss *ShadowSocks) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { - // fix tls handshake not timeout - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) - defer cancel() - return ss.StreamConnContext(ctx, c, metadata) -} - +// StreamConnContext implements C.ProxyAdapter func (ss *ShadowSocks) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { useEarly := false switch ss.obfsMode { @@ -102,7 +95,7 @@ func (ss *ShadowSocks) StreamConnContext(ctx context.Context, c net.Conn, metada c = obfs.NewHTTPObfs(c, ss.obfsOption.Host, port) case "websocket": var err error - c, err = v2rayObfs.NewV2rayObfs(c, ss.v2rayOption) + c, err = v2rayObfs.NewV2rayObfs(ctx, c, ss.v2rayOption) if err != nil { return nil, fmt.Errorf("%s connect error: %w", ss.addr, err) } diff --git a/adapter/outbound/shadowsocksr.go b/adapter/outbound/shadowsocksr.go index 2b94ab0c..d33d6586 100644 --- a/adapter/outbound/shadowsocksr.go +++ b/adapter/outbound/shadowsocksr.go @@ -38,8 +38,8 @@ type ShadowSocksROption struct { UDP bool `proxy:"udp,omitempty"` } -// StreamConn implements C.ProxyAdapter -func (ssr *ShadowSocksR) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { +// StreamConnContext implements C.ProxyAdapter +func (ssr *ShadowSocksR) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { c = ssr.obfs.StreamConn(c) c = ssr.cipher.StreamConn(c) var ( @@ -83,7 +83,7 @@ func (ssr *ShadowSocksR) DialContextWithDialer(ctx context.Context, dialer C.Dia safeConnClose(c, err) }(c) - c, err = ssr.StreamConn(c, metadata) + c, err = ssr.StreamConnContext(ctx, c, metadata) return NewConn(c, ssr), err } diff --git a/adapter/outbound/snell.go b/adapter/outbound/snell.go index 1ec0a430..fc1f4eb3 100644 --- a/adapter/outbound/snell.go +++ b/adapter/outbound/snell.go @@ -52,8 +52,8 @@ func streamConn(c net.Conn, option streamOption) *snell.Snell { return snell.StreamConn(c, option.psk, option.version) } -// StreamConn implements C.ProxyAdapter -func (s *Snell) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { +// StreamConnContext implements C.ProxyAdapter +func (s *Snell) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { c = streamConn(c, streamOption{s.psk, s.version, s.addr, s.obfsOption}) if metadata.NetWork == C.UDP { err := snell.WriteUDPHeader(c, s.version) @@ -101,7 +101,7 @@ func (s *Snell) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta safeConnClose(c, err) }(c) - c, err = s.StreamConn(c, metadata) + c, err = s.StreamConnContext(ctx, c, metadata) return NewConn(c, s), err } diff --git a/adapter/outbound/socks5.go b/adapter/outbound/socks5.go index 26f5733b..9af4d0fc 100644 --- a/adapter/outbound/socks5.go +++ b/adapter/outbound/socks5.go @@ -39,12 +39,10 @@ type Socks5Option struct { Fingerprint string `proxy:"fingerprint,omitempty"` } -// StreamConn implements C.ProxyAdapter -func (ss *Socks5) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { +// StreamConnContext implements C.ProxyAdapter +func (ss *Socks5) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { if ss.tls { cc := tls.Client(c, ss.tlsConfig) - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) - defer cancel() err := cc.HandshakeContext(ctx) c = cc if err != nil { @@ -88,7 +86,7 @@ func (ss *Socks5) DialContextWithDialer(ctx context.Context, dialer C.Dialer, me safeConnClose(c, err) }(c) - c, err = ss.StreamConn(c, metadata) + c, err = ss.StreamConnContext(ctx, c, metadata) if err != nil { return nil, err } diff --git a/adapter/outbound/trojan.go b/adapter/outbound/trojan.go index b9bbc33f..81fb1ceb 100644 --- a/adapter/outbound/trojan.go +++ b/adapter/outbound/trojan.go @@ -50,7 +50,7 @@ type TrojanOption struct { ClientFingerprint string `proxy:"client-fingerprint,omitempty"` } -func (t *Trojan) plainStream(c net.Conn) (net.Conn, error) { +func (t *Trojan) plainStream(ctx context.Context, c net.Conn) (net.Conn, error) { if t.option.Network == "ws" { host, port, _ := net.SplitHostPort(t.addr) wsOpts := &trojan.WebsocketOption{ @@ -71,14 +71,14 @@ func (t *Trojan) plainStream(c net.Conn) (net.Conn, error) { wsOpts.Headers = header } - return t.instance.StreamWebsocketConn(c, wsOpts) + return t.instance.StreamWebsocketConn(ctx, c, wsOpts) } - return t.instance.StreamConn(c) + return t.instance.StreamConn(ctx, c) } -// StreamConn implements C.ProxyAdapter -func (t *Trojan) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { +// StreamConnContext implements C.ProxyAdapter +func (t *Trojan) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { var err error if tlsC.HaveGlobalFingerprint() && len(t.option.ClientFingerprint) == 0 { @@ -88,7 +88,7 @@ func (t *Trojan) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) if t.transport != nil { c, err = gun.StreamGunWithConn(c, t.gunTLSConfig, t.gunConfig, t.realityConfig) } else { - c, err = t.plainStream(c) + c, err = t.plainStream(ctx, c) } if err != nil { @@ -151,7 +151,7 @@ func (t *Trojan) DialContextWithDialer(ctx context.Context, dialer C.Dialer, met safeConnClose(c, err) }(c) - c, err = t.StreamConn(c, metadata) + c, err = t.StreamConnContext(ctx, c, metadata) if err != nil { return nil, err } @@ -199,7 +199,7 @@ func (t *Trojan) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, me safeConnClose(c, err) }(c) tcpKeepAlive(c) - c, err = t.plainStream(c) + c, err = t.plainStream(ctx, c) if err != nil { return nil, fmt.Errorf("%s connect error: %w", t.addr, err) } diff --git a/adapter/outbound/vless.go b/adapter/outbound/vless.go index 048350e9..e3aff5fb 100644 --- a/adapter/outbound/vless.go +++ b/adapter/outbound/vless.go @@ -75,7 +75,7 @@ type VlessOption struct { ClientFingerprint string `proxy:"client-fingerprint,omitempty"` } -func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { +func (v *Vless) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { var err error if tlsC.HaveGlobalFingerprint() && len(v.option.ClientFingerprint) == 0 { @@ -129,10 +129,10 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { convert.SetUserAgent(wsOpts.Headers) } } - c, err = vmess.StreamWebsocketConn(c, wsOpts) + c, err = vmess.StreamWebsocketConn(ctx, c, wsOpts) case "http": // readability first, so just copy default TLS logic - c, err = v.streamTLSOrXTLSConn(c, false) + c, err = v.streamTLSOrXTLSConn(ctx, c, false) if err != nil { return nil, err } @@ -147,7 +147,7 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { c = vmess.StreamHTTPConn(c, httpOpts) case "h2": - c, err = v.streamTLSOrXTLSConn(c, true) + c, err = v.streamTLSOrXTLSConn(ctx, c, true) if err != nil { return nil, err } @@ -163,7 +163,7 @@ func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { default: // default tcp network // handle TLS And XTLS - c, err = v.streamTLSOrXTLSConn(c, false) + c, err = v.streamTLSOrXTLSConn(ctx, c, false) } if err != nil { @@ -201,7 +201,7 @@ func (v *Vless) streamConn(c net.Conn, metadata *C.Metadata) (conn net.Conn, err return } -func (v *Vless) streamTLSOrXTLSConn(conn net.Conn, isH2 bool) (net.Conn, error) { +func (v *Vless) streamTLSOrXTLSConn(ctx context.Context, conn net.Conn, isH2 bool) (net.Conn, error) { host, _, _ := net.SplitHostPort(v.addr) if v.isLegacyXTLSEnabled() && !isH2 { @@ -215,7 +215,7 @@ func (v *Vless) streamTLSOrXTLSConn(conn net.Conn, isH2 bool) (net.Conn, error) xtlsOpts.Host = v.option.ServerName } - return vless.StreamXTLSConn(conn, &xtlsOpts) + return vless.StreamXTLSConn(ctx, conn, &xtlsOpts) } else if v.option.TLS { tlsOpts := vmess.TLSConfig{ @@ -234,7 +234,7 @@ func (v *Vless) streamTLSOrXTLSConn(conn net.Conn, isH2 bool) (net.Conn, error) tlsOpts.Host = v.option.ServerName } - return vmess.StreamTLSConn(conn, &tlsOpts) + return vmess.StreamTLSConn(ctx, conn, &tlsOpts) } return conn, nil @@ -283,7 +283,7 @@ func (v *Vless) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta safeConnClose(c, err) }(c) - c, err = v.StreamConn(c, metadata) + c, err = v.StreamConnContext(ctx, c, metadata) if err != nil { return nil, fmt.Errorf("%s connect error: %s", v.addr, err.Error()) } @@ -348,7 +348,7 @@ func (v *Vless) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met safeConnClose(c, err) }(c) - c, err = v.StreamConn(c, metadata) + c, err = v.StreamConnContext(ctx, c, metadata) if err != nil { return nil, fmt.Errorf("new vless client error: %v", err) } diff --git a/adapter/outbound/vmess.go b/adapter/outbound/vmess.go index c0063b3e..058ce49d 100644 --- a/adapter/outbound/vmess.go +++ b/adapter/outbound/vmess.go @@ -89,8 +89,8 @@ type WSOptions struct { EarlyDataHeaderName string `proxy:"early-data-header-name,omitempty"` } -// StreamConn implements C.ProxyAdapter -func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { +// StreamConnContext implements C.ProxyAdapter +func (v *Vmess) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { var err error if tlsC.HaveGlobalFingerprint() && (len(v.option.ClientFingerprint) == 0) { @@ -138,7 +138,7 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { wsOpts.TLSConfig.ServerName = host } } - c, err = clashVMess.StreamWebsocketConn(c, wsOpts) + c, err = clashVMess.StreamWebsocketConn(ctx, c, wsOpts) case "http": // readability first, so just copy default TLS logic if v.option.TLS { @@ -153,7 +153,7 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { if v.option.ServerName != "" { tlsOpts.Host = v.option.ServerName } - c, err = clashVMess.StreamTLSConn(c, tlsOpts) + c, err = clashVMess.StreamTLSConn(ctx, c, tlsOpts) if err != nil { return nil, err } @@ -182,7 +182,7 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { tlsOpts.Host = v.option.ServerName } - c, err = clashVMess.StreamTLSConn(c, &tlsOpts) + c, err = clashVMess.StreamTLSConn(ctx, c, &tlsOpts) if err != nil { return nil, err } @@ -210,7 +210,7 @@ func (v *Vmess) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { tlsOpts.Host = v.option.ServerName } - c, err = clashVMess.StreamTLSConn(c, tlsOpts) + c, err = clashVMess.StreamTLSConn(ctx, c, tlsOpts) } } @@ -294,7 +294,7 @@ func (v *Vmess) DialContextWithDialer(ctx context.Context, dialer C.Dialer, meta safeConnClose(c, err) }(c) - c, err = v.StreamConn(c, metadata) + c, err = v.StreamConnContext(ctx, c, metadata) return NewConn(c, v), err } @@ -355,7 +355,7 @@ func (v *Vmess) ListenPacketWithDialer(ctx context.Context, dialer C.Dialer, met safeConnClose(c, err) }(c) - c, err = v.StreamConn(c, metadata) + c, err = v.StreamConnContext(ctx, c, metadata) if err != nil { return nil, fmt.Errorf("new vmess client error: %v", err) } diff --git a/adapter/outbound/wireguard.go b/adapter/outbound/wireguard.go index 67cd9092..38b5aa02 100644 --- a/adapter/outbound/wireguard.go +++ b/adapter/outbound/wireguard.go @@ -499,9 +499,9 @@ func (r *refProxyAdapter) MarshalJSON() ([]byte, error) { return nil, C.ErrNotSupport } -func (r *refProxyAdapter) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { +func (r *refProxyAdapter) StreamConnContext(ctx context.Context, c net.Conn, metadata *C.Metadata) (net.Conn, error) { if r.proxyAdapter != nil { - return r.proxyAdapter.StreamConn(c, metadata) + return r.proxyAdapter.StreamConnContext(ctx, c, metadata) } return nil, C.ErrNotSupport } diff --git a/constant/adapters.go b/constant/adapters.go index 73877dec..12579685 100644 --- a/constant/adapters.go +++ b/constant/adapters.go @@ -106,11 +106,11 @@ type ProxyAdapter interface { // // Examples: // conn, _ := net.DialContext(context.Background(), "tcp", "host:port") - // conn, _ = adapter.StreamConn(conn, metadata) + // conn, _ = adapter.StreamConnContext(context.Background(), conn, metadata) // // It returns a C.Conn with protocol which start with // a new session (if any) - StreamConn(c net.Conn, metadata *Metadata) (net.Conn, error) + StreamConnContext(ctx context.Context, c net.Conn, metadata *Metadata) (net.Conn, error) // DialContext return a C.Conn with protocol which // contains multiplexing-related reuse logic (if any) diff --git a/transport/trojan/trojan.go b/transport/trojan/trojan.go index 8eae8237..8b4146c6 100644 --- a/transport/trojan/trojan.go +++ b/transport/trojan/trojan.go @@ -70,7 +70,7 @@ type Trojan struct { hexPassword []byte } -func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) { +func (t *Trojan) StreamConn(ctx context.Context, conn net.Conn) (net.Conn, error) { alpn := defaultALPN if len(t.option.ALPN) != 0 { alpn = t.option.ALPN @@ -149,7 +149,7 @@ func (t *Trojan) StreamConn(conn net.Conn) (net.Conn, error) { } } -func (t *Trojan) StreamWebsocketConn(conn net.Conn, wsOptions *WebsocketOption) (net.Conn, error) { +func (t *Trojan) StreamWebsocketConn(ctx context.Context, conn net.Conn, wsOptions *WebsocketOption) (net.Conn, error) { alpn := defaultWebsocketALPN if len(t.option.ALPN) != 0 { alpn = t.option.ALPN @@ -162,7 +162,7 @@ func (t *Trojan) StreamWebsocketConn(conn net.Conn, wsOptions *WebsocketOption) ServerName: t.option.ServerName, } - return vmess.StreamWebsocketConn(conn, &vmess.WebsocketConfig{ + return vmess.StreamWebsocketConn(ctx, conn, &vmess.WebsocketConfig{ Host: wsOptions.Host, Port: wsOptions.Port, Path: wsOptions.Path, diff --git a/transport/v2ray-plugin/websocket.go b/transport/v2ray-plugin/websocket.go index 7c2c8a88..25483670 100644 --- a/transport/v2ray-plugin/websocket.go +++ b/transport/v2ray-plugin/websocket.go @@ -1,6 +1,7 @@ package obfs import ( + "context" "crypto/tls" "net" "net/http" @@ -22,7 +23,7 @@ type Option struct { } // NewV2rayObfs return a HTTPObfs -func NewV2rayObfs(conn net.Conn, option *Option) (net.Conn, error) { +func NewV2rayObfs(ctx context.Context, conn net.Conn, option *Option) (net.Conn, error) { header := http.Header{} for k, v := range option.Headers { header.Add(k, v) @@ -57,7 +58,7 @@ func NewV2rayObfs(conn net.Conn, option *Option) (net.Conn, error) { } var err error - conn, err = vmess.StreamWebsocketConn(conn, config) + conn, err = vmess.StreamWebsocketConn(ctx, conn, config) if err != nil { return nil, err } diff --git a/transport/vless/xtls.go b/transport/vless/xtls.go index 3a319568..09929fc3 100644 --- a/transport/vless/xtls.go +++ b/transport/vless/xtls.go @@ -6,7 +6,6 @@ import ( "net" tlsC "github.com/Dreamacro/clash/component/tls" - C "github.com/Dreamacro/clash/constant" xtls "github.com/xtls/go" ) @@ -21,7 +20,7 @@ type XTLSConfig struct { NextProtos []string } -func StreamXTLSConn(conn net.Conn, cfg *XTLSConfig) (net.Conn, error) { +func StreamXTLSConn(ctx context.Context, conn net.Conn, cfg *XTLSConfig) (net.Conn, error) { xtlsConfig := &xtls.Config{ ServerName: cfg.Host, InsecureSkipVerify: cfg.SkipCertVerify, @@ -38,9 +37,6 @@ func StreamXTLSConn(conn net.Conn, cfg *XTLSConfig) (net.Conn, error) { xtlsConn := xtls.Client(conn, xtlsConfig) - // fix xtls handshake not timeout - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) - defer cancel() err := xtlsConn.HandshakeContext(ctx) return xtlsConn, err } diff --git a/transport/vmess/tls.go b/transport/vmess/tls.go index f020d273..54813029 100644 --- a/transport/vmess/tls.go +++ b/transport/vmess/tls.go @@ -7,7 +7,6 @@ import ( "net" tlsC "github.com/Dreamacro/clash/component/tls" - C "github.com/Dreamacro/clash/constant" ) type TLSConfig struct { @@ -19,7 +18,7 @@ type TLSConfig struct { Reality *tlsC.RealityConfig } -func StreamTLSConn(conn net.Conn, cfg *TLSConfig) (net.Conn, error) { +func StreamTLSConn(ctx context.Context, conn net.Conn, cfg *TLSConfig) (net.Conn, error) { tlsConfig := &tls.Config{ ServerName: cfg.Host, InsecureSkipVerify: cfg.SkipCertVerify, @@ -39,15 +38,10 @@ func StreamTLSConn(conn net.Conn, cfg *TLSConfig) (net.Conn, error) { if cfg.Reality == nil { utlsConn, valid := GetUTLSConn(conn, cfg.ClientFingerprint, tlsConfig) if valid { - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) - defer cancel() - err := utlsConn.(*tlsC.UConn).HandshakeContext(ctx) return utlsConn, err } } else { - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) - defer cancel() return tlsC.GetRealityConn(ctx, conn, cfg.ClientFingerprint, tlsConfig, cfg.Reality) } } @@ -57,9 +51,6 @@ func StreamTLSConn(conn net.Conn, cfg *TLSConfig) (net.Conn, error) { tlsConn := tls.Client(conn, tlsConfig) - ctx, cancel := context.WithTimeout(context.Background(), C.DefaultTLSTimeout) - defer cancel() - err := tlsConn.HandshakeContext(ctx) return tlsConn, err } diff --git a/transport/vmess/websocket.go b/transport/vmess/websocket.go index e7335d84..a4ce99a9 100644 --- a/transport/vmess/websocket.go +++ b/transport/vmess/websocket.go @@ -194,17 +194,17 @@ func (wsedc *websocketWithEarlyDataConn) Dial(earlyData []byte) error { earlyDataBuf := bytes.NewBuffer(earlyData) if _, err := base64EarlyDataEncoder.Write(earlyDataBuf.Next(wsedc.config.MaxEarlyData)); err != nil { - return errors.New("failed to encode early data: " + err.Error()) + return fmt.Errorf("failed to encode early data: %w", err) } if errc := base64EarlyDataEncoder.Close(); errc != nil { - return errors.New("failed to encode early data tail: " + errc.Error()) + return fmt.Errorf("failed to encode early data tail: %w", errc) } var err error - if wsedc.Conn, err = streamWebsocketConn(wsedc.underlay, wsedc.config, base64DataBuf); err != nil { + if wsedc.Conn, err = streamWebsocketConn(wsedc.ctx, wsedc.underlay, wsedc.config, base64DataBuf); err != nil { wsedc.Close() - return errors.New("failed to dial WebSocket: " + err.Error()) + return fmt.Errorf("failed to dial WebSocket: %w", err) } wsedc.dialed <- true @@ -340,7 +340,7 @@ func streamWebsocketWithEarlyDataConn(conn net.Conn, c *WebsocketConfig) (net.Co return N.NewDeadlineConn(conn), nil } -func streamWebsocketConn(conn net.Conn, c *WebsocketConfig, earlyData *bytes.Buffer) (net.Conn, error) { +func streamWebsocketConn(ctx context.Context, conn net.Conn, c *WebsocketConfig, earlyData *bytes.Buffer) (net.Conn, error) { dialer := &websocket.Dialer{ NetDial: func(network, addr string) (net.Conn, error) { @@ -396,13 +396,13 @@ func streamWebsocketConn(conn net.Conn, c *WebsocketConfig, earlyData *bytes.Buf } } - wsConn, resp, err := dialer.Dial(uri.String(), headers) + wsConn, resp, err := dialer.DialContext(ctx, uri.String(), headers) if err != nil { - reason := err.Error() + reason := err if resp != nil { - reason = resp.Status + reason = errors.New(resp.Status) } - return nil, fmt.Errorf("dial %s error: %s", uri.Host, reason) + return nil, fmt.Errorf("dial %s error: %w", uri.Host, reason) } conn = &websocketConn{ @@ -417,7 +417,7 @@ func streamWebsocketConn(conn net.Conn, c *WebsocketConfig, earlyData *bytes.Buf return N.NewDeadlineConn(conn), nil } -func StreamWebsocketConn(conn net.Conn, c *WebsocketConfig) (net.Conn, error) { +func StreamWebsocketConn(ctx context.Context, conn net.Conn, c *WebsocketConfig) (net.Conn, error) { if u, err := url.Parse(c.Path); err == nil { if q := u.Query(); q.Get("ed") != "" { if ed, err := strconv.Atoi(q.Get("ed")); err == nil { @@ -434,5 +434,5 @@ func StreamWebsocketConn(conn net.Conn, c *WebsocketConfig) (net.Conn, error) { return streamWebsocketWithEarlyDataConn(conn, c) } - return streamWebsocketConn(conn, c, nil) + return streamWebsocketConn(ctx, conn, c, nil) } From 6e0c3a368f94efc1535f2f08a78e0cc5e927722a Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Fri, 19 May 2023 11:08:14 +0800 Subject: [PATCH 42/62] chore: upgrade dependencies --- go.mod | 8 ++++---- go.sum | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 3ecee7a1..a55cc3d8 100644 --- a/go.mod +++ b/go.mod @@ -17,11 +17,12 @@ require ( github.com/hashicorp/golang-lru v0.5.4 github.com/insomniacslk/dhcp v0.0.0-20230407062729-974c6f05fe16 github.com/jpillora/backoff v1.0.0 + github.com/klauspost/cpuid/v2 v2.0.12 github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 github.com/mdlayher/netlink v1.7.2 github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c - github.com/metacubex/sing-shadowsocks2 v0.0.0-20230515071211-0c3604faef69 + github.com/metacubex/sing-shadowsocks2 v0.0.0-20230519030442-556ef530768f github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a github.com/miekg/dns v1.1.54 @@ -29,8 +30,8 @@ require ( github.com/openacid/low v0.1.21 github.com/oschwald/geoip2-golang v1.8.0 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.2.5-0.20230512033628-9be7806bab51 - github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e + github.com/sagernet/sing v0.2.5-0.20230519030052-49166ac42700 + github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646 github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 @@ -74,7 +75,6 @@ require ( github.com/hashicorp/yamux v0.1.1 // indirect github.com/josharian/native v1.1.0 // indirect github.com/klauspost/compress v1.15.15 // indirect - github.com/klauspost/cpuid/v2 v2.0.12 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mdlayher/socket v0.4.1 // indirect github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c // indirect diff --git a/go.sum b/go.sum index 80d18133..4a7601b8 100644 --- a/go.sum +++ b/go.sum @@ -98,8 +98,8 @@ github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 h1:E/sNW9tugF github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230515071211-0c3604faef69 h1:6mwe6TyQUqjpqu8QwRlY5xR5VjENzXtM3LVRhjq00nw= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230515071211-0c3604faef69/go.mod h1:r+JnKYxqLJIkRhpT9xb3b11icXsvM6yVjCxr2Smp1Og= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230519030442-556ef530768f h1:aWgVMoAm5V2Ur9key6L//mUSBrVMl/zw/4GDG4ZjyZI= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230519030442-556ef530768f/go.mod h1:jVDD4N22bDPPKA73NvB7aqdlLWiAwv8D+jx7HwhcWak= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= @@ -143,10 +143,10 @@ github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6E 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.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.5-0.20230512033628-9be7806bab51 h1:ySJuouhl890pBZly51Hkb2mbDnz+qSQCLF5j+4IFHis= -github.com/sagernet/sing v0.2.5-0.20230512033628-9be7806bab51/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= -github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e h1:t8nuY9plpHEzlnPxOpuv64jhjz3teIvccu3YMFX4fJI= -github.com/sagernet/sing-mux v0.0.0-20230427141602-9836fc9b052e/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= +github.com/sagernet/sing v0.2.5-0.20230519030052-49166ac42700 h1:NTiK4CtFIzD+OZkjR2/jP8IZJ/S8gKhiOoeU2ycXKDg= +github.com/sagernet/sing v0.2.5-0.20230519030052-49166ac42700/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646 h1:X3ADfMqeGns1Q1FlXc9kaL9FwW1UM6D6tEQo8jFstpc= +github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI= github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U= From 89ae640487f62981bdd6de3d8e5c5be065f54c79 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Fri, 19 May 2023 19:57:55 +0800 Subject: [PATCH 43/62] fix: ensure group not empty --- adapter/outboundgroup/groupbase.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/adapter/outboundgroup/groupbase.go b/adapter/outboundgroup/groupbase.go index 8e253e63..895ca421 100644 --- a/adapter/outboundgroup/groupbase.go +++ b/adapter/outboundgroup/groupbase.go @@ -130,10 +130,6 @@ func (gb *GroupBase) GetProxies(touch bool) []C.Proxy { } } - if len(proxies) == 0 { - return append(proxies, tunnel.Proxies()["COMPATIBLE"]) - } - if len(gb.providers) > 1 && len(gb.filterRegs) > 1 { var newProxies []C.Proxy proxiesSet := map[string]struct{}{} @@ -189,6 +185,10 @@ func (gb *GroupBase) GetProxies(touch bool) []C.Proxy { proxies = newProxies } + if len(proxies) == 0 { + return append(proxies, tunnel.Proxies()["COMPATIBLE"]) + } + return proxies } From ae8d42fb8271204a2c9ece3c1f6389d10a5728d2 Mon Sep 17 00:00:00 2001 From: 8Mi_Yile Date: Fri, 19 May 2023 21:00:00 +0800 Subject: [PATCH 44/62] Fix: update action to support Node 16 (#565) --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ecc9c8a5..bbf8e721 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -223,7 +223,7 @@ jobs: working-directory: bin - name: Delete current release assets - uses: andreaswilli/delete-release-assets-action@v2.0.0 + uses: 8Mi-Tech/delete-release-assets-action@main with: github_token: ${{ secrets.GITHUB_TOKEN }} tag: Prerelease-${{ github.ref_name }} From 2b1e69153b5b15740e3aa7f47d162ce3fd41b7d5 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Fri, 19 May 2023 23:29:43 +0800 Subject: [PATCH 45/62] chore: better packet deadline --- common/net/deadline/packet.go | 109 ++++++++++---------------- common/net/deadline/packet_enhance.go | 73 +++++++++++++++++ common/net/deadline/packet_sing.go | 96 +++++++++++++++++++++++ common/net/packet.go | 4 +- common/net/packet/packet.go | 6 +- common/net/packet/packet_sing.go | 5 ++ 6 files changed, 222 insertions(+), 71 deletions(-) create mode 100644 common/net/deadline/packet_enhance.go create mode 100644 common/net/deadline/packet_sing.go diff --git a/common/net/deadline/packet.go b/common/net/deadline/packet.go index 38b5f579..f68aadaf 100644 --- a/common/net/deadline/packet.go +++ b/common/net/deadline/packet.go @@ -11,12 +11,13 @@ import ( type readResult struct { data []byte - put func() addr net.Addr err error + enhanceReadResult + singReadResult } -type PacketConn struct { +type NetPacketConn struct { net.PacketConn deadline atomic.TypedValue[time.Time] pipeDeadline pipeDeadline @@ -25,23 +26,45 @@ type PacketConn struct { resultCh chan *readResult } -func NewPacketConn(pc net.PacketConn) net.PacketConn { - c := &PacketConn{ +func NewNetPacketConn(pc net.PacketConn) net.PacketConn { + npc := &NetPacketConn{ PacketConn: pc, pipeDeadline: makePipeDeadline(), resultCh: make(chan *readResult, 1), } - c.resultCh <- nil - if enhancePacketConn, isEnhance := pc.(packet.EnhancePacketConn); isEnhance { - return &EnhancePacketConn{ - PacketConn: c, - enhancePacketConn: enhancePacketConn, + npc.resultCh <- nil + if enhancePC, isEnhance := pc.(packet.EnhancePacketConn); isEnhance { + epc := &EnhancePacketConn{ + NetPacketConn: npc, + enhancePacketConn: enhancePacketConn{ + netPacketConn: npc, + enhancePacketConn: enhancePC, + }, + } + if singPC, isSingPC := pc.(packet.SingPacketConn); isSingPC { + return &EnhanceSingPacketConn{ + EnhancePacketConn: epc, + singPacketConn: singPacketConn{ + netPacketConn: npc, + singPacketConn: singPC, + }, + } + } + return epc + } + if singPC, isSingPC := pc.(packet.SingPacketConn); isSingPC { + return &SingPacketConn{ + NetPacketConn: npc, + singPacketConn: singPacketConn{ + netPacketConn: npc, + singPacketConn: singPC, + }, } } - return c + return npc } -func (c *PacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { +func (c *NetPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { select { case result := <-c.resultCh: if result != nil { @@ -73,7 +96,7 @@ func (c *PacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { return c.ReadFrom(p) } -func (c *PacketConn) pipeReadFrom(size int) { +func (c *NetPacketConn) pipeReadFrom(size int) { buffer := make([]byte, size) n, addr, err := c.PacketConn.ReadFrom(buffer) buffer = buffer[:n] @@ -84,7 +107,7 @@ func (c *PacketConn) pipeReadFrom(size int) { } } -func (c *PacketConn) SetReadDeadline(t time.Time) error { +func (c *NetPacketConn) SetReadDeadline(t time.Time) error { if c.disablePipe.Load() { return c.PacketConn.SetReadDeadline(t) } else if c.inRead.Load() { @@ -96,7 +119,7 @@ func (c *PacketConn) SetReadDeadline(t time.Time) error { return nil } -func (c *PacketConn) ReaderReplaceable() bool { +func (c *NetPacketConn) ReaderReplaceable() bool { select { case result := <-c.resultCh: c.resultCh <- result @@ -111,66 +134,14 @@ func (c *PacketConn) ReaderReplaceable() bool { return c.disablePipe.Load() || c.deadline.Load().IsZero() } -func (c *PacketConn) WriterReplaceable() bool { +func (c *NetPacketConn) WriterReplaceable() bool { return true } -func (c *PacketConn) Upstream() any { +func (c *NetPacketConn) Upstream() any { return c.PacketConn } -func (c *PacketConn) NeedAdditionalReadDeadline() bool { +func (c *NetPacketConn) NeedAdditionalReadDeadline() bool { return false } - -type EnhancePacketConn struct { - *PacketConn - enhancePacketConn packet.EnhancePacketConn -} - -func NewEnhancePacketConn(pc packet.EnhancePacketConn) packet.EnhancePacketConn { - return NewPacketConn(pc).(packet.EnhancePacketConn) -} - -func (c *EnhancePacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { - select { - case result := <-c.resultCh: - if result != nil { - data = result.data - put = result.put - addr = result.addr - err = result.err - c.resultCh <- nil // finish cache read - return - } else { - c.resultCh <- nil - break - } - case <-c.pipeDeadline.wait(): - return nil, nil, nil, os.ErrDeadlineExceeded - } - - if c.disablePipe.Load() { - return c.enhancePacketConn.WaitReadFrom() - } else if c.deadline.Load().IsZero() { - c.inRead.Store(true) - defer c.inRead.Store(false) - data, put, addr, err = c.enhancePacketConn.WaitReadFrom() - return - } - - <-c.resultCh - go c.pipeWaitReadFrom() - - return c.WaitReadFrom() -} - -func (c *EnhancePacketConn) pipeWaitReadFrom() { - data, put, addr, err := c.enhancePacketConn.WaitReadFrom() - c.resultCh <- &readResult{ - data: data, - put: put, - addr: addr, - err: err, - } -} diff --git a/common/net/deadline/packet_enhance.go b/common/net/deadline/packet_enhance.go new file mode 100644 index 00000000..589e1447 --- /dev/null +++ b/common/net/deadline/packet_enhance.go @@ -0,0 +1,73 @@ +package deadline + +import ( + "net" + "os" + + "github.com/Dreamacro/clash/common/net/packet" +) + +type EnhancePacketConn struct { + *NetPacketConn + enhancePacketConn +} + +var _ packet.EnhancePacketConn = (*EnhancePacketConn)(nil) + +func NewEnhancePacketConn(pc packet.EnhancePacketConn) packet.EnhancePacketConn { + return NewNetPacketConn(pc).(packet.EnhancePacketConn) +} + +type enhanceReadResult struct { + put func() +} + +type enhancePacketConn struct { + netPacketConn *NetPacketConn + enhancePacketConn packet.EnhancePacketConn +} + +func (c *enhancePacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + select { + case result := <-c.netPacketConn.resultCh: + if result != nil { + data = result.data + put = result.put + addr = result.addr + err = result.err + c.netPacketConn.resultCh <- nil // finish cache read + return + } else { + c.netPacketConn.resultCh <- nil + break + } + case <-c.netPacketConn.pipeDeadline.wait(): + return nil, nil, nil, os.ErrDeadlineExceeded + } + + if c.netPacketConn.disablePipe.Load() { + return c.enhancePacketConn.WaitReadFrom() + } else if c.netPacketConn.deadline.Load().IsZero() { + c.netPacketConn.inRead.Store(true) + defer c.netPacketConn.inRead.Store(false) + data, put, addr, err = c.enhancePacketConn.WaitReadFrom() + return + } + + <-c.netPacketConn.resultCh + go c.pipeWaitReadFrom() + + return c.WaitReadFrom() +} + +func (c *enhancePacketConn) pipeWaitReadFrom() { + data, put, addr, err := c.enhancePacketConn.WaitReadFrom() + c.netPacketConn.resultCh <- &readResult{ + data: data, + enhanceReadResult: enhanceReadResult{ + put: put, + }, + addr: addr, + err: err, + } +} diff --git a/common/net/deadline/packet_sing.go b/common/net/deadline/packet_sing.go new file mode 100644 index 00000000..f69022ab --- /dev/null +++ b/common/net/deadline/packet_sing.go @@ -0,0 +1,96 @@ +package deadline + +import ( + "os" + + "github.com/Dreamacro/clash/common/net/packet" + "github.com/sagernet/sing/common/buf" + M "github.com/sagernet/sing/common/metadata" +) + +type SingPacketConn struct { + *NetPacketConn + singPacketConn +} + +var _ packet.SingPacketConn = (*SingPacketConn)(nil) + +func NewSingPacketConn(pc packet.SingPacketConn) packet.SingPacketConn { + return NewNetPacketConn(pc).(packet.SingPacketConn) +} + +type EnhanceSingPacketConn struct { + *EnhancePacketConn + singPacketConn +} + +func NewEnhanceSingPacketConn(pc packet.EnhanceSingPacketConn) packet.EnhanceSingPacketConn { + return NewNetPacketConn(pc).(packet.EnhanceSingPacketConn) +} + +var _ packet.EnhanceSingPacketConn = (*EnhanceSingPacketConn)(nil) + +type singReadResult struct { + buffer *buf.Buffer + destination M.Socksaddr +} + +type singPacketConn struct { + netPacketConn *NetPacketConn + singPacketConn packet.SingPacketConn +} + +func (c *singPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { + select { + case result := <-c.netPacketConn.resultCh: + if result != nil { + destination = result.destination + err = result.err + buffer.Resize(result.buffer.Start(), 0) + n := copy(buffer.FreeBytes(), result.buffer.Bytes()) + buffer.Truncate(n) + result.buffer.Advance(n) + if result.buffer.IsEmpty() { + result.buffer.Release() + } + c.netPacketConn.resultCh <- nil // finish cache read + return + } else { + c.netPacketConn.resultCh <- nil + break + } + case <-c.netPacketConn.pipeDeadline.wait(): + return M.Socksaddr{}, os.ErrDeadlineExceeded + } + + if c.netPacketConn.disablePipe.Load() { + return c.singPacketConn.ReadPacket(buffer) + } else if c.netPacketConn.deadline.Load().IsZero() { + c.netPacketConn.inRead.Store(true) + defer c.netPacketConn.inRead.Store(false) + destination, err = c.singPacketConn.ReadPacket(buffer) + return + } + + <-c.netPacketConn.resultCh + go c.pipeReadPacket(buffer.Cap(), buffer.Start()) + + return c.ReadPacket(buffer) +} + +func (c *singPacketConn) pipeReadPacket(bufLen int, bufStart int) { + buffer := buf.NewSize(bufLen) + buffer.Advance(bufStart) + destination, err := c.singPacketConn.ReadPacket(buffer) + c.netPacketConn.resultCh <- &readResult{ + singReadResult: singReadResult{ + buffer: buffer, + destination: destination, + }, + err: err, + } +} + +func (c *singPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { + return c.singPacketConn.WritePacket(buffer, destination) +} diff --git a/common/net/packet.go b/common/net/packet.go index d01c9efe..865590ce 100644 --- a/common/net/packet.go +++ b/common/net/packet.go @@ -11,8 +11,10 @@ import ( type EnhancePacketConn = packet.EnhancePacketConn var NewEnhancePacketConn = packet.NewEnhancePacketConn -var NewDeadlinePacketConn = deadline.NewPacketConn +var NewDeadlineNetPacketConn = deadline.NewNetPacketConn var NewDeadlineEnhancePacketConn = deadline.NewEnhancePacketConn +var NewDeadlineSingPacketConn = deadline.NewSingPacketConn +var NewDeadlineEnhanceSingPacketConn = deadline.NewEnhanceSingPacketConn type threadSafePacketConn struct { EnhancePacketConn diff --git a/common/net/packet/packet.go b/common/net/packet/packet.go index 6329803b..6c9542c1 100644 --- a/common/net/packet/packet.go +++ b/common/net/packet/packet.go @@ -6,9 +6,13 @@ import ( "github.com/Dreamacro/clash/common/pool" ) +type WaitReadFrom interface { + WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) +} + type EnhancePacketConn interface { net.PacketConn - WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) + WaitReadFrom } func NewEnhancePacketConn(pc net.PacketConn) EnhancePacketConn { diff --git a/common/net/packet/packet_sing.go b/common/net/packet/packet_sing.go index 9be1a4a1..daa352c8 100644 --- a/common/net/packet/packet_sing.go +++ b/common/net/packet/packet_sing.go @@ -11,6 +11,11 @@ import ( type SingPacketConn = N.NetPacketConn +type EnhanceSingPacketConn interface { + N.NetPacketConn + EnhancePacketConn +} + type enhanceSingPacketConn struct { N.NetPacketConn readWaiter N.PacketReadWaiter From b047ca02942c8e6d154f400331725f0ee805b43d Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sat, 20 May 2023 11:44:11 +0800 Subject: [PATCH 46/62] chore: packet deadline support CreateReadWaiter interface --- common/net/deadline/packet.go | 51 +++++----- common/net/deadline/packet_enhance.go | 56 ++++++----- common/net/deadline/packet_sing.go | 134 +++++++++++++++++++++----- 3 files changed, 171 insertions(+), 70 deletions(-) diff --git a/common/net/deadline/packet.go b/common/net/deadline/packet.go index f68aadaf..bcf2db9d 100644 --- a/common/net/deadline/packet.go +++ b/common/net/deadline/packet.go @@ -3,6 +3,7 @@ package deadline import ( "net" "os" + "runtime" "time" "github.com/Dreamacro/clash/common/atomic" @@ -13,8 +14,6 @@ type readResult struct { data []byte addr net.Addr err error - enhanceReadResult - singReadResult } type NetPacketConn struct { @@ -23,14 +22,14 @@ type NetPacketConn struct { pipeDeadline pipeDeadline disablePipe atomic.Bool inRead atomic.Bool - resultCh chan *readResult + resultCh chan any } func NewNetPacketConn(pc net.PacketConn) net.PacketConn { npc := &NetPacketConn{ PacketConn: pc, pipeDeadline: makePipeDeadline(), - resultCh: make(chan *readResult, 1), + resultCh: make(chan any, 1), } npc.resultCh <- nil if enhancePC, isEnhance := pc.(packet.EnhancePacketConn); isEnhance { @@ -65,20 +64,28 @@ func NewNetPacketConn(pc net.PacketConn) net.PacketConn { } func (c *NetPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { - select { - case result := <-c.resultCh: - if result != nil { - n = copy(p, result.data) - addr = result.addr - err = result.err - c.resultCh <- nil // finish cache read - return - } else { - c.resultCh <- nil - break +FOR: + for { + select { + case result := <-c.resultCh: + if result != nil { + if result, ok := result.(*readResult); ok { + n = copy(p, result.data) + addr = result.addr + err = result.err + c.resultCh <- nil // finish cache read + return + } + c.resultCh <- result // another type of read + runtime.Gosched() // allowing other goroutines to run + continue FOR + } else { + c.resultCh <- nil + break FOR + } + case <-c.pipeDeadline.wait(): + return 0, nil, os.ErrDeadlineExceeded } - case <-c.pipeDeadline.wait(): - return 0, nil, os.ErrDeadlineExceeded } if c.disablePipe.Load() { @@ -100,11 +107,11 @@ func (c *NetPacketConn) pipeReadFrom(size int) { buffer := make([]byte, size) n, addr, err := c.PacketConn.ReadFrom(buffer) buffer = buffer[:n] - c.resultCh <- &readResult{ - data: buffer, - addr: addr, - err: err, - } + result := &readResult{} + result.data = buffer + result.addr = addr + result.err = err + c.resultCh <- result } func (c *NetPacketConn) SetReadDeadline(t time.Time) error { diff --git a/common/net/deadline/packet_enhance.go b/common/net/deadline/packet_enhance.go index 589e1447..5b7d767f 100644 --- a/common/net/deadline/packet_enhance.go +++ b/common/net/deadline/packet_enhance.go @@ -3,6 +3,7 @@ package deadline import ( "net" "os" + "runtime" "github.com/Dreamacro/clash/common/net/packet" ) @@ -19,7 +20,10 @@ func NewEnhancePacketConn(pc packet.EnhancePacketConn) packet.EnhancePacketConn } type enhanceReadResult struct { - put func() + data []byte + put func() + addr net.Addr + err error } type enhancePacketConn struct { @@ -28,21 +32,29 @@ type enhancePacketConn struct { } func (c *enhancePacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { - select { - case result := <-c.netPacketConn.resultCh: - if result != nil { - data = result.data - put = result.put - addr = result.addr - err = result.err - c.netPacketConn.resultCh <- nil // finish cache read - return - } else { - c.netPacketConn.resultCh <- nil - break +FOR: + for { + select { + case result := <-c.netPacketConn.resultCh: + if result != nil { + if result, ok := result.(*enhanceReadResult); ok { + data = result.data + put = result.put + addr = result.addr + err = result.err + c.netPacketConn.resultCh <- nil // finish cache read + return + } + c.netPacketConn.resultCh <- result // another type of read + runtime.Gosched() // allowing other goroutines to run + continue FOR + } else { + c.netPacketConn.resultCh <- nil + break FOR + } + case <-c.netPacketConn.pipeDeadline.wait(): + return nil, nil, nil, os.ErrDeadlineExceeded } - case <-c.netPacketConn.pipeDeadline.wait(): - return nil, nil, nil, os.ErrDeadlineExceeded } if c.netPacketConn.disablePipe.Load() { @@ -62,12 +74,10 @@ func (c *enhancePacketConn) WaitReadFrom() (data []byte, put func(), addr net.Ad func (c *enhancePacketConn) pipeWaitReadFrom() { data, put, addr, err := c.enhancePacketConn.WaitReadFrom() - c.netPacketConn.resultCh <- &readResult{ - data: data, - enhanceReadResult: enhanceReadResult{ - put: put, - }, - addr: addr, - err: err, - } + result := &enhanceReadResult{} + result.data = data + result.put = put + result.addr = addr + result.err = err + c.netPacketConn.resultCh <- result } diff --git a/common/net/deadline/packet_sing.go b/common/net/deadline/packet_sing.go index f69022ab..a3da34f4 100644 --- a/common/net/deadline/packet_sing.go +++ b/common/net/deadline/packet_sing.go @@ -2,10 +2,13 @@ package deadline import ( "os" + "runtime" "github.com/Dreamacro/clash/common/net/packet" "github.com/sagernet/sing/common/buf" + "github.com/sagernet/sing/common/bufio" M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" ) type SingPacketConn struct { @@ -33,6 +36,7 @@ var _ packet.EnhanceSingPacketConn = (*EnhanceSingPacketConn)(nil) type singReadResult struct { buffer *buf.Buffer destination M.Socksaddr + err error } type singPacketConn struct { @@ -41,26 +45,34 @@ type singPacketConn struct { } func (c *singPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { - select { - case result := <-c.netPacketConn.resultCh: - if result != nil { - destination = result.destination - err = result.err - buffer.Resize(result.buffer.Start(), 0) - n := copy(buffer.FreeBytes(), result.buffer.Bytes()) - buffer.Truncate(n) - result.buffer.Advance(n) - if result.buffer.IsEmpty() { - result.buffer.Release() +FOR: + for { + select { + case result := <-c.netPacketConn.resultCh: + if result != nil { + if result, ok := result.(*singReadResult); ok { + destination = result.destination + err = result.err + buffer.Resize(result.buffer.Start(), 0) + n := copy(buffer.FreeBytes(), result.buffer.Bytes()) + buffer.Truncate(n) + result.buffer.Advance(n) + if result.buffer.IsEmpty() { + result.buffer.Release() + } + c.netPacketConn.resultCh <- nil // finish cache read + return + } + c.netPacketConn.resultCh <- result // another type of read + runtime.Gosched() // allowing other goroutines to run + continue FOR + } else { + c.netPacketConn.resultCh <- nil + break FOR } - c.netPacketConn.resultCh <- nil // finish cache read - return - } else { - c.netPacketConn.resultCh <- nil - break + case <-c.netPacketConn.pipeDeadline.wait(): + return M.Socksaddr{}, os.ErrDeadlineExceeded } - case <-c.netPacketConn.pipeDeadline.wait(): - return M.Socksaddr{}, os.ErrDeadlineExceeded } if c.netPacketConn.disablePipe.Load() { @@ -82,15 +94,87 @@ func (c *singPacketConn) pipeReadPacket(bufLen int, bufStart int) { buffer := buf.NewSize(bufLen) buffer.Advance(bufStart) destination, err := c.singPacketConn.ReadPacket(buffer) - c.netPacketConn.resultCh <- &readResult{ - singReadResult: singReadResult{ - buffer: buffer, - destination: destination, - }, - err: err, - } + result := &singReadResult{} + result.destination = destination + result.err = err + c.netPacketConn.resultCh <- result } func (c *singPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { return c.singPacketConn.WritePacket(buffer, destination) } + +func (c *singPacketConn) CreateReadWaiter() (N.PacketReadWaiter, bool) { + prw, isReadWaiter := bufio.CreatePacketReadWaiter(c.singPacketConn) + if isReadWaiter { + return &singPacketReadWaiter{ + netPacketConn: c.netPacketConn, + packetReadWaiter: prw, + }, true + } + return nil, false +} + +var _ N.PacketReadWaiter = (*singPacketReadWaiter)(nil) + +type singPacketReadWaiter struct { + netPacketConn *NetPacketConn + packetReadWaiter N.PacketReadWaiter +} + +type singWaitReadResult singReadResult + +func (c *singPacketReadWaiter) InitializeReadWaiter(newBuffer func() *buf.Buffer) { + c.packetReadWaiter.InitializeReadWaiter(newBuffer) +} + +func (c *singPacketReadWaiter) WaitReadPacket() (destination M.Socksaddr, err error) { +FOR: + for { + select { + case result := <-c.netPacketConn.resultCh: + if result != nil { + if result, ok := result.(*singWaitReadResult); ok { + destination = result.destination + err = result.err + c.netPacketConn.resultCh <- nil // finish cache read + return + } + c.netPacketConn.resultCh <- result // another type of read + runtime.Gosched() // allowing other goroutines to run + continue FOR + } else { + c.netPacketConn.resultCh <- nil + break FOR + } + case <-c.netPacketConn.pipeDeadline.wait(): + return M.Socksaddr{}, os.ErrDeadlineExceeded + } + } + + if c.netPacketConn.disablePipe.Load() { + return c.packetReadWaiter.WaitReadPacket() + } else if c.netPacketConn.deadline.Load().IsZero() { + c.netPacketConn.inRead.Store(true) + defer c.netPacketConn.inRead.Store(false) + destination, err = c.packetReadWaiter.WaitReadPacket() + return + } + + <-c.netPacketConn.resultCh + go c.pipeWaitReadPacket() + + return c.WaitReadPacket() +} + +func (c *singPacketReadWaiter) pipeWaitReadPacket() { + destination, err := c.packetReadWaiter.WaitReadPacket() + result := &singWaitReadResult{} + result.destination = destination + result.err = err + c.netPacketConn.resultCh <- result +} + +func (c *singPacketReadWaiter) Upstream() any { + return c.packetReadWaiter +} From d4e4f6d2d7939eae182680a7d83096bb0828c3f1 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sat, 20 May 2023 16:57:42 +0800 Subject: [PATCH 47/62] chore: rebuild ref and threadSafe packetConn --- common/net/packet.go | 29 ++---------- common/net/packet/packet_sing.go | 24 +++++----- common/net/packet/ref.go | 75 ++++++++++++++++++++++++++++++++ common/net/packet/ref_sing.go | 26 +++++++++++ common/net/packet/thread.go | 36 +++++++++++++++ common/net/packet/thread_sing.go | 24 ++++++++++ common/net/refconn.go | 61 -------------------------- 7 files changed, 176 insertions(+), 99 deletions(-) create mode 100644 common/net/packet/ref.go create mode 100644 common/net/packet/ref_sing.go create mode 100644 common/net/packet/thread.go create mode 100644 common/net/packet/thread_sing.go diff --git a/common/net/packet.go b/common/net/packet.go index 865590ce..9afe86b0 100644 --- a/common/net/packet.go +++ b/common/net/packet.go @@ -1,9 +1,6 @@ package net import ( - "net" - "sync" - "github.com/Dreamacro/clash/common/net/deadline" "github.com/Dreamacro/clash/common/net/packet" ) @@ -11,30 +8,10 @@ import ( type EnhancePacketConn = packet.EnhancePacketConn var NewEnhancePacketConn = packet.NewEnhancePacketConn +var NewThreadSafePacketConn = packet.NewThreadSafePacketConn +var NewRefPacketConn = packet.NewRefPacketConn + var NewDeadlineNetPacketConn = deadline.NewNetPacketConn var NewDeadlineEnhancePacketConn = deadline.NewEnhancePacketConn var NewDeadlineSingPacketConn = deadline.NewSingPacketConn var NewDeadlineEnhanceSingPacketConn = deadline.NewEnhanceSingPacketConn - -type threadSafePacketConn struct { - EnhancePacketConn - access sync.Mutex -} - -func (c *threadSafePacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { - c.access.Lock() - defer c.access.Unlock() - return c.EnhancePacketConn.WriteTo(b, addr) -} - -func (c *threadSafePacketConn) Upstream() any { - return c.EnhancePacketConn -} - -func (c *threadSafePacketConn) ReaderReplaceable() bool { - return true -} - -func NewThreadSafePacketConn(pc net.PacketConn) net.PacketConn { - return &threadSafePacketConn{EnhancePacketConn: NewEnhancePacketConn(pc)} -} diff --git a/common/net/packet/packet_sing.go b/common/net/packet/packet_sing.go index daa352c8..cfcf5ed0 100644 --- a/common/net/packet/packet_sing.go +++ b/common/net/packet/packet_sing.go @@ -12,13 +12,13 @@ import ( type SingPacketConn = N.NetPacketConn type EnhanceSingPacketConn interface { - N.NetPacketConn + SingPacketConn EnhancePacketConn } type enhanceSingPacketConn struct { - N.NetPacketConn - readWaiter N.PacketReadWaiter + SingPacketConn + packetReadWaiter N.PacketReadWaiter } func (c *enhanceSingPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { @@ -28,12 +28,12 @@ func (c *enhanceSingPacketConn) WaitReadFrom() (data []byte, put func(), addr ne buff = buf.NewPacket() // do not use stack buffer return buff } - if c.readWaiter != nil { - c.readWaiter.InitializeReadWaiter(newBuffer) - defer c.readWaiter.InitializeReadWaiter(nil) - dest, err = c.readWaiter.WaitReadPacket() + if c.packetReadWaiter != nil { + c.packetReadWaiter.InitializeReadWaiter(newBuffer) + defer c.packetReadWaiter.InitializeReadWaiter(nil) + dest, err = c.packetReadWaiter.WaitReadPacket() } else { - dest, err = c.NetPacketConn.ReadPacket(newBuffer()) + dest, err = c.SingPacketConn.ReadPacket(newBuffer()) } if dest.IsFqdn() { addr = dest @@ -59,7 +59,7 @@ func (c *enhanceSingPacketConn) WaitReadFrom() (data []byte, put func(), addr ne } func (c *enhanceSingPacketConn) Upstream() any { - return c.NetPacketConn + return c.SingPacketConn } func (c *enhanceSingPacketConn) WriterReplaceable() bool { @@ -70,10 +70,10 @@ func (c *enhanceSingPacketConn) ReaderReplaceable() bool { return true } -func newEnhanceSingPacketConn(conn N.NetPacketConn) *enhanceSingPacketConn { - epc := &enhanceSingPacketConn{NetPacketConn: conn} +func newEnhanceSingPacketConn(conn SingPacketConn) *enhanceSingPacketConn { + epc := &enhanceSingPacketConn{SingPacketConn: conn} if readWaiter, isReadWaiter := bufio.CreatePacketReadWaiter(conn); isReadWaiter { - epc.readWaiter = readWaiter + epc.packetReadWaiter = readWaiter } return epc } diff --git a/common/net/packet/ref.go b/common/net/packet/ref.go new file mode 100644 index 00000000..a562b2e2 --- /dev/null +++ b/common/net/packet/ref.go @@ -0,0 +1,75 @@ +package packet + +import ( + "net" + "runtime" + "time" +) + +type refPacketConn struct { + pc EnhancePacketConn + ref any +} + +func (c *refPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + defer runtime.KeepAlive(c.ref) + return c.pc.WaitReadFrom() +} + +func (c *refPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { + defer runtime.KeepAlive(c.ref) + return c.pc.ReadFrom(p) +} + +func (c *refPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { + defer runtime.KeepAlive(c.ref) + return c.pc.WriteTo(p, addr) +} + +func (c *refPacketConn) Close() error { + defer runtime.KeepAlive(c.ref) + return c.pc.Close() +} + +func (c *refPacketConn) LocalAddr() net.Addr { + defer runtime.KeepAlive(c.ref) + return c.pc.LocalAddr() +} + +func (c *refPacketConn) SetDeadline(t time.Time) error { + defer runtime.KeepAlive(c.ref) + return c.pc.SetDeadline(t) +} + +func (c *refPacketConn) SetReadDeadline(t time.Time) error { + defer runtime.KeepAlive(c.ref) + return c.pc.SetReadDeadline(t) +} + +func (c *refPacketConn) SetWriteDeadline(t time.Time) error { + defer runtime.KeepAlive(c.ref) + return c.pc.SetWriteDeadline(t) +} + +func (c *refPacketConn) Upstream() any { + return c.pc +} + +func (c *refPacketConn) ReaderReplaceable() bool { // Relay() will handle reference + return true +} + +func (c *refPacketConn) WriterReplaceable() bool { // Relay() will handle reference + return true +} + +func NewRefPacketConn(pc net.PacketConn, ref any) EnhancePacketConn { + rPC := &refPacketConn{pc: NewEnhancePacketConn(pc), ref: ref} + if singPC, isSingPC := pc.(SingPacketConn); isSingPC { + return &refSingPacketConn{ + refPacketConn: rPC, + singPacketConn: singPC, + } + } + return rPC +} diff --git a/common/net/packet/ref_sing.go b/common/net/packet/ref_sing.go new file mode 100644 index 00000000..2ca955fa --- /dev/null +++ b/common/net/packet/ref_sing.go @@ -0,0 +1,26 @@ +package packet + +import ( + "runtime" + + "github.com/sagernet/sing/common/buf" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" +) + +type refSingPacketConn struct { + *refPacketConn + singPacketConn SingPacketConn +} + +var _ N.NetPacketConn = (*refSingPacketConn)(nil) + +func (c *refSingPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { + defer runtime.KeepAlive(c.ref) + return c.singPacketConn.WritePacket(buffer, destination) +} + +func (c *refSingPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { + defer runtime.KeepAlive(c.ref) + return c.singPacketConn.ReadPacket(buffer) +} diff --git a/common/net/packet/thread.go b/common/net/packet/thread.go new file mode 100644 index 00000000..14d64233 --- /dev/null +++ b/common/net/packet/thread.go @@ -0,0 +1,36 @@ +package packet + +import ( + "net" + "sync" +) + +type threadSafePacketConn struct { + EnhancePacketConn + access sync.Mutex +} + +func (c *threadSafePacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { + c.access.Lock() + defer c.access.Unlock() + return c.EnhancePacketConn.WriteTo(b, addr) +} + +func (c *threadSafePacketConn) Upstream() any { + return c.EnhancePacketConn +} + +func (c *threadSafePacketConn) ReaderReplaceable() bool { + return true +} + +func NewThreadSafePacketConn(pc net.PacketConn) EnhancePacketConn { + tsPC := &threadSafePacketConn{EnhancePacketConn: NewEnhancePacketConn(pc)} + if singPC, isSingPC := pc.(SingPacketConn); isSingPC { + return &threadSafeSingPacketConn{ + threadSafePacketConn: tsPC, + singPacketConn: singPC, + } + } + return tsPC +} diff --git a/common/net/packet/thread_sing.go b/common/net/packet/thread_sing.go new file mode 100644 index 00000000..0869a512 --- /dev/null +++ b/common/net/packet/thread_sing.go @@ -0,0 +1,24 @@ +package packet + +import ( + "github.com/sagernet/sing/common/buf" + M "github.com/sagernet/sing/common/metadata" + N "github.com/sagernet/sing/common/network" +) + +type threadSafeSingPacketConn struct { + *threadSafePacketConn + singPacketConn SingPacketConn +} + +var _ N.NetPacketConn = (*threadSafeSingPacketConn)(nil) + +func (c *threadSafeSingPacketConn) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error { + c.access.Lock() + defer c.access.Unlock() + return c.singPacketConn.WritePacket(buffer, destination) +} + +func (c *threadSafeSingPacketConn) ReadPacket(buffer *buf.Buffer) (destination M.Socksaddr, err error) { + return c.singPacketConn.ReadPacket(buffer) +} diff --git a/common/net/refconn.go b/common/net/refconn.go index 0f32ebc1..5caaebc8 100644 --- a/common/net/refconn.go +++ b/common/net/refconn.go @@ -80,64 +80,3 @@ var _ ExtendedConn = (*refConn)(nil) func NewRefConn(conn net.Conn, ref any) net.Conn { return &refConn{conn: NewExtendedConn(conn), ref: ref} } - -type refPacketConn struct { - pc EnhancePacketConn - ref any -} - -func (pc *refPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { - defer runtime.KeepAlive(pc.ref) - return pc.pc.WaitReadFrom() -} - -func (pc *refPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { - defer runtime.KeepAlive(pc.ref) - return pc.pc.ReadFrom(p) -} - -func (pc *refPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { - defer runtime.KeepAlive(pc.ref) - return pc.pc.WriteTo(p, addr) -} - -func (pc *refPacketConn) Close() error { - defer runtime.KeepAlive(pc.ref) - return pc.pc.Close() -} - -func (pc *refPacketConn) LocalAddr() net.Addr { - defer runtime.KeepAlive(pc.ref) - return pc.pc.LocalAddr() -} - -func (pc *refPacketConn) SetDeadline(t time.Time) error { - defer runtime.KeepAlive(pc.ref) - return pc.pc.SetDeadline(t) -} - -func (pc *refPacketConn) SetReadDeadline(t time.Time) error { - defer runtime.KeepAlive(pc.ref) - return pc.pc.SetReadDeadline(t) -} - -func (pc *refPacketConn) SetWriteDeadline(t time.Time) error { - defer runtime.KeepAlive(pc.ref) - return pc.pc.SetWriteDeadline(t) -} - -func (pc *refPacketConn) Upstream() any { - return pc.pc -} - -func (pc *refPacketConn) ReaderReplaceable() bool { // Relay() will handle reference - return true -} - -func (pc *refPacketConn) WriterReplaceable() bool { // Relay() will handle reference - return true -} - -func NewRefPacketConn(pc net.PacketConn, ref any) net.PacketConn { - return &refPacketConn{pc: NewEnhancePacketConn(pc), ref: ref} -} From 546b2bc24bcca696f47704c96a85dc501c57d872 Mon Sep 17 00:00:00 2001 From: H1JK Date: Sat, 20 May 2023 17:00:43 +0800 Subject: [PATCH 48/62] chore: Decrease UoT read memory --- go.mod | 4 ++++ go.sum | 12 ++++------- transport/trojan/trojan.go | 41 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index a55cc3d8..40a92438 100644 --- a/go.mod +++ b/go.mod @@ -104,3 +104,7 @@ require ( golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect golang.org/x/tools v0.6.0 // indirect ) + +replace github.com/sagernet/sing => github.com/h1jk/sing v0.0.0-20230519121640-6db84f45244d + +replace github.com/sagernet/sing-vmess => github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899 diff --git a/go.sum b/go.sum index 4a7601b8..0e9e38a7 100644 --- a/go.sum +++ b/go.sum @@ -65,6 +65,8 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/h1jk/sing v0.0.0-20230519121640-6db84f45244d h1:ih6tNzl1uxuuX+Naz2qAPqSS20E6jfXFmcvyDRAy8rY= +github.com/h1jk/sing v0.0.0-20230519121640-6db84f45244d/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= @@ -102,6 +104,8 @@ github.com/metacubex/sing-shadowsocks2 v0.0.0-20230519030442-556ef530768f h1:aWg github.com/metacubex/sing-shadowsocks2 v0.0.0-20230519030442-556ef530768f/go.mod h1:jVDD4N22bDPPKA73NvB7aqdlLWiAwv8D+jx7HwhcWak= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= +github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899 h1:iRfcuztp7REfmOyasSlCL/pqNWfUDMTJ2CwbGpxpeks= +github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899/go.mod h1:RSt9rxGHllLdc5JUebkQwaqyWLx09Lqya37DlBe8CP8= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a/go.mod h1:Bsw2BvKMMMY0FhZPseDI50ZOalvoUPMKYyGpyqvIIqY= github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI= @@ -141,16 +145,10 @@ github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 h1:5+m7c 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.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk= -github.com/sagernet/sing v0.2.5-0.20230519030052-49166ac42700 h1:NTiK4CtFIzD+OZkjR2/jP8IZJ/S8gKhiOoeU2ycXKDg= -github.com/sagernet/sing v0.2.5-0.20230519030052-49166ac42700/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646 h1:X3ADfMqeGns1Q1FlXc9kaL9FwW1UM6D6tEQo8jFstpc= github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646/go.mod h1:pF+RnLvCAOhECrvauy6LYOpBakJ/vuaF1Wm4lPsWryI= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b h1:ouW/6IDCrxkBe19YSbdCd7buHix7b+UZ6BM4Zz74XF4= github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b/go.mod h1:oG8bPerYI6cZ74KquY3DvA7ynECyrILPBnce6wtBqeI= -github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 h1:BHOnxrbC929JonuKqFdJ7ZbDp7zs4oTlH5KFvKtWu9U= -github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3/go.mod h1:yKrAr+dqZd64DxBXCHWrYicp+n4qbqO73mtwv3dck8U= github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as= github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37/go.mod h1:3skNSftZDJWTGVtVaM2jfbce8qHnmH/AGDRe62iNOg0= github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9 h1:2ItpW1nMNkPzmBTxV0/eClCklHrFSQMnUGcpUmJxVeE= @@ -239,10 +237,8 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/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-20220622161953-175b2fd9d664/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.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/transport/trojan/trojan.go b/transport/trojan/trojan.go index 8b4146c6..90700491 100644 --- a/transport/trojan/trojan.go +++ b/transport/trojan/trojan.go @@ -13,6 +13,7 @@ import ( "net/http" "sync" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/pool" tlsC "github.com/Dreamacro/clash/component/tls" C "github.com/Dreamacro/clash/constant" @@ -20,6 +21,7 @@ import ( "github.com/Dreamacro/clash/transport/vless" "github.com/Dreamacro/clash/transport/vmess" + M "github.com/sagernet/sing/common/metadata" xtls "github.com/xtls/go" ) @@ -303,6 +305,8 @@ func New(option *Option) *Trojan { return &Trojan{option, hexSha224([]byte(option.Password))} } +var _ N.EnhancePacketConn = (*PacketConn)(nil) + type PacketConn struct { net.Conn remain int @@ -350,6 +354,43 @@ func (pc *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) { return n, addr, nil } +func (pc *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + pc.mux.Lock() + defer pc.mux.Unlock() + + destination, err := M.SocksaddrSerializer.ReadAddrPort(pc.Conn) + if err != nil { + return nil, nil, nil, err + } + addr = destination.UDPAddr() + + data = pool.Get(pool.UDPBufferSize) + put = func() { + _ = pool.Put(data) + } + + _, err = io.ReadFull(pc.Conn, data[:2+2]) // u16be length + CR LF + if err != nil { + put() + return nil, nil, nil, err + } + length := binary.BigEndian.Uint16(data) + + if length > 0 { + data = data[:length] + _, err = io.ReadFull(pc.Conn, data) + if err != nil { + put() + return nil, nil, nil, err + } + } else { + put() + return nil, nil, addr, nil + } + + return +} + func hexSha224(data []byte) []byte { buf := make([]byte, 56) hash := sha256.New224() From 984bf27d9b0bd1193acc1921652e18c9e1b10aea Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sat, 20 May 2023 18:35:04 +0800 Subject: [PATCH 49/62] chore: using internal socks5.ReadAddr0 in trojan --- listener/shadowsocks/tcp.go | 2 +- transport/socks5/socks5.go | 44 +++++++++++++++++++++++++++++++++++++ transport/trojan/trojan.go | 3 +-- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/listener/shadowsocks/tcp.go b/listener/shadowsocks/tcp.go index 6884b960..febf87c3 100644 --- a/listener/shadowsocks/tcp.go +++ b/listener/shadowsocks/tcp.go @@ -103,7 +103,7 @@ func (l *Listener) HandleConn(conn net.Conn, in chan<- C.ConnContext, additions conn = l.pickCipher.StreamConn(conn) conn = N.NewDeadlineConn(conn) // embed ss can't handle readDeadline correctly - target, err := socks5.ReadAddr(conn, make([]byte, socks5.MaxAddrLen)) + target, err := socks5.ReadAddr0(conn) if err != nil { _ = conn.Close() return diff --git a/transport/socks5/socks5.go b/transport/socks5/socks5.go index 7d4f11ae..6f95cce9 100644 --- a/transport/socks5/socks5.go +++ b/transport/socks5/socks5.go @@ -299,6 +299,50 @@ func ReadAddr(r io.Reader, b []byte) (Addr, error) { return nil, ErrAddressNotSupported } +func ReadAddr0(r io.Reader) (Addr, error) { + aType, err := ReadByte(r) // read 1st byte for address type + if err != nil { + return nil, err + } + + switch aType { + case AtypDomainName: + var domainLength byte + domainLength, err = ReadByte(r) // read 2nd byte for domain length + if err != nil { + return nil, err + } + b := make([]byte, 1+1+uint16(domainLength)+2) + _, err = io.ReadFull(r, b[2:]) + b[0] = aType + b[1] = domainLength + return b, err + case AtypIPv4: + var b [1 + net.IPv4len + 2]byte + _, err = io.ReadFull(r, b[1:]) + b[0] = aType + return b[:], err + case AtypIPv6: + var b [1 + net.IPv6len + 2]byte + _, err = io.ReadFull(r, b[1:]) + b[0] = aType + return b[:], err + } + + return nil, ErrAddressNotSupported +} + +func ReadByte(reader io.Reader) (byte, error) { + if br, isBr := reader.(io.ByteReader); isBr { + return br.ReadByte() + } + var b [1]byte + if _, err := io.ReadFull(reader, b[:]); err != nil { + return 0, err + } + return b[0], nil +} + // SplitAddr slices a SOCKS address from beginning of b. Returns nil if failed. func SplitAddr(b []byte) Addr { addrLen := 1 diff --git a/transport/trojan/trojan.go b/transport/trojan/trojan.go index 90700491..d37026c1 100644 --- a/transport/trojan/trojan.go +++ b/transport/trojan/trojan.go @@ -21,7 +21,6 @@ import ( "github.com/Dreamacro/clash/transport/vless" "github.com/Dreamacro/clash/transport/vmess" - M "github.com/sagernet/sing/common/metadata" xtls "github.com/xtls/go" ) @@ -358,7 +357,7 @@ func (pc *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, er pc.mux.Lock() defer pc.mux.Unlock() - destination, err := M.SocksaddrSerializer.ReadAddrPort(pc.Conn) + destination, err := socks5.ReadAddr0(pc.Conn) if err != nil { return nil, nil, nil, err } From 654e76d91e6c20b8da1bc0e44eb9e9f737b1d590 Mon Sep 17 00:00:00 2001 From: H1JK Date: Fri, 26 May 2023 20:11:06 +0800 Subject: [PATCH 50/62] refactor: Move vision implementation to a new package --- transport/vless/conn.go | 305 +----------------- transport/vless/vision/conn.go | 274 ++++++++++++++++ transport/vless/{ => vision}/filter.go | 2 +- .../vless/{vision.go => vision/padding.go} | 6 +- transport/vless/vision/vision.go | 70 ++++ transport/vless/xtls.go | 5 - 6 files changed, 362 insertions(+), 300 deletions(-) create mode 100644 transport/vless/vision/conn.go rename transport/vless/{ => vision}/filter.go (99%) rename transport/vless/{vision.go => vision/padding.go} (94%) create mode 100644 transport/vless/vision/vision.go diff --git a/transport/vless/conn.go b/transport/vless/conn.go index 9289afcf..9e2e5e89 100644 --- a/transport/vless/conn.go +++ b/transport/vless/conn.go @@ -1,25 +1,18 @@ package vless import ( - "bytes" - "crypto/subtle" - gotls "crypto/tls" "encoding/binary" "errors" "fmt" "io" "net" - "reflect" "sync" - "unsafe" "github.com/Dreamacro/clash/common/buf" N "github.com/Dreamacro/clash/common/net" - tlsC "github.com/Dreamacro/clash/component/tls" - "github.com/Dreamacro/clash/log" + "github.com/Dreamacro/clash/transport/vless/vision" "github.com/gofrs/uuid/v5" - utls "github.com/sagernet/utls" xtls "github.com/xtls/go" "google.golang.org/protobuf/proto" ) @@ -36,33 +29,10 @@ type Conn struct { handshakeMutex sync.Mutex needHandshake bool err error - - tlsConn net.Conn - input *bytes.Reader - rawInput *bytes.Buffer - - packetsToFilter int - isTLS bool - isTLS12orAbove bool - enableXTLS bool - cipher uint16 - remainingServerHello uint16 - readRemainingContent int - readRemainingPadding int - readProcess bool - readFilterUUID bool - readLastCommand byte - writeFilterApplicationData bool - writeDirect bool } func (vc *Conn) Read(b []byte) (int, error) { if vc.received { - if vc.readProcess { - buffer := buf.With(b) - err := vc.ReadBuffer(buffer) - return buffer.Len(), err - } return vc.ExtendedReader.Read(b) } @@ -70,106 +40,11 @@ func (vc *Conn) Read(b []byte) (int, error) { return 0, err } vc.received = true - return vc.Read(b) + return vc.ExtendedReader.Read(b) } func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error { if vc.received { - toRead := buffer.FreeBytes() - if vc.readRemainingContent > 0 { - if vc.readRemainingContent < buffer.FreeLen() { - toRead = toRead[:vc.readRemainingContent] - } - n, err := vc.ExtendedReader.Read(toRead) - buffer.Truncate(n) - vc.readRemainingContent -= n - vc.FilterTLS(toRead) - return err - } - if vc.readRemainingPadding > 0 { - _, err := io.CopyN(io.Discard, vc.ExtendedReader, int64(vc.readRemainingPadding)) - if err != nil { - return err - } - vc.readRemainingPadding = 0 - } - if vc.readProcess { - switch vc.readLastCommand { - case commandPaddingContinue: - //if vc.isTLS || vc.packetsToFilter > 0 { - headerUUIDLen := 0 - if vc.readFilterUUID { - headerUUIDLen = uuid.Size - } - var header []byte - if need := headerUUIDLen + paddingHeaderLen; buffer.FreeLen() < need { - header = make([]byte, need) - } else { - header = buffer.FreeBytes()[:need] - } - _, err := io.ReadFull(vc.ExtendedReader, header) - if err != nil { - return err - } - pos := 0 - if vc.readFilterUUID { - vc.readFilterUUID = false - pos = uuid.Size - if subtle.ConstantTimeCompare(vc.id.Bytes(), header[:uuid.Size]) != 1 { - err = fmt.Errorf("XTLS Vision server responded unknown UUID: %s", - uuid.FromBytesOrNil(header[:uuid.Size]).String()) - log.Errorln(err.Error()) - return err - } - } - vc.readLastCommand = header[pos] - vc.readRemainingContent = int(binary.BigEndian.Uint16(header[pos+1:])) - vc.readRemainingPadding = int(binary.BigEndian.Uint16(header[pos+3:])) - log.Debugln("XTLS Vision read padding: command=%d, payloadLen=%d, paddingLen=%d", - vc.readLastCommand, vc.readRemainingContent, vc.readRemainingPadding) - return vc.ReadBuffer(buffer) - //} - case commandPaddingEnd: - vc.readProcess = false - return vc.ReadBuffer(buffer) - case commandPaddingDirect: - needReturn := false - if vc.input != nil { - _, err := buffer.ReadFrom(vc.input) - if err != nil { - return err - } - if vc.input.Len() == 0 { - needReturn = true - vc.input = nil - } else { // buffer is full - return nil - } - } - if vc.rawInput != nil { - _, err := buffer.ReadFrom(vc.rawInput) - if err != nil { - return err - } - needReturn = true - if vc.rawInput.Len() == 0 { - vc.rawInput = nil - } - } - if vc.input == nil && vc.rawInput == nil { - vc.readProcess = false - vc.ExtendedReader = N.NewExtendedReader(vc.Conn) - log.Debugln("XTLS Vision direct read start") - } - if needReturn { - return nil - } - default: - err := fmt.Errorf("XTLS Vision read unknown command: %d", vc.readLastCommand) - log.Debugln(err.Error()) - return err - } - } return vc.ExtendedReader.ReadBuffer(buffer) } @@ -177,7 +52,7 @@ func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error { return err } vc.received = true - return vc.ReadBuffer(buffer) + return vc.ExtendedReader.ReadBuffer(buffer) } func (vc *Conn) Write(p []byte) (int, error) { @@ -200,18 +75,6 @@ func (vc *Conn) Write(p []byte) (int, error) { vc.handshakeMutex.Unlock() } - if vc.writeFilterApplicationData { - _buffer := buf.StackNew() - defer buf.KeepAlive(_buffer) - buffer := buf.Dup(_buffer) - defer buffer.Release() - buffer.Write(p) - err := vc.WriteBuffer(buffer) - if err != nil { - return 0, err - } - return len(p), nil - } return vc.ExtendedWriter.Write(p) } @@ -232,63 +95,6 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) error { vc.handshakeMutex.Unlock() } - if vc.writeFilterApplicationData { - buffer2 := ReshapeBuffer(buffer) - defer buffer2.Release() - vc.FilterTLS(buffer.Bytes()) - command := commandPaddingContinue - if !vc.isTLS { - command = commandPaddingEnd - - // disable XTLS - //vc.readProcess = false - vc.writeFilterApplicationData = false - vc.packetsToFilter = 0 - } else if buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true - } - vc.writeFilterApplicationData = false - } - ApplyPadding(buffer, command, nil, vc.isTLS) - err := vc.ExtendedWriter.WriteBuffer(buffer) - if err != nil { - return err - } - if vc.writeDirect { - vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn) - log.Debugln("XTLS Vision direct write start") - //time.Sleep(5 * time.Millisecond) - } - if buffer2 != nil { - if vc.writeDirect || !vc.isTLS { - return vc.ExtendedWriter.WriteBuffer(buffer2) - } - vc.FilterTLS(buffer2.Bytes()) - command = commandPaddingContinue - if buffer2.Len() > 6 && bytes.Equal(buffer2.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { - command = commandPaddingEnd - if vc.enableXTLS { - command = commandPaddingDirect - vc.writeDirect = true - } - vc.writeFilterApplicationData = false - } - ApplyPadding(buffer2, command, nil, vc.isTLS) - err = vc.ExtendedWriter.WriteBuffer(buffer2) - if vc.writeDirect { - vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn) - log.Debugln("XTLS Vision direct write start") - //time.Sleep(10 * time.Millisecond) - } - } - return err - } - /*if vc.writeDirect { - log.Debugln("XTLS Vision Direct write, payloadLen=%d", buffer.Len()) - }*/ return vc.ExtendedWriter.WriteBuffer(buffer) } @@ -300,10 +106,9 @@ func (vc *Conn) sendRequest(p []byte) bool { return true } } - isVision := vc.IsXTLSVisionEnabled() var buffer *buf.Buffer - if isVision { + if vc.IsXTLSVisionEnabled() { _buffer := buf.StackNew() defer buf.KeepAlive(_buffer) buffer = buf.Dup(_buffer) @@ -350,50 +155,14 @@ func (vc *Conn) sendRequest(p []byte) bool { ) } - if isVision && !vc.dst.UDP && !vc.dst.Mux { - if len(p) == 0 { - WriteWithPadding(buffer, nil, commandPaddingContinue, vc.id, vc.isTLS) - } else { - vc.FilterTLS(p) - //if vc.isTLS { - WriteWithPadding(buffer, p, commandPaddingContinue, vc.id, vc.isTLS) - //} else { - // buf.Must(buf.Error(buffer.Write(p))) - // - // // disable XTLS - // vc.readProcess = false - // vc.writeFilterApplicationData = false - // vc.packetsToFilter = 0 - //} - } - } else { - buf.Must(buf.Error(buffer.Write(p))) - } + buf.Must(buf.Error(buffer.Write(p))) _, vc.err = vc.ExtendedWriter.Write(buffer.Bytes()) - if vc.err != nil { - return true - } - if isVision { - switch underlying := vc.tlsConn.(type) { - case *gotls.Conn: - if underlying.ConnectionState().Version != gotls.VersionTLS13 { - vc.err = ErrNotTLS13 - } - case *utls.UConn: - if underlying.ConnectionState().Version != utls.VersionTLS13 { - vc.err = ErrNotTLS13 - } - default: - vc.err = fmt.Errorf(`failed to use %s, maybe "security" is not "tls" or "utls"`, vc.addons.Flow) - } - vc.tlsConn = nil - } return true } func (vc *Conn) recvResponse() error { - var buffer [1]byte + var buffer [2]byte _, vc.err = io.ReadFull(vc.ExtendedReader, buffer[:]) if vc.err != nil { return vc.err @@ -403,12 +172,7 @@ func (vc *Conn) recvResponse() error { return errors.New("unexpected response version") } - _, vc.err = io.ReadFull(vc.ExtendedReader, buffer[:]) - if vc.err != nil { - return vc.err - } - - length := int64(buffer[0]) + length := int64(buffer[1]) if length != 0 { // addon data length > 0 io.CopyN(io.Discard, vc.ExtendedReader, length) // just discard } @@ -416,18 +180,8 @@ func (vc *Conn) recvResponse() error { return nil } -func (vc *Conn) FrontHeadroom() int { - if vc.IsXTLSVisionEnabled() { - return paddingHeaderLen - } - return 0 -} - func (vc *Conn) Upstream() any { - if vc.tlsConn == nil { - return vc.Conn - } - return vc.tlsConn + return vc.Conn } func (vc *Conn) NeedHandshake() bool { @@ -439,7 +193,7 @@ func (vc *Conn) IsXTLSVisionEnabled() bool { } // newConn return a Conn instance -func newConn(conn net.Conn, client *Client, dst *DstAddr) (*Conn, error) { +func newConn(conn net.Conn, client *Client, dst *DstAddr) (net.Conn, error) { c := &Conn{ ExtendedReader: N.NewExtendedReader(conn), ExtendedWriter: N.NewExtendedWriter(conn), @@ -468,43 +222,12 @@ func newConn(conn net.Conn, client *Client, dst *DstAddr) (*Conn, error) { return nil, fmt.Errorf("failed to use %s, maybe \"security\" is not \"xtls\"", client.Addons.Flow) } case XRV: - c.packetsToFilter = 6 - c.readProcess = true - c.readFilterUUID = true - c.writeFilterApplicationData = true - c.addons = client.Addons - var t reflect.Type - var p unsafe.Pointer - switch underlying := conn.(type) { - case *gotls.Conn: - //log.Debugln("type tls") - c.Conn = underlying.NetConn() - c.tlsConn = underlying - t = reflect.TypeOf(underlying).Elem() - p = unsafe.Pointer(underlying) - case *utls.UConn: - //log.Debugln("type *utls.UConn") - c.Conn = underlying.NetConn() - c.tlsConn = underlying - t = reflect.TypeOf(underlying.Conn).Elem() - p = unsafe.Pointer(underlying.Conn) - case *tlsC.UConn: - //log.Debugln("type *tlsC.UConn") - c.Conn = underlying.NetConn() - c.tlsConn = underlying.UConn - t = reflect.TypeOf(underlying.Conn).Elem() - //log.Debugln("t:%v", t) - p = unsafe.Pointer(underlying.Conn) - default: - return nil, fmt.Errorf(`failed to use %s, maybe "security" is not "tls" or "utls"`, client.Addons.Flow) + visionConn, err := vision.NewConn(c, c.id) + if err != nil { + return nil, err } - i, _ := t.FieldByName("input") - r, _ := t.FieldByName("rawInput") - c.input = (*bytes.Reader)(unsafe.Add(p, i.Offset)) - c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset)) - //if _, ok := c.Conn.(*net.TCPConn); !ok { - // log.Debugln("XTLS underlying conn is not *net.TCPConn, got %T", c.Conn) - //} + c.addons = client.Addons + return visionConn, nil } } diff --git a/transport/vless/vision/conn.go b/transport/vless/vision/conn.go new file mode 100644 index 00000000..650d094d --- /dev/null +++ b/transport/vless/vision/conn.go @@ -0,0 +1,274 @@ +package vision + +import ( + "bytes" + "crypto/subtle" + gotls "crypto/tls" + "encoding/binary" + "fmt" + "io" + "net" + + "github.com/Dreamacro/clash/common/buf" + N "github.com/Dreamacro/clash/common/net" + "github.com/Dreamacro/clash/log" + + "github.com/gofrs/uuid/v5" + utls "github.com/sagernet/utls" +) + +var ( + _ N.ExtendedConn = (*Conn)(nil) +) + +type Conn struct { + net.Conn + N.ExtendedReader + N.ExtendedWriter + upstream net.Conn + userUUID *uuid.UUID + + tlsConn net.Conn + input *bytes.Reader + rawInput *bytes.Buffer + + needHandshake bool + packetsToFilter int + isTLS bool + isTLS12orAbove bool + enableXTLS bool + cipher uint16 + remainingServerHello uint16 + readRemainingContent int + readRemainingPadding int + readProcess bool + readFilterUUID bool + readLastCommand byte + writeFilterApplicationData bool + writeDirect bool +} + +func (vc *Conn) Read(b []byte) (int, error) { + if vc.readProcess { + buffer := buf.With(b) + err := vc.ReadBuffer(buffer) + return buffer.Len(), err + } + return vc.ExtendedReader.Read(b) +} + +func (vc *Conn) ReadBuffer(buffer *buf.Buffer) error { + toRead := buffer.FreeBytes() + if vc.readRemainingContent > 0 { + if vc.readRemainingContent < buffer.FreeLen() { + toRead = toRead[:vc.readRemainingContent] + } + n, err := vc.ExtendedReader.Read(toRead) + buffer.Truncate(n) + vc.readRemainingContent -= n + vc.FilterTLS(toRead) + return err + } + if vc.readRemainingPadding > 0 { + _, err := io.CopyN(io.Discard, vc.ExtendedReader, int64(vc.readRemainingPadding)) + if err != nil { + return err + } + vc.readRemainingPadding = 0 + } + if vc.readProcess { + switch vc.readLastCommand { + case commandPaddingContinue: + //if vc.isTLS || vc.packetsToFilter > 0 { + headerUUIDLen := 0 + if vc.readFilterUUID { + headerUUIDLen = uuid.Size + } + var header []byte + if need := headerUUIDLen + PaddingHeaderLen - uuid.Size; buffer.FreeLen() < need { + header = make([]byte, need) + } else { + header = buffer.FreeBytes()[:need] + } + _, err := io.ReadFull(vc.ExtendedReader, header) + if err != nil { + return err + } + if vc.readFilterUUID { + vc.readFilterUUID = false + if subtle.ConstantTimeCompare(vc.userUUID.Bytes(), header[:uuid.Size]) != 1 { + err = fmt.Errorf("XTLS Vision server responded unknown UUID: %s", + uuid.FromBytesOrNil(header[:uuid.Size]).String()) + log.Errorln(err.Error()) + return err + } + header = header[uuid.Size:] + } + vc.readRemainingPadding = int(binary.BigEndian.Uint16(header[3:])) + vc.readRemainingContent = int(binary.BigEndian.Uint16(header[1:])) + vc.readLastCommand = header[0] + log.Debugln("XTLS Vision read padding: command=%d, payloadLen=%d, paddingLen=%d", + vc.readLastCommand, vc.readRemainingContent, vc.readRemainingPadding) + return vc.ReadBuffer(buffer) + //} + case commandPaddingEnd: + vc.readProcess = false + return vc.ReadBuffer(buffer) + case commandPaddingDirect: + needReturn := false + if vc.input != nil { + _, err := buffer.ReadFrom(vc.input) + if err != nil { + return err + } + if vc.input.Len() == 0 { + needReturn = true + vc.input = nil + } else { // buffer is full + return nil + } + } + if vc.rawInput != nil { + _, err := buffer.ReadFrom(vc.rawInput) + if err != nil { + return err + } + needReturn = true + if vc.rawInput.Len() == 0 { + vc.rawInput = nil + } + } + if vc.input == nil && vc.rawInput == nil { + vc.readProcess = false + vc.ExtendedReader = N.NewExtendedReader(vc.Conn) + log.Debugln("XTLS Vision direct read start") + } + if needReturn { + return nil + } + default: + err := fmt.Errorf("XTLS Vision read unknown command: %d", vc.readLastCommand) + log.Debugln(err.Error()) + return err + } + } + return vc.ExtendedReader.ReadBuffer(buffer) +} + +func (vc *Conn) Write(p []byte) (int, error) { + if vc.writeFilterApplicationData { + _buffer := buf.StackNew() + defer buf.KeepAlive(_buffer) + buffer := buf.Dup(_buffer) + defer buffer.Release() + buffer.Write(p) + err := vc.WriteBuffer(buffer) + if err != nil { + return 0, err + } + return len(p), nil + } + return vc.ExtendedWriter.Write(p) +} + +func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { + if vc.needHandshake { + vc.needHandshake = false + if buffer.IsEmpty() { + ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, false) + } else { + vc.FilterTLS(buffer.Bytes()) + ApplyPadding(buffer, commandPaddingContinue, vc.userUUID, vc.isTLS) + } + err = vc.ExtendedWriter.WriteBuffer(buffer) + if err != nil { + buffer.Release() + return err + } + switch underlying := vc.tlsConn.(type) { + case *gotls.Conn: + if underlying.ConnectionState().Version != gotls.VersionTLS13 { + buffer.Release() + return ErrNotTLS13 + } + case *utls.UConn: + if underlying.ConnectionState().Version != utls.VersionTLS13 { + buffer.Release() + return ErrNotTLS13 + } + } + vc.tlsConn = nil + return nil + } + + if vc.writeFilterApplicationData { + buffer2 := ReshapeBuffer(buffer) + defer buffer2.Release() + vc.FilterTLS(buffer.Bytes()) + command := commandPaddingContinue + if !vc.isTLS { + command = commandPaddingEnd + + // disable XTLS + //vc.readProcess = false + vc.writeFilterApplicationData = false + vc.packetsToFilter = 0 + } else if buffer.Len() > 6 && bytes.Equal(buffer.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { + command = commandPaddingEnd + if vc.enableXTLS { + command = commandPaddingDirect + vc.writeDirect = true + } + vc.writeFilterApplicationData = false + } + ApplyPadding(buffer, command, nil, vc.isTLS) + err = vc.ExtendedWriter.WriteBuffer(buffer) + if err != nil { + return err + } + if vc.writeDirect { + vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn) + log.Debugln("XTLS Vision direct write start") + //time.Sleep(5 * time.Millisecond) + } + if buffer2 != nil { + if vc.writeDirect || !vc.isTLS { + return vc.ExtendedWriter.WriteBuffer(buffer2) + } + vc.FilterTLS(buffer2.Bytes()) + command = commandPaddingContinue + if buffer2.Len() > 6 && bytes.Equal(buffer2.To(3), tlsApplicationDataStart) || vc.packetsToFilter <= 0 { + command = commandPaddingEnd + if vc.enableXTLS { + command = commandPaddingDirect + vc.writeDirect = true + } + vc.writeFilterApplicationData = false + } + ApplyPadding(buffer2, command, nil, vc.isTLS) + err = vc.ExtendedWriter.WriteBuffer(buffer2) + if vc.writeDirect { + vc.ExtendedWriter = N.NewExtendedWriter(vc.Conn) + log.Debugln("XTLS Vision direct write start") + //time.Sleep(10 * time.Millisecond) + } + } + return err + } + /*if vc.writeDirect { + log.Debugln("XTLS Vision Direct write, payloadLen=%d", buffer.Len()) + }*/ + return vc.ExtendedWriter.WriteBuffer(buffer) +} + +func (vc *Conn) FrontHeadroom() int { + return PaddingHeaderLen +} + +func (vc *Conn) NeedHandshake() bool { + return vc.needHandshake +} + +func (vc *Conn) Upstream() any { + return vc.upstream +} diff --git a/transport/vless/filter.go b/transport/vless/vision/filter.go similarity index 99% rename from transport/vless/filter.go rename to transport/vless/vision/filter.go index f577be7a..e070de35 100644 --- a/transport/vless/filter.go +++ b/transport/vless/vision/filter.go @@ -1,4 +1,4 @@ -package vless +package vision import ( "bytes" diff --git a/transport/vless/vision.go b/transport/vless/vision/padding.go similarity index 94% rename from transport/vless/vision.go rename to transport/vless/vision/padding.go index 5649dde4..d5a230d1 100644 --- a/transport/vless/vision.go +++ b/transport/vless/vision/padding.go @@ -1,4 +1,4 @@ -package vless +package vision import ( "bytes" @@ -12,7 +12,7 @@ import ( ) const ( - paddingHeaderLen = 1 + 2 + 2 // =5 + PaddingHeaderLen = uuid.Size + 1 + 2 + 2 // =21 commandPaddingContinue byte = 0x00 commandPaddingEnd byte = 0x01 @@ -67,7 +67,7 @@ func ApplyPadding(buffer *buf.Buffer, command byte, userUUID *uuid.UUID, padding } func ReshapeBuffer(buffer *buf.Buffer) *buf.Buffer { - if buffer.Len() <= buf.BufferSize-paddingHeaderLen { + if buffer.Len() <= buf.BufferSize-PaddingHeaderLen { return nil } cutAt := bytes.LastIndex(buffer.Bytes(), tlsApplicationDataStart) diff --git a/transport/vless/vision/vision.go b/transport/vless/vision/vision.go new file mode 100644 index 00000000..3b52dd4b --- /dev/null +++ b/transport/vless/vision/vision.go @@ -0,0 +1,70 @@ +// Package vision implements VLESS flow `xtls-rprx-vision` introduced by Xray-core. +package vision + +import ( + "bytes" + gotls "crypto/tls" + "errors" + "fmt" + "net" + "reflect" + "unsafe" + + N "github.com/Dreamacro/clash/common/net" + tlsC "github.com/Dreamacro/clash/component/tls" + + "github.com/gofrs/uuid/v5" + "github.com/sagernet/sing/common" + utls "github.com/sagernet/utls" +) + +var ErrNotTLS13 = errors.New("XTLS Vision based on TLS 1.3 outer connection") + +type connWithUpstream interface { + net.Conn + common.WithUpstream +} + +func NewConn(conn connWithUpstream, userUUID *uuid.UUID) (*Conn, error) { + c := &Conn{ + ExtendedReader: N.NewExtendedReader(conn), + ExtendedWriter: N.NewExtendedWriter(conn), + upstream: conn, + userUUID: userUUID, + packetsToFilter: 6, + needHandshake: true, + readProcess: true, + readFilterUUID: true, + writeFilterApplicationData: true, + } + var t reflect.Type + var p unsafe.Pointer + switch underlying := conn.Upstream().(type) { + case *gotls.Conn: + //log.Debugln("type tls") + c.Conn = underlying.NetConn() + c.tlsConn = underlying + t = reflect.TypeOf(underlying).Elem() + p = unsafe.Pointer(underlying) + case *utls.UConn: + //log.Debugln("type *utls.UConn") + c.Conn = underlying.NetConn() + c.tlsConn = underlying + t = reflect.TypeOf(underlying.Conn).Elem() + p = unsafe.Pointer(underlying.Conn) + case *tlsC.UConn: + //log.Debugln("type *tlsC.UConn") + c.Conn = underlying.NetConn() + c.tlsConn = underlying.UConn + t = reflect.TypeOf(underlying.Conn).Elem() + //log.Debugln("t:%v", t) + p = unsafe.Pointer(underlying.Conn) + default: + return nil, fmt.Errorf(`failed to use vision, maybe "security" is not "tls" or "utls"`) + } + i, _ := t.FieldByName("input") + r, _ := t.FieldByName("rawInput") + c.input = (*bytes.Reader)(unsafe.Add(p, i.Offset)) + c.rawInput = (*bytes.Buffer)(unsafe.Add(p, r.Offset)) + return c, nil +} diff --git a/transport/vless/xtls.go b/transport/vless/xtls.go index 09929fc3..071e6e8f 100644 --- a/transport/vless/xtls.go +++ b/transport/vless/xtls.go @@ -2,17 +2,12 @@ package vless import ( "context" - "errors" "net" tlsC "github.com/Dreamacro/clash/component/tls" xtls "github.com/xtls/go" ) -var ( - ErrNotTLS13 = errors.New("XTLS Vision based on TLS 1.3 outer connection") -) - type XTLSConfig struct { Host string SkipCertVerify bool From 4971b9d8046713226ede50d939316e82c5343da8 Mon Sep 17 00:00:00 2001 From: H1JK Date: Sat, 27 May 2023 10:14:02 +0800 Subject: [PATCH 51/62] chore: Add vision splice support --- go.mod | 2 +- go.sum | 4 ++-- transport/vless/vision/conn.go | 32 +++++++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 40a92438..e5b4882f 100644 --- a/go.mod +++ b/go.mod @@ -105,6 +105,6 @@ require ( golang.org/x/tools v0.6.0 // indirect ) -replace github.com/sagernet/sing => github.com/h1jk/sing v0.0.0-20230519121640-6db84f45244d +replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070 replace github.com/sagernet/sing-vmess => github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899 diff --git a/go.sum b/go.sum index 0e9e38a7..bee79cc9 100644 --- a/go.sum +++ b/go.sum @@ -65,8 +65,6 @@ github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLe github.com/google/tink/go v1.6.1 h1:t7JHqO8Ath2w2ig5vjwQYJzhGEZymedQc90lQXUBa4I= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/h1jk/sing v0.0.0-20230519121640-6db84f45244d h1:ih6tNzl1uxuuX+Naz2qAPqSS20E6jfXFmcvyDRAy8rY= -github.com/h1jk/sing v0.0.0-20230519121640-6db84f45244d/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= @@ -98,6 +96,8 @@ github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c h1:D62872jiuzC6b+ github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c/go.mod h1:wqEuzdImyqD2MCGE8CYRJXbB77oSEJeoSSXXdwKjnsE= github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 h1:E/sNW9tugFjoBjAkth89MHlKHRaMdo43tGQ3MOPVayQ= github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= +github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070 h1:AT/Qfe9MvCxyrI9uybcXcVDLDEqR6+9ZK7a7pgis9xQ= +github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= github.com/metacubex/sing-shadowsocks2 v0.0.0-20230519030442-556ef530768f h1:aWgVMoAm5V2Ur9key6L//mUSBrVMl/zw/4GDG4ZjyZI= diff --git a/transport/vless/vision/conn.go b/transport/vless/vision/conn.go index 650d094d..23721c0b 100644 --- a/transport/vless/vision/conn.go +++ b/transport/vless/vision/conn.go @@ -262,7 +262,10 @@ func (vc *Conn) WriteBuffer(buffer *buf.Buffer) (err error) { } func (vc *Conn) FrontHeadroom() int { - return PaddingHeaderLen + if vc.readFilterUUID { + return PaddingHeaderLen + } + return PaddingHeaderLen - uuid.Size } func (vc *Conn) NeedHandshake() bool { @@ -270,5 +273,32 @@ func (vc *Conn) NeedHandshake() bool { } func (vc *Conn) Upstream() any { + if vc.writeDirect || + vc.readLastCommand == commandPaddingDirect { + return vc.Conn + } return vc.upstream } + +func (vc *Conn) ReaderPossiblyReplaceable() bool { + return vc.readProcess +} + +func (vc *Conn) ReaderReplaceable() bool { + if !vc.readProcess && + vc.readLastCommand == commandPaddingDirect { + return true + } + return false +} + +func (vc *Conn) WriterPossiblyReplaceable() bool { + return vc.writeFilterApplicationData +} + +func (vc *Conn) WriterReplaceable() bool { + if vc.writeDirect { + return true + } + return false +} From 73140ab826109c1c6737ae762994a8d21ffdc6e2 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sat, 27 May 2023 13:43:41 +0800 Subject: [PATCH 52/62] fix: udp panic when server return a domain name --- constant/metadata.go | 11 ++++++----- tunnel/connection.go | 29 +++++++++++++++++------------ tunnel/tunnel.go | 4 ++-- 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/constant/metadata.go b/constant/metadata.go index 1c344d5d..198c447d 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -205,15 +205,16 @@ func (m *Metadata) Pure() *Metadata { return m } +func (m *Metadata) AddrPort() netip.AddrPort { + port, _ := strconv.ParseUint(m.DstPort, 10, 16) + return netip.AddrPortFrom(m.DstIP.Unmap(), uint16(port)) +} + func (m *Metadata) UDPAddr() *net.UDPAddr { if m.NetWork != UDP || !m.DstIP.IsValid() { return nil } - port, _ := strconv.ParseUint(m.DstPort, 10, 16) - return &net.UDPAddr{ - IP: m.DstIP.AsSlice(), - Port: int(port), - } + return net.UDPAddrFromAddrPort(m.AddrPort()) } func (m *Metadata) String() string { diff --git a/tunnel/connection.go b/tunnel/connection.go index 321c7d06..b130f79a 100644 --- a/tunnel/connection.go +++ b/tunnel/connection.go @@ -26,7 +26,7 @@ func handleUDPToRemote(packet C.UDPPacket, pc C.PacketConn, metadata *C.Metadata return nil } -func handleUDPToLocal(packet C.UDPPacket, pc N.EnhancePacketConn, key string, oAddr, fAddr netip.Addr) { +func handleUDPToLocal(packet C.UDPPacket, pc N.EnhancePacketConn, key string, oAddrPort netip.AddrPort, fAddr netip.Addr) { defer func() { _ = pc.Close() closeAllLocalCoon(key) @@ -40,18 +40,23 @@ func handleUDPToLocal(packet C.UDPPacket, pc N.EnhancePacketConn, key string, oA return } - fromUDPAddr := from.(*net.UDPAddr) - _fromUDPAddr := *fromUDPAddr - fromUDPAddr = &_fromUDPAddr // make a copy - if fromAddr, ok := netip.AddrFromSlice(fromUDPAddr.IP); ok { - fromAddr = fromAddr.Unmap() - if fAddr.IsValid() && (oAddr.Unmap() == fromAddr) { - fromAddr = fAddr.Unmap() - } - fromUDPAddr.IP = fromAddr.AsSlice() - if fromAddr.Is4() { - fromUDPAddr.Zone = "" // only ipv6 can have the zone + fromUDPAddr, isUDPAddr := from.(*net.UDPAddr) + if isUDPAddr { + _fromUDPAddr := *fromUDPAddr + fromUDPAddr = &_fromUDPAddr // make a copy + if fromAddr, ok := netip.AddrFromSlice(fromUDPAddr.IP); ok { + fromAddr = fromAddr.Unmap() + if fAddr.IsValid() && (oAddrPort.Addr() == fromAddr) { // oAddrPort was Unmapped + fromAddr = fAddr.Unmap() + } + fromUDPAddr.IP = fromAddr.AsSlice() + if fromAddr.Is4() { + fromUDPAddr.Zone = "" // only ipv6 can have the zone + } } + } else { + fromUDPAddr = net.UDPAddrFromAddrPort(oAddrPort) // oAddrPort was Unmapped + log.Warnln("server return a [%T](%s) which isn't a *net.UDPAddr, force replace to (%s), this may be caused by a wrongly implemented server", from, from, oAddrPort) } _, err = packet.WriteBack(data, fromUDPAddr) diff --git a/tunnel/tunnel.go b/tunnel/tunnel.go index a4a473e9..4e00aca2 100644 --- a/tunnel/tunnel.go +++ b/tunnel/tunnel.go @@ -383,10 +383,10 @@ func handleUDPConn(packet C.PacketAdapter) { log.Infoln("[UDP] %s --> %s doesn't match any rule using DIRECT", metadata.SourceDetail(), metadata.RemoteAddress()) } - oAddr := metadata.DstIP + oAddrPort := metadata.AddrPort() natTable.Set(key, pc) - go handleUDPToLocal(packet, pc, key, oAddr, fAddr) + go handleUDPToLocal(packet, pc, key, oAddrPort, fAddr) handle() }() From f44ba26f0c321d3e84388a71e8858079428c93eb Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sun, 28 May 2023 08:50:02 +0800 Subject: [PATCH 53/62] chore: switch ss uot default back to version 1 --- adapter/outbound/shadowsocks.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index e6c74592..2edc7080 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -304,7 +304,7 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) { switch option.UDPOverTCPVersion { case uot.Version, uot.LegacyVersion: case 0: - option.UDPOverTCPVersion = uot.Version + option.UDPOverTCPVersion = uot.LegacyVersion default: return nil, fmt.Errorf("ss %s unknown udp over tcp protocol version: %d", addr, option.UDPOverTCPVersion) } From 92f71fd25fb6c87735c38abee6e0d3565eb05d12 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sun, 28 May 2023 09:33:42 +0800 Subject: [PATCH 54/62] chore: add WaitReadFrom support in hyPacketConn --- adapter/outbound/hysteria.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/adapter/outbound/hysteria.go b/adapter/outbound/hysteria.go index 6024ea10..2d5b90ac 100644 --- a/adapter/outbound/hysteria.go +++ b/adapter/outbound/hysteria.go @@ -318,6 +318,17 @@ func (c *hyPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err error) { return } +func (c *hyPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + b, addrStr, err := c.UDPConn.ReadFrom() + if err != nil { + return + } + data = b + put = func() {} + addr = M.ParseSocksaddr(addrStr).UDPAddr() + return +} + func (c *hyPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { err = c.UDPConn.WriteTo(p, M.SocksaddrFromNet(addr).String()) if err != nil { From 7aae781569b9cb1fd3b7048bc5704021e381582a Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sun, 28 May 2023 15:22:08 +0800 Subject: [PATCH 55/62] chore: add WaitReadFrom support in quicStreamPacketConn --- adapter/outbound/hysteria.go | 3 ++- common/net/packet.go | 2 ++ common/net/packet/packet.go | 2 ++ transport/tuic/conn.go | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/adapter/outbound/hysteria.go b/adapter/outbound/hysteria.go index 2d5b90ac..161a4546 100644 --- a/adapter/outbound/hysteria.go +++ b/adapter/outbound/hysteria.go @@ -19,6 +19,7 @@ import ( "github.com/metacubex/quic-go/congestion" M "github.com/sagernet/sing/common/metadata" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/proxydialer" tlsC "github.com/Dreamacro/clash/component/tls" @@ -324,7 +325,7 @@ func (c *hyPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, e return } data = b - put = func() {} + put = N.NilPut addr = M.ParseSocksaddr(addrStr).UDPAddr() return } diff --git a/common/net/packet.go b/common/net/packet.go index 9afe86b0..e949ecf2 100644 --- a/common/net/packet.go +++ b/common/net/packet.go @@ -6,7 +6,9 @@ import ( ) type EnhancePacketConn = packet.EnhancePacketConn +type WaitReadFrom = packet.WaitReadFrom +var NilPut = packet.NilPut var NewEnhancePacketConn = packet.NewEnhancePacketConn var NewThreadSafePacketConn = packet.NewThreadSafePacketConn var NewRefPacketConn = packet.NewRefPacketConn diff --git a/common/net/packet/packet.go b/common/net/packet/packet.go index 6c9542c1..a3f1dd72 100644 --- a/common/net/packet/packet.go +++ b/common/net/packet/packet.go @@ -10,6 +10,8 @@ type WaitReadFrom interface { WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) } +func NilPut() {} + type EnhancePacketConn interface { net.PacketConn WaitReadFrom diff --git a/transport/tuic/conn.go b/transport/tuic/conn.go index 567f6ce5..d46a3556 100644 --- a/transport/tuic/conn.go +++ b/transport/tuic/conn.go @@ -197,6 +197,22 @@ func (q *quicStreamPacketConn) ReadFrom(p []byte) (n int, addr net.Addr, err err return } +func (q *quicStreamPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + if q.inputConn != nil { + var packet Packet + packet, err = ReadPacket(q.inputConn) + if err != nil { + return + } + data = packet.DATA + put = N.NilPut + addr = packet.ADDR.UDPAddr() + } else { + err = net.ErrClosed + } + return +} + func (q *quicStreamPacketConn) WriteTo(p []byte, addr net.Addr) (n int, err error) { if q.udpRelayMode != "quic" && len(p) > q.maxUdpRelayPacketSize { return 0, quic.ErrMessageTooLarge(q.maxUdpRelayPacketSize) From 9c2972afb066adaedfe5b65e581dbe7505d941aa Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sun, 28 May 2023 17:19:57 +0800 Subject: [PATCH 56/62] chore: add `IN-USER` and `IN-NAME` rules --- adapter/inbound/addition.go | 6 +++++ constant/metadata.go | 1 + constant/rule.go | 12 ++++++--- listener/sing/context.go | 20 +++++++++++++++ listener/sing/sing.go | 15 ++---------- rules/common/in_name.go | 49 +++++++++++++++++++++++++++++++++++++ rules/common/in_type.go | 4 +-- rules/common/in_user.go | 49 +++++++++++++++++++++++++++++++++++++ rules/parser.go | 4 +++ 9 files changed, 142 insertions(+), 18 deletions(-) create mode 100644 rules/common/in_name.go create mode 100644 rules/common/in_user.go diff --git a/adapter/inbound/addition.go b/adapter/inbound/addition.go index 5966e784..47307ed7 100644 --- a/adapter/inbound/addition.go +++ b/adapter/inbound/addition.go @@ -16,6 +16,12 @@ func WithInName(name string) Addition { } } +func WithInUser(user string) Addition { + return func(metadata *C.Metadata) { + metadata.InUser = user + } +} + func WithSpecialRules(specialRules string) Addition { return func(metadata *C.Metadata) { metadata.SpecialRules = specialRules diff --git a/constant/metadata.go b/constant/metadata.go index 198c447d..edc58aec 100644 --- a/constant/metadata.go +++ b/constant/metadata.go @@ -133,6 +133,7 @@ type Metadata struct { InIP netip.Addr `json:"inboundIP"` InPort string `json:"inboundPort"` InName string `json:"inboundName"` + InUser string `json:"inboundUser"` Host string `json:"host"` DNSMode DNSMode `json:"dnsMode"` Uid uint32 `json:"uid"` diff --git a/constant/rule.go b/constant/rule.go index 28c629a0..906f3cef 100644 --- a/constant/rule.go +++ b/constant/rule.go @@ -14,12 +14,14 @@ const ( SrcPort DstPort InPort + InUser + InName + InType Process ProcessPath RuleSet Network Uid - INTYPE SubRules MATCH AND @@ -55,6 +57,12 @@ func (rt RuleType) String() string { return "DstPort" case InPort: return "InPort" + case InUser: + return "InUser" + case InName: + return "InName" + case InType: + return "InType" case Process: return "Process" case ProcessPath: @@ -67,8 +75,6 @@ func (rt RuleType) String() string { return "Network" case Uid: return "Uid" - case INTYPE: - return "InType" case SubRules: return "SubRules" case AND: diff --git a/listener/sing/context.go b/listener/sing/context.go index f7aed851..a500e4a4 100644 --- a/listener/sing/context.go +++ b/listener/sing/context.go @@ -2,8 +2,11 @@ package sing import ( "context" + "golang.org/x/exp/slices" "github.com/Dreamacro/clash/adapter/inbound" + + "github.com/sagernet/sing/common/auth" ) type contextKey string @@ -22,3 +25,20 @@ func getAdditions(ctx context.Context) []inbound.Addition { } return nil } + +func combineAdditions(ctx context.Context, additions []inbound.Addition) []inbound.Addition { + additionsCloned := false + if ctxAdditions := getAdditions(ctx); len(ctxAdditions) > 0 { + additions = slices.Clone(additions) + additionsCloned = true + additions = append(additions, ctxAdditions...) + } + if user, ok := auth.UserFromContext[string](ctx); ok { + if !additionsCloned { + additions = slices.Clone(additions) + additionsCloned = true + } + additions = append(additions, inbound.WithInUser(user)) + } + return additions +} diff --git a/listener/sing/sing.go b/listener/sing/sing.go index 9bf52e9c..c60bbe67 100644 --- a/listener/sing/sing.go +++ b/listener/sing/sing.go @@ -3,7 +3,6 @@ package sing import ( "context" "errors" - "golang.org/x/exp/slices" "net" "net/netip" "sync" @@ -74,11 +73,6 @@ func UpstreamMetadata(metadata M.Metadata) M.Metadata { } func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, metadata M.Metadata) error { - additions := h.Additions - if ctxAdditions := getAdditions(ctx); len(ctxAdditions) > 0 { - additions = slices.Clone(additions) - additions = append(additions, ctxAdditions...) - } switch metadata.Destination.Fqdn { case mux.Destination.Fqdn: return mux.HandleConnection(ctx, h, log.SingLogger, conn, UpstreamMetadata(metadata)) @@ -103,16 +97,11 @@ func (h *ListenerHandler) NewConnection(ctx context.Context, conn net.Conn, meta if deadline.NeedAdditionalReadDeadline(conn) { conn = N.NewDeadlineConn(conn) // conn from sing should check NeedAdditionalReadDeadline } - h.TcpIn <- inbound.NewSocket(target, &waitCloseConn{ExtendedConn: N.NewExtendedConn(conn), wg: wg, rAddr: metadata.Source.TCPAddr()}, h.Type, additions...) + h.TcpIn <- inbound.NewSocket(target, &waitCloseConn{ExtendedConn: N.NewExtendedConn(conn), wg: wg, rAddr: metadata.Source.TCPAddr()}, h.Type, combineAdditions(ctx, h.Additions)...) return nil } func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network.PacketConn, metadata M.Metadata) error { - additions := h.Additions - if ctxAdditions := getAdditions(ctx); len(ctxAdditions) > 0 { - additions = slices.Clone(additions) - additions = append(additions, ctxAdditions...) - } if deadline.NeedAdditionalReadDeadline(conn) { conn = deadline.NewFallbackPacketConn(bufio.NewNetPacketConn(conn)) // conn from sing should check NeedAdditionalReadDeadline } @@ -162,7 +151,7 @@ func (h *ListenerHandler) NewPacketConnection(ctx context.Context, conn network. buff: buff, } select { - case h.UdpIn <- inbound.NewPacket(target, packet, h.Type, additions...): + case h.UdpIn <- inbound.NewPacket(target, packet, h.Type, combineAdditions(ctx, h.Additions)...): default: } } diff --git a/rules/common/in_name.go b/rules/common/in_name.go new file mode 100644 index 00000000..1e2abe15 --- /dev/null +++ b/rules/common/in_name.go @@ -0,0 +1,49 @@ +package common + +import ( + "fmt" + C "github.com/Dreamacro/clash/constant" + "strings" +) + +type InName struct { + *Base + names []string + adapter string + payload string +} + +func (u *InName) Match(metadata *C.Metadata) (bool, string) { + for _, name := range u.names { + if metadata.InName == name { + return true, u.adapter + } + } + return false, "" +} + +func (u *InName) RuleType() C.RuleType { + return C.InName +} + +func (u *InName) Adapter() string { + return u.adapter +} + +func (u *InName) Payload() string { + return u.payload +} + +func NewInName(iNames, adapter string) (*InName, error) { + names := strings.Split(iNames, "/") + if len(names) == 0 { + return nil, fmt.Errorf("in name couldn't be empty") + } + + return &InName{ + Base: &Base{}, + names: names, + adapter: adapter, + payload: iNames, + }, nil +} diff --git a/rules/common/in_type.go b/rules/common/in_type.go index 520c9594..453045d8 100644 --- a/rules/common/in_type.go +++ b/rules/common/in_type.go @@ -23,7 +23,7 @@ func (u *InType) Match(metadata *C.Metadata) (bool, string) { } func (u *InType) RuleType() C.RuleType { - return C.INTYPE + return C.InType } func (u *InType) Adapter() string { @@ -37,7 +37,7 @@ func (u *InType) Payload() string { func NewInType(iTypes, adapter string) (*InType, error) { types := strings.Split(iTypes, "/") if len(types) == 0 { - return nil, fmt.Errorf("in type could be empty") + return nil, fmt.Errorf("in type couldn't be empty") } tps, err := parseInTypes(types) diff --git a/rules/common/in_user.go b/rules/common/in_user.go new file mode 100644 index 00000000..24f4b2e5 --- /dev/null +++ b/rules/common/in_user.go @@ -0,0 +1,49 @@ +package common + +import ( + "fmt" + C "github.com/Dreamacro/clash/constant" + "strings" +) + +type InUser struct { + *Base + users []string + adapter string + payload string +} + +func (u *InUser) Match(metadata *C.Metadata) (bool, string) { + for _, user := range u.users { + if metadata.InUser == user { + return true, u.adapter + } + } + return false, "" +} + +func (u *InUser) RuleType() C.RuleType { + return C.InUser +} + +func (u *InUser) Adapter() string { + return u.adapter +} + +func (u *InUser) Payload() string { + return u.payload +} + +func NewInUser(iUsers, adapter string) (*InUser, error) { + users := strings.Split(iUsers, "/") + if len(users) == 0 { + return nil, fmt.Errorf("in user couldn't be empty") + } + + return &InUser{ + Base: &Base{}, + users: users, + adapter: adapter, + payload: iUsers, + }, nil +} diff --git a/rules/parser.go b/rules/parser.go index 1a336225..df790bc3 100644 --- a/rules/parser.go +++ b/rules/parser.go @@ -47,6 +47,10 @@ func ParseRule(tp, payload, target string, params []string, subRules map[string] parsed, parseErr = RC.NewUid(payload, target) case "IN-TYPE": parsed, parseErr = RC.NewInType(payload, target) + case "IN-USER": + parsed, parseErr = RC.NewInUser(payload, target) + case "IN-NAME": + parsed, parseErr = RC.NewInName(payload, target) case "SUB-RULE": parsed, parseErr = logic.NewSubRule(payload, target, subRules, ParseRule) case "AND": From 097f3e250c7f7cf301446e1bbcb799564c6cceff Mon Sep 17 00:00:00 2001 From: Larvan2 <78135608+Larvan2@users.noreply.github.com> Date: Sun, 28 May 2023 20:14:57 +0800 Subject: [PATCH 57/62] chore: slightly improve quic-bbr performance --- transport/tuic/congestion/bbr_sender.go | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/transport/tuic/congestion/bbr_sender.go b/transport/tuic/congestion/bbr_sender.go index 99164362..17368386 100644 --- a/transport/tuic/congestion/bbr_sender.go +++ b/transport/tuic/congestion/bbr_sender.go @@ -17,17 +17,12 @@ const ( InitialMaxDatagramSize = 1252 InitialPacketSizeIPv4 = 1252 InitialPacketSizeIPv6 = 1232 - InitialCongestionWindow = 10 + InitialCongestionWindow = 32 DefaultBBRMaxCongestionWindow = 10000 ) -const ( - initialMinCongestionWindow = 4 - minInitialPacketSize = 1200 -) - func GetInitialPacketSize(addr net.Addr) congestion.ByteCount { - maxSize := congestion.ByteCount(minInitialPacketSize) + maxSize := congestion.ByteCount(1200) // If this is not a UDP address, we don't know anything about the MTU. // Use the minimum size of an Initial packet as the max packet size. if udpAddr, ok := addr.(*net.UDPAddr); ok { @@ -37,7 +32,7 @@ func GetInitialPacketSize(addr net.Addr) congestion.ByteCount { maxSize = InitialPacketSizeIPv6 } } - return maxSize + return congestion.ByteCount(maxSize) } var ( @@ -45,8 +40,8 @@ var ( // Default initial rtt used before any samples are received. InitialRtt = 100 * time.Millisecond - // The gain used for the STARTUP, equal to 2/ln(2). - DefaultHighGain = 2.89 + // The gain used for the STARTUP, equal to 4*ln(2). + DefaultHighGain = 2.77 // The gain used in STARTUP after loss has been detected. // 1.5 is enough to allow for 25% exogenous loss and still observe a 25% growth @@ -281,7 +276,7 @@ func (b *bbrSender) maxCongestionWindow() congestion.ByteCount { } func (b *bbrSender) minCongestionWindow() congestion.ByteCount { - return b.maxDatagramSize * initialMinCongestionWindow + return b.maxDatagramSize * b.initialCongestionWindow } func (b *bbrSender) SetRTTStatsProvider(provider congestion.RTTStatsProvider) { From 8e88e0b9f5c0ba04564ee70d0cd2b0c4da75d8eb Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Sun, 28 May 2023 22:51:26 +0800 Subject: [PATCH 58/62] chore: add WaitReadFrom support in ssr --- adapter/outbound/hysteria.go | 2 - adapter/outbound/shadowsocks.go | 34 ---------- adapter/outbound/shadowsocksr.go | 68 +++++++++++++++++++- common/net/packet.go | 1 - common/net/packet/packet.go | 2 - go.mod | 2 +- go.sum | 4 +- listener/shadowsocks/udp.go | 21 +++--- listener/shadowsocks/utils.go | 7 +- transport/shadowsocks/core/cipher.go | 11 ++-- transport/shadowsocks/shadowaead/packet.go | 30 +++++++-- transport/shadowsocks/shadowstream/packet.go | 30 +++++++-- transport/ssr/protocol/auth_aes128_sha1.go | 5 +- transport/ssr/protocol/auth_chain_a.go | 5 +- transport/ssr/protocol/auth_sha1_v4.go | 3 +- transport/ssr/protocol/origin.go | 4 +- transport/ssr/protocol/packet.go | 24 ++++++- transport/ssr/protocol/protocol.go | 4 +- transport/trojan/trojan.go | 12 +++- transport/tuic/conn.go | 1 - 20 files changed, 182 insertions(+), 88 deletions(-) diff --git a/adapter/outbound/hysteria.go b/adapter/outbound/hysteria.go index 161a4546..7da4975d 100644 --- a/adapter/outbound/hysteria.go +++ b/adapter/outbound/hysteria.go @@ -19,7 +19,6 @@ import ( "github.com/metacubex/quic-go/congestion" M "github.com/sagernet/sing/common/metadata" - N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/proxydialer" tlsC "github.com/Dreamacro/clash/component/tls" @@ -325,7 +324,6 @@ func (c *hyPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, e return } data = b - put = N.NilPut addr = M.ParseSocksaddr(addrStr).UDPAddr() return } diff --git a/adapter/outbound/shadowsocks.go b/adapter/outbound/shadowsocks.go index 2edc7080..32558eac 100644 --- a/adapter/outbound/shadowsocks.go +++ b/adapter/outbound/shadowsocks.go @@ -16,7 +16,6 @@ import ( "github.com/Dreamacro/clash/transport/restls" obfs "github.com/Dreamacro/clash/transport/simple-obfs" shadowtls "github.com/Dreamacro/clash/transport/sing-shadowtls" - "github.com/Dreamacro/clash/transport/socks5" v2rayObfs "github.com/Dreamacro/clash/transport/v2ray-plugin" restlsC "github.com/3andne/restls-client-go" @@ -330,36 +329,3 @@ func NewShadowSocks(option ShadowSocksOption) (*ShadowSocks, error) { restlsConfig: restlsConfig, }, nil } - -type ssPacketConn struct { - net.PacketConn - rAddr net.Addr -} - -func (spc *ssPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) { - packet, err := socks5.EncodeUDPPacket(socks5.ParseAddrToSocksAddr(addr), b) - if err != nil { - return - } - return spc.PacketConn.WriteTo(packet[3:], spc.rAddr) -} - -func (spc *ssPacketConn) ReadFrom(b []byte) (int, net.Addr, error) { - n, _, e := spc.PacketConn.ReadFrom(b) - if e != nil { - return 0, nil, e - } - - addr := socks5.SplitAddr(b[:n]) - if addr == nil { - return 0, nil, errors.New("parse addr error") - } - - udpAddr := addr.UDPAddr() - if udpAddr == nil { - return 0, nil, errors.New("parse addr error") - } - - copy(b, b[len(addr):]) - return n - len(addr), udpAddr, e -} diff --git a/adapter/outbound/shadowsocksr.go b/adapter/outbound/shadowsocksr.go index d33d6586..07778032 100644 --- a/adapter/outbound/shadowsocksr.go +++ b/adapter/outbound/shadowsocksr.go @@ -2,16 +2,19 @@ package outbound import ( "context" + "errors" "fmt" "net" "strconv" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/component/dialer" "github.com/Dreamacro/clash/component/proxydialer" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/transport/shadowsocks/core" "github.com/Dreamacro/clash/transport/shadowsocks/shadowaead" "github.com/Dreamacro/clash/transport/shadowsocks/shadowstream" + "github.com/Dreamacro/clash/transport/socks5" "github.com/Dreamacro/clash/transport/ssr/obfs" "github.com/Dreamacro/clash/transport/ssr/protocol" ) @@ -110,9 +113,9 @@ func (ssr *ShadowSocksR) ListenPacketWithDialer(ctx context.Context, dialer C.Di return nil, err } - pc = ssr.cipher.PacketConn(pc) - pc = ssr.protocol.PacketConn(pc) - return newPacketConn(&ssPacketConn{PacketConn: pc, rAddr: addr}, ssr), nil + epc := ssr.cipher.PacketConn(N.NewEnhancePacketConn(pc)) + epc = ssr.protocol.PacketConn(epc) + return newPacketConn(&ssrPacketConn{EnhancePacketConn: epc, rAddr: addr}, ssr), nil } // SupportWithDialer implements C.ProxyAdapter @@ -188,3 +191,62 @@ func NewShadowSocksR(option ShadowSocksROption) (*ShadowSocksR, error) { protocol: protocol, }, nil } + +type ssrPacketConn struct { + N.EnhancePacketConn + rAddr net.Addr +} + +func (spc *ssrPacketConn) WriteTo(b []byte, addr net.Addr) (n int, err error) { + packet, err := socks5.EncodeUDPPacket(socks5.ParseAddrToSocksAddr(addr), b) + if err != nil { + return + } + return spc.EnhancePacketConn.WriteTo(packet[3:], spc.rAddr) +} + +func (spc *ssrPacketConn) ReadFrom(b []byte) (int, net.Addr, error) { + n, _, e := spc.EnhancePacketConn.ReadFrom(b) + if e != nil { + return 0, nil, e + } + + addr := socks5.SplitAddr(b[:n]) + if addr == nil { + return 0, nil, errors.New("parse addr error") + } + + udpAddr := addr.UDPAddr() + if udpAddr == nil { + return 0, nil, errors.New("parse addr error") + } + + copy(b, b[len(addr):]) + return n - len(addr), udpAddr, e +} + +func (spc *ssrPacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + data, put, _, err = spc.EnhancePacketConn.WaitReadFrom() + if err != nil { + return nil, nil, nil, err + } + + _addr := socks5.SplitAddr(data) + if _addr == nil { + if put != nil { + put() + } + return nil, nil, nil, errors.New("parse addr error") + } + + addr = _addr.UDPAddr() + if addr == nil { + if put != nil { + put() + } + return nil, nil, nil, errors.New("parse addr error") + } + + data = data[len(_addr):] + return +} diff --git a/common/net/packet.go b/common/net/packet.go index e949ecf2..fc562c42 100644 --- a/common/net/packet.go +++ b/common/net/packet.go @@ -8,7 +8,6 @@ import ( type EnhancePacketConn = packet.EnhancePacketConn type WaitReadFrom = packet.WaitReadFrom -var NilPut = packet.NilPut var NewEnhancePacketConn = packet.NewEnhancePacketConn var NewThreadSafePacketConn = packet.NewThreadSafePacketConn var NewRefPacketConn = packet.NewRefPacketConn diff --git a/common/net/packet/packet.go b/common/net/packet/packet.go index a3f1dd72..6c9542c1 100644 --- a/common/net/packet/packet.go +++ b/common/net/packet/packet.go @@ -10,8 +10,6 @@ type WaitReadFrom interface { WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) } -func NilPut() {} - type EnhancePacketConn interface { net.PacketConn WaitReadFrom diff --git a/go.mod b/go.mod index e5b4882f..b203dd40 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/mdlayher/netlink v1.7.2 github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c - github.com/metacubex/sing-shadowsocks2 v0.0.0-20230519030442-556ef530768f + github.com/metacubex/sing-shadowsocks2 v0.0.0-20230528144023-05418c94ed2d github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a github.com/miekg/dns v1.1.54 diff --git a/go.sum b/go.sum index bee79cc9..25448530 100644 --- a/go.sum +++ b/go.sum @@ -100,8 +100,8 @@ github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070 h1:AT/Qfe9MvCxyrI9u github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230519030442-556ef530768f h1:aWgVMoAm5V2Ur9key6L//mUSBrVMl/zw/4GDG4ZjyZI= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230519030442-556ef530768f/go.mod h1:jVDD4N22bDPPKA73NvB7aqdlLWiAwv8D+jx7HwhcWak= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230528144023-05418c94ed2d h1:lWbWl3pZA1x8TgYDw07jo1u5RtbBRIlxuJDV4FW0WeQ= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230528144023-05418c94ed2d/go.mod h1:jVDD4N22bDPPKA73NvB7aqdlLWiAwv8D+jx7HwhcWak= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899 h1:iRfcuztp7REfmOyasSlCL/pqNWfUDMTJ2CwbGpxpeks= diff --git a/listener/shadowsocks/udp.go b/listener/shadowsocks/udp.go index ef67d4e8..4efafa60 100644 --- a/listener/shadowsocks/udp.go +++ b/listener/shadowsocks/udp.go @@ -4,7 +4,7 @@ import ( "net" "github.com/Dreamacro/clash/adapter/inbound" - "github.com/Dreamacro/clash/common/pool" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/sockopt" C "github.com/Dreamacro/clash/constant" "github.com/Dreamacro/clash/log" @@ -29,19 +29,20 @@ func NewUDP(addr string, pickCipher core.Cipher, in chan<- C.PacketAdapter) (*UD } sl := &UDPListener{l, false} - conn := pickCipher.PacketConn(l) + conn := pickCipher.PacketConn(N.NewEnhancePacketConn(l)) go func() { for { - buf := pool.Get(pool.UDPBufferSize) - n, remoteAddr, err := conn.ReadFrom(buf) + data, put, remoteAddr, err := conn.WaitReadFrom() if err != nil { - pool.Put(buf) + if put != nil { + put() + } if sl.closed { break } continue } - handleSocksUDP(conn, in, buf[:n], remoteAddr) + handleSocksUDP(conn, in, data, put, remoteAddr) } }() @@ -57,11 +58,13 @@ func (l *UDPListener) LocalAddr() net.Addr { return l.packetConn.LocalAddr() } -func handleSocksUDP(pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, addr net.Addr) { +func handleSocksUDP(pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, put func(), addr net.Addr) { tgtAddr := socks5.SplitAddr(buf) if tgtAddr == nil { // Unresolved UDP packet, return buffer to the pool - pool.Put(buf) + if put != nil { + put() + } return } target := socks5.ParseAddr(tgtAddr.String()) @@ -71,7 +74,7 @@ func handleSocksUDP(pc net.PacketConn, in chan<- C.PacketAdapter, buf []byte, ad pc: pc, rAddr: addr, payload: payload, - bufRef: buf, + put: put, } select { case in <- inbound.NewPacket(target, packet, C.SHADOWSOCKS): diff --git a/listener/shadowsocks/utils.go b/listener/shadowsocks/utils.go index 2e9fd003..c34c5cd0 100644 --- a/listener/shadowsocks/utils.go +++ b/listener/shadowsocks/utils.go @@ -6,7 +6,6 @@ import ( "net" "net/url" - "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/transport/socks5" ) @@ -14,7 +13,7 @@ type packet struct { pc net.PacketConn rAddr net.Addr payload []byte - bufRef []byte + put func() } func (c *packet) Data() []byte { @@ -37,7 +36,9 @@ func (c *packet) LocalAddr() net.Addr { } func (c *packet) Drop() { - pool.Put(c.bufRef) + if c.put != nil { + c.put() + } } func (c *packet) InAddr() net.Addr { diff --git a/transport/shadowsocks/core/cipher.go b/transport/shadowsocks/core/cipher.go index 7f4f7f71..cd30360c 100644 --- a/transport/shadowsocks/core/cipher.go +++ b/transport/shadowsocks/core/cipher.go @@ -7,6 +7,7 @@ import ( "sort" "strings" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/transport/shadowsocks/shadowaead" "github.com/Dreamacro/clash/transport/shadowsocks/shadowstream" ) @@ -21,7 +22,7 @@ type StreamConnCipher interface { } type PacketConnCipher interface { - PacketConn(net.PacketConn) net.PacketConn + PacketConn(N.EnhancePacketConn) N.EnhancePacketConn } // ErrCipherNotSupported occurs when a cipher is not supported (likely because of security concerns). @@ -128,7 +129,7 @@ type AeadCipher struct { } func (aead *AeadCipher) StreamConn(c net.Conn) net.Conn { return shadowaead.NewConn(c, aead) } -func (aead *AeadCipher) PacketConn(c net.PacketConn) net.PacketConn { +func (aead *AeadCipher) PacketConn(c N.EnhancePacketConn) N.EnhancePacketConn { return shadowaead.NewPacketConn(c, aead) } @@ -139,7 +140,7 @@ type StreamCipher struct { } func (ciph *StreamCipher) StreamConn(c net.Conn) net.Conn { return shadowstream.NewConn(c, ciph) } -func (ciph *StreamCipher) PacketConn(c net.PacketConn) net.PacketConn { +func (ciph *StreamCipher) PacketConn(c N.EnhancePacketConn) N.EnhancePacketConn { return shadowstream.NewPacketConn(c, ciph) } @@ -147,8 +148,8 @@ func (ciph *StreamCipher) PacketConn(c net.PacketConn) net.PacketConn { type dummy struct{} -func (dummy) StreamConn(c net.Conn) net.Conn { return c } -func (dummy) PacketConn(c net.PacketConn) net.PacketConn { return c } +func (dummy) StreamConn(c net.Conn) net.Conn { return c } +func (dummy) PacketConn(c N.EnhancePacketConn) N.EnhancePacketConn { return c } // key-derivation function from original Shadowsocks func Kdf(password string, keyLen int) []byte { diff --git a/transport/shadowsocks/shadowaead/packet.go b/transport/shadowsocks/shadowaead/packet.go index 7043ead7..e84ac570 100644 --- a/transport/shadowsocks/shadowaead/packet.go +++ b/transport/shadowsocks/shadowaead/packet.go @@ -6,6 +6,7 @@ import ( "io" "net" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/pool" ) @@ -57,15 +58,15 @@ func Unpack(dst, pkt []byte, ciph Cipher) ([]byte, error) { } type PacketConn struct { - net.PacketConn + N.EnhancePacketConn Cipher } const maxPacketSize = 64 * 1024 -// NewPacketConn wraps a net.PacketConn with cipher -func NewPacketConn(c net.PacketConn, ciph Cipher) *PacketConn { - return &PacketConn{PacketConn: c, Cipher: ciph} +// NewPacketConn wraps an N.EnhancePacketConn with cipher +func NewPacketConn(c N.EnhancePacketConn, ciph Cipher) *PacketConn { + return &PacketConn{EnhancePacketConn: c, Cipher: ciph} } // WriteTo encrypts b and write to addr using the embedded PacketConn. @@ -76,13 +77,13 @@ func (c *PacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { if err != nil { return 0, err } - _, err = c.PacketConn.WriteTo(buf, addr) + _, err = c.EnhancePacketConn.WriteTo(buf, addr) return len(b), err } // ReadFrom reads from the embedded PacketConn and decrypts into b. func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) { - n, addr, err := c.PacketConn.ReadFrom(b) + n, addr, err := c.EnhancePacketConn.ReadFrom(b) if err != nil { return n, addr, err } @@ -93,3 +94,20 @@ func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) { copy(b, bb) return len(bb), addr, err } + +func (c *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + data, put, addr, err = c.EnhancePacketConn.WaitReadFrom() + if err != nil { + return + } + data, err = Unpack(data[c.Cipher.SaltSize():], data, c) + if err != nil { + if put != nil { + put() + } + data = nil + put = nil + return + } + return +} diff --git a/transport/shadowsocks/shadowstream/packet.go b/transport/shadowsocks/shadowstream/packet.go index 0b46dea1..f0bf43ef 100644 --- a/transport/shadowsocks/shadowstream/packet.go +++ b/transport/shadowsocks/shadowstream/packet.go @@ -6,6 +6,7 @@ import ( "io" "net" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/pool" ) @@ -43,13 +44,13 @@ func Unpack(dst, pkt []byte, s Cipher) ([]byte, error) { } type PacketConn struct { - net.PacketConn + N.EnhancePacketConn Cipher } -// NewPacketConn wraps a net.PacketConn with stream cipher encryption/decryption. -func NewPacketConn(c net.PacketConn, ciph Cipher) *PacketConn { - return &PacketConn{PacketConn: c, Cipher: ciph} +// NewPacketConn wraps an N.EnhancePacketConn with stream cipher encryption/decryption. +func NewPacketConn(c N.EnhancePacketConn, ciph Cipher) *PacketConn { + return &PacketConn{EnhancePacketConn: c, Cipher: ciph} } const maxPacketSize = 64 * 1024 @@ -61,12 +62,12 @@ func (c *PacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { if err != nil { return 0, err } - _, err = c.PacketConn.WriteTo(buf, addr) + _, err = c.EnhancePacketConn.WriteTo(buf, addr) return len(b), err } func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) { - n, addr, err := c.PacketConn.ReadFrom(b) + n, addr, err := c.EnhancePacketConn.ReadFrom(b) if err != nil { return n, addr, err } @@ -77,3 +78,20 @@ func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) { copy(b, bb) return len(bb), addr, err } + +func (c *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + data, put, addr, err = c.EnhancePacketConn.WaitReadFrom() + if err != nil { + return + } + data, err = Unpack(data[c.IVSize():], data, c) + if err != nil { + if put != nil { + put() + } + data = nil + put = nil + return + } + return +} diff --git a/transport/ssr/protocol/auth_aes128_sha1.go b/transport/ssr/protocol/auth_aes128_sha1.go index 4de48151..e2f0e143 100644 --- a/transport/ssr/protocol/auth_aes128_sha1.go +++ b/transport/ssr/protocol/auth_aes128_sha1.go @@ -8,6 +8,7 @@ import ( "strconv" "strings" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/transport/ssr/tools" @@ -82,13 +83,13 @@ func (a *authAES128) StreamConn(c net.Conn, iv []byte) net.Conn { return &Conn{Conn: c, Protocol: p} } -func (a *authAES128) PacketConn(c net.PacketConn) net.PacketConn { +func (a *authAES128) PacketConn(c N.EnhancePacketConn) N.EnhancePacketConn { p := &authAES128{ Base: a.Base, authAES128Function: a.authAES128Function, userData: a.userData, } - return &PacketConn{PacketConn: c, Protocol: p} + return &PacketConn{EnhancePacketConn: c, Protocol: p} } func (a *authAES128) Decode(dst, src *bytes.Buffer) error { diff --git a/transport/ssr/protocol/auth_chain_a.go b/transport/ssr/protocol/auth_chain_a.go index 6b12ab9b..23efb390 100644 --- a/transport/ssr/protocol/auth_chain_a.go +++ b/transport/ssr/protocol/auth_chain_a.go @@ -11,6 +11,7 @@ import ( "strconv" "strings" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/log" "github.com/Dreamacro/clash/transport/shadowsocks/core" @@ -83,13 +84,13 @@ func (a *authChainA) StreamConn(c net.Conn, iv []byte) net.Conn { return &Conn{Conn: c, Protocol: p} } -func (a *authChainA) PacketConn(c net.PacketConn) net.PacketConn { +func (a *authChainA) PacketConn(c N.EnhancePacketConn) N.EnhancePacketConn { p := &authChainA{ Base: a.Base, salt: a.salt, userData: a.userData, } - return &PacketConn{PacketConn: c, Protocol: p} + return &PacketConn{EnhancePacketConn: c, Protocol: p} } func (a *authChainA) Decode(dst, src *bytes.Buffer) error { diff --git a/transport/ssr/protocol/auth_sha1_v4.go b/transport/ssr/protocol/auth_sha1_v4.go index 9e814ac2..26039181 100644 --- a/transport/ssr/protocol/auth_sha1_v4.go +++ b/transport/ssr/protocol/auth_sha1_v4.go @@ -7,6 +7,7 @@ import ( "hash/crc32" "net" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/pool" "github.com/Dreamacro/clash/transport/ssr/tools" @@ -35,7 +36,7 @@ func (a *authSHA1V4) StreamConn(c net.Conn, iv []byte) net.Conn { return &Conn{Conn: c, Protocol: p} } -func (a *authSHA1V4) PacketConn(c net.PacketConn) net.PacketConn { +func (a *authSHA1V4) PacketConn(c N.EnhancePacketConn) N.EnhancePacketConn { return c } diff --git a/transport/ssr/protocol/origin.go b/transport/ssr/protocol/origin.go index 80fdfa9a..52525a2f 100644 --- a/transport/ssr/protocol/origin.go +++ b/transport/ssr/protocol/origin.go @@ -3,6 +3,8 @@ package protocol import ( "bytes" "net" + + N "github.com/Dreamacro/clash/common/net" ) type origin struct{} @@ -13,7 +15,7 @@ func newOrigin(b *Base) Protocol { return &origin{} } func (o *origin) StreamConn(c net.Conn, iv []byte) net.Conn { return c } -func (o *origin) PacketConn(c net.PacketConn) net.PacketConn { return c } +func (o *origin) PacketConn(c N.EnhancePacketConn) N.EnhancePacketConn { return c } func (o *origin) Decode(dst, src *bytes.Buffer) error { dst.ReadFrom(src) diff --git a/transport/ssr/protocol/packet.go b/transport/ssr/protocol/packet.go index 249db70a..988ff75d 100644 --- a/transport/ssr/protocol/packet.go +++ b/transport/ssr/protocol/packet.go @@ -3,11 +3,12 @@ package protocol import ( "net" + N "github.com/Dreamacro/clash/common/net" "github.com/Dreamacro/clash/common/pool" ) type PacketConn struct { - net.PacketConn + N.EnhancePacketConn Protocol } @@ -18,12 +19,12 @@ func (c *PacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { if err != nil { return 0, err } - _, err = c.PacketConn.WriteTo(buf.Bytes(), addr) + _, err = c.EnhancePacketConn.WriteTo(buf.Bytes(), addr) return len(b), err } func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) { - n, addr, err := c.PacketConn.ReadFrom(b) + n, addr, err := c.EnhancePacketConn.ReadFrom(b) if err != nil { return n, addr, err } @@ -34,3 +35,20 @@ func (c *PacketConn) ReadFrom(b []byte) (int, net.Addr, error) { copy(b, decoded) return len(decoded), addr, nil } + +func (c *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, err error) { + data, put, addr, err = c.EnhancePacketConn.WaitReadFrom() + if err != nil { + return + } + data, err = c.DecodePacket(data) + if err != nil { + if put != nil { + put() + } + data = nil + put = nil + return + } + return +} diff --git a/transport/ssr/protocol/protocol.go b/transport/ssr/protocol/protocol.go index 5b86ecb9..1c27da48 100644 --- a/transport/ssr/protocol/protocol.go +++ b/transport/ssr/protocol/protocol.go @@ -6,6 +6,8 @@ import ( "fmt" "net" + N "github.com/Dreamacro/clash/common/net" + "github.com/zhangyunhao116/fastrand" ) @@ -22,7 +24,7 @@ var ( type Protocol interface { StreamConn(net.Conn, []byte) net.Conn - PacketConn(net.PacketConn) net.PacketConn + PacketConn(N.EnhancePacketConn) N.EnhancePacketConn Decode(dst, src *bytes.Buffer) error Encode(buf *bytes.Buffer, b []byte) error DecodePacket([]byte) ([]byte, error) diff --git a/transport/trojan/trojan.go b/transport/trojan/trojan.go index d37026c1..abe21f34 100644 --- a/transport/trojan/trojan.go +++ b/transport/trojan/trojan.go @@ -370,7 +370,9 @@ func (pc *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, er _, err = io.ReadFull(pc.Conn, data[:2+2]) // u16be length + CR LF if err != nil { - put() + if put != nil { + put() + } return nil, nil, nil, err } length := binary.BigEndian.Uint16(data) @@ -379,11 +381,15 @@ func (pc *PacketConn) WaitReadFrom() (data []byte, put func(), addr net.Addr, er data = data[:length] _, err = io.ReadFull(pc.Conn, data) if err != nil { - put() + if put != nil { + put() + } return nil, nil, nil, err } } else { - put() + if put != nil { + put() + } return nil, nil, addr, nil } diff --git a/transport/tuic/conn.go b/transport/tuic/conn.go index d46a3556..f226746d 100644 --- a/transport/tuic/conn.go +++ b/transport/tuic/conn.go @@ -205,7 +205,6 @@ func (q *quicStreamPacketConn) WaitReadFrom() (data []byte, put func(), addr net return } data = packet.DATA - put = N.NilPut addr = packet.ADDR.UDPAddr() } else { err = net.ErrClosed From 36539bb6705a213c3b75b59a1c8474c965ec2eee Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Tue, 30 May 2023 07:59:55 +0800 Subject: [PATCH 59/62] fix: sing-ss2's Reader not set buffer end --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index b203dd40..864f6121 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/mdlayher/netlink v1.7.2 github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c - github.com/metacubex/sing-shadowsocks2 v0.0.0-20230528144023-05418c94ed2d + github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a github.com/miekg/dns v1.1.54 diff --git a/go.sum b/go.sum index 25448530..75975620 100644 --- a/go.sum +++ b/go.sum @@ -100,8 +100,8 @@ github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070 h1:AT/Qfe9MvCxyrI9u github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230528144023-05418c94ed2d h1:lWbWl3pZA1x8TgYDw07jo1u5RtbBRIlxuJDV4FW0WeQ= -github.com/metacubex/sing-shadowsocks2 v0.0.0-20230528144023-05418c94ed2d/go.mod h1:jVDD4N22bDPPKA73NvB7aqdlLWiAwv8D+jx7HwhcWak= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca h1:10qc50Q1hHrfGO4NjEJpIAgHX63Y256tHE0dFCTN8J4= +github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca/go.mod h1:jVDD4N22bDPPKA73NvB7aqdlLWiAwv8D+jx7HwhcWak= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899 h1:iRfcuztp7REfmOyasSlCL/pqNWfUDMTJ2CwbGpxpeks= From 41af94ea66c2e9a4c347d70b4e63784bc79201ae Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Tue, 30 May 2023 20:21:51 +0800 Subject: [PATCH 60/62] fix: deadline reader cause panic --- common/net/deadline/packet_sing.go | 11 ++++------- go.mod | 4 ++-- go.sum | 4 ++-- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/common/net/deadline/packet_sing.go b/common/net/deadline/packet_sing.go index a3da34f4..f41f3f5b 100644 --- a/common/net/deadline/packet_sing.go +++ b/common/net/deadline/packet_sing.go @@ -53,9 +53,7 @@ FOR: if result, ok := result.(*singReadResult); ok { destination = result.destination err = result.err - buffer.Resize(result.buffer.Start(), 0) - n := copy(buffer.FreeBytes(), result.buffer.Bytes()) - buffer.Truncate(n) + n, _ := buffer.Write(result.buffer.Bytes()) result.buffer.Advance(n) if result.buffer.IsEmpty() { result.buffer.Release() @@ -85,14 +83,13 @@ FOR: } <-c.netPacketConn.resultCh - go c.pipeReadPacket(buffer.Cap(), buffer.Start()) + go c.pipeReadPacket(buffer.FreeLen()) return c.ReadPacket(buffer) } -func (c *singPacketConn) pipeReadPacket(bufLen int, bufStart int) { - buffer := buf.NewSize(bufLen) - buffer.Advance(bufStart) +func (c *singPacketConn) pipeReadPacket(pLen int) { + buffer := buf.NewSize(pLen) destination, err := c.singPacketConn.ReadPacket(buffer) result := &singReadResult{} result.destination = destination diff --git a/go.mod b/go.mod index 864f6121..3cafaabe 100644 --- a/go.mod +++ b/go.mod @@ -30,7 +30,7 @@ require ( github.com/openacid/low v0.1.21 github.com/oschwald/geoip2-golang v1.8.0 github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 - github.com/sagernet/sing v0.2.5-0.20230519030052-49166ac42700 + github.com/sagernet/sing v0.2.5-0.20230530114415-221f066dba7c github.com/sagernet/sing-mux v0.0.0-20230517134606-1ebe6bb26646 github.com/sagernet/sing-shadowtls v0.1.2-0.20230417103049-4f682e05f19b github.com/sagernet/sing-vmess v0.1.5-0.20230417103030-8c3070ae3fb3 @@ -105,6 +105,6 @@ require ( golang.org/x/tools v0.6.0 // indirect ) -replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070 +replace github.com/sagernet/sing => github.com/metacubex/sing v0.0.0-20230530121223-b768faae5c6b replace github.com/sagernet/sing-vmess => github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899 diff --git a/go.sum b/go.sum index 75975620..49d31b80 100644 --- a/go.sum +++ b/go.sum @@ -96,8 +96,8 @@ github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c h1:D62872jiuzC6b+ github.com/metacubex/gvisor v0.0.0-20230417114019-3c3ee672d60c/go.mod h1:wqEuzdImyqD2MCGE8CYRJXbB77oSEJeoSSXXdwKjnsE= github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 h1:E/sNW9tugFjoBjAkth89MHlKHRaMdo43tGQ3MOPVayQ= github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58/go.mod h1:9nOiGX6kqV3+ZbkDKdTNzdFD726QQHPH6WDb36jUSpA= -github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070 h1:AT/Qfe9MvCxyrI9uybcXcVDLDEqR6+9ZK7a7pgis9xQ= -github.com/metacubex/sing v0.0.0-20230526162852-6afe73474070/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= +github.com/metacubex/sing v0.0.0-20230530121223-b768faae5c6b h1:Bw4j3ktf5vivi5qm/ZQGtyRAgybRKSGJaMV1t3rtC+I= +github.com/metacubex/sing v0.0.0-20230530121223-b768faae5c6b/go.mod h1:Ta8nHnDLAwqySzKhGoKk4ZIB+vJ3GTKj7UPrWYvM+4w= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:LpVNvlW/xE+mR8z76xJeYZlYznZXEmU4TeWeuygYdJg= github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca h1:10qc50Q1hHrfGO4NjEJpIAgHX63Y256tHE0dFCTN8J4= From 1120c8185d11c884cab88b61ca8c9412a4080f19 Mon Sep 17 00:00:00 2001 From: Larvan2 <78135608+Larvan2@users.noreply.github.com> Date: Tue, 30 May 2023 20:52:28 +0800 Subject: [PATCH 61/62] chore: Use API to create windows firewall rule --- adapter/outbound/wireguard.go | 2 +- go.mod | 9 +++++---- go.sum | 19 ++++++++++--------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/adapter/outbound/wireguard.go b/adapter/outbound/wireguard.go index 38b5aa02..c12321f3 100644 --- a/adapter/outbound/wireguard.go +++ b/adapter/outbound/wireguard.go @@ -67,7 +67,7 @@ type WireGuardPeerOption struct { PublicKey string `proxy:"public-key,omitempty"` PreSharedKey string `proxy:"pre-shared-key,omitempty"` Reserved []uint8 `proxy:"reserved,omitempty"` - AllowedIPs []string `proxy:"allowed_ips,omitempty"` + AllowedIPs []string `proxy:"allowed-ips,omitempty"` } type wgSingDialer struct { diff --git a/go.mod b/go.mod index 3cafaabe..b79f8e70 100644 --- a/go.mod +++ b/go.mod @@ -23,7 +23,7 @@ require ( github.com/metacubex/quic-go v0.33.3-0.20230510010206-687b537b6a58 github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca - github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 + github.com/metacubex/sing-tun v0.1.5-0.20230530125750-171afb2dfd8e github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a github.com/miekg/dns v1.1.54 github.com/mroth/weightedrand/v2 v2.0.1 @@ -69,7 +69,7 @@ require ( github.com/go-ole/go-ole v1.2.6 // 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.0.1 // indirect + github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect github.com/hashicorp/yamux v0.1.1 // indirect @@ -89,6 +89,7 @@ require ( github.com/quic-go/qtls-go1-20 v0.1.1 // indirect github.com/sagernet/go-tun2socks v1.16.12-0.20220818015926-16cb67876a61 // indirect github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 // indirect + github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 // indirect github.com/shoenig/go-m1cpu v0.1.5 // indirect github.com/sina-ghaderi/poly1305 v0.0.0-20220724002748-c5926b03988b // indirect github.com/sina-ghaderi/rabaead v0.0.0-20220730151906-ab6e06b96e8c // indirect @@ -96,12 +97,12 @@ require ( github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/numcpus v0.6.0 // indirect github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 // indirect - github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect + github.com/vishvananda/netns v0.0.4 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect gitlab.com/yawning/bsaes.git v0.0.0-20190805113838-0a714cd429ec // indirect golang.org/x/mod v0.8.0 // indirect golang.org/x/text v0.9.0 // indirect - golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect + golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.6.0 // indirect ) diff --git a/go.sum b/go.sum index 49d31b80..11d98c03 100644 --- a/go.sum +++ b/go.sum @@ -52,8 +52,8 @@ github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+Licev github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= -github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +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/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= @@ -102,8 +102,8 @@ github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c h1:Lp github.com/metacubex/sing-shadowsocks v0.2.2-0.20230509230448-a5157cc00a1c/go.mod h1:4uQQReKMTU7KTfOykVBe/oGJ00pl38d+BYJ99+mx26s= github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca h1:10qc50Q1hHrfGO4NjEJpIAgHX63Y256tHE0dFCTN8J4= github.com/metacubex/sing-shadowsocks2 v0.0.0-20230529235701-a238874242ca/go.mod h1:jVDD4N22bDPPKA73NvB7aqdlLWiAwv8D+jx7HwhcWak= -github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376 h1:zKNsbFQyleMFAP7NJYRew9sEMJuniuODH3V0FdWnEtk= -github.com/metacubex/sing-tun v0.1.5-0.20230509224930-30065d4b6376/go.mod h1:BMfG00enVf90/CzcdX9PK3Dymgl7BZqHXJfexEyB7Cc= +github.com/metacubex/sing-tun v0.1.5-0.20230530125750-171afb2dfd8e h1:7QlJQl4S3F3YXn48fYxjymMw8HkXg9bl++hLi4ZRyCY= +github.com/metacubex/sing-tun v0.1.5-0.20230530125750-171afb2dfd8e/go.mod h1:u9onX49LZPYuIPQ7SdM64Gnins8y5wg4Cn6ZYRSxWHU= github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899 h1:iRfcuztp7REfmOyasSlCL/pqNWfUDMTJ2CwbGpxpeks= github.com/metacubex/sing-vmess v0.1.5-0.20230520082358-78b126617899/go.mod h1:RSt9rxGHllLdc5JUebkQwaqyWLx09Lqya37DlBe8CP8= github.com/metacubex/sing-wireguard v0.0.0-20230426030325-41db09ae771a h1:cWKym33Qvl6HA3hj4/YuYD8hHyqQPb47wT5cJRAPgco= @@ -159,6 +159,8 @@ github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77 h1:g6QtRWQ2d github.com/sagernet/wireguard-go v0.0.0-20230420044414-a7bac1754e77/go.mod h1:pJDdXzZIwJ+2vmnT0TKzmf8meeum+e2mTDSehw79eE0= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= +github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9 h1:rc/CcqLH3lh8n+csdOuDfP+NuykE0U6AeYSJJHKDgSg= +github.com/scjalliance/comshim v0.0.0-20230315213746-5e51f40bd3b9/go.mod h1:a/83NAfUXvEuLpmxDssAXxgUgrEy12MId3Wd7OTs76s= github.com/shirou/gopsutil/v3 v3.23.4 h1:hZwmDxZs7Ewt75DV81r4pFMqbq+di2cbt9FsQBqLD2o= github.com/shirou/gopsutil/v3 v3.23.4/go.mod h1:ZcGxyfzAMRevhUR2+cfhXDH6gQdFYE/t8j1nsU4mPI8= github.com/shoenig/go-m1cpu v0.1.5 h1:LF57Z/Fpb/WdGLjt2HZilNnmZOxg/q2bSKTQhgbrLrQ= @@ -190,8 +192,8 @@ github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYm github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923 h1:tHNk7XK9GkmKUR6Gh8gVBKXc2MVSZ4G/NnWLtzw4gNA= github.com/u-root/uio v0.0.0-20230220225925-ffce2a382923/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 h1:gga7acRE695APm9hlsSMoOoE65U4/TcqNj90mc69Rlg= -github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= +github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8= +github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM= github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3 h1:a3Y4WVjCxwoyO4E2xdNvq577tW8lkSBgyrA8E9+2NtM= github.com/xtls/go v0.0.0-20230107031059-4610f88d00f3/go.mod h1:YJTRELIWrGxR1s8xcEBgxcxBfwQfMGjdvNLTjN9XFgY= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= @@ -230,7 +232,6 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -247,8 +248,8 @@ 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.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44= -golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= From 7fa3d3aa0b8111f3f9c9305d1245b67f700f7737 Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Thu, 1 Jun 2023 12:36:53 +0800 Subject: [PATCH 62/62] chore: cleanup system dns code --- dns/system.go | 22 +++---------------- dns/system_posix.go | 27 +++++++++++++++++++++++ dns/system_windows.go | 51 +++++++++++-------------------------------- 3 files changed, 43 insertions(+), 57 deletions(-) create mode 100644 dns/system_posix.go diff --git a/dns/system.go b/dns/system.go index 2e52f90f..f5ab0efb 100644 --- a/dns/system.go +++ b/dns/system.go @@ -1,37 +1,21 @@ -//go:build !windows - package dns import ( - "fmt" - "os" - "regexp" -) - -var ( - // nameserver xxx.xxx.xxx.xxx - nameserverPattern = regexp.MustCompile(`nameserver\s+(?P\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})`) + "net" ) func loadSystemResolver() (clients []dnsClient, err error) { - content, err := os.ReadFile("/etc/resolv.conf") + nameservers, err := dnsReadConfig() if err != nil { - err = fmt.Errorf("failed to read /etc/resolv.conf: %w", err) return } - nameservers := make([]string, 0) - for _, line := range nameserverPattern.FindAllStringSubmatch(string(content), -1) { - addr := line[1] - nameservers = append(nameservers, addr) - } if len(nameservers) == 0 { - err = fmt.Errorf("no nameserver found in /etc/resolv.conf") return } servers := make([]NameServer, 0, len(nameservers)) for _, addr := range nameservers { servers = append(servers, NameServer{ - Addr: fmt.Sprintf("%s:%d", addr, 53), + Addr: net.JoinHostPort(addr, "53"), Net: "udp", }) } diff --git a/dns/system_posix.go b/dns/system_posix.go new file mode 100644 index 00000000..d486b4fb --- /dev/null +++ b/dns/system_posix.go @@ -0,0 +1,27 @@ +//go:build !windows + +package dns + +import ( + "fmt" + "os" + "regexp" +) + +var ( + // nameserver xxx.xxx.xxx.xxx + nameserverPattern = regexp.MustCompile(`nameserver\s+(?P\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})`) +) + +func dnsReadConfig() (servers []string, err error) { + content, err := os.ReadFile("/etc/resolv.conf") + if err != nil { + err = fmt.Errorf("failed to read /etc/resolv.conf: %w", err) + return + } + for _, line := range nameserverPattern.FindAllStringSubmatch(string(content), -1) { + addr := line[1] + servers = append(servers, addr) + } + return +} diff --git a/dns/system_windows.go b/dns/system_windows.go index 2e0aa237..47c1ebaa 100644 --- a/dns/system_windows.go +++ b/dns/system_windows.go @@ -3,7 +3,6 @@ package dns import ( - "fmt" "net" "os" "syscall" @@ -12,34 +11,10 @@ import ( "golang.org/x/sys/windows" ) -type dnsConfig struct { - servers []string // server addresses (in host:port form) to use -} - -func loadSystemResolver() (clients []dnsClient, err error) { - content, err := dnsReadConfig() - if err != nil { - err = fmt.Errorf("failed to read system DNS: %w", err) - } - nameservers := content.servers - if len(nameservers) == 0 { - return - } - servers := make([]NameServer, 0, len(nameservers)) - for _, addr := range nameservers { - servers = append(servers, NameServer{ - Addr: addr, - Net: "udp", - }) - } - return transform(servers, nil), nil -} - -func dnsReadConfig() (conf *dnsConfig, err error) { - conf = &dnsConfig{} +func dnsReadConfig() (servers []string, err error) { aas, err := adapterAddresses() if err != nil { - return conf, err + return } for _, aa := range aas { for dns := aa.FirstDnsServerAddress; dns != nil; dns = dns.Next { @@ -52,23 +27,23 @@ func dnsReadConfig() (conf *dnsConfig, err error) { case *syscall.SockaddrInet4: ip = net.IPv4(sa.Addr[0], sa.Addr[1], sa.Addr[2], sa.Addr[3]) case *syscall.SockaddrInet6: - //ip = make(net.IP, net.IPv6len) - //copy(ip, sa.Addr[:]) - //if ip[0] == 0xfe && ip[1] == 0xc0 { - // // Ignore these fec0/10 ones. Windows seems to - // // populate them as defaults on its misc rando - // // interfaces. - // continue - //} - continue + ip = make(net.IP, net.IPv6len) + copy(ip, sa.Addr[:]) + if ip[0] == 0xfe && ip[1] == 0xc0 { + // Ignore these fec0/10 ones. Windows seems to + // populate them as defaults on its misc rando + // interfaces. + continue + } + //continue default: // Unexpected type. continue } - conf.servers = append(conf.servers, net.JoinHostPort(ip.String(), "53")) + servers = append(servers, ip.String()) } } - return conf, nil + return } // adapterAddresses returns a list of IP adapter and address