瀏覽代碼

Merge branch 'stable' into v2

tags/v2.1.10
9seconds 4 月之前
父節點
當前提交
b854b16e1a

+ 4
- 4
.mise.toml 查看文件

1
 [tools]
1
 [tools]
2
-go = "latest"
2
+"go:golang.org/x/pkgsite/cmd/pkgsite" = "latest"
3
 "go:golang.org/x/tools/gopls" = "latest"
3
 "go:golang.org/x/tools/gopls" = "latest"
4
 "go:mvdan.cc/gofumpt" = "latest"
4
 "go:mvdan.cc/gofumpt" = "latest"
5
+go = "latest"
6
+golangci-lint = "latest"
7
+goreleaser = "latest"
5
 
8
 
6
 [vars]
9
 [vars]
7
 fuzzflags = "-fuzztime=120s"
10
 fuzzflags = "-fuzztime=120s"
21
 
24
 
22
 [tasks.lint]
25
 [tasks.lint]
23
 description = "Run linter"
26
 description = "Run linter"
24
-tools.golangci-lint = "latest"
25
 run = "golangci-lint run"
27
 run = "golangci-lint run"
26
 
28
 
27
 [tasks.test]
29
 [tasks.test]
77
 
79
 
78
 [tasks.release]
80
 [tasks.release]
79
 description = "Create release tarballs"
81
 description = "Create release tarballs"
80
-tools.goreleaser = "latest"
81
 sources = ["**/*.go", "go.mod", "go.sum", ".goreleaser.yml"]
82
 sources = ["**/*.go", "go.mod", "go.sum", ".goreleaser.yml"]
82
 run = [
83
 run = [
83
     "goreleaser --snapshot --clean",
84
     "goreleaser --snapshot --clean",
92
 
93
 
93
 [tasks.docs]
94
 [tasks.docs]
94
 description = "Run doc server"
95
 description = "Run doc server"
95
-tools."go:golang.org/x/pkgsite/cmd/pkgsite" = "latest"
96
 run = "pkgsite -http 0.0.0.0:10000"
96
 run = "pkgsite -http 0.0.0.0:10000"
97
 
97
 
98
 [tasks.fmt]
98
 [tasks.fmt]

+ 27
- 2
README.md 查看文件

10
 **If you use v1.0 or upgrade broke you proxy, please read the chapter
10
 **If you use v1.0 or upgrade broke you proxy, please read the chapter
11
 [Version 2](#version-2)**
11
 [Version 2](#version-2)**
12
 
12
 
13
+If you want to have a proxy that _supports adtag_ (possibility to promote a
14
+channel with a special Telegram bot), I recommend to use
15
+[telemt](https://github.com/telemt/telemt) project. v1 of mtg supports it
16
+but I do not see any reasonable point of using it: adtag requires communication
17
+via a fragile set of middle proxies, requires complex setup that must expose
18
+a public IPs, has lower bandwidth and latency.
19
+
20
+mtg idea is simple: minimal unbloated proxy that can handle a reasonable scale
21
+~10-20k simultaneous connections, has no user management, but ticks all
22
+checkboxes related to its main intent: provide a way to use Telegram.
23
+
13
 ## Rationale
24
 ## Rationale
14
 
25
 
15
 There are several available proxies for Telegram MTPROTO available. Here
26
 There are several available proxies for Telegram MTPROTO available. Here
18
 * [Official](https://github.com/TelegramMessenger/MTProxy)
29
 * [Official](https://github.com/TelegramMessenger/MTProxy)
19
 * [Python](https://github.com/alexbers/mtprotoproxy)
30
 * [Python](https://github.com/alexbers/mtprotoproxy)
20
 * [Erlang](https://github.com/seriyps/mtproto_proxy)
31
 * [Erlang](https://github.com/seriyps/mtproto_proxy)
32
+* [Telemt (Rust)](https://github.com/telemt/telemt)
21
 
33
 
22
 You can use any of these. They work great and all implementations have
34
 You can use any of these. They work great and all implementations have
23
 feature parity now. This includes support of adtag, replay attack
35
 feature parity now. This includes support of adtag, replay attack
40
   way of doing business I suppose. I think the only viable way is to
52
   way of doing business I suppose. I think the only viable way is to
41
   have a proxy that can be restored anywhere easily.
53
   have a proxy that can be restored anywhere easily.
42
 
54
 
55
+* **Supports proxy protocol v1/v2**
56
+
57
+  This makes integration with loadbalancers like HAProxy and ELB a first class
58
+  citizen by supporting their
59
+  [commuication protocols](https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt).
60
+
43
 * **A single secret**
61
 * **A single secret**
44
 
62
 
45
   I think that multiple secrets solve no problems and just complex
63
   I think that multiple secrets solve no problems and just complex
162
 
180
 
163
 ## Getting started
181
 ## Getting started
164
 
182
 
183
+### Download mise
184
+
185
+mtg uses [mise](https://mise.jdx.dev/) to maintain its development
186
+dependencies + replaces a make for building things. Please
187
+[install](https://mise.jdx.dev/getting-started.html) it first.
188
+
165
 ### Download a tool
189
 ### Download a tool
166
 
190
 
167
 #### Download binaries
191
 #### Download binaries
198
 ```console
222
 ```console
199
 git clone https://github.com/9seconds/mtg.git
223
 git clone https://github.com/9seconds/mtg.git
200
 cd mtg
224
 cd mtg
201
-make static
225
+mise install
226
+mise tasks run build
202
 ```
227
 ```
203
 
228
 
204
 or for the docker image:
229
 or for the docker image:
205
 
230
 
206
 ```console
231
 ```console
207
-make docker
232
+mise tasks run image
208
 ```
233
 ```
209
 
234
 
210
 ### Generate secret
235
 ### Generate secret

+ 2
- 2
events/event_stream.go 查看文件

2
 
2
 
3
 import (
3
 import (
4
 	"context"
4
 	"context"
5
-	"math/rand"
5
+	"math/rand/v2"
6
 	"runtime"
6
 	"runtime"
7
 
7
 
8
 	"github.com/9seconds/mtg/v2/mtglib"
8
 	"github.com/9seconds/mtg/v2/mtglib"
64
 		chans:     make([]chan mtglib.Event, runtime.NumCPU()),
64
 		chans:     make([]chan mtglib.Event, runtime.NumCPU()),
65
 	}
65
 	}
66
 
66
 
67
-	for i := 0; i < runtime.NumCPU(); i++ {
67
+	for i := range runtime.NumCPU() {
68
 		rv.chans[i] = make(chan mtglib.Event, 1)
68
 		rv.chans[i] = make(chan mtglib.Event, 1)
69
 
69
 
70
 		if len(observerFactories) == 1 {
70
 		if len(observerFactories) == 1 {

+ 27
- 54
events/multi_observer.go 查看文件

12
 
12
 
13
 func (m multiObserver) EventStart(evt mtglib.EventStart) {
13
 func (m multiObserver) EventStart(evt mtglib.EventStart) {
14
 	wg := &sync.WaitGroup{}
14
 	wg := &sync.WaitGroup{}
15
-	wg.Add(len(m.observers))
16
 
15
 
17
 	for _, v := range m.observers {
16
 	for _, v := range m.observers {
18
-		go func(obs Observer) {
19
-			defer wg.Done()
20
-
21
-			obs.EventStart(evt)
22
-		}(v)
17
+		wg.Go(func() {
18
+			v.EventStart(evt)
19
+		})
23
 	}
20
 	}
24
 
21
 
25
 	wg.Wait()
22
 	wg.Wait()
27
 
24
 
28
 func (m multiObserver) EventConnectedToDC(evt mtglib.EventConnectedToDC) {
25
 func (m multiObserver) EventConnectedToDC(evt mtglib.EventConnectedToDC) {
29
 	wg := &sync.WaitGroup{}
26
 	wg := &sync.WaitGroup{}
30
-	wg.Add(len(m.observers))
31
 
27
 
32
 	for _, v := range m.observers {
28
 	for _, v := range m.observers {
33
-		go func(obs Observer) {
34
-			defer wg.Done()
35
-
36
-			obs.EventConnectedToDC(evt)
37
-		}(v)
29
+		wg.Go(func() {
30
+			v.EventConnectedToDC(evt)
31
+		})
38
 	}
32
 	}
39
 
33
 
40
 	wg.Wait()
34
 	wg.Wait()
42
 
36
 
43
 func (m multiObserver) EventDomainFronting(evt mtglib.EventDomainFronting) {
37
 func (m multiObserver) EventDomainFronting(evt mtglib.EventDomainFronting) {
44
 	wg := &sync.WaitGroup{}
38
 	wg := &sync.WaitGroup{}
45
-	wg.Add(len(m.observers))
46
 
39
 
47
 	for _, v := range m.observers {
40
 	for _, v := range m.observers {
48
-		go func(obs Observer) {
49
-			defer wg.Done()
50
-
51
-			obs.EventDomainFronting(evt)
52
-		}(v)
41
+		wg.Go(func() {
42
+			v.EventDomainFronting(evt)
43
+		})
53
 	}
44
 	}
54
 
45
 
55
 	wg.Wait()
46
 	wg.Wait()
57
 
48
 
58
 func (m multiObserver) EventTraffic(evt mtglib.EventTraffic) {
49
 func (m multiObserver) EventTraffic(evt mtglib.EventTraffic) {
59
 	wg := &sync.WaitGroup{}
50
 	wg := &sync.WaitGroup{}
60
-	wg.Add(len(m.observers))
61
 
51
 
62
 	for _, v := range m.observers {
52
 	for _, v := range m.observers {
63
-		go func(obs Observer) {
64
-			defer wg.Done()
65
-
66
-			obs.EventTraffic(evt)
67
-		}(v)
53
+		wg.Go(func() {
54
+			v.EventTraffic(evt)
55
+		})
68
 	}
56
 	}
69
 
57
 
70
 	wg.Wait()
58
 	wg.Wait()
72
 
60
 
73
 func (m multiObserver) EventFinish(evt mtglib.EventFinish) {
61
 func (m multiObserver) EventFinish(evt mtglib.EventFinish) {
74
 	wg := &sync.WaitGroup{}
62
 	wg := &sync.WaitGroup{}
75
-	wg.Add(len(m.observers))
76
 
63
 
77
 	for _, v := range m.observers {
64
 	for _, v := range m.observers {
78
-		go func(obs Observer) {
79
-			defer wg.Done()
80
-
81
-			obs.EventFinish(evt)
82
-		}(v)
65
+		wg.Go(func() {
66
+			v.EventFinish(evt)
67
+		})
83
 	}
68
 	}
84
 
69
 
85
 	wg.Wait()
70
 	wg.Wait()
87
 
72
 
88
 func (m multiObserver) EventConcurrencyLimited(evt mtglib.EventConcurrencyLimited) {
73
 func (m multiObserver) EventConcurrencyLimited(evt mtglib.EventConcurrencyLimited) {
89
 	wg := &sync.WaitGroup{}
74
 	wg := &sync.WaitGroup{}
90
-	wg.Add(len(m.observers))
91
 
75
 
92
 	for _, v := range m.observers {
76
 	for _, v := range m.observers {
93
-		go func(obs Observer) {
94
-			defer wg.Done()
95
-
96
-			obs.EventConcurrencyLimited(evt)
97
-		}(v)
77
+		wg.Go(func() {
78
+			v.EventConcurrencyLimited(evt)
79
+		})
98
 	}
80
 	}
99
 
81
 
100
 	wg.Wait()
82
 	wg.Wait()
102
 
84
 
103
 func (m multiObserver) EventIPBlocklisted(evt mtglib.EventIPBlocklisted) {
85
 func (m multiObserver) EventIPBlocklisted(evt mtglib.EventIPBlocklisted) {
104
 	wg := &sync.WaitGroup{}
86
 	wg := &sync.WaitGroup{}
105
-	wg.Add(len(m.observers))
106
 
87
 
107
 	for _, v := range m.observers {
88
 	for _, v := range m.observers {
108
-		go func(obs Observer) {
109
-			defer wg.Done()
110
-
111
-			obs.EventIPBlocklisted(evt)
112
-		}(v)
89
+		wg.Go(func() {
90
+			v.EventIPBlocklisted(evt)
91
+		})
113
 	}
92
 	}
114
 
93
 
115
 	wg.Wait()
94
 	wg.Wait()
117
 
96
 
118
 func (m multiObserver) EventReplayAttack(evt mtglib.EventReplayAttack) {
97
 func (m multiObserver) EventReplayAttack(evt mtglib.EventReplayAttack) {
119
 	wg := &sync.WaitGroup{}
98
 	wg := &sync.WaitGroup{}
120
-	wg.Add(len(m.observers))
121
 
99
 
122
 	for _, v := range m.observers {
100
 	for _, v := range m.observers {
123
-		go func(obs Observer) {
124
-			defer wg.Done()
125
-
126
-			obs.EventReplayAttack(evt)
127
-		}(v)
101
+		wg.Go(func() {
102
+			v.EventReplayAttack(evt)
103
+		})
128
 	}
104
 	}
129
 
105
 
130
 	wg.Wait()
106
 	wg.Wait()
132
 
108
 
133
 func (m multiObserver) EventIPListSize(evt mtglib.EventIPListSize) {
109
 func (m multiObserver) EventIPListSize(evt mtglib.EventIPListSize) {
134
 	wg := &sync.WaitGroup{}
110
 	wg := &sync.WaitGroup{}
135
-	wg.Add(len(m.observers))
136
 
111
 
137
 	for _, v := range m.observers {
112
 	for _, v := range m.observers {
138
-		go func(obs Observer) {
139
-			defer wg.Done()
140
-
141
-			obs.EventIPListSize(evt)
142
-		}(v)
113
+		wg.Go(func() {
114
+			v.EventIPListSize(evt)
115
+		})
143
 	}
116
 	}
144
 
117
 
145
 	wg.Wait()
118
 	wg.Wait()

+ 9
- 0
example.config.toml 查看文件

23
 # Host:port pair to run proxy on.
23
 # Host:port pair to run proxy on.
24
 bind-to = "0.0.0.0:3128"
24
 bind-to = "0.0.0.0:3128"
25
 
25
 
26
+# This defines what types of traffic mtg listens to. If you are not sure,
27
+# then definitely keep it disable. Enable it only and only if incoming traffic
28
+# is coming from some sort of load-balancer like HAProxy or ELB.
29
+# https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt
30
+#
31
+# mtg uses a library that supports v1 and v2 versions of ProxyProtocol.
32
+# default value is false.
33
+# proxy-protocol-listener = false
34
+
26
 # Defines how many concurrent connections are allowed to this proxy.
35
 # Defines how many concurrent connections are allowed to this proxy.
27
 # All other incoming connections are going to be dropped.
36
 # All other incoming connections are going to be dropped.
28
 concurrency = 8192
37
 concurrency = 8192

+ 1
- 0
go.mod 查看文件

28
 
28
 
29
 require (
29
 require (
30
 	github.com/pelletier/go-toml/v2 v2.2.4
30
 	github.com/pelletier/go-toml/v2 v2.2.4
31
+	github.com/pires/go-proxyproto v0.11.0
31
 	github.com/txthinking/socks5 v0.0.0-20251011041537-5c31f201a10e
32
 	github.com/txthinking/socks5 v0.0.0-20251011041537-5c31f201a10e
32
 	github.com/yl2chen/cidranger v1.0.2
33
 	github.com/yl2chen/cidranger v1.0.2
33
 )
34
 )

+ 2
- 0
go.sum 查看文件

57
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
57
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
58
 github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
58
 github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
59
 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
59
 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
60
+github.com/pires/go-proxyproto v0.11.0 h1:gUQpS85X/VJMdUsYyEgyn59uLJvGqPhJV5YvG68wXH4=
61
+github.com/pires/go-proxyproto v0.11.0/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
60
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
62
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
61
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
63
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
62
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
64
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

+ 4
- 10
internal/cli/access.go 查看文件

61
 	}
61
 	}
62
 
62
 
63
 	wg := &sync.WaitGroup{}
63
 	wg := &sync.WaitGroup{}
64
-	wg.Add(2)
65
-
66
-	go func() {
67
-		defer wg.Done()
68
 
64
 
65
+	wg.Go(func() {
69
 		ip := a.PublicIPv4
66
 		ip := a.PublicIPv4
70
 		if ip == nil {
67
 		if ip == nil {
71
 			ip = a.getIP(ntw, "tcp4")
68
 			ip = a.getIP(ntw, "tcp4")
76
 		}
73
 		}
77
 
74
 
78
 		resp.IPv4 = a.makeURLs(conf, ip)
75
 		resp.IPv4 = a.makeURLs(conf, ip)
79
-	}()
80
-
81
-	go func() {
82
-		defer wg.Done()
83
-
76
+	})
77
+	wg.Go(func() {
84
 		ip := a.PublicIPv6
78
 		ip := a.PublicIPv6
85
 		if ip == nil {
79
 		if ip == nil {
86
 			ip = a.getIP(ntw, "tcp6")
80
 			ip = a.getIP(ntw, "tcp6")
91
 		}
85
 		}
92
 
86
 
93
 		resp.IPv6 = a.makeURLs(conf, ip)
87
 		resp.IPv6 = a.makeURLs(conf, ip)
94
-	}()
88
+	})
95
 
89
 
96
 	wg.Wait()
90
 	wg.Wait()
97
 
91
 

+ 10
- 0
internal/cli/run_proxy.go 查看文件

10
 	"github.com/9seconds/mtg/v2/antireplay"
10
 	"github.com/9seconds/mtg/v2/antireplay"
11
 	"github.com/9seconds/mtg/v2/events"
11
 	"github.com/9seconds/mtg/v2/events"
12
 	"github.com/9seconds/mtg/v2/internal/config"
12
 	"github.com/9seconds/mtg/v2/internal/config"
13
+	"github.com/9seconds/mtg/v2/internal/proxyprotocol"
13
 	"github.com/9seconds/mtg/v2/internal/utils"
14
 	"github.com/9seconds/mtg/v2/internal/utils"
14
 	"github.com/9seconds/mtg/v2/ipblocklist"
15
 	"github.com/9seconds/mtg/v2/ipblocklist"
15
 	"github.com/9seconds/mtg/v2/ipblocklist/files"
16
 	"github.com/9seconds/mtg/v2/ipblocklist/files"
17
 	"github.com/9seconds/mtg/v2/mtglib"
18
 	"github.com/9seconds/mtg/v2/mtglib"
18
 	"github.com/9seconds/mtg/v2/network"
19
 	"github.com/9seconds/mtg/v2/network"
19
 	"github.com/9seconds/mtg/v2/stats"
20
 	"github.com/9seconds/mtg/v2/stats"
21
+	"github.com/pires/go-proxyproto"
20
 	"github.com/rs/zerolog"
22
 	"github.com/rs/zerolog"
21
 	"github.com/yl2chen/cidranger"
23
 	"github.com/yl2chen/cidranger"
22
 )
24
 )
275
 		return fmt.Errorf("cannot start proxy: %w", err)
277
 		return fmt.Errorf("cannot start proxy: %w", err)
276
 	}
278
 	}
277
 
279
 
280
+	if conf.ProxyProtocolListener.Get(false) {
281
+		listener = &proxyprotocol.ListenerAdapter{
282
+			Listener: proxyproto.Listener{
283
+				Listener: listener,
284
+			},
285
+		}
286
+	}
287
+
278
 	ctx := utils.RootContext()
288
 	ctx := utils.RootContext()
279
 
289
 
280
 	go proxy.Serve(listener) //nolint: errcheck
290
 	go proxy.Serve(listener) //nolint: errcheck

+ 1
- 0
internal/config/config.go 查看文件

25
 	AllowFallbackOnUnknownDC TypeBool        `json:"allowFallbackOnUnknownDc"`
25
 	AllowFallbackOnUnknownDC TypeBool        `json:"allowFallbackOnUnknownDc"`
26
 	Secret                   mtglib.Secret   `json:"secret"`
26
 	Secret                   mtglib.Secret   `json:"secret"`
27
 	BindTo                   TypeHostPort    `json:"bindTo"`
27
 	BindTo                   TypeHostPort    `json:"bindTo"`
28
+	ProxyProtocolListener    TypeBool        `json:"proxyProtocolListener"`
28
 	PreferIP                 TypePreferIP    `json:"preferIp"`
29
 	PreferIP                 TypePreferIP    `json:"preferIp"`
29
 	DomainFrontingPort       TypePort        `json:"domainFrontingPort"`
30
 	DomainFrontingPort       TypePort        `json:"domainFrontingPort"`
30
 	TolerateTimeSkewness     TypeDuration    `json:"tolerateTimeSkewness"`
31
 	TolerateTimeSkewness     TypeDuration    `json:"tolerateTimeSkewness"`

+ 1
- 0
internal/config/parse.go 查看文件

13
 	AllowFallbackOnUnknownDC bool   `toml:"allow-fallback-on-unknown-dc" json:"allowFallbackOnUnknownDc,omitempty"`
13
 	AllowFallbackOnUnknownDC bool   `toml:"allow-fallback-on-unknown-dc" json:"allowFallbackOnUnknownDc,omitempty"`
14
 	Secret                   string `toml:"secret" json:"secret"`
14
 	Secret                   string `toml:"secret" json:"secret"`
15
 	BindTo                   string `toml:"bind-to" json:"bindTo"`
15
 	BindTo                   string `toml:"bind-to" json:"bindTo"`
16
+	ProxyProtocolListener    bool   `toml:"proxy-protocol-listener" json:"proxyProtocolListener"`
16
 	PreferIP                 string `toml:"prefer-ip" json:"preferIp,omitempty"`
17
 	PreferIP                 string `toml:"prefer-ip" json:"preferIp,omitempty"`
17
 	DomainFrontingPort       uint   `toml:"domain-fronting-port" json:"domainFrontingPort,omitempty"`
18
 	DomainFrontingPort       uint   `toml:"domain-fronting-port" json:"domainFrontingPort,omitempty"`
18
 	TolerateTimeSkewness     string `toml:"tolerate-time-skewness" json:"tolerateTimeSkewness,omitempty"`
19
 	TolerateTimeSkewness     string `toml:"tolerate-time-skewness" json:"tolerateTimeSkewness,omitempty"`

+ 2
- 2
internal/config/type_bool_test.go 查看文件

20
 }
20
 }
21
 
21
 
22
 func (suite *TypeBoolTestSuite) TestUnmarshalFail() {
22
 func (suite *TypeBoolTestSuite) TestUnmarshalFail() {
23
-	testData := []interface{}{
23
+	testData := []any{
24
 		"",
24
 		"",
25
 		"np",
25
 		"np",
26
 		"нет",
26
 		"нет",
29
 	}
29
 	}
30
 
30
 
31
 	for _, v := range testData {
31
 	for _, v := range testData {
32
-		data, err := json.Marshal(map[string]interface{}{
32
+		data, err := json.Marshal(map[string]any{
33
 			"value": v,
33
 			"value": v,
34
 		})
34
 		})
35
 		suite.NoError(err)
35
 		suite.NoError(err)

+ 20
- 0
internal/proxyprotocol/adapter.go 查看文件

1
+package proxyprotocol
2
+
3
+import (
4
+	"net"
5
+
6
+	"github.com/pires/go-proxyproto"
7
+)
8
+
9
+type ListenerAdapter struct {
10
+	proxyproto.Listener
11
+}
12
+
13
+func (l *ListenerAdapter) Accept() (net.Conn, error) {
14
+	conn, err := l.Listener.Accept()
15
+	if err != nil {
16
+		return nil, err
17
+	}
18
+
19
+	return connWrapper{conn.(*proxyproto.Conn)}, nil
20
+}

+ 25
- 0
internal/proxyprotocol/conn.go 查看文件

1
+package proxyprotocol
2
+
3
+import "github.com/pires/go-proxyproto"
4
+
5
+type connWrapper struct {
6
+	*proxyproto.Conn
7
+}
8
+
9
+func (c connWrapper) CloseRead() error {
10
+	tcpConn, ok := c.TCPConn()
11
+	if !ok {
12
+		panic("we support only tcp connections")
13
+	}
14
+
15
+	return tcpConn.CloseRead()
16
+}
17
+
18
+func (c connWrapper) CloseWrite() error {
19
+	tcpConn, ok := c.TCPConn()
20
+	if !ok {
21
+		panic("we support only tcp connections")
22
+	}
23
+
24
+	return tcpConn.CloseWrite()
25
+}

+ 4
- 7
ipblocklist/firehol.go 查看文件

112
 	defer cancel()
112
 	defer cancel()
113
 
113
 
114
 	wg := &sync.WaitGroup{}
114
 	wg := &sync.WaitGroup{}
115
-	wg.Add(len(f.blocklists))
116
 
115
 
117
 	mutex := &sync.Mutex{}
116
 	mutex := &sync.Mutex{}
118
 	ranger := cidranger.NewPCTrieRanger()
117
 	ranger := cidranger.NewPCTrieRanger()
119
 
118
 
120
 	for _, v := range f.blocklists {
119
 	for _, v := range f.blocklists {
121
-		go func(file files.File) {
122
-			defer wg.Done()
120
+		wg.Go(func() {
121
+			logger := f.logger.BindStr("filename", v.String())
123
 
122
 
124
-			logger := f.logger.BindStr("filename", file.String())
125
-
126
-			fileContent, err := file.Open(ctx)
123
+			fileContent, err := v.Open(ctx)
127
 			if err != nil {
124
 			if err != nil {
128
 				logger.WarningError("update has failed", err)
125
 				logger.WarningError("update has failed", err)
129
 
126
 
135
 			if err := f.updateFromFile(mutex, ranger, bufio.NewScanner(fileContent)); err != nil {
132
 			if err := f.updateFromFile(mutex, ranger, bufio.NewScanner(fileContent)); err != nil {
136
 				logger.WarningError("update has failed", err)
133
 				logger.WarningError("update has failed", err)
137
 			}
134
 			}
138
-		}(v)
135
+		})
139
 	}
136
 	}
140
 
137
 
141
 	wg.Wait()
138
 	wg.Wait()

+ 1
- 1
logger/init.go 查看文件

8
 // commonly used by many 3pp tools. While mtglib itself does not need it, it is
8
 // commonly used by many 3pp tools. While mtglib itself does not need it, it is
9
 // always a good idea to support it and have a transient end to end logging.
9
 // always a good idea to support it and have a transient end to end logging.
10
 type StdLikeLogger interface {
10
 type StdLikeLogger interface {
11
-	Printf(format string, args ...interface{})
11
+	Printf(format string, args ...any)
12
 }
12
 }

+ 1
- 1
logger/noop.go 查看文件

8
 func (n noopLogger) BindInt(_ string, _ int) mtglib.Logger { return n }
8
 func (n noopLogger) BindInt(_ string, _ int) mtglib.Logger { return n }
9
 func (n noopLogger) BindStr(_, _ string) mtglib.Logger     { return n }
9
 func (n noopLogger) BindStr(_, _ string) mtglib.Logger     { return n }
10
 func (n noopLogger) BindJSON(_, _ string) mtglib.Logger    { return n }
10
 func (n noopLogger) BindJSON(_, _ string) mtglib.Logger    { return n }
11
-func (n noopLogger) Printf(_ string, _ ...interface{})     {}
11
+func (n noopLogger) Printf(_ string, _ ...any)             {}
12
 func (n noopLogger) Info(_ string)                         {}
12
 func (n noopLogger) Info(_ string)                         {}
13
 func (n noopLogger) Warning(_ string)                      {}
13
 func (n noopLogger) Warning(_ string)                      {}
14
 func (n noopLogger) Debug(_ string)                        {}
14
 func (n noopLogger) Debug(_ string)                        {}

+ 1
- 1
logger/zerolog.go 查看文件

78
 	}
78
 	}
79
 }
79
 }
80
 
80
 
81
-func (z *zeroLogContext) Printf(format string, args ...interface{}) {
81
+func (z *zeroLogContext) Printf(format string, args ...any) {
82
 	z.Debug(fmt.Sprintf(format, args...))
82
 	z.Debug(fmt.Sprintf(format, args...))
83
 }
83
 }
84
 
84
 

+ 23
- 1
mise.lock 查看文件

7
 "platforms.macos-x64" = { checksum = "sha256:1ca28b7703cbea05a65b2a1d92d6b308610ef92f8824578a0874f2e60c9d5a22", url = "https://dl.google.com/go/go1.26.0.darwin-amd64.tar.gz"}
7
 "platforms.macos-x64" = { checksum = "sha256:1ca28b7703cbea05a65b2a1d92d6b308610ef92f8824578a0874f2e60c9d5a22", url = "https://dl.google.com/go/go1.26.0.darwin-amd64.tar.gz"}
8
 "platforms.windows-x64" = { checksum = "sha256:9bbe0fc64236b2b51f6255c05c4232532b8ecc0e6d2e00950bd3021d8a4d07d4", url = "https://dl.google.com/go/go1.26.0.windows-amd64.zip"}
8
 "platforms.windows-x64" = { checksum = "sha256:9bbe0fc64236b2b51f6255c05c4232532b8ecc0e6d2e00950bd3021d8a4d07d4", url = "https://dl.google.com/go/go1.26.0.windows-amd64.zip"}
9
 
9
 
10
+[[tools."go:golang.org/x/pkgsite/cmd/pkgsite"]]
11
+version = "latest"
12
+backend = "go:golang.org/x/pkgsite/cmd/pkgsite"
13
+
10
 [[tools."go:golang.org/x/tools/gopls"]]
14
 [[tools."go:golang.org/x/tools/gopls"]]
11
-version = "0.21.0"
15
+version = "0.21.1"
12
 backend = "go:golang.org/x/tools/gopls"
16
 backend = "go:golang.org/x/tools/gopls"
13
 
17
 
14
 [[tools."go:mvdan.cc/gofumpt"]]
18
 [[tools."go:mvdan.cc/gofumpt"]]
15
 version = "0.9.2"
19
 version = "0.9.2"
16
 backend = "go:mvdan.cc/gofumpt"
20
 backend = "go:mvdan.cc/gofumpt"
21
+
22
+[[tools.golangci-lint]]
23
+version = "2.10.1"
24
+backend = "aqua:golangci/golangci-lint"
25
+"platforms.linux-arm64" = { checksum = "sha256:6652b42ae02915eb2f9cb2a2e0cac99514c8eded8388d88ae3e06e1a52c00de8", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-linux-arm64.tar.gz"}
26
+"platforms.linux-x64" = { checksum = "sha256:dfa775874cf0561b404a02a8f4481fc69b28091da95aa697259820d429b09c99", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-linux-amd64.tar.gz"}
27
+"platforms.macos-arm64" = { checksum = "sha256:03bfadf67e52b441b7ec21305e501c717df93c959836d66c7f97312654acb297", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-darwin-arm64.tar.gz"}
28
+"platforms.macos-x64" = { checksum = "sha256:66fb0da81b8033b477f97eea420d4b46b230ca172b8bb87c6610109f3772b6b6", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-darwin-amd64.tar.gz"}
29
+"platforms.windows-x64" = { checksum = "sha256:c60c87695e79db8e320f0e5be885059859de52bb5ee5f11be5577828570bc2a3", url = "https://github.com/golangci/golangci-lint/releases/download/v2.10.1/golangci-lint-2.10.1-windows-amd64.zip"}
30
+
31
+[[tools.goreleaser]]
32
+version = "2.13.3"
33
+backend = "aqua:goreleaser/goreleaser"
34
+"platforms.linux-arm64" = { checksum = "sha256:156656d0f874542d618568bd50afd3d33ced2e8aab2c60cc7c21e1b9fa52031e", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Linux_arm64.tar.gz"}
35
+"platforms.linux-x64" = { checksum = "sha256:4b66f2f78f78561330350651ade557b70328664718490f37834749073af21d20", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Linux_x86_64.tar.gz"}
36
+"platforms.macos-arm64" = { checksum = "sha256:5516c37779efb3935d5b213cda3b0b9025ae94ddbcb51df6919acbcdef4194b0", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Darwin_all.tar.gz"}
37
+"platforms.macos-x64" = { checksum = "sha256:5516c37779efb3935d5b213cda3b0b9025ae94ddbcb51df6919acbcdef4194b0", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Darwin_all.tar.gz"}
38
+"platforms.windows-x64" = { checksum = "sha256:c5586c4ed749ca358ad61ed73ee4b8039cfa68daae8c23e69fb086d549dfb31d", url = "https://github.com/goreleaser/goreleaser/releases/download/v2.13.3/goreleaser_Windows_x86_64.zip"}

+ 1
- 1
mtglib/init.go 查看文件

249
 	BindJSON(name, value string) Logger
249
 	BindJSON(name, value string) Logger
250
 
250
 
251
 	// Printf is to support log.Logger behavior.
251
 	// Printf is to support log.Logger behavior.
252
-	Printf(format string, args ...interface{})
252
+	Printf(format string, args ...any)
253
 
253
 
254
 	// Info puts a message about some normal situation.
254
 	// Info puts a message about some normal situation.
255
 	Info(msg string)
255
 	Info(msg string)

+ 11
- 11
mtglib/init_internal_test.go 查看文件

8
 
8
 
9
 type NoopLogger struct{}
9
 type NoopLogger struct{}
10
 
10
 
11
-func (n NoopLogger) Named(_ string) Logger             { return n }
12
-func (n NoopLogger) BindInt(_ string, _ int) Logger    { return n }
13
-func (n NoopLogger) BindStr(_, _ string) Logger        { return n }
14
-func (n NoopLogger) BindJSON(_, _ string) Logger       { return n }
15
-func (n NoopLogger) Printf(_ string, _ ...interface{}) {}
16
-func (n NoopLogger) Info(_ string)                     {}
17
-func (n NoopLogger) Warning(_ string)                  {}
18
-func (n NoopLogger) Debug(_ string)                    {}
19
-func (n NoopLogger) InfoError(_ string, _ error)       {}
20
-func (n NoopLogger) WarningError(_ string, _ error)    {}
21
-func (n NoopLogger) DebugError(_ string, _ error)      {}
11
+func (n NoopLogger) Named(_ string) Logger          { return n }
12
+func (n NoopLogger) BindInt(_ string, _ int) Logger { return n }
13
+func (n NoopLogger) BindStr(_, _ string) Logger     { return n }
14
+func (n NoopLogger) BindJSON(_, _ string) Logger    { return n }
15
+func (n NoopLogger) Printf(_ string, _ ...any)      {}
16
+func (n NoopLogger) Info(_ string)                  {}
17
+func (n NoopLogger) Warning(_ string)               {}
18
+func (n NoopLogger) Debug(_ string)                 {}
19
+func (n NoopLogger) InfoError(_ string, _ error)    {}
20
+func (n NoopLogger) WarningError(_ string, _ error) {}
21
+func (n NoopLogger) DebugError(_ string, _ error)   {}
22
 
22
 
23
 type EventStreamMock struct {
23
 type EventStreamMock struct {
24
 	mock.Mock
24
 	mock.Mock

+ 1
- 1
mtglib/internal/faketls/client_hello.go 查看文件

76
 
76
 
77
 	computedRandom := mac.Sum(nil)
77
 	computedRandom := mac.Sum(nil)
78
 
78
 
79
-	for i := 0; i < RandomLen; i++ {
79
+	for i := range RandomLen {
80
 		computedRandom[i] ^= hello.Random[i]
80
 		computedRandom[i] ^= hello.Random[i]
81
 	}
81
 	}
82
 
82
 

+ 2
- 2
mtglib/internal/faketls/conn.go 查看文件

3
 import (
3
 import (
4
 	"bytes"
4
 	"bytes"
5
 	"fmt"
5
 	"fmt"
6
-	"math/rand"
6
+	"math/rand/v2"
7
 
7
 
8
 	"github.com/9seconds/mtg/v2/essentials"
8
 	"github.com/9seconds/mtg/v2/essentials"
9
 	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
9
 	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
53
 	lenP := len(p)
53
 	lenP := len(p)
54
 
54
 
55
 	for len(p) > 0 {
55
 	for len(p) > 0 {
56
-		chunkSize := rand.Intn(record.TLSMaxRecordSize)
56
+		chunkSize := rand.IntN(record.TLSMaxRecordSize)
57
 		if chunkSize > len(p) || chunkSize == 0 {
57
 		if chunkSize > len(p) || chunkSize == 0 {
58
 			chunkSize = len(p)
58
 			chunkSize = len(p)
59
 		}
59
 		}

+ 2
- 2
mtglib/internal/faketls/conn_test.go 查看文件

2
 
2
 
3
 import (
3
 import (
4
 	"bytes"
4
 	"bytes"
5
+	"crypto/rand"
5
 	"errors"
6
 	"errors"
6
 	"io"
7
 	"io"
7
-	"math/rand"
8
 	"testing"
8
 	"testing"
9
 
9
 
10
 	"github.com/9seconds/mtg/v2/internal/testlib"
10
 	"github.com/9seconds/mtg/v2/internal/testlib"
123
 	suite.connMock.On("Write", mock.Anything).Return(0, nil)
123
 	suite.connMock.On("Write", mock.Anything).Return(0, nil)
124
 
124
 
125
 	dataToRec := make([]byte, record.TLSMaxRecordSize*2)
125
 	dataToRec := make([]byte, record.TLSMaxRecordSize*2)
126
-	rand.Read(dataToRec) //nolint: staticcheck
126
+	rand.Read(dataToRec) //nolint: staticcheck, errcheck
127
 
127
 
128
 	n, err := suite.c.Write(dataToRec)
128
 	n, err := suite.c.Write(dataToRec)
129
 	suite.NoError(err)
129
 	suite.NoError(err)

+ 1
- 1
mtglib/internal/faketls/pools.go 查看文件

6
 )
6
 )
7
 
7
 
8
 var bytesBufferPool = sync.Pool{
8
 var bytesBufferPool = sync.Pool{
9
-	New: func() interface{} {
9
+	New: func() any {
10
 		return &bytes.Buffer{}
10
 		return &bytes.Buffer{}
11
 	},
11
 	},
12
 }
12
 }

+ 1
- 1
mtglib/internal/faketls/record/pools.go 查看文件

5
 )
5
 )
6
 
6
 
7
 var recordPool = sync.Pool{
7
 var recordPool = sync.Pool{
8
-	New: func() interface{} {
8
+	New: func() any {
9
 		return &Record{}
9
 		return &Record{}
10
 	},
10
 	},
11
 }
11
 }

+ 2
- 2
mtglib/internal/faketls/welcome.go 查看文件

6
 	"crypto/sha256"
6
 	"crypto/sha256"
7
 	"encoding/binary"
7
 	"encoding/binary"
8
 	"io"
8
 	"io"
9
-	mrand "math/rand"
9
+	mrand "math/rand/v2"
10
 
10
 
11
 	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
11
 	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
12
 	"golang.org/x/crypto/curve25519"
12
 	"golang.org/x/crypto/curve25519"
36
 	rec.Type = record.TypeApplicationData
36
 	rec.Type = record.TypeApplicationData
37
 	rec.Version = record.Version12
37
 	rec.Version = record.Version12
38
 
38
 
39
-	if _, err := io.CopyN(&rec.Payload, rand.Reader, int64(1024+mrand.Intn(3092))); err != nil {
39
+	if _, err := io.CopyN(&rec.Payload, rand.Reader, int64(1024+mrand.IntN(3092))); err != nil {
40
 		panic(err)
40
 		panic(err)
41
 	}
41
 	}
42
 
42
 

+ 1
- 1
mtglib/internal/faketls/welcome_test.go 查看文件

3
 import (
3
 import (
4
 	"bytes"
4
 	"bytes"
5
 	"crypto/hmac"
5
 	"crypto/hmac"
6
+	"crypto/rand"
6
 	"crypto/sha256"
7
 	"crypto/sha256"
7
-	"math/rand"
8
 	"testing"
8
 	"testing"
9
 	"time"
9
 	"time"
10
 
10
 

+ 1
- 1
mtglib/internal/obfuscated2/handshake_frame.go 查看文件

63
 func (h *handshakeFrame) invert() handshakeFrame {
63
 func (h *handshakeFrame) invert() handshakeFrame {
64
 	copyFrame := *h
64
 	copyFrame := *h
65
 
65
 
66
-	for i := 0; i < handshakeFrameLenKey+handshakeFrameLenIV; i++ {
66
+	for i := range handshakeFrameLenKey + handshakeFrameLenIV {
67
 		copyFrame.data[handshakeFrameOffsetKey+i] = h.data[handshakeFrameOffsetConnectionType-1-i]
67
 		copyFrame.data[handshakeFrameOffsetKey+i] = h.data[handshakeFrameOffsetConnectionType-1-i]
68
 	}
68
 	}
69
 
69
 

+ 1
- 1
mtglib/internal/obfuscated2/init_test.go 查看文件

117
 
117
 
118
 	serverEncryptedReverted := make([]byte, len(serverEncrypted))
118
 	serverEncryptedReverted := make([]byte, len(serverEncrypted))
119
 
119
 
120
-	for i := 0; i < 32+16; i++ {
120
+	for i := range 32 + 16 {
121
 		serverEncryptedReverted[8+i] = serverEncrypted[8+32+16-1-i]
121
 		serverEncryptedReverted[8+i] = serverEncrypted[8+32+16-1-i]
122
 	}
122
 	}
123
 
123
 

+ 2
- 2
mtglib/internal/obfuscated2/pools.go 查看文件

9
 
9
 
10
 var (
10
 var (
11
 	sha256HasherPool = sync.Pool{
11
 	sha256HasherPool = sync.Pool{
12
-		New: func() interface{} {
12
+		New: func() any {
13
 			return sha256.New()
13
 			return sha256.New()
14
 		},
14
 		},
15
 	}
15
 	}
16
 	bytesBufferPool = sync.Pool{
16
 	bytesBufferPool = sync.Pool{
17
-		New: func() interface{} {
17
+		New: func() any {
18
 			return &bytes.Buffer{}
18
 			return &bytes.Buffer{}
19
 		},
19
 		},
20
 	}
20
 	}

+ 1
- 1
mtglib/internal/relay/init.go 查看文件

5
 )
5
 )
6
 
6
 
7
 type Logger interface {
7
 type Logger interface {
8
-	Printf(msg string, args ...interface{})
8
+	Printf(msg string, args ...any)
9
 }
9
 }

+ 1
- 1
mtglib/internal/relay/init_test.go 查看文件

2
 
2
 
3
 type loggerMock struct{}
3
 type loggerMock struct{}
4
 
4
 
5
-func (l loggerMock) Printf(format string, args ...interface{}) {}
5
+func (l loggerMock) Printf(format string, args ...any) {}

+ 1
- 1
mtglib/internal/relay/pools.go 查看文件

3
 import "sync"
3
 import "sync"
4
 
4
 
5
 var copyBufferPool = sync.Pool{
5
 var copyBufferPool = sync.Pool{
6
-	New: func() interface{} {
6
+	New: func() any {
7
 		rv := make([]byte, copyBufferSize)
7
 		rv := make([]byte, copyBufferSize)
8
 
8
 
9
 		return &rv
9
 		return &rv

+ 1
- 1
mtglib/proxy.go 查看文件

323
 	}
323
 	}
324
 
324
 
325
 	pool, err := ants.NewPoolWithFunc(opts.getConcurrency(),
325
 	pool, err := ants.NewPoolWithFunc(opts.getConcurrency(),
326
-		func(arg interface{}) {
326
+		func(arg any) {
327
 			proxy.ServeConn(arg.(essentials.Conn)) //nolint: forcetypeassert
327
 			proxy.ServeConn(arg.(essentials.Conn)) //nolint: forcetypeassert
328
 		},
328
 		},
329
 		ants.WithLogger(opts.getLogger("ants")),
329
 		ants.WithLogger(opts.getLogger("ants")),

+ 1
- 1
mtglib/stream_context.go 查看文件

32
 	return s.ctx.Err() //nolint: wrapcheck
32
 	return s.ctx.Err() //nolint: wrapcheck
33
 }
33
 }
34
 
34
 
35
-func (s *streamContext) Value(key interface{}) interface{} {
35
+func (s *streamContext) Value(key any) any {
36
 	return s.ctx.Value(key)
36
 	return s.ctx.Value(key)
37
 }
37
 }
38
 
38
 

+ 8
- 11
network/circuit_breaker_internal_test.go 查看文件

52
 		Return(suite.connMock, nil)
52
 		Return(suite.connMock, nil)
53
 
53
 
54
 	wg := &sync.WaitGroup{}
54
 	wg := &sync.WaitGroup{}
55
-	wg.Add(5)
56
-
57
-	go func() {
58
-		wg.Wait()
59
-		suite.ctxCancel()
60
-	}()
61
-
62
-	for i := 0; i < 5; i++ {
63
-		go func() {
64
-			defer wg.Done()
65
 
55
 
56
+	for range 5 {
57
+		wg.Go(func() {
66
 			conn, err := suite.d.DialContext(suite.ctx, "tcp", "127.0.0.1")
58
 			conn, err := suite.d.DialContext(suite.ctx, "tcp", "127.0.0.1")
67
 
59
 
68
 			suite.mutex.Lock()
60
 			suite.mutex.Lock()
70
 
62
 
71
 			suite.NoError(err)
63
 			suite.NoError(err)
72
 			suite.Equal("127.0.0.1:3128", conn.RemoteAddr().String())
64
 			suite.Equal("127.0.0.1:3128", conn.RemoteAddr().String())
73
-		}()
65
+		})
74
 	}
66
 	}
75
 
67
 
68
+	go func() {
69
+		wg.Wait()
70
+		suite.ctxCancel()
71
+	}()
72
+
76
 	suite.Eventually(func() bool {
73
 	suite.Eventually(func() bool {
77
 		_, ok := <-suite.ctx.Done()
74
 		_, ok := <-suite.ctx.Done()
78
 
75
 

+ 2
- 2
network/load_balanced_socks5.go 查看文件

3
 import (
3
 import (
4
 	"context"
4
 	"context"
5
 	"fmt"
5
 	"fmt"
6
-	"math/rand"
6
+	"math/rand/v2"
7
 	"net/url"
7
 	"net/url"
8
 
8
 
9
 	"github.com/9seconds/mtg/v2/essentials"
9
 	"github.com/9seconds/mtg/v2/essentials"
19
 
19
 
20
 func (l loadBalancedSocks5Dialer) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
20
 func (l loadBalancedSocks5Dialer) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
21
 	length := len(l.dialers)
21
 	length := len(l.dialers)
22
-	start := rand.Intn(length)
22
+	start := rand.IntN(length)
23
 	moved := false
23
 	moved := false
24
 
24
 
25
 	for i := start; i != start || !moved; i = (i + 1) % length {
25
 	for i := start; i != start || !moved; i = (i + 1) % length {

+ 1
- 1
network/load_balanced_socks5_test.go 查看文件

64
 	})
64
 	})
65
 	suite.NoError(err)
65
 	suite.NoError(err)
66
 
66
 
67
-	for i := 0; i < network.ProxyDialerOpenThreshold*2; i++ {
67
+	for range network.ProxyDialerOpenThreshold * 2 {
68
 		_, err = lbDialer.Dial("tcp", "127.1.1.1:80")
68
 		_, err = lbDialer.Dial("tcp", "127.1.1.1:80")
69
 		suite.True(errors.Is(err, network.ErrCannotDialWithAllProxies))
69
 		suite.True(errors.Is(err, network.ErrCannotDialWithAllProxies))
70
 	}
70
 	}

+ 5
- 13
network/network.go 查看文件

3
 import (
3
 import (
4
 	"context"
4
 	"context"
5
 	"fmt"
5
 	"fmt"
6
-	"math/rand"
6
+	"math/rand/v2"
7
 	"net"
7
 	"net"
8
 	"net/http"
8
 	"net/http"
9
 	"sync"
9
 	"sync"
81
 
81
 
82
 	switch protocol {
82
 	switch protocol {
83
 	case "tcp", "tcp4":
83
 	case "tcp", "tcp4":
84
-		wg.Add(1)
85
-
86
-		go func() {
87
-			defer wg.Done()
88
-
84
+		wg.Go(func() {
89
 			resolved := n.dns.LookupA(address)
85
 			resolved := n.dns.LookupA(address)
90
 
86
 
91
 			mutex.Lock()
87
 			mutex.Lock()
92
 			ips = append(ips, resolved...)
88
 			ips = append(ips, resolved...)
93
 			mutex.Unlock()
89
 			mutex.Unlock()
94
-		}()
90
+		})
95
 	}
91
 	}
96
 
92
 
97
 	switch protocol {
93
 	switch protocol {
98
 	case "tcp", "tcp6":
94
 	case "tcp", "tcp6":
99
-		wg.Add(1)
100
-
101
-		go func() {
102
-			defer wg.Done()
103
-
95
+		wg.Go(func() {
104
 			resolved := n.dns.LookupAAAA(address)
96
 			resolved := n.dns.LookupAAAA(address)
105
 
97
 
106
 			mutex.Lock()
98
 			mutex.Lock()
107
 			ips = append(ips, resolved...)
99
 			ips = append(ips, resolved...)
108
 			mutex.Unlock()
100
 			mutex.Unlock()
109
-		}()
101
+		})
110
 	}
102
 	}
111
 
103
 
112
 	wg.Wait()
104
 	wg.Wait()

+ 1
- 1
stats/pools.go 查看文件

3
 import "sync"
3
 import "sync"
4
 
4
 
5
 var streamInfoPool = sync.Pool{
5
 var streamInfoPool = sync.Pool{
6
-	New: func() interface{} {
6
+	New: func() any {
7
 		return &streamInfo{
7
 		return &streamInfo{
8
 			tags: make(map[string]string),
8
 			tags: make(map[string]string),
9
 		}
9
 		}

Loading…
取消
儲存