Преглед на файлове

Merge branch 'master' into stable

tags/v2.1.10^2
9seconds преди 2 месеца
родител
ревизия
f4b296d1e0
променени са 41 файла, в които са добавени 213 реда и са изтрити 144 реда
  1. 4
    4
      .mise.toml
  2. 27
    2
      README.md
  3. 2
    2
      events/event_stream.go
  4. 27
    54
      events/multi_observer.go
  5. 9
    0
      example.config.toml
  6. 1
    0
      go.mod
  7. 2
    0
      go.sum
  8. 4
    10
      internal/cli/access.go
  9. 10
    0
      internal/cli/run_proxy.go
  10. 1
    0
      internal/config/config.go
  11. 1
    0
      internal/config/parse.go
  12. 2
    2
      internal/config/type_bool_test.go
  13. 20
    0
      internal/proxyprotocol/adapter.go
  14. 25
    0
      internal/proxyprotocol/conn.go
  15. 4
    7
      ipblocklist/firehol.go
  16. 1
    1
      logger/init.go
  17. 1
    1
      logger/noop.go
  18. 1
    1
      logger/zerolog.go
  19. 23
    1
      mise.lock
  20. 1
    1
      mtglib/init.go
  21. 11
    11
      mtglib/init_internal_test.go
  22. 1
    1
      mtglib/internal/faketls/client_hello.go
  23. 2
    2
      mtglib/internal/faketls/conn.go
  24. 2
    2
      mtglib/internal/faketls/conn_test.go
  25. 1
    1
      mtglib/internal/faketls/pools.go
  26. 1
    1
      mtglib/internal/faketls/record/pools.go
  27. 2
    2
      mtglib/internal/faketls/welcome.go
  28. 1
    1
      mtglib/internal/faketls/welcome_test.go
  29. 1
    1
      mtglib/internal/obfuscated2/handshake_frame.go
  30. 1
    1
      mtglib/internal/obfuscated2/init_test.go
  31. 2
    2
      mtglib/internal/obfuscated2/pools.go
  32. 1
    1
      mtglib/internal/relay/init.go
  33. 1
    1
      mtglib/internal/relay/init_test.go
  34. 1
    1
      mtglib/internal/relay/pools.go
  35. 1
    1
      mtglib/proxy.go
  36. 1
    1
      mtglib/stream_context.go
  37. 8
    11
      network/circuit_breaker_internal_test.go
  38. 2
    2
      network/load_balanced_socks5.go
  39. 1
    1
      network/load_balanced_socks5_test.go
  40. 5
    13
      network/network.go
  41. 1
    1
      stats/pools.go

+ 4
- 4
.mise.toml Целия файл

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

+ 27
- 2
README.md Целия файл

@@ -10,6 +10,17 @@ Highly-opinionated (ex-bullshit-free) MTPROTO proxy for
10 10
 **If you use v1.0 or upgrade broke you proxy, please read the chapter
11 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 24
 ## Rationale
14 25
 
15 26
 There are several available proxies for Telegram MTPROTO available. Here
@@ -18,6 +29,7 @@ are the most notable:
18 29
 * [Official](https://github.com/TelegramMessenger/MTProxy)
19 30
 * [Python](https://github.com/alexbers/mtprotoproxy)
20 31
 * [Erlang](https://github.com/seriyps/mtproto_proxy)
32
+* [Telemt (Rust)](https://github.com/telemt/telemt)
21 33
 
22 34
 You can use any of these. They work great and all implementations have
23 35
 feature parity now. This includes support of adtag, replay attack
@@ -40,6 +52,12 @@ that probably matter.
40 52
   way of doing business I suppose. I think the only viable way is to
41 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 61
 * **A single secret**
44 62
 
45 63
   I think that multiple secrets solve no problems and just complex
@@ -162,6 +180,12 @@ This project has several main branches
162 180
 
163 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 189
 ### Download a tool
166 190
 
167 191
 #### Download binaries
@@ -198,13 +222,14 @@ go install github.com/9seconds/mtg/v2@latest
198 222
 ```console
199 223
 git clone https://github.com/9seconds/mtg.git
200 224
 cd mtg
201
-make static
225
+mise install
226
+mise tasks run build
202 227
 ```
203 228
 
204 229
 or for the docker image:
205 230
 
206 231
 ```console
207
-make docker
232
+mise tasks run image
208 233
 ```
209 234
 
210 235
 ### Generate secret

+ 2
- 2
events/event_stream.go Целия файл

@@ -2,7 +2,7 @@ package events
2 2
 
3 3
 import (
4 4
 	"context"
5
-	"math/rand"
5
+	"math/rand/v2"
6 6
 	"runtime"
7 7
 
8 8
 	"github.com/9seconds/mtg/v2/mtglib"
@@ -64,7 +64,7 @@ func NewEventStream(observerFactories []ObserverFactory) EventStream {
64 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 68
 		rv.chans[i] = make(chan mtglib.Event, 1)
69 69
 
70 70
 		if len(observerFactories) == 1 {

+ 27
- 54
events/multi_observer.go Целия файл

@@ -12,14 +12,11 @@ type multiObserver struct {
12 12
 
13 13
 func (m multiObserver) EventStart(evt mtglib.EventStart) {
14 14
 	wg := &sync.WaitGroup{}
15
-	wg.Add(len(m.observers))
16 15
 
17 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 22
 	wg.Wait()
@@ -27,14 +24,11 @@ func (m multiObserver) EventStart(evt mtglib.EventStart) {
27 24
 
28 25
 func (m multiObserver) EventConnectedToDC(evt mtglib.EventConnectedToDC) {
29 26
 	wg := &sync.WaitGroup{}
30
-	wg.Add(len(m.observers))
31 27
 
32 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 34
 	wg.Wait()
@@ -42,14 +36,11 @@ func (m multiObserver) EventConnectedToDC(evt mtglib.EventConnectedToDC) {
42 36
 
43 37
 func (m multiObserver) EventDomainFronting(evt mtglib.EventDomainFronting) {
44 38
 	wg := &sync.WaitGroup{}
45
-	wg.Add(len(m.observers))
46 39
 
47 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 46
 	wg.Wait()
@@ -57,14 +48,11 @@ func (m multiObserver) EventDomainFronting(evt mtglib.EventDomainFronting) {
57 48
 
58 49
 func (m multiObserver) EventTraffic(evt mtglib.EventTraffic) {
59 50
 	wg := &sync.WaitGroup{}
60
-	wg.Add(len(m.observers))
61 51
 
62 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 58
 	wg.Wait()
@@ -72,14 +60,11 @@ func (m multiObserver) EventTraffic(evt mtglib.EventTraffic) {
72 60
 
73 61
 func (m multiObserver) EventFinish(evt mtglib.EventFinish) {
74 62
 	wg := &sync.WaitGroup{}
75
-	wg.Add(len(m.observers))
76 63
 
77 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 70
 	wg.Wait()
@@ -87,14 +72,11 @@ func (m multiObserver) EventFinish(evt mtglib.EventFinish) {
87 72
 
88 73
 func (m multiObserver) EventConcurrencyLimited(evt mtglib.EventConcurrencyLimited) {
89 74
 	wg := &sync.WaitGroup{}
90
-	wg.Add(len(m.observers))
91 75
 
92 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 82
 	wg.Wait()
@@ -102,14 +84,11 @@ func (m multiObserver) EventConcurrencyLimited(evt mtglib.EventConcurrencyLimite
102 84
 
103 85
 func (m multiObserver) EventIPBlocklisted(evt mtglib.EventIPBlocklisted) {
104 86
 	wg := &sync.WaitGroup{}
105
-	wg.Add(len(m.observers))
106 87
 
107 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 94
 	wg.Wait()
@@ -117,14 +96,11 @@ func (m multiObserver) EventIPBlocklisted(evt mtglib.EventIPBlocklisted) {
117 96
 
118 97
 func (m multiObserver) EventReplayAttack(evt mtglib.EventReplayAttack) {
119 98
 	wg := &sync.WaitGroup{}
120
-	wg.Add(len(m.observers))
121 99
 
122 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 106
 	wg.Wait()
@@ -132,14 +108,11 @@ func (m multiObserver) EventReplayAttack(evt mtglib.EventReplayAttack) {
132 108
 
133 109
 func (m multiObserver) EventIPListSize(evt mtglib.EventIPListSize) {
134 110
 	wg := &sync.WaitGroup{}
135
-	wg.Add(len(m.observers))
136 111
 
137 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 118
 	wg.Wait()

+ 9
- 0
example.config.toml Целия файл

@@ -23,6 +23,15 @@ secret = "ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c6561706973
23 23
 # Host:port pair to run proxy on.
24 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 35
 # Defines how many concurrent connections are allowed to this proxy.
27 36
 # All other incoming connections are going to be dropped.
28 37
 concurrency = 8192

+ 1
- 0
go.mod Целия файл

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

+ 2
- 0
go.sum Целия файл

@@ -57,6 +57,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaR
57 57
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
58 58
 github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
59 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 62
 github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
61 63
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
62 64
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=

+ 4
- 10
internal/cli/access.go Целия файл

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

+ 10
- 0
internal/cli/run_proxy.go Целия файл

@@ -10,6 +10,7 @@ import (
10 10
 	"github.com/9seconds/mtg/v2/antireplay"
11 11
 	"github.com/9seconds/mtg/v2/events"
12 12
 	"github.com/9seconds/mtg/v2/internal/config"
13
+	"github.com/9seconds/mtg/v2/internal/proxyprotocol"
13 14
 	"github.com/9seconds/mtg/v2/internal/utils"
14 15
 	"github.com/9seconds/mtg/v2/ipblocklist"
15 16
 	"github.com/9seconds/mtg/v2/ipblocklist/files"
@@ -17,6 +18,7 @@ import (
17 18
 	"github.com/9seconds/mtg/v2/mtglib"
18 19
 	"github.com/9seconds/mtg/v2/network"
19 20
 	"github.com/9seconds/mtg/v2/stats"
21
+	"github.com/pires/go-proxyproto"
20 22
 	"github.com/rs/zerolog"
21 23
 	"github.com/yl2chen/cidranger"
22 24
 )
@@ -275,6 +277,14 @@ func runProxy(conf *config.Config, version string) error { //nolint: funlen
275 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 288
 	ctx := utils.RootContext()
279 289
 
280 290
 	go proxy.Serve(listener) //nolint: errcheck

+ 1
- 0
internal/config/config.go Целия файл

@@ -25,6 +25,7 @@ type Config struct {
25 25
 	AllowFallbackOnUnknownDC TypeBool        `json:"allowFallbackOnUnknownDc"`
26 26
 	Secret                   mtglib.Secret   `json:"secret"`
27 27
 	BindTo                   TypeHostPort    `json:"bindTo"`
28
+	ProxyProtocolListener    TypeBool        `json:"proxyProtocolListener"`
28 29
 	PreferIP                 TypePreferIP    `json:"preferIp"`
29 30
 	DomainFrontingPort       TypePort        `json:"domainFrontingPort"`
30 31
 	TolerateTimeSkewness     TypeDuration    `json:"tolerateTimeSkewness"`

+ 1
- 0
internal/config/parse.go Целия файл

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

+ 2
- 2
internal/config/type_bool_test.go Целия файл

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

+ 20
- 0
internal/proxyprotocol/adapter.go Целия файл

@@ -0,0 +1,20 @@
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 Целия файл

@@ -0,0 +1,25 @@
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,18 +112,15 @@ func (f *Firehol) update() {
112 112
 	defer cancel()
113 113
 
114 114
 	wg := &sync.WaitGroup{}
115
-	wg.Add(len(f.blocklists))
116 115
 
117 116
 	mutex := &sync.Mutex{}
118 117
 	ranger := cidranger.NewPCTrieRanger()
119 118
 
120 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 124
 			if err != nil {
128 125
 				logger.WarningError("update has failed", err)
129 126
 
@@ -135,7 +132,7 @@ func (f *Firehol) update() {
135 132
 			if err := f.updateFromFile(mutex, ranger, bufio.NewScanner(fileContent)); err != nil {
136 133
 				logger.WarningError("update has failed", err)
137 134
 			}
138
-		}(v)
135
+		})
139 136
 	}
140 137
 
141 138
 	wg.Wait()

+ 1
- 1
logger/init.go Целия файл

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

+ 1
- 1
logger/noop.go Целия файл

@@ -8,7 +8,7 @@ func (n noopLogger) Named(_ string) mtglib.Logger          { return n }
8 8
 func (n noopLogger) BindInt(_ string, _ int) mtglib.Logger { return n }
9 9
 func (n noopLogger) BindStr(_, _ string) mtglib.Logger     { return n }
10 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 12
 func (n noopLogger) Info(_ string)                         {}
13 13
 func (n noopLogger) Warning(_ string)                      {}
14 14
 func (n noopLogger) Debug(_ string)                        {}

+ 1
- 1
logger/zerolog.go Целия файл

@@ -78,7 +78,7 @@ func (z *zeroLogContext) BindJSON(name, value string) mtglib.Logger {
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 82
 	z.Debug(fmt.Sprintf(format, args...))
83 83
 }
84 84
 

+ 23
- 1
mise.lock Целия файл

@@ -7,10 +7,32 @@ backend = "core:go"
7 7
 "platforms.macos-x64" = { checksum = "sha256:1ca28b7703cbea05a65b2a1d92d6b308610ef92f8824578a0874f2e60c9d5a22", url = "https://dl.google.com/go/go1.26.0.darwin-amd64.tar.gz"}
8 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 14
 [[tools."go:golang.org/x/tools/gopls"]]
11
-version = "0.21.0"
15
+version = "0.21.1"
12 16
 backend = "go:golang.org/x/tools/gopls"
13 17
 
14 18
 [[tools."go:mvdan.cc/gofumpt"]]
15 19
 version = "0.9.2"
16 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,7 +249,7 @@ type Logger interface {
249 249
 	BindJSON(name, value string) Logger
250 250
 
251 251
 	// Printf is to support log.Logger behavior.
252
-	Printf(format string, args ...interface{})
252
+	Printf(format string, args ...any)
253 253
 
254 254
 	// Info puts a message about some normal situation.
255 255
 	Info(msg string)

+ 11
- 11
mtglib/init_internal_test.go Целия файл

@@ -8,17 +8,17 @@ import (
8 8
 
9 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 23
 type EventStreamMock struct {
24 24
 	mock.Mock

+ 1
- 1
mtglib/internal/faketls/client_hello.go Целия файл

@@ -76,7 +76,7 @@ func ParseClientHello(secret, handshake []byte) (ClientHello, error) {
76 76
 
77 77
 	computedRandom := mac.Sum(nil)
78 78
 
79
-	for i := 0; i < RandomLen; i++ {
79
+	for i := range RandomLen {
80 80
 		computedRandom[i] ^= hello.Random[i]
81 81
 	}
82 82
 

+ 2
- 2
mtglib/internal/faketls/conn.go Целия файл

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

+ 2
- 2
mtglib/internal/faketls/conn_test.go Целия файл

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

+ 1
- 1
mtglib/internal/faketls/pools.go Целия файл

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

+ 1
- 1
mtglib/internal/faketls/record/pools.go Целия файл

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

+ 2
- 2
mtglib/internal/faketls/welcome.go Целия файл

@@ -6,7 +6,7 @@ import (
6 6
 	"crypto/sha256"
7 7
 	"encoding/binary"
8 8
 	"io"
9
-	mrand "math/rand"
9
+	mrand "math/rand/v2"
10 10
 
11 11
 	"github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
12 12
 	"golang.org/x/crypto/curve25519"
@@ -36,7 +36,7 @@ func SendWelcomePacket(writer io.Writer, secret []byte, clientHello ClientHello)
36 36
 	rec.Type = record.TypeApplicationData
37 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 40
 		panic(err)
41 41
 	}
42 42
 

+ 1
- 1
mtglib/internal/faketls/welcome_test.go Целия файл

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

+ 1
- 1
mtglib/internal/obfuscated2/handshake_frame.go Целия файл

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

+ 1
- 1
mtglib/internal/obfuscated2/init_test.go Целия файл

@@ -117,7 +117,7 @@ func NewServerHandshakeTestData(t *testing.T) ServerHandshakeTestData {
117 117
 
118 118
 	serverEncryptedReverted := make([]byte, len(serverEncrypted))
119 119
 
120
-	for i := 0; i < 32+16; i++ {
120
+	for i := range 32 + 16 {
121 121
 		serverEncryptedReverted[8+i] = serverEncrypted[8+32+16-1-i]
122 122
 	}
123 123
 

+ 2
- 2
mtglib/internal/obfuscated2/pools.go Целия файл

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

+ 1
- 1
mtglib/internal/relay/init.go Целия файл

@@ -5,5 +5,5 @@ const (
5 5
 )
6 6
 
7 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,4 +2,4 @@ package relay_test
2 2
 
3 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,7 +3,7 @@ package relay
3 3
 import "sync"
4 4
 
5 5
 var copyBufferPool = sync.Pool{
6
-	New: func() interface{} {
6
+	New: func() any {
7 7
 		rv := make([]byte, copyBufferSize)
8 8
 
9 9
 		return &rv

+ 1
- 1
mtglib/proxy.go Целия файл

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

+ 1
- 1
mtglib/stream_context.go Целия файл

@@ -32,7 +32,7 @@ func (s *streamContext) Err() error {
32 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 36
 	return s.ctx.Value(key)
37 37
 }
38 38
 

+ 8
- 11
network/circuit_breaker_internal_test.go Целия файл

@@ -52,17 +52,9 @@ func (suite *CircuitBreakerTestSuite) TestMultipleRunsOk() {
52 52
 		Return(suite.connMock, nil)
53 53
 
54 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 58
 			conn, err := suite.d.DialContext(suite.ctx, "tcp", "127.0.0.1")
67 59
 
68 60
 			suite.mutex.Lock()
@@ -70,9 +62,14 @@ func (suite *CircuitBreakerTestSuite) TestMultipleRunsOk() {
70 62
 
71 63
 			suite.NoError(err)
72 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 73
 	suite.Eventually(func() bool {
77 74
 		_, ok := <-suite.ctx.Done()
78 75
 

+ 2
- 2
network/load_balanced_socks5.go Целия файл

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

+ 1
- 1
network/load_balanced_socks5_test.go Целия файл

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

+ 5
- 13
network/network.go Целия файл

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

+ 1
- 1
stats/pools.go Целия файл

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

Loading…
Отказ
Запис