Преглед изворни кода

Merge remote-tracking branch 'origin/master' into stable

tags/v2.1.5
9seconds пре 4 година
родитељ
комит
6d89f14c9b

+ 1
- 2
.github/workflows/ci.yaml Прегледај датотеку

42
     strategy:
42
     strategy:
43
       matrix:
43
       matrix:
44
         go_version:
44
         go_version:
45
-          - ~1.16
46
           - ^1.17
45
           - ^1.17
47
     steps:
46
     steps:
48
       - name: Checkout
47
       - name: Checkout
83
       - name: Run linter
82
       - name: Run linter
84
         uses: golangci/golangci-lint-action@v2
83
         uses: golangci/golangci-lint-action@v2
85
         with:
84
         with:
86
-          version: v1.43.0
85
+          version: v1.44.2
87
 
86
 
88
   docker:
87
   docker:
89
     name: Docker
88
     name: Docker

+ 1
- 1
.golangci.toml Прегледај датотеку

9
 
9
 
10
 [linters]
10
 [linters]
11
 enable-all = true
11
 enable-all = true
12
-disable = ["ireturn", "varnamelen", "gochecknoglobals", "gas", "goerr113", "exhaustivestruct"]
12
+disable = ["ireturn", "varnamelen", "gochecknoglobals", "gas", "goerr113", "exhaustivestruct", "containedctx"]

+ 1
- 1
Makefile Прегледај датотеку

2
 IMAGE_NAME   := mtg
2
 IMAGE_NAME   := mtg
3
 APP_NAME     := $(IMAGE_NAME)
3
 APP_NAME     := $(IMAGE_NAME)
4
 
4
 
5
-GOLANGCI_LINT_VERSION := v1.43.0
5
+GOLANGCI_LINT_VERSION := v1.44.2
6
 
6
 
7
 VERSION_GO         := $(shell go version)
7
 VERSION_GO         := $(shell go version)
8
 VERSION_DATE       := $(shell date -Ru)
8
 VERSION_DATE       := $(shell date -Ru)

+ 20
- 2
README.md Прегледај датотеку

1
 # mtg
1
 # mtg
2
 
2
 
3
-Highly-opionated (ex-bullshit-free) MTPROTO proxy for
3
+Highly-opinionated (ex-bullshit-free) MTPROTO proxy for
4
 [Telegram](https://telegram.org/).
4
 [Telegram](https://telegram.org/).
5
 
5
 
6
 [![CI](https://github.com/9seconds/mtg/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/9seconds/mtg/actions/workflows/ci.yaml)
6
 [![CI](https://github.com/9seconds/mtg/actions/workflows/ci.yaml/badge.svg?branch=master)](https://github.com/9seconds/mtg/actions/workflows/ci.yaml)
224
 ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d
224
 ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d
225
 ```
225
 ```
226
 
226
 
227
+equivalent commands with docker:
228
+
229
+```console
230
+$ docker run --rm nineseconds/mtg:2 generate-secret google.com
231
+7ibaERuTSGPH1RdztfYnN4tnb29nbGUuY29t
232
+
233
+$ docker run --rm nineseconds/mtg:2 generate-secret --hex google.com
234
+ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d
235
+```
236
+
227
 This secret is a keystone for a proxy and your password for a client.
237
 This secret is a keystone for a proxy and your password for a client.
228
 You need to keep it secured.
238
 You need to keep it secured.
229
 
239
 
324
 or you can run a docker image
334
 or you can run a docker image
325
 
335
 
326
 ```console
336
 ```console
327
-docker run -d -v /etc/mtg.toml:/config.toml -p 443:3128 --restart=unless-stopped nineseconds/mtg:2
337
+docker run -d -v /etc/mtg.toml:/config.toml -p 443:3128 --name mtg-proxy --restart=unless-stopped nineseconds/mtg:2
328
 ```
338
 ```
329
 
339
 
330
 where _443_ is a host port (a port you want to connect to from a
340
 where _443_ is a host port (a port you want to connect to from a
353
 }
363
 }
354
 ```
364
 ```
355
 
365
 
366
+or if you are using docker:
367
+
368
+```console
369
+$ docker exec mtg-proxy /mtg access /config.toml
370
+```
371
+
356
 ## Metrics
372
 ## Metrics
357
 
373
 
358
 Out of the box, mtg works with
374
 Out of the box, mtg works with
367
 | client_connections          | gauge   | `ip_family`                      | Count of processing client connections.                                                    |
383
 | client_connections          | gauge   | `ip_family`                      | Count of processing client connections.                                                    |
368
 | telegram_connections        | gauge   | `telegram_ip`, `dc`              | Count of connections to Telegram servers.                                                  |
384
 | telegram_connections        | gauge   | `telegram_ip`, `dc`              | Count of connections to Telegram servers.                                                  |
369
 | domain_fronting_connections | gauge   | `ip_family`                      | Count of connections to fronting domain.                                                   |
385
 | domain_fronting_connections | gauge   | `ip_family`                      | Count of connections to fronting domain.                                                   |
386
+| iplist_size                 | gauge   | `ip_list`                        | A size of either allowlist or blocklist in use.                                            |
370
 | telegram_traffic            | counter | `telegram_ip`, `dc`, `direction` | Count of bytes, transmitted to/from Telegram.                                              |
387
 | telegram_traffic            | counter | `telegram_ip`, `dc`, `direction` | Count of bytes, transmitted to/from Telegram.                                              |
371
 | domain_fronting_traffic     | counter | `direction`                      | Count of bytes, transmitted to/from fronting domain.                                       |
388
 | domain_fronting_traffic     | counter | `direction`                      | Count of bytes, transmitted to/from fronting domain.                                       |
372
 | domain_fronting             | counter | –                                | Count of domain fronting events.                                                           |
389
 | domain_fronting             | counter | –                                | Count of domain fronting events.                                                           |
382
 | dc          |                            | A number of the Telegram DC for a connection. |
399
 | dc          |                            | A number of the Telegram DC for a connection. |
383
 | telegram_ip |                            | IP address of the Telegram server.            |
400
 | telegram_ip |                            | IP address of the Telegram server.            |
384
 | direction   | `to_client`, `from_client` | A direction of the traffic flow.              |
401
 | direction   | `to_client`, `from_client` | A direction of the traffic flow.              |
402
+| ip_list     | `allowlist`, `blocklist`   | A type of the IP list.                        |

+ 2
- 0
events/event_stream.go Прегледај датотеку

102
 				observer.EventConcurrencyLimited(typedEvt)
102
 				observer.EventConcurrencyLimited(typedEvt)
103
 			case mtglib.EventReplayAttack:
103
 			case mtglib.EventReplayAttack:
104
 				observer.EventReplayAttack(typedEvt)
104
 				observer.EventReplayAttack(typedEvt)
105
+			case mtglib.EventIPListSize:
106
+				observer.EventIPListSize(typedEvt)
105
 			}
107
 			}
106
 		}
108
 		}
107
 	}
109
 	}

+ 21
- 0
events/event_stream_test.go Прегледај датотеку

204
 	time.Sleep(100 * time.Millisecond)
204
 	time.Sleep(100 * time.Millisecond)
205
 }
205
 }
206
 
206
 
207
+func (suite *EventStreamTestSuite) TestEventIPListSize() {
208
+	evt := mtglib.NewEventIPListSize(10, true)
209
+
210
+	for _, v := range []*ObserverMock{suite.observerMock1, suite.observerMock2} {
211
+		v.
212
+			On("EventIPListSize", mock.Anything).
213
+			Once().
214
+			Run(func(args mock.Arguments) {
215
+				caught, ok := args.Get(0).(mtglib.EventIPListSize)
216
+
217
+				suite.True(ok)
218
+				suite.Equal(evt.Timestamp(), caught.Timestamp())
219
+				suite.Equal(evt.Size, caught.Size)
220
+				suite.Equal(evt.IsBlockList, caught.IsBlockList)
221
+			})
222
+	}
223
+
224
+	suite.stream.Send(suite.ctx, evt)
225
+	time.Sleep(100 * time.Millisecond)
226
+}
227
+
207
 func (suite *EventStreamTestSuite) TearDownTest() {
228
 func (suite *EventStreamTestSuite) TearDownTest() {
208
 	suite.stream.Shutdown()
229
 	suite.stream.Shutdown()
209
 	suite.ctxCancel()
230
 	suite.ctxCancel()

+ 3
- 0
events/init.go Прегледај датотеку

53
 	// EventReplayAttack reacts on incoming mtglib.EventReplayAttack event.
53
 	// EventReplayAttack reacts on incoming mtglib.EventReplayAttack event.
54
 	EventReplayAttack(mtglib.EventReplayAttack)
54
 	EventReplayAttack(mtglib.EventReplayAttack)
55
 
55
 
56
+	// EventIPListSize reacts on incoming mtglib.EventIPListSize
57
+	EventIPListSize(mtglib.EventIPListSize)
58
+
56
 	// Shutdown stop observer. Default event stream guarantees:
59
 	// Shutdown stop observer. Default event stream guarantees:
57
 	//   1. If shutdown is executed, it is executed only once
60
 	//   1. If shutdown is executed, it is executed only once
58
 	//   2. Observer won't receieve any new message after this
61
 	//   2. Observer won't receieve any new message after this

+ 4
- 0
events/init_test.go Прегледај датотеку

41
 	o.Called(evt)
41
 	o.Called(evt)
42
 }
42
 }
43
 
43
 
44
+func (o *ObserverMock) EventIPListSize(evt mtglib.EventIPListSize) {
45
+	o.Called(evt)
46
+}
47
+
44
 func (o *ObserverMock) Shutdown() {
48
 func (o *ObserverMock) Shutdown() {
45
 	o.Called()
49
 	o.Called()
46
 }
50
 }

+ 15
- 0
events/multi_observer.go Прегледај датотеку

130
 	wg.Wait()
130
 	wg.Wait()
131
 }
131
 }
132
 
132
 
133
+func (m multiObserver) EventIPListSize(evt mtglib.EventIPListSize) {
134
+	wg := &sync.WaitGroup{}
135
+	wg.Add(len(m.observers))
136
+
137
+	for _, v := range m.observers {
138
+		go func(obs Observer) {
139
+			defer wg.Done()
140
+
141
+			obs.EventIPListSize(evt)
142
+		}(v)
143
+	}
144
+
145
+	wg.Wait()
146
+}
147
+
133
 func (m multiObserver) Shutdown() {
148
 func (m multiObserver) Shutdown() {
134
 	for _, v := range m.observers {
149
 	for _, v := range m.observers {
135
 		v.Shutdown()
150
 		v.Shutdown()

+ 1
- 0
events/noop.go Прегледај датотеку

25
 func (n noopObserver) EventConcurrencyLimited(_ mtglib.EventConcurrencyLimited) {}
25
 func (n noopObserver) EventConcurrencyLimited(_ mtglib.EventConcurrencyLimited) {}
26
 func (n noopObserver) EventIPBlocklisted(_ mtglib.EventIPBlocklisted)           {}
26
 func (n noopObserver) EventIPBlocklisted(_ mtglib.EventIPBlocklisted)           {}
27
 func (n noopObserver) EventReplayAttack(_ mtglib.EventReplayAttack)             {}
27
 func (n noopObserver) EventReplayAttack(_ mtglib.EventReplayAttack)             {}
28
+func (n noopObserver) EventIPListSize(_ mtglib.EventIPListSize)                 {}
28
 func (n noopObserver) Shutdown()                                                {}
29
 func (n noopObserver) Shutdown()                                                {}
29
 
30
 
30
 // NewNoopObserver creates an observer which discards each message.
31
 // NewNoopObserver creates an observer which discards each message.

+ 3
- 0
events/noop_test.go Прегледај датотеку

27
 		"concurrency-limited": mtglib.NewEventConcurrencyLimited(),
27
 		"concurrency-limited": mtglib.NewEventConcurrencyLimited(),
28
 		"ip-blacklisted":      mtglib.NewEventIPBlocklisted(net.ParseIP("10.0.0.10")),
28
 		"ip-blacklisted":      mtglib.NewEventIPBlocklisted(net.ParseIP("10.0.0.10")),
29
 		"replay-attack":       mtglib.NewEventReplayAttack("connID"),
29
 		"replay-attack":       mtglib.NewEventReplayAttack("connID"),
30
+		"ip-list-size":        mtglib.NewEventIPListSize(10, true),
30
 	}
31
 	}
31
 	suite.ctx = context.Background()
32
 	suite.ctx = context.Background()
32
 }
33
 }
65
 				observer.EventIPBlocklisted(typedEvt)
66
 				observer.EventIPBlocklisted(typedEvt)
66
 			case mtglib.EventReplayAttack:
67
 			case mtglib.EventReplayAttack:
67
 				observer.EventReplayAttack(typedEvt)
68
 				observer.EventReplayAttack(typedEvt)
69
+			case mtglib.EventIPListSize:
70
+				observer.EventIPListSize(typedEvt)
68
 			}
71
 			}
69
 		})
72
 		})
70
 	}
73
 	}

+ 1
- 1
example.config.toml Прегледај датотеку

170
 # You can provider links here (starts with https:// or http://) or
170
 # You can provider links here (starts with https:// or http://) or
171
 # path to a local file, but in this case it should be absolute.
171
 # path to a local file, but in this case it should be absolute.
172
 urls = [
172
 urls = [
173
-    # "https://iplists.firehol.org/files/firehol_level1.netset",
173
+    "https://iplists.firehol.org/files/firehol_level1.netset",
174
     # "/local.file"
174
     # "/local.file"
175
 ]
175
 ]
176
 # How often do we need to update a blocklist set.
176
 # How often do we need to update a blocklist set.

+ 12
- 10
go.mod Прегледај датотеку

4
 
4
 
5
 require (
5
 require (
6
 	github.com/OneOfOne/xxhash v1.2.8
6
 	github.com/OneOfOne/xxhash v1.2.8
7
-	github.com/alecthomas/kong v0.2.19
8
-	github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a
7
+	github.com/alecthomas/kong v0.5.0
8
+	github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137
9
 	github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
9
 	github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
10
 	github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6
10
 	github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6
11
 	github.com/d4l3k/messagediff v1.2.1 // indirect
11
 	github.com/d4l3k/messagediff v1.2.1 // indirect
12
 	github.com/golang/protobuf v1.5.2 // indirect
12
 	github.com/golang/protobuf v1.5.2 // indirect
13
 	github.com/gotd/td v0.34.0
13
 	github.com/gotd/td v0.34.0
14
 	github.com/jarcoal/httpmock v1.0.8
14
 	github.com/jarcoal/httpmock v1.0.8
15
-	github.com/kentik/patricia v0.0.0-20210909164817-21603333b70e
16
 	github.com/mccutchen/go-httpbin v1.1.1
15
 	github.com/mccutchen/go-httpbin v1.1.1
17
-	github.com/panjf2000/ants/v2 v2.4.7
16
+	github.com/panjf2000/ants/v2 v2.4.8
18
 	github.com/pelletier/go-toml v1.9.4
17
 	github.com/pelletier/go-toml v1.9.4
19
-	github.com/prometheus/client_golang v1.11.0
18
+	github.com/prometheus/client_golang v1.12.1
20
 	github.com/prometheus/common v0.32.1 // indirect
19
 	github.com/prometheus/common v0.32.1 // indirect
21
 	github.com/prometheus/procfs v0.7.3 // indirect
20
 	github.com/prometheus/procfs v0.7.3 // indirect
22
-	github.com/rs/zerolog v1.26.0
21
+	github.com/rs/zerolog v1.26.1
23
 	github.com/smira/go-statsd v1.3.2
22
 	github.com/smira/go-statsd v1.3.2
24
 	github.com/stretchr/objx v0.3.0 // indirect
23
 	github.com/stretchr/objx v0.3.0 // indirect
25
 	github.com/stretchr/testify v1.7.0
24
 	github.com/stretchr/testify v1.7.0
26
 	github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43
25
 	github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43
27
-	golang.org/x/crypto v0.0.0-20211202192323-5770296d904e
26
+	golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70
28
 	golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
27
 	golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
29
-	golang.org/x/sys v0.0.0-20211124211545-fe61309f8881
28
+	golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5
30
 	google.golang.org/protobuf v1.27.1 // indirect
29
 	google.golang.org/protobuf v1.27.1 // indirect
31
 )
30
 )
32
 
31
 
33
-require github.com/txthinking/socks5 v0.0.0-20211121111206-e03c1217a50b
32
+require (
33
+	github.com/txthinking/socks5 v0.0.0-20220212043548-414499347d4a
34
+	github.com/yl2chen/cidranger v1.0.2
35
+)
34
 
36
 
35
 require (
37
 require (
36
 	github.com/beorn7/perks v1.0.1 // indirect
38
 	github.com/beorn7/perks v1.0.1 // indirect
44
 	github.com/pkg/errors v0.9.1 // indirect
46
 	github.com/pkg/errors v0.9.1 // indirect
45
 	github.com/pmezard/go-difflib v1.0.0 // indirect
47
 	github.com/pmezard/go-difflib v1.0.0 // indirect
46
 	github.com/prometheus/client_model v0.2.0 // indirect
48
 	github.com/prometheus/client_model v0.2.0 // indirect
47
-	github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf // indirect
49
+	github.com/txthinking/runnergroup v0.0.0-20220212043759-8da8edb7dae8 // indirect
48
 	github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe // indirect
50
 	github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe // indirect
49
 	go.uber.org/atomic v1.7.0 // indirect
51
 	go.uber.org/atomic v1.7.0 // indirect
50
 	go.uber.org/multierr v1.6.0 // indirect
52
 	go.uber.org/multierr v1.6.0 // indirect

+ 27
- 19
go.sum Прегледај датотеку

37
 github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
37
 github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
38
 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
38
 github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
39
 github.com/PuerkitoBio/goquery v1.6.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
39
 github.com/PuerkitoBio/goquery v1.6.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
40
-github.com/alecthomas/kong v0.2.19 h1:qBDfByO5XgWUXyNB4D6OOhGh5Z1eNOwWayDPQJFNWdc=
41
-github.com/alecthomas/kong v0.2.19/go.mod h1:ka3VZ8GZNPXv9Ov+j4YNLkI8mTuhXyr/0ktSlqIydQQ=
40
+github.com/alecthomas/kong v0.5.0 h1:u8Kdw+eeml93qtMZ04iei0CFYve/WPcA5IFh+9wSskE=
41
+github.com/alecthomas/kong v0.5.0/go.mod h1:uzxf/HUh0tj43x1AyJROl3JT7SgsZ5m+icOv1csRhc0=
42
+github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142 h1:8Uy0oSf5co/NZXje7U1z8Mpep++QJOldL2hs/sBQf48=
43
+github.com/alecthomas/repr v0.0.0-20210801044451-80ca428c5142/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
42
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
44
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
43
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
45
 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
44
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
46
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
45
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
47
 github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
46
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
48
 github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
47
-github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a h1:E/8AP5dFtMhl5KPJz66Kt9G0n+7Sn41Fy1wv9/jHOrc=
48
-github.com/alecthomas/units v0.0.0-20210927113745-59d0afb8317a/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
49
+github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAuRjVTiNNhvNRfY2Wxp9nhfyel4rklc=
50
+github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
49
 github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg=
51
 github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129/go.mod h1:rFgpPQZYZ8vdbc+48xibu8ALc3yeyd64IhHS+PU6Yyg=
50
 github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
52
 github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
51
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
53
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
163
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
165
 github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
164
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
166
 github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
165
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
167
 github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
168
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
166
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
169
 github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
167
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
170
 github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
168
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
171
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
169
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
172
 github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
170
 github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
173
 github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
171
 github.com/k0kubun/pp v2.4.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
174
 github.com/k0kubun/pp v2.4.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
172
-github.com/kentik/patricia v0.0.0-20210909164817-21603333b70e h1:1wAVuGu1c+lsdaOPQN+9xoP9+gaIMJV6H0ehGc+K5iA=
173
-github.com/kentik/patricia v0.0.0-20210909164817-21603333b70e/go.mod h1:2OfLA+0esiUJpwMjrH39pEk79cb8MvGTBS9YlZpejJ4=
174
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
175
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
175
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
176
 github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
176
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
177
 github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
191
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
192
 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
192
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
193
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
193
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
194
 github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
195
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
194
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
196
 github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
195
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
197
 github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
196
-github.com/panjf2000/ants/v2 v2.4.7 h1:MZnw2JRyTJxFwtaMtUJcwE618wKD04POWk2gwwP4E2M=
197
-github.com/panjf2000/ants/v2 v2.4.7/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A=
198
+github.com/panjf2000/ants/v2 v2.4.8 h1:JgTbolX6K6RreZ4+bfctI0Ifs+3mrE5BIHudQxUDQ9k=
199
+github.com/panjf2000/ants/v2 v2.4.8/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A=
198
 github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
200
 github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
199
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
201
 github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
200
 github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
202
 github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
209
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
211
 github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
210
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
212
 github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
211
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
213
 github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
212
-github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
213
 github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
214
 github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
215
+github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
216
+github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
214
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
217
 github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
215
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
218
 github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
216
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
219
 github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
231
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
234
 github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
232
 github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
235
 github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
233
 github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
236
 github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
234
-github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE=
235
-github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo=
237
+github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc=
238
+github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc=
236
 github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
239
 github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
237
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
240
 github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
238
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
241
 github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
245
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
248
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
246
 github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
249
 github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
247
 github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
250
 github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
248
-github.com/stretchr/testify v1.1.5-0.20170809224252-890a5c3458b4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
249
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
251
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
250
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
252
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
251
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
253
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
252
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
254
 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
253
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
255
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
254
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
256
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
255
-github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf h1:7PflaKRtU4np/epFxRXlFhlzLXZzKFrH5/I4so5Ove0=
256
 github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf/go.mod h1:CLUSJbazqETbaR+i0YAhXBICV9TrKH93pziccMhmhpM=
257
 github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf/go.mod h1:CLUSJbazqETbaR+i0YAhXBICV9TrKH93pziccMhmhpM=
257
-github.com/txthinking/socks5 v0.0.0-20211121111206-e03c1217a50b h1:6J/38A0Xmdnjacfie0Udams7OP/GdoExyTipKwuQWjY=
258
-github.com/txthinking/socks5 v0.0.0-20211121111206-e03c1217a50b/go.mod h1:7NloQcrxaZYKURWph5HLxVDlIwMHJXCPkeWPtpftsIg=
258
+github.com/txthinking/runnergroup v0.0.0-20220212043759-8da8edb7dae8 h1:iYc+JnXtzv6sdMx9Q7OTKkDAn7FhDPDogcjeSfEQcLY=
259
+github.com/txthinking/runnergroup v0.0.0-20220212043759-8da8edb7dae8/go.mod h1:CLUSJbazqETbaR+i0YAhXBICV9TrKH93pziccMhmhpM=
260
+github.com/txthinking/socks5 v0.0.0-20220212043548-414499347d4a h1:BOqgJ4jku0LHPDoR51RD8Mxmo0LHxCzJT/M9MemYdHo=
261
+github.com/txthinking/socks5 v0.0.0-20220212043548-414499347d4a/go.mod h1:7NloQcrxaZYKURWph5HLxVDlIwMHJXCPkeWPtpftsIg=
259
 github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe h1:gMWxZxBFRAXqoGkwkYlPX2zvyyKNWJpxOxCrjqJkm5A=
262
 github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe h1:gMWxZxBFRAXqoGkwkYlPX2zvyyKNWJpxOxCrjqJkm5A=
260
 github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe/go.mod h1:WgqbSEmUYSjEV3B1qmee/PpP2NYEz4bL9/+mF1ma+s4=
263
 github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe/go.mod h1:WgqbSEmUYSjEV3B1qmee/PpP2NYEz4bL9/+mF1ma+s4=
261
 github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43 h1:QEePdg0ty2r0t1+qwfZmQ4OOl/MB2UXIeJSpIZv56lg=
264
 github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43 h1:QEePdg0ty2r0t1+qwfZmQ4OOl/MB2UXIeJSpIZv56lg=
262
 github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43/go.mod h1:OYRfF6eb5wY9VRFkXJH8FFBi3plw2v+giaIu7P054pM=
265
 github.com/tylertreat/BoomFilters v0.0.0-20210315201527-1a82519a3e43/go.mod h1:OYRfF6eb5wY9VRFkXJH8FFBi3plw2v+giaIu7P054pM=
266
+github.com/yl2chen/cidranger v1.0.2 h1:lbOWZVCG1tCRX4u24kuM1Tb4nHqWkDxwLdoS+SevawU=
267
+github.com/yl2chen/cidranger v1.0.2/go.mod h1:9U1yz7WPYDwf0vpNWFaeRh0bjwz5RVgRy/9UEQfHl0g=
263
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
268
 github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
264
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
269
 github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
265
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
270
 github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
285
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
290
 golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
286
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
291
 golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
287
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
292
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
288
-golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8=
289
-golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
293
+golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
294
+golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70 h1:syTAU9FwmvzEoIYMqcPHOcVm4H3U5u90WsvuYgwpETU=
295
+golang.org/x/crypto v0.0.0-20220307211146-efcb8507fb70/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
290
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
296
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
291
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
297
 golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
292
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
298
 golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
350
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
356
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
351
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
357
 golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
352
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
358
 golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
359
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
353
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
360
 golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
354
 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
361
 golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
355
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
362
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
411
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
418
 golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
412
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
419
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
413
 golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
420
 golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
414
-golang.org/x/sys v0.0.0-20211124211545-fe61309f8881 h1:TyHqChC80pFkXWraUUf6RuB5IqFdQieMLwwCJokV2pc=
415
-golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
421
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
422
+golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng=
423
+golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
416
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
424
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
417
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
425
 golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
418
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
426
 golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

+ 29
- 10
internal/cli/run_proxy.go Прегледај датотеку

1
 package cli
1
 package cli
2
 
2
 
3
 import (
3
 import (
4
+	"context"
4
 	"fmt"
5
 	"fmt"
5
 	"net"
6
 	"net"
6
 	"net/url"
7
 	"net/url"
85
 	)
86
 	)
86
 }
87
 }
87
 
88
 
88
-func makeIPBlocklist(conf config.ListConfig, logger mtglib.Logger, ntw mtglib.Network) (mtglib.IPBlocklist, error) {
89
+func makeIPBlocklist(conf config.ListConfig,
90
+	logger mtglib.Logger,
91
+	ntw mtglib.Network,
92
+	updateCallback ipblocklist.FireholUpdateCallback) (mtglib.IPBlocklist, error) {
89
 	if !conf.Enabled.Get(false) {
93
 	if !conf.Enabled.Get(false) {
90
 		return ipblocklist.NewNoop(), nil
94
 		return ipblocklist.NewNoop(), nil
91
 	}
95
 	}
105
 		ntw,
109
 		ntw,
106
 		conf.DownloadConcurrency.Get(1),
110
 		conf.DownloadConcurrency.Get(1),
107
 		remoteURLs,
111
 		remoteURLs,
108
-		localFiles)
112
+		localFiles,
113
+		updateCallback)
109
 	if err != nil {
114
 	if err != nil {
110
 		return nil, fmt.Errorf("incorrect parameters for firehol: %w", err)
115
 		return nil, fmt.Errorf("incorrect parameters for firehol: %w", err)
111
 	}
116
 	}
112
 
117
 
118
+	go firehol.Run(conf.UpdateEach.Get(ipblocklist.DefaultFireholUpdateEach))
119
+
113
 	return firehol, nil
120
 	return firehol, nil
114
 }
121
 }
115
 
122
 
157
 
164
 
158
 	logger.BindJSON("configuration", conf.String()).Debug("configuration")
165
 	logger.BindJSON("configuration", conf.String()).Debug("configuration")
159
 
166
 
167
+	eventStream, err := makeEventStream(conf, logger)
168
+	if err != nil {
169
+		return fmt.Errorf("cannot build event stream: %w", err)
170
+	}
171
+
160
 	ntw, err := makeNetwork(conf, version)
172
 	ntw, err := makeNetwork(conf, version)
161
 	if err != nil {
173
 	if err != nil {
162
 		return fmt.Errorf("cannot build network: %w", err)
174
 		return fmt.Errorf("cannot build network: %w", err)
163
 	}
175
 	}
164
 
176
 
165
-	blocklist, err := makeIPBlocklist(conf.Defense.Blocklist, logger, ntw)
177
+	blocklist, err := makeIPBlocklist(
178
+		conf.Defense.Blocklist,
179
+		logger.Named("blocklist"),
180
+		ntw,
181
+		func(ctx context.Context, size int) {
182
+			eventStream.Send(ctx, mtglib.NewEventIPListSize(size, true))
183
+		})
166
 	if err != nil {
184
 	if err != nil {
167
 		return fmt.Errorf("cannot build ip blocklist: %w", err)
185
 		return fmt.Errorf("cannot build ip blocklist: %w", err)
168
 	}
186
 	}
170
 	var whitelist mtglib.IPBlocklist
188
 	var whitelist mtglib.IPBlocklist
171
 
189
 
172
 	if conf.Defense.Allowlist.Enabled.Get(false) {
190
 	if conf.Defense.Allowlist.Enabled.Get(false) {
173
-		whlist, err := makeIPBlocklist(conf.Defense.Allowlist, logger, ntw)
191
+		whlist, err := makeIPBlocklist(
192
+			conf.Defense.Allowlist,
193
+			logger.Named("allowlist"),
194
+			ntw,
195
+			func(ctx context.Context, size int) {
196
+				eventStream.Send(ctx, mtglib.NewEventIPListSize(size, false))
197
+			})
174
 		if err != nil {
198
 		if err != nil {
175
-			return fmt.Errorf("cannot build ip blocklist: %w", err)
199
+			return fmt.Errorf("cannot build ip allowlist: %w", err)
176
 		}
200
 		}
177
 
201
 
178
 		whitelist = whlist
202
 		whitelist = whlist
179
 	}
203
 	}
180
 
204
 
181
-	eventStream, err := makeEventStream(conf, logger)
182
-	if err != nil {
183
-		return fmt.Errorf("cannot build event stream: %w", err)
184
-	}
185
-
186
 	opts := mtglib.ProxyOpts{
205
 	opts := mtglib.ProxyOpts{
187
 		Logger:          logger,
206
 		Logger:          logger,
188
 		Network:         ntw,
207
 		Network:         ntw,

+ 3
- 3
internal/testlib/mtglib_network_mock.go Прегледај датотеку

15
 func (m *MtglibNetworkMock) Dial(network, address string) (essentials.Conn, error) {
15
 func (m *MtglibNetworkMock) Dial(network, address string) (essentials.Conn, error) {
16
 	args := m.Called(network, address)
16
 	args := m.Called(network, address)
17
 
17
 
18
-	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck
18
+	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck, forcetypeassert
19
 }
19
 }
20
 
20
 
21
 func (m *MtglibNetworkMock) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
21
 func (m *MtglibNetworkMock) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
22
 	args := m.Called(ctx, network, address)
22
 	args := m.Called(ctx, network, address)
23
 
23
 
24
-	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck
24
+	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck, forcetypeassert
25
 }
25
 }
26
 
26
 
27
 func (m *MtglibNetworkMock) MakeHTTPClient(dialFunc func(ctx context.Context,
27
 func (m *MtglibNetworkMock) MakeHTTPClient(dialFunc func(ctx context.Context,
28
 	network, address string) (essentials.Conn, error)) *http.Client {
28
 	network, address string) (essentials.Conn, error)) *http.Client {
29
-	return m.Called(dialFunc).Get(0).(*http.Client)
29
+	return m.Called(dialFunc).Get(0).(*http.Client) // nolint: forcetypeassert
30
 }
30
 }

+ 2
- 2
internal/testlib/net_conn_mock.go Прегледај датотеку

36
 }
36
 }
37
 
37
 
38
 func (n *EssentialsConnMock) LocalAddr() net.Addr {
38
 func (n *EssentialsConnMock) LocalAddr() net.Addr {
39
-	return n.Called().Get(0).(net.Addr)
39
+	return n.Called().Get(0).(net.Addr) // nolint: forcetypeassert
40
 }
40
 }
41
 
41
 
42
 func (n *EssentialsConnMock) RemoteAddr() net.Addr {
42
 func (n *EssentialsConnMock) RemoteAddr() net.Addr {
43
-	return n.Called().Get(0).(net.Addr)
43
+	return n.Called().Get(0).(net.Addr) // nolint: forcetypeassert
44
 }
44
 }
45
 
45
 
46
 func (n *EssentialsConnMock) SetDeadline(t time.Time) error {
46
 func (n *EssentialsConnMock) SetDeadline(t time.Time) error {

+ 61
- 79
ipblocklist/firehol.go Прегледај датотеку

12
 
12
 
13
 	"github.com/9seconds/mtg/v2/ipblocklist/files"
13
 	"github.com/9seconds/mtg/v2/ipblocklist/files"
14
 	"github.com/9seconds/mtg/v2/mtglib"
14
 	"github.com/9seconds/mtg/v2/mtglib"
15
-	"github.com/kentik/patricia"
16
-	"github.com/kentik/patricia/bool_tree"
17
 	"github.com/panjf2000/ants/v2"
15
 	"github.com/panjf2000/ants/v2"
16
+	"github.com/yl2chen/cidranger"
18
 )
17
 )
19
 
18
 
20
-const (
21
-	fireholIPv4DefaultCIDR = 32
22
-	fireholIPv6DefaultCIDR = 128
19
+var (
20
+	fireholRegexpComment = regexp.MustCompile(`\s*#.*?$`)
21
+
22
+	fireholIPv4DefaultCIDR = net.CIDRMask(32, 32)   // nolint: gomnd
23
+	fireholIPv6DefaultCIDR = net.CIDRMask(128, 128) // nolint: gomnd
23
 )
24
 )
24
 
25
 
25
-var fireholRegexpComment = regexp.MustCompile(`\s*#.*?$`)
26
+// FireholUpdateCallback defines a signature of the callback that has to be
27
+// execute when ip list is updated.
28
+type FireholUpdateCallback func(context.Context, int)
26
 
29
 
27
 // Firehol is IPBlocklist which uses lists from FireHOL:
30
 // Firehol is IPBlocklist which uses lists from FireHOL:
28
 // https://iplists.firehol.org/
31
 // https://iplists.firehol.org/
43
 	logger      mtglib.Logger
46
 	logger      mtglib.Logger
44
 	updateMutex sync.RWMutex
47
 	updateMutex sync.RWMutex
45
 
48
 
49
+	updateCallback FireholUpdateCallback
50
+	ranger         cidranger.Ranger
51
+
46
 	blocklists []files.File
52
 	blocklists []files.File
47
 
53
 
48
 	workerPool *ants.Pool
54
 	workerPool *ants.Pool
49
-	treeV4     *bool_tree.TreeV4
50
-	treeV6     *bool_tree.TreeV6
51
 }
55
 }
52
 
56
 
53
 // Shutdown stop a background update process.
57
 // Shutdown stop a background update process.
64
 	f.updateMutex.RLock()
68
 	f.updateMutex.RLock()
65
 	defer f.updateMutex.RUnlock()
69
 	defer f.updateMutex.RUnlock()
66
 
70
 
67
-	if ip4 := ip.To4(); ip4 != nil {
68
-		return f.containsIPv4(ip4)
71
+	ok, err := f.ranger.Contains(ip)
72
+	if err != nil {
73
+		f.logger.BindStr("ip", ip.String()).DebugError("Cannot check if ip is present", err)
69
 	}
74
 	}
70
 
75
 
71
-	return f.containsIPv6(ip.To16())
76
+	return ok && err == nil
72
 }
77
 }
73
 
78
 
74
 // Run starts a background update process.
79
 // Run starts a background update process.
103
 	}
108
 	}
104
 }
109
 }
105
 
110
 
106
-func (f *Firehol) containsIPv4(addr net.IP) bool {
107
-	ip := patricia.NewIPv4AddressFromBytes(addr, 32) // nolint: gomnd
108
-
109
-	if ok, _ := f.treeV4.FindDeepestTag(ip); ok {
110
-		return true
111
-	}
112
-
113
-	return false
114
-}
115
-
116
-func (f *Firehol) containsIPv6(addr net.IP) bool {
117
-	ip := patricia.NewIPv6Address(addr, 128) // nolint: gomnd
118
-
119
-	if ok, _ := f.treeV6.FindDeepestTag(ip); ok {
120
-		return true
121
-	}
122
-
123
-	return false
124
-}
125
-
126
 func (f *Firehol) update() {
111
 func (f *Firehol) update() {
127
 	ctx, cancel := context.WithCancel(f.ctx)
112
 	ctx, cancel := context.WithCancel(f.ctx)
128
 	defer cancel()
113
 	defer cancel()
130
 	wg := &sync.WaitGroup{}
115
 	wg := &sync.WaitGroup{}
131
 	wg.Add(len(f.blocklists))
116
 	wg.Add(len(f.blocklists))
132
 
117
 
133
-	treeMutex := &sync.Mutex{}
134
-	v4tree := bool_tree.NewTreeV4()
135
-	v6tree := bool_tree.NewTreeV6()
118
+	mutex := &sync.Mutex{}
119
+	ranger := cidranger.NewPCTrieRanger()
136
 
120
 
137
 	for _, v := range f.blocklists {
121
 	for _, v := range f.blocklists {
138
 		go func(file files.File) {
122
 		go func(file files.File) {
149
 
133
 
150
 			defer fileContent.Close()
134
 			defer fileContent.Close()
151
 
135
 
152
-			if err := f.updateFromFile(treeMutex, v4tree, v6tree, bufio.NewScanner(fileContent)); err != nil {
136
+			if err := f.updateFromFile(mutex, ranger, bufio.NewScanner(fileContent)); err != nil {
153
 				logger.WarningError("update has failed", err)
137
 				logger.WarningError("update has failed", err)
154
 			}
138
 			}
155
 		}(v)
139
 		}(v)
160
 	f.updateMutex.Lock()
144
 	f.updateMutex.Lock()
161
 	defer f.updateMutex.Unlock()
145
 	defer f.updateMutex.Unlock()
162
 
146
 
163
-	f.treeV4 = v4tree
164
-	f.treeV6 = v6tree
147
+	f.ranger = ranger
165
 
148
 
166
-	f.logger.Info("blocklist was updated")
149
+	if f.updateCallback != nil {
150
+		f.updateCallback(ctx, ranger.Len())
151
+	}
152
+
153
+	f.logger.Info("ip list was updated")
167
 }
154
 }
168
 
155
 
169
 func (f *Firehol) updateFromFile(mutex sync.Locker,
156
 func (f *Firehol) updateFromFile(mutex sync.Locker,
170
-	v4tree *bool_tree.TreeV4,
171
-	v6tree *bool_tree.TreeV6,
157
+	ranger cidranger.Ranger,
172
 	scanner *bufio.Scanner) error {
158
 	scanner *bufio.Scanner) error {
173
 	for scanner.Scan() {
159
 	for scanner.Scan() {
174
 		text := scanner.Text()
160
 		text := scanner.Text()
179
 			continue
165
 			continue
180
 		}
166
 		}
181
 
167
 
182
-		ip, cidr, err := f.updateParseLine(text)
168
+		ipnet, err := f.updateParseLine(text)
183
 		if err != nil {
169
 		if err != nil {
184
 			return fmt.Errorf("cannot parse a line: %w", err)
170
 			return fmt.Errorf("cannot parse a line: %w", err)
185
 		}
171
 		}
186
 
172
 
187
-		f.updateAddToTrees(ip, cidr, mutex, v4tree, v6tree)
173
+		mutex.Lock()
174
+		err = ranger.Insert(cidranger.NewBasicRangerEntry(*ipnet))
175
+		mutex.Unlock()
176
+
177
+		if err != nil {
178
+			return fmt.Errorf("cannot insert %v into ranger: %w", ipnet, err)
179
+		}
188
 	}
180
 	}
189
 
181
 
190
 	if scanner.Err() != nil {
182
 	if scanner.Err() != nil {
194
 	return nil
186
 	return nil
195
 }
187
 }
196
 
188
 
197
-func (f *Firehol) updateParseLine(text string) (net.IP, uint, error) {
198
-	_, ipnet, err := net.ParseCIDR(text)
199
-	if err != nil {
200
-		ipaddr := net.ParseIP(text)
201
-		if ipaddr == nil {
202
-			return nil, 0, fmt.Errorf("incorrect ip address %s", text)
203
-		}
204
-
205
-		ip4 := ipaddr.To4()
206
-		if ip4 != nil {
207
-			return ip4, fireholIPv4DefaultCIDR, nil
208
-		}
209
-
210
-		return ipaddr.To16(), fireholIPv6DefaultCIDR, nil
189
+func (f *Firehol) updateParseLine(text string) (*net.IPNet, error) {
190
+	if _, ipnet, err := net.ParseCIDR(text); err == nil {
191
+		return ipnet, nil
211
 	}
192
 	}
212
 
193
 
213
-	ones, _ := ipnet.Mask.Size()
214
-
215
-	return ipnet.IP, uint(ones), nil
216
-}
194
+	ipaddr := net.ParseIP(text)
195
+	if ipaddr == nil {
196
+		return nil, fmt.Errorf("incorrect ip address %s", text)
197
+	}
217
 
198
 
218
-func (f *Firehol) updateAddToTrees(ip net.IP, cidr uint,
219
-	mutex sync.Locker,
220
-	v4tree *bool_tree.TreeV4, v6tree *bool_tree.TreeV6) {
221
-	mutex.Lock()
222
-	defer mutex.Unlock()
199
+	mask := fireholIPv4DefaultCIDR
223
 
200
 
224
-	if ip.To4() != nil {
225
-		v4tree.Set(patricia.NewIPv4AddressFromBytes(ip, cidr), true)
226
-	} else {
227
-		v6tree.Set(patricia.NewIPv6Address(ip, cidr), true)
201
+	if ipaddr.To4() == nil {
202
+		mask = fireholIPv6DefaultCIDR
228
 	}
203
 	}
204
+
205
+	return &net.IPNet{
206
+		IP:   ipaddr,
207
+		Mask: mask,
208
+	}, nil
229
 }
209
 }
230
 
210
 
231
 // NewFirehol creates a new instance of FireHOL IP blocklist.
211
 // NewFirehol creates a new instance of FireHOL IP blocklist.
235
 func NewFirehol(logger mtglib.Logger, network mtglib.Network,
215
 func NewFirehol(logger mtglib.Logger, network mtglib.Network,
236
 	downloadConcurrency uint,
216
 	downloadConcurrency uint,
237
 	urls []string,
217
 	urls []string,
238
-	localFiles []string) (*Firehol, error) {
218
+	localFiles []string,
219
+	updateCallback FireholUpdateCallback) (*Firehol, error) {
239
 	blocklists := []files.File{}
220
 	blocklists := []files.File{}
240
 
221
 
241
 	for _, v := range localFiles {
222
 	for _, v := range localFiles {
258
 		blocklists = append(blocklists, file)
239
 		blocklists = append(blocklists, file)
259
 	}
240
 	}
260
 
241
 
261
-	return NewFireholFromFiles(logger, downloadConcurrency, blocklists)
242
+	return NewFireholFromFiles(logger, downloadConcurrency, blocklists, updateCallback)
262
 }
243
 }
263
 
244
 
264
 func NewFireholFromFiles(logger mtglib.Logger,
245
 func NewFireholFromFiles(logger mtglib.Logger,
265
 	downloadConcurrency uint,
246
 	downloadConcurrency uint,
266
-	blocklists []files.File) (*Firehol, error) {
247
+	blocklists []files.File,
248
+	updateCallback FireholUpdateCallback) (*Firehol, error) {
267
 	if downloadConcurrency == 0 {
249
 	if downloadConcurrency == 0 {
268
 		downloadConcurrency = DefaultFireholDownloadConcurrency
250
 		downloadConcurrency = DefaultFireholDownloadConcurrency
269
 	}
251
 	}
272
 	ctx, cancel := context.WithCancel(context.Background())
254
 	ctx, cancel := context.WithCancel(context.Background())
273
 
255
 
274
 	return &Firehol{
256
 	return &Firehol{
275
-		ctx:        ctx,
276
-		ctxCancel:  cancel,
277
-		logger:     logger.Named("firehol"),
278
-		treeV4:     bool_tree.NewTreeV4(),
279
-		treeV6:     bool_tree.NewTreeV6(),
280
-		workerPool: workerPool,
281
-		blocklists: blocklists,
257
+		ctx:            ctx,
258
+		ctxCancel:      cancel,
259
+		logger:         logger.Named("firehol"),
260
+		ranger:         cidranger.NewPCTrieRanger(),
261
+		workerPool:     workerPool,
262
+		blocklists:     blocklists,
263
+		updateCallback: updateCallback,
282
 	}, nil
264
 	}, nil
283
 }
265
 }

+ 6
- 4
ipblocklist/firehol_test.go Прегледај датотеку

67
 func (suite *FireholTestSuite) TestLocalFail() {
67
 func (suite *FireholTestSuite) TestLocalFail() {
68
 	blocklist, err := ipblocklist.NewFirehol(logger.NewNoopLogger(),
68
 	blocklist, err := ipblocklist.NewFirehol(logger.NewNoopLogger(),
69
 		suite.networkMock, 2,
69
 		suite.networkMock, 2,
70
-		nil, []string{filepath.Join("testdata", "broken_ipset.ipset")})
70
+		nil, []string{filepath.Join("testdata", "broken_ipset.ipset")},
71
+		nil)
71
 
72
 
72
 	suite.NoError(err)
73
 	suite.NoError(err)
73
 
74
 
85
 func (suite *FireholTestSuite) TestLocalOk() {
86
 func (suite *FireholTestSuite) TestLocalOk() {
86
 	blocklist, err := ipblocklist.NewFirehol(logger.NewNoopLogger(),
87
 	blocklist, err := ipblocklist.NewFirehol(logger.NewNoopLogger(),
87
 		suite.networkMock, 2,
88
 		suite.networkMock, 2,
88
-		nil, []string{filepath.Join("testdata", "good_ipset.ipset")})
89
+		nil, []string{filepath.Join("testdata", "good_ipset.ipset")},
90
+		nil)
89
 
91
 
90
 	suite.NoError(err)
92
 	suite.NoError(err)
91
 
93
 
103
 func (suite *FireholTestSuite) TestRemoteFail() {
105
 func (suite *FireholTestSuite) TestRemoteFail() {
104
 	blocklist, err := ipblocklist.NewFirehol(logger.NewNoopLogger(),
106
 	blocklist, err := ipblocklist.NewFirehol(logger.NewNoopLogger(),
105
 		suite.networkMock, 2,
107
 		suite.networkMock, 2,
106
-		[]string{"https://google.com"}, nil)
108
+		[]string{"https://google.com"}, nil, nil)
107
 
109
 
108
 	suite.NoError(err)
110
 	suite.NoError(err)
109
 
111
 
127
 			suite.httpServer.URL,
129
 			suite.httpServer.URL,
128
 		}, []string{
130
 		}, []string{
129
 			filepath.Join("testdata", "good_ipset.ipset"),
131
 			filepath.Join("testdata", "good_ipset.ipset"),
130
-		})
132
+		}, nil)
131
 
133
 
132
 	suite.NoError(err)
134
 	suite.NoError(err)
133
 
135
 

+ 4
- 1
ipblocklist/noop.go Прегледај датотеку

2
 
2
 
3
 import (
3
 import (
4
 	"net"
4
 	"net"
5
+	"time"
5
 
6
 
6
 	"github.com/9seconds/mtg/v2/mtglib"
7
 	"github.com/9seconds/mtg/v2/mtglib"
7
 )
8
 )
8
 
9
 
9
 type noop struct{}
10
 type noop struct{}
10
 
11
 
11
-func (n noop) Contains(ip net.IP) bool { return false }
12
+func (n noop) Contains(ip net.IP) bool      { return false }
13
+func (n noop) Run(updateEach time.Duration) {}
14
+func (n noop) Shutdown()                    {}
12
 
15
 
13
 // NewNoop returns a dummy ipblocklist which allows all incoming
16
 // NewNoop returns a dummy ipblocklist which allows all incoming
14
 // connections.
17
 // connections.

+ 7
- 0
ipblocklist/noop_test.go Прегледај датотеку

17
 	suite.False(ipblocklist.NewNoop().Contains(net.ParseIP("10.0.0.10")))
17
 	suite.False(ipblocklist.NewNoop().Contains(net.ParseIP("10.0.0.10")))
18
 }
18
 }
19
 
19
 
20
+func (suite *NoopTestSuite) TestRun() {
21
+	blocklist := ipblocklist.NewNoop()
22
+
23
+	blocklist.Run(0)
24
+	blocklist.Shutdown()
25
+}
26
+
20
 func TestNoop(t *testing.T) {
27
 func TestNoop(t *testing.T) {
21
 	t.Parallel()
28
 	t.Parallel()
22
 	suite.Run(t, &NoopTestSuite{})
29
 	suite.Run(t, &NoopTestSuite{})

+ 20
- 0
mtglib/events.go Прегледај датотеку

92
 	eventBase
92
 	eventBase
93
 }
93
 }
94
 
94
 
95
+// EventIPListSize is emitted when mtg updates a contents of the ip lists:
96
+// allowlist or blocklist.
97
+type EventIPListSize struct {
98
+	eventBase
99
+
100
+	Size        int
101
+	IsBlockList bool
102
+}
103
+
95
 // NewEventStart creates a new EventStart event.
104
 // NewEventStart creates a new EventStart event.
96
 func NewEventStart(streamID string, remoteIP net.IP) EventStart {
105
 func NewEventStart(streamID string, remoteIP net.IP) EventStart {
97
 	return EventStart{
106
 	return EventStart{
176
 		},
185
 		},
177
 	}
186
 	}
178
 }
187
 }
188
+
189
+// NewEventIPListSize creates a new EventIPListSize event.
190
+func NewEventIPListSize(size int, isBlockList bool) EventIPListSize {
191
+	return EventIPListSize{
192
+		eventBase: eventBase{
193
+			timestamp: time.Now(),
194
+		},
195
+		Size:        size,
196
+		IsBlockList: isBlockList,
197
+	}
198
+}

+ 9
- 0
mtglib/events_test.go Прегледај датотеку

69
 	suite.WithinDuration(time.Now(), evt.Timestamp(), 10*time.Millisecond)
69
 	suite.WithinDuration(time.Now(), evt.Timestamp(), 10*time.Millisecond)
70
 }
70
 }
71
 
71
 
72
+func (suite *EventsTestSuite) TestEventIPListSize() {
73
+	evt := mtglib.NewEventIPListSize(10, false)
74
+
75
+	suite.Empty(evt.StreamID())
76
+	suite.WithinDuration(time.Now(), evt.Timestamp(), 10*time.Millisecond)
77
+	suite.Equal(10, evt.Size)
78
+	suite.False(evt.IsBlockList)
79
+}
80
+
72
 func TestEvents(t *testing.T) {
81
 func TestEvents(t *testing.T) {
73
 	t.Parallel()
82
 	t.Parallel()
74
 	suite.Run(t, &EventsTestSuite{})
83
 	suite.Run(t, &EventsTestSuite{})

+ 6
- 0
mtglib/init.go Прегледај датотеку

176
 	// Contains checks if given IP address belongs to this blocklist If.
176
 	// Contains checks if given IP address belongs to this blocklist If.
177
 	// it is, a connection is terminated                               .
177
 	// it is, a connection is terminated                               .
178
 	Contains(net.IP) bool
178
 	Contains(net.IP) bool
179
+
180
+	// Run starts a background update procedure for a blocklist
181
+	Run(time.Duration)
182
+
183
+	// Shutdown stops a blocklist. It is assumed that none will access it after.
184
+	Shutdown()
179
 }
185
 }
180
 
186
 
181
 // Event is a data structure which is populated during mtg request
187
 // Event is a data structure which is populated during mtg request

+ 1
- 1
mtglib/internal/faketls/pools.go Прегледај датотеку

12
 }
12
 }
13
 
13
 
14
 func acquireBytesBuffer() *bytes.Buffer {
14
 func acquireBytesBuffer() *bytes.Buffer {
15
-	return bytesBufferPool.Get().(*bytes.Buffer)
15
+	return bytesBufferPool.Get().(*bytes.Buffer) // nolint: forcetypeassert
16
 }
16
 }
17
 
17
 
18
 func releaseBytesBuffer(b *bytes.Buffer) {
18
 func releaseBytesBuffer(b *bytes.Buffer) {

+ 1
- 1
mtglib/internal/faketls/record/pools.go Прегледај датотеку

11
 }
11
 }
12
 
12
 
13
 func AcquireRecord() *Record {
13
 func AcquireRecord() *Record {
14
-	return recordPool.Get().(*Record)
14
+	return recordPool.Get().(*Record) // nolint: forcetypeassert
15
 }
15
 }
16
 
16
 
17
 func ReleaseRecord(r *Record) {
17
 func ReleaseRecord(r *Record) {

+ 2
- 2
mtglib/internal/obfuscated2/pools.go Прегледај датотеку

21
 )
21
 )
22
 
22
 
23
 func acquireSha256Hasher() hash.Hash {
23
 func acquireSha256Hasher() hash.Hash {
24
-	return sha256HasherPool.Get().(hash.Hash)
24
+	return sha256HasherPool.Get().(hash.Hash) // nolint: forcetypeassert
25
 }
25
 }
26
 
26
 
27
 func releaseSha256Hasher(h hash.Hash) {
27
 func releaseSha256Hasher(h hash.Hash) {
30
 }
30
 }
31
 
31
 
32
 func acquireBytesBuffer() *bytes.Buffer {
32
 func acquireBytesBuffer() *bytes.Buffer {
33
-	return bytesBufferPool.Get().(*bytes.Buffer)
33
+	return bytesBufferPool.Get().(*bytes.Buffer) // nolint: forcetypeassert
34
 }
34
 }
35
 
35
 
36
 func releaseBytesBuffer(buf *bytes.Buffer) {
36
 func releaseBytesBuffer(buf *bytes.Buffer) {

+ 2
- 2
mtglib/internal/obfuscated2/server_handshake_test.go Прегледај датотеку

69
 		Once().
69
 		Once().
70
 		Run(func(args mock.Arguments) {
70
 		Run(func(args mock.Arguments) {
71
 			message := make([]byte, len(messageToTelegram))
71
 			message := make([]byte, len(messageToTelegram))
72
-			suite.decryptor.XORKeyStream(message, args.Get(0).([]byte))
72
+			suite.decryptor.XORKeyStream(message, args.Get(0).([]byte)) // nolint: forcetypeassert
73
 			suite.Equal(messageToTelegram, message)
73
 			suite.Equal(messageToTelegram, message)
74
 		})
74
 		})
75
 
75
 
89
 		Run(func(args mock.Arguments) {
89
 		Run(func(args mock.Arguments) {
90
 			message := make([]byte, len(messageFromTelegram))
90
 			message := make([]byte, len(messageFromTelegram))
91
 			suite.encryptor.XORKeyStream(message, messageFromTelegram)
91
 			suite.encryptor.XORKeyStream(message, messageFromTelegram)
92
-			copy(args.Get(0).([]byte), message)
92
+			copy(args.Get(0).([]byte), message) // nolint: forcetypeassert
93
 		})
93
 		})
94
 
94
 
95
 	n, err := suite.proxyConn.Read(buffer)
95
 	n, err := suite.proxyConn.Read(buffer)

+ 1
- 1
mtglib/internal/relay/pools.go Прегледај датотеку

11
 }
11
 }
12
 
12
 
13
 func acquireCopyBuffer() *[]byte {
13
 func acquireCopyBuffer() *[]byte {
14
-	return copyBufferPool.Get().(*[]byte)
14
+	return copyBufferPool.Get().(*[]byte) // nolint: forcetypeassert
15
 }
15
 }
16
 
16
 
17
 func releaseCopyBuffer(buf *[]byte) {
17
 func releaseCopyBuffer(buf *[]byte) {

+ 3
- 0
mtglib/internal/telegram/init.go Прегледај датотеку

2
 
2
 
3
 import (
3
 import (
4
 	"context"
4
 	"context"
5
+	"errors"
5
 
6
 
6
 	"github.com/9seconds/mtg/v2/essentials"
7
 	"github.com/9seconds/mtg/v2/essentials"
7
 )
8
 )
8
 
9
 
10
+var errNoAddresses = errors.New("no addresses")
11
+
9
 type preferIP uint8
12
 type preferIP uint8
10
 
13
 
11
 const (
14
 const (

+ 3
- 4
mtglib/internal/telegram/telegram.go Прегледај датотеку

28
 		addresses = append(t.pool.getV6(dc), t.pool.getV4(dc)...)
28
 		addresses = append(t.pool.getV6(dc), t.pool.getV4(dc)...)
29
 	}
29
 	}
30
 
30
 
31
-	var (
32
-		conn essentials.Conn
33
-		err  error
34
-	)
31
+	var conn essentials.Conn
32
+
33
+	err := errNoAddresses
35
 
34
 
36
 	for _, v := range addresses {
35
 	for _, v := range addresses {
37
 		conn, err = t.dialer.DialContext(ctx, v.network, v.address)
36
 		conn, err = t.dialer.DialContext(ctx, v.network, v.address)

+ 12
- 3
mtglib/proxy.go Прегледај датотеку

106
 			}
106
 			}
107
 		}
107
 		}
108
 
108
 
109
-		ipAddr := conn.RemoteAddr().(*net.TCPAddr).IP
109
+		ipAddr := conn.RemoteAddr().(*net.TCPAddr).IP // nolint: forcetypeassert
110
 		logger := p.logger.BindStr("ip", ipAddr.String())
110
 		logger := p.logger.BindStr("ip", ipAddr.String())
111
 
111
 
112
 		if p.whitelist != nil && !p.whitelist.Contains(ipAddr) {
112
 		if p.whitelist != nil && !p.whitelist.Contains(ipAddr) {
144
 	p.ctxCancel()
144
 	p.ctxCancel()
145
 	p.streamWaitGroup.Wait()
145
 	p.streamWaitGroup.Wait()
146
 	p.workerPool.Release()
146
 	p.workerPool.Release()
147
+
148
+	if p.whitelist != nil {
149
+		p.whitelist.Shutdown()
150
+	}
151
+
152
+	p.blocklist.Shutdown()
147
 }
153
 }
148
 
154
 
149
 func (p *Proxy) doFakeTLSHandshake(ctx *streamContext) bool {
155
 func (p *Proxy) doFakeTLSHandshake(ctx *streamContext) bool {
249
 	}
255
 	}
250
 
256
 
251
 	p.eventStream.Send(ctx,
257
 	p.eventStream.Send(ctx,
252
-		NewEventConnectedToDC(ctx.streamID, conn.RemoteAddr().(*net.TCPAddr).IP, ctx.dc))
258
+		NewEventConnectedToDC(ctx.streamID,
259
+			conn.RemoteAddr().(*net.TCPAddr).IP, // nolint: forcetypeassert
260
+			ctx.dc),
261
+	)
253
 
262
 
254
 	return nil
263
 	return nil
255
 }
264
 }
310
 
319
 
311
 	pool, err := ants.NewPoolWithFunc(opts.getConcurrency(),
320
 	pool, err := ants.NewPoolWithFunc(opts.getConcurrency(),
312
 		func(arg interface{}) {
321
 		func(arg interface{}) {
313
-			proxy.ServeConn(arg.(essentials.Conn))
322
+			proxy.ServeConn(arg.(essentials.Conn)) // nolint: forcetypeassert
314
 		},
323
 		},
315
 		ants.WithLogger(opts.getLogger("ants")),
324
 		ants.WithLogger(opts.getLogger("ants")),
316
 		ants.WithNonblocking(true))
325
 		ants.WithNonblocking(true))

+ 1
- 1
mtglib/stream_context.go Прегледај датотеку

49
 }
49
 }
50
 
50
 
51
 func (s *streamContext) ClientIP() net.IP {
51
 func (s *streamContext) ClientIP() net.IP {
52
-	return s.clientConn.RemoteAddr().(*net.TCPAddr).IP
52
+	return s.clientConn.RemoteAddr().(*net.TCPAddr).IP // nolint: forcetypeassert
53
 }
53
 }
54
 
54
 
55
 func newStreamContext(ctx context.Context, logger Logger, clientConn essentials.Conn) *streamContext {
55
 func newStreamContext(ctx context.Context, logger Logger, clientConn essentials.Conn) *streamContext {

+ 1
- 1
network/default.go Прегледај датотеку

36
 		return nil, fmt.Errorf("cannot set socket options: %w", err)
36
 		return nil, fmt.Errorf("cannot set socket options: %w", err)
37
 	}
37
 	}
38
 
38
 
39
-	return conn.(essentials.Conn), nil
39
+	return conn.(essentials.Conn), nil // nolint: forcetypeassert
40
 }
40
 }
41
 
41
 
42
 // NewDefaultDialer build a new dialer which dials bypassing proxies
42
 // NewDefaultDialer build a new dialer which dials bypassing proxies

+ 2
- 2
network/init_internal_test.go Прегледај датотеку

14
 func (d *DialerMock) Dial(network, address string) (essentials.Conn, error) {
14
 func (d *DialerMock) Dial(network, address string) (essentials.Conn, error) {
15
 	args := d.Called(network, address)
15
 	args := d.Called(network, address)
16
 
16
 
17
-	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck
17
+	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck, forcetypeassert
18
 }
18
 }
19
 
19
 
20
 func (d *DialerMock) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
20
 func (d *DialerMock) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
21
 	args := d.Called(ctx, network, address)
21
 	args := d.Called(ctx, network, address)
22
 
22
 
23
-	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck
23
+	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck, forcetypeassert
24
 }
24
 }

+ 2
- 2
network/init_test.go Прегледај датотеку

22
 func (d *DialerMock) Dial(network, address string) (essentials.Conn, error) {
22
 func (d *DialerMock) Dial(network, address string) (essentials.Conn, error) {
23
 	args := d.Called(network, address)
23
 	args := d.Called(network, address)
24
 
24
 
25
-	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck
25
+	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck, forcetypeassert
26
 }
26
 }
27
 
27
 
28
 func (d *DialerMock) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
28
 func (d *DialerMock) DialContext(ctx context.Context, network, address string) (essentials.Conn, error) {
29
 	args := d.Called(ctx, network, address)
29
 	args := d.Called(ctx, network, address)
30
 
30
 
31
-	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck
31
+	return args.Get(0).(essentials.Conn), args.Error(1) // nolint: wrapcheck, forcetypeassert
32
 }
32
 }
33
 
33
 
34
 type HTTPServerTestSuite struct {
34
 type HTTPServerTestSuite struct {

+ 2
- 2
network/sockopts.go Прегледај датотеку

10
 //
10
 //
11
 // bufferSize setting is deprecated and ignored.
11
 // bufferSize setting is deprecated and ignored.
12
 func SetClientSocketOptions(conn net.Conn, bufferSize int) error {
12
 func SetClientSocketOptions(conn net.Conn, bufferSize int) error {
13
-	return setCommonSocketOptions(conn.(*net.TCPConn))
13
+	return setCommonSocketOptions(conn.(*net.TCPConn)) // nolint: forcetypeassert
14
 }
14
 }
15
 
15
 
16
 // SetServerSocketOptions tunes a TCP socket that represents a connection to
16
 // SetServerSocketOptions tunes a TCP socket that represents a connection to
17
 // remote server like Telegram or fronting domain (but not end user).
17
 // remote server like Telegram or fronting domain (but not end user).
18
 func SetServerSocketOptions(conn net.Conn, bufferSize int) error {
18
 func SetServerSocketOptions(conn net.Conn, bufferSize int) error {
19
-	return setCommonSocketOptions(conn.(*net.TCPConn))
19
+	return setCommonSocketOptions(conn.(*net.TCPConn)) // nolint: forcetypeassert
20
 }
20
 }
21
 
21
 
22
 func setCommonSocketOptions(conn *net.TCPConn) error {
22
 func setCommonSocketOptions(conn *net.TCPConn) error {

+ 16
- 0
stats/init.go Прегледај датотеку

89
 	//     Type: counter
89
 	//     Type: counter
90
 	MetricReplayAttacks = "replay_attacks"
90
 	MetricReplayAttacks = "replay_attacks"
91
 
91
 
92
+	// MetricIPListSize defines a metric for the size of the the ip list.
93
+	//
94
+	//     Type: gauge
95
+	//     Tags:
96
+	//       ip_list | 'allowlist' or 'blocklist'
97
+	MetricIPListSize = "iplist_size"
98
+
92
 	// TagIPFamily defines a name of the 'ip_family' tag and all values.
99
 	// TagIPFamily defines a name of the 'ip_family' tag and all values.
93
 	TagIPFamily = "ip_family"
100
 	TagIPFamily = "ip_family"
94
 
101
 
114
 	// TagDirectionFromClient defines that traffic is sent from a client to
121
 	// TagDirectionFromClient defines that traffic is sent from a client to
115
 	// Telegram.
122
 	// Telegram.
116
 	TagDirectionFromClient = "from_client"
123
 	TagDirectionFromClient = "from_client"
124
+
125
+	// TagIPList defines a name of the 'ip_list' and all values.
126
+	TagIPList = "ip_list"
127
+
128
+	// TagIPListAllow defines a value of 'ip_list' of allowlist.
129
+	TagIPListAllow = "allowlist"
130
+
131
+	// TagIPListBlock defines a value of 'ip_list' of blocklist.
132
+	TagIPListBlock = "blocklist"
117
 )
133
 )

+ 1
- 1
stats/pools.go Прегледај датотеку

11
 }
11
 }
12
 
12
 
13
 func acquireStreamInfo() *streamInfo {
13
 func acquireStreamInfo() *streamInfo {
14
-	return streamInfoPool.Get().(*streamInfo)
14
+	return streamInfoPool.Get().(*streamInfo) // nolint: forcetypeassert
15
 }
15
 }
16
 
16
 
17
 func releaseStreamInfo(info *streamInfo) {
17
 func releaseStreamInfo(info *streamInfo) {

+ 16
- 0
stats/prometheus.go Прегледај датотеку

118
 	p.factory.metricReplayAttacks.Inc()
118
 	p.factory.metricReplayAttacks.Inc()
119
 }
119
 }
120
 
120
 
121
+func (p prometheusProcessor) EventIPListSize(evt mtglib.EventIPListSize) {
122
+	tag := TagIPListBlock
123
+	if !evt.IsBlockList {
124
+		tag = TagIPListAllow
125
+	}
126
+
127
+	p.factory.metricIPListSize.WithLabelValues(tag).Set(float64(evt.Size))
128
+}
129
+
121
 func (p prometheusProcessor) Shutdown() {
130
 func (p prometheusProcessor) Shutdown() {
122
 	for k, v := range p.streams {
131
 	for k, v := range p.streams {
123
 		releaseStreamInfo(v)
132
 		releaseStreamInfo(v)
137
 	metricClientConnections         *prometheus.GaugeVec
146
 	metricClientConnections         *prometheus.GaugeVec
138
 	metricTelegramConnections       *prometheus.GaugeVec
147
 	metricTelegramConnections       *prometheus.GaugeVec
139
 	metricDomainFrontingConnections *prometheus.GaugeVec
148
 	metricDomainFrontingConnections *prometheus.GaugeVec
149
+	metricIPListSize                *prometheus.GaugeVec
140
 
150
 
141
 	metricTelegramTraffic       *prometheus.CounterVec
151
 	metricTelegramTraffic       *prometheus.CounterVec
142
 	metricDomainFrontingTraffic *prometheus.CounterVec
152
 	metricDomainFrontingTraffic *prometheus.CounterVec
197
 			Name:      MetricDomainFrontingConnections,
207
 			Name:      MetricDomainFrontingConnections,
198
 			Help:      "A number of connections which talk to front domain.",
208
 			Help:      "A number of connections which talk to front domain.",
199
 		}, []string{TagIPFamily}),
209
 		}, []string{TagIPFamily}),
210
+		metricIPListSize: prometheus.NewGaugeVec(prometheus.GaugeOpts{
211
+			Namespace: metricPrefix,
212
+			Name:      MetricIPListSize,
213
+			Help:      "A size of the ip list (blocklist or allowlist)",
214
+		}, []string{TagIPList}),
200
 
215
 
201
 		metricTelegramTraffic: prometheus.NewCounterVec(prometheus.CounterOpts{
216
 		metricTelegramTraffic: prometheus.NewCounterVec(prometheus.CounterOpts{
202
 			Namespace: metricPrefix,
217
 			Namespace: metricPrefix,
234
 	registry.MustRegister(factory.metricClientConnections)
249
 	registry.MustRegister(factory.metricClientConnections)
235
 	registry.MustRegister(factory.metricTelegramConnections)
250
 	registry.MustRegister(factory.metricTelegramConnections)
236
 	registry.MustRegister(factory.metricDomainFrontingConnections)
251
 	registry.MustRegister(factory.metricDomainFrontingConnections)
252
+	registry.MustRegister(factory.metricIPListSize)
237
 
253
 
238
 	registry.MustRegister(factory.metricTelegramTraffic)
254
 	registry.MustRegister(factory.metricTelegramTraffic)
239
 	registry.MustRegister(factory.metricDomainFrontingTraffic)
255
 	registry.MustRegister(factory.metricDomainFrontingTraffic)

+ 12
- 0
stats/prometheus_test.go Прегледај датотеку

169
 	suite.Contains(data, `mtg_replay_attacks 1`)
169
 	suite.Contains(data, `mtg_replay_attacks 1`)
170
 }
170
 }
171
 
171
 
172
+func (suite *PrometheusTestSuite) TestEventIPListSize() {
173
+	suite.prometheus.EventIPListSize(mtglib.NewEventIPListSize(10, false))
174
+	suite.prometheus.EventIPListSize(mtglib.NewEventIPListSize(3, true))
175
+
176
+	time.Sleep(100 * time.Millisecond)
177
+
178
+	data, err := suite.Get()
179
+	suite.NoError(err)
180
+	suite.Contains(data, `mtg_iplist_size{ip_list="allowlist"} 10`)
181
+	suite.Contains(data, `mtg_iplist_size{ip_list="blocklist"} 3`)
182
+}
183
+
172
 func TestPrometheus(t *testing.T) {
184
 func TestPrometheus(t *testing.T) {
173
 	t.Parallel()
185
 	t.Parallel()
174
 	suite.Run(t, &PrometheusTestSuite{})
186
 	suite.Run(t, &PrometheusTestSuite{})

+ 9
- 0
stats/statsd.go Прегледај датотеку

121
 	s.client.Incr(MetricReplayAttacks, 1)
121
 	s.client.Incr(MetricReplayAttacks, 1)
122
 }
122
 }
123
 
123
 
124
+func (s statsdProcessor) EventIPListSize(evt mtglib.EventIPListSize) {
125
+	tag := TagIPListBlock
126
+	if !evt.IsBlockList {
127
+		tag = TagIPListAllow
128
+	}
129
+
130
+	s.client.Gauge(MetricIPListSize, int64(evt.Size), statsd.StringTag(TagIPList, tag))
131
+}
132
+
124
 func (s statsdProcessor) Shutdown() {
133
 func (s statsdProcessor) Shutdown() {
125
 	events := make([]mtglib.EventFinish, 0, len(s.streams))
134
 	events := make([]mtglib.EventFinish, 0, len(s.streams))
126
 
135
 

+ 16
- 0
stats/statsd_test.go Прегледај датотеку

196
 	suite.Equal("mtg.replay_attacks:1|c", suite.statsdServer.String())
196
 	suite.Equal("mtg.replay_attacks:1|c", suite.statsdServer.String())
197
 }
197
 }
198
 
198
 
199
+func (suite *StatsdTestSuite) TestEventIPListSizeAllowlist() {
200
+	suite.statsd.EventIPListSize(mtglib.NewEventIPListSize(10, false))
201
+
202
+	time.Sleep(statsdSleepTime)
203
+	suite.Contains(suite.statsdServer.String(), "mtg.iplist_size:10|g")
204
+	suite.Contains(suite.statsdServer.String(), "allowlist")
205
+}
206
+
207
+func (suite *StatsdTestSuite) TestEventIPListSizeBlocklist() {
208
+	suite.statsd.EventIPListSize(mtglib.NewEventIPListSize(10, true))
209
+
210
+	time.Sleep(statsdSleepTime)
211
+	suite.Contains(suite.statsdServer.String(), "mtg.iplist_size:10|g")
212
+	suite.Contains(suite.statsdServer.String(), "blocklist")
213
+}
214
+
199
 func TestStatsd(t *testing.T) {
215
 func TestStatsd(t *testing.T) {
200
 	t.Parallel()
216
 	t.Parallel()
201
 	suite.Run(t, &StatsdTestSuite{})
217
 	suite.Run(t, &StatsdTestSuite{})

Loading…
Откажи
Сачувај