瀏覽代碼

Add correct configuration

tags/v2.0.0-rc1
9seconds 5 年之前
父節點
當前提交
d1dd56550f
共有 6 個檔案被更改,包括 389 行新增43 行删除
  1. 376
    7
      config.go
  2. 5
    30
      example.config.toml
  3. 1
    0
      go.mod
  4. 3
    0
      go.sum
  5. 1
    3
      mtglib/init.go
  6. 3
    3
      mtglib/secret.go

+ 376
- 7
config.go 查看文件

@@ -5,14 +5,383 @@ import (
5 5
 	"encoding/json"
6 6
 	"fmt"
7 7
 	"io"
8
+	"net"
9
+	"net/url"
10
+	"regexp"
11
+	"strconv"
12
+	"strings"
13
+	"time"
8 14
 
9 15
 	"github.com/9seconds/mtg/v2/mtglib"
16
+	"github.com/alecthomas/units"
10 17
 	"github.com/pelletier/go-toml"
11 18
 )
12 19
 
20
+type configTypeHostPort struct {
21
+	host configTypeIP
22
+	port configTypePort
23
+}
24
+
25
+func (c *configTypeHostPort) UnmarshalText(data []byte) error {
26
+	if len(data) == 0 {
27
+		return nil
28
+	}
29
+
30
+	host, port, err := net.SplitHostPort(string(data))
31
+	if err != nil {
32
+		return fmt.Errorf("incorrect host:port syntax: %w", err)
33
+	}
34
+
35
+	if err := c.port.UnmarshalJSON([]byte(port)); err != nil {
36
+		return fmt.Errorf("incorrect port in host:port: %w", err)
37
+	}
38
+
39
+	if err := c.host.UnmarshalText([]byte(host)); err != nil {
40
+		return fmt.Errorf("incorrect host: %w", err)
41
+	}
42
+
43
+	return nil
44
+}
45
+
46
+func (c configTypeHostPort) String() string {
47
+	return c.Value(net.IP{}, 0)
48
+}
49
+
50
+func (c configTypeHostPort) Value(defaultHostValue net.IP, defaultPortValue uint) string {
51
+	return net.JoinHostPort(c.host.Value(defaultHostValue).String(),
52
+		strconv.Itoa(int(c.port.Value(defaultPortValue))))
53
+}
54
+
55
+type configTypePort struct {
56
+	value uint
57
+}
58
+
59
+func (c *configTypePort) UnmarshalJSON(data []byte) error {
60
+	if len(data) == 0 {
61
+		return nil
62
+	}
63
+
64
+	intValue, err := strconv.ParseUint(string(data), 10, 16)
65
+	if err != nil {
66
+		return fmt.Errorf("port number is not a number: %w", err)
67
+	}
68
+
69
+	if intValue == 0 || intValue > 65536 {
70
+		return fmt.Errorf("port number should be 0 < portNo < 65536: %d", intValue)
71
+	}
72
+
73
+	c.value = uint(intValue)
74
+
75
+	return nil
76
+}
77
+
78
+func (c configTypePort) String() string {
79
+	return strconv.Itoa(int(c.value))
80
+}
81
+
82
+func (c configTypePort) Value(defaultValue uint) uint {
83
+	if c.value == 0 {
84
+		return defaultValue
85
+	}
86
+
87
+	return c.value
88
+}
89
+
90
+type configTypeBytes struct {
91
+	value uint
92
+}
93
+
94
+func (c *configTypeBytes) UnmarshalText(data []byte) error {
95
+	if len(data) == 0 {
96
+		return nil
97
+	}
98
+
99
+	value, err := units.ParseStrictBytes(strings.ToUpper(string(data)))
100
+	if err != nil {
101
+		return fmt.Errorf("incorrect bytes value: %w", err)
102
+	}
103
+
104
+	if value < 0 {
105
+		return fmt.Errorf("%d should be positive number", value)
106
+	}
107
+
108
+	c.value = uint(value)
109
+
110
+	return nil
111
+}
112
+
113
+func (c configTypeBytes) String() string {
114
+	return units.ToString(int64(c.value), 1024, "ib", "b")
115
+}
116
+
117
+func (c configTypeBytes) Value(defaultValue uint) uint {
118
+	if c.value == 0 {
119
+		return defaultValue
120
+	}
121
+
122
+	return c.value
123
+}
124
+
125
+type configTypePreferIP struct {
126
+	value string
127
+}
128
+
129
+func (c *configTypePreferIP) UnmarshalText(data []byte) error {
130
+	if len(data) == 0 {
131
+		return nil
132
+	}
133
+
134
+	text := strings.ToLower(string(data))
135
+
136
+	switch text {
137
+	case "prefer-ipv4", "prefer-ipv6", "only-ipv4", "only-ipv6":
138
+		c.value = text
139
+	default:
140
+		return fmt.Errorf("incorrect prefer-ip value: %s", string(data))
141
+	}
142
+
143
+	return nil
144
+}
145
+
146
+func (c *configTypePreferIP) String() string {
147
+	return c.value
148
+}
149
+
150
+func (c *configTypePreferIP) Value(defaultValue string) string {
151
+	if c.value == "" {
152
+		return defaultValue
153
+	}
154
+
155
+	return c.value
156
+}
157
+
158
+type configTypeDuration struct {
159
+	value time.Duration
160
+}
161
+
162
+func (c *configTypeDuration) UnmarshalText(data []byte) error {
163
+	if len(data) == 0 {
164
+		return nil
165
+	}
166
+
167
+	dur, err := time.ParseDuration(strings.ToLower(string(data)))
168
+	if err != nil {
169
+		return fmt.Errorf("incorrect duration: %w", err)
170
+	}
171
+
172
+	if dur < 0 {
173
+		return fmt.Errorf("%s should be positive duration", dur)
174
+	}
175
+
176
+	c.value = dur
177
+
178
+	return nil
179
+}
180
+
181
+func (c configTypeDuration) String() string {
182
+	return c.value.String()
183
+}
184
+
185
+func (c configTypeDuration) Value(defaultValue time.Duration) time.Duration {
186
+	if c.value == 0 {
187
+		return defaultValue
188
+	}
189
+
190
+	return c.value
191
+}
192
+
193
+type configTypeFloat struct {
194
+	value float64
195
+}
196
+
197
+func (c *configTypeFloat) UnmarshalJSON(data []byte) error {
198
+	value, err := strconv.ParseFloat(string(data), 64)
199
+	if err != nil {
200
+		return fmt.Errorf("incorrect float value: %w", err)
201
+	}
202
+
203
+	if value < 0 {
204
+		return fmt.Errorf("%f should be positive", value)
205
+	}
206
+
207
+	c.value = value
208
+
209
+	return nil
210
+}
211
+
212
+func (c configTypeFloat) String() string {
213
+	return strconv.FormatFloat(c.value, 'f', -1, 64)
214
+}
215
+
216
+func (c configTypeFloat) Value(defaultValue float64) float64 {
217
+	if c.value < 0.00001 {
218
+		return defaultValue
219
+	}
220
+
221
+	return c.value
222
+}
223
+
224
+type configTypeIP struct {
225
+	value net.IP
226
+}
227
+
228
+func (c *configTypeIP) UnmarshalText(data []byte) error {
229
+	if len(data) == 0 {
230
+		return nil
231
+	}
232
+
233
+	ip := net.ParseIP(string(data))
234
+	if ip == nil {
235
+		return fmt.Errorf("incorrect ip address: %s", string(data))
236
+	}
237
+
238
+	c.value = ip
239
+
240
+	return nil
241
+}
242
+
243
+func (c configTypeIP) String() string {
244
+	return c.value.String()
245
+}
246
+
247
+func (c configTypeIP) Value(defaultValue net.IP) net.IP {
248
+	if c.value == nil {
249
+		return defaultValue
250
+	}
251
+
252
+	return c.value
253
+}
254
+
255
+type configTypeURL struct {
256
+	value *url.URL
257
+}
258
+
259
+func (c *configTypeURL) UnmarshalText(data []byte) error {
260
+	if len(data) == 0 {
261
+		return nil
262
+	}
263
+
264
+	value, err := url.Parse(string(data))
265
+	if err != nil {
266
+		return fmt.Errorf("incorrect URL: %w", err)
267
+	}
268
+
269
+	c.value = value
270
+
271
+	return nil
272
+}
273
+
274
+func (c configTypeURL) String() string {
275
+	if c.value == nil {
276
+		return ""
277
+	}
278
+
279
+	return c.value.String()
280
+}
281
+
282
+func (c configTypeURL) Value(defaultValue *url.URL) *url.URL {
283
+	if c.value == nil {
284
+		return defaultValue
285
+	}
286
+
287
+	return c.value
288
+}
289
+
290
+type configTypeMetricPrefix struct {
291
+	value string
292
+}
293
+
294
+func (c *configTypeMetricPrefix) UnmarshalText(data []byte) error {
295
+	if len(data) == 0 {
296
+		return nil
297
+	}
298
+
299
+	prefix := string(data)
300
+
301
+	if ok, err := regexp.MatchString("^[a-z0-9]+$", prefix); !ok || err != nil {
302
+		return fmt.Errorf("incorrect metric prefix: %s", prefix)
303
+	}
304
+
305
+	c.value = prefix
306
+
307
+	return nil
308
+}
309
+
310
+func (c configTypeMetricPrefix) String() string {
311
+	return c.value
312
+}
313
+
314
+func (c configTypeMetricPrefix) Value(defaultValue string) string {
315
+	if c.value == "" {
316
+		return defaultValue
317
+	}
318
+
319
+	return c.value
320
+}
321
+
322
+type configTypeHTTPPath struct {
323
+	value string
324
+}
325
+
326
+func (c *configTypeHTTPPath) UnmarshalText(data []byte) error { // nolint: unparam
327
+	if len(data) > 0 {
328
+		c.value = "/" + strings.Trim(string(data), "/")
329
+	}
330
+
331
+	return nil
332
+}
333
+
334
+func (c configTypeHTTPPath) String() string {
335
+	return c.value
336
+}
337
+
338
+func (c configTypeHTTPPath) Value(defaultValue string) string {
339
+	if c.value == "" {
340
+		return defaultValue
341
+	}
342
+
343
+	return c.value
344
+}
345
+
13 346
 type config struct {
14
-	Debug  bool          `json:"debug"`
15
-	Secret mtglib.Secret `json:"secret"`
347
+	Debug     bool               `json:"debug"`
348
+	Secret    mtglib.Secret      `json:"secret"`
349
+	BindTo    configTypeHostPort `json:"bind-to"`
350
+	TCPBuffer configTypeBytes    `json:"tcp-buffer"`
351
+	PreferIP  configTypePreferIP `json:"prefer-ip"`
352
+	CloakPort configTypePort     `json:"cloak-port"`
353
+	Probes    struct {
354
+		Time struct {
355
+			Enabled       bool               `json:"enabled"`
356
+			AllowSkewness configTypeDuration `json:"allow-skewness"`
357
+		} `json:"time"`
358
+		AntiReplay struct {
359
+			Enabled   bool            `json:"enabled"`
360
+			MaxSize   configTypeBytes `json:"max-size"`
361
+			ErrorRate configTypeFloat `json:"error-rate"`
362
+		} `json:"anti-replay"`
363
+	} `json:"probes"`
364
+	Network struct {
365
+		PublicIP struct {
366
+			IPv4 configTypeIP `json:"ipv4"`
367
+			IPv6 configTypeIP `json:"ipv6"`
368
+		} `json:"public-ip"`
369
+		DOHIP   configTypeIP    `json:"doh-ip"`
370
+		Proxies []configTypeURL `json:"proxies"`
371
+	} `json:"network"`
372
+	Stats struct {
373
+		StatsD struct {
374
+			Enabled      bool                   `json:"enabled"`
375
+			Address      configTypeHostPort     `json:"address"`
376
+			MetricPrefix configTypeMetricPrefix `json:"metric-prefix"`
377
+		} `json:"statsd"`
378
+		Prometheus struct {
379
+			Enabled      bool                   `json:"enabled"`
380
+			BindTo       configTypeHostPort     `json:"bind-to"`
381
+			HTTPPath     configTypeHTTPPath     `json:"http-path"`
382
+			MetricPrefix configTypeMetricPrefix `json:"metric-prefix"`
383
+		} `json:"prometheus"`
384
+	} `json:"stats"`
16 385
 }
17 386
 
18 387
 func (c *config) Validate() error {
@@ -36,9 +405,9 @@ type configRaw struct {
36 405
 			AllowSkewness string `toml:"allow-skewness" json:"allow-skewness"`
37 406
 		} `toml:"time" json:"time"`
38 407
 		AntiReplay struct {
39
-			Enabled bool   `toml:"enabled" json:"enabled"`
40
-			MaxSize string `toml:"max-size" json:"max-size"`
41
-			TTL     string `toml:"ttl" json:"ttl"`
408
+			Enabled   bool    `toml:"enabled" json:"enabled"`
409
+			MaxSize   string  `toml:"max-size" json:"max-size"`
410
+			ErrorRate float64 `toml:"error-rate" json:"error-rate"`
42 411
 		} `toml:"anti-replay" json:"anti-replay"`
43 412
 	} `toml:"probes" json:"probes"`
44 413
 	Network struct {
@@ -46,8 +415,8 @@ type configRaw struct {
46 415
 			IPv4 string `toml:"ipv4" json:"ipv4"`
47 416
 			IPv6 string `toml:"ipv6" json:"ipv6"`
48 417
 		} `toml:"public-ip" json:"public-ip"`
49
-		DOHHostname string   `toml:"doh-hostname" json:"doh-hostname"`
50
-		Proxies     []string `toml:"proxies" json:"proxies"`
418
+		DOHIP   string   `toml:"doh-ip" json:"doh-ip"`
419
+		Proxies []string `toml:"proxies" json:"proxies"`
51 420
 	} `toml:"network" json:"network"`
52 421
 	Stats struct {
53 422
 		StatsD struct {

+ 5
- 30
example.config.toml 查看文件

@@ -38,7 +38,7 @@ tcp-buffer = "4kb"
38 38
 #     Only ipv6 connectivity is used
39 39
 #   - only-ipv4:
40 40
 #     Only ipv4 connectivity is used
41
-prefer-ips = "prefer-ipv6"
41
+prefer-ip = "prefer-ipv6"
42 42
 
43 43
 # FakeTLS uses domain fronting protection. So it needs to know a port to
44 44
 # access.
@@ -58,7 +58,7 @@ cloak-port = 443
58 58
 # it has to access.
59 59
 #
60 60
 # By default we use Quad9.
61
-doh-hostname = "9.9.9.9"
61
+doh-ip = "9.9.9.9"
62 62
 
63 63
 # mtg can work via proxies (for now, we support only socks5). Proxy
64 64
 # configuration is done via list. So, you can specify many proxies
@@ -75,7 +75,6 @@ doh-hostname = "9.9.9.9"
75 75
 #
76 76
 #     socks5://user:password@host:port?open_threshold=5&half_open_timeout=1m&reset_failures_timeout=10s
77 77
 #
78
-
79 78
 # Only socks5 proxy is used. user/password is optional. As you can
80 79
 # see, you can specify some parameters in GET query. These parameters
81 80
 # configure circuit breaker.
@@ -102,31 +101,6 @@ proxies = [
102 101
 ipv4 = ""
103 102
 ipv6 = ""
104 103
 
105
-# you can redefine a dialer for mtg. Dialer is how we 'dial' to either
106
-# some external services or telegram. empty string means default
107
-# connectivity.
108
-#
109
-# it is also possible to use socks5 or shadowsocks here
110
-#
111
-# socks5 example:
112
-#   socks5://user:password@host:port
113
-# shadowsocks example (SIP002):
114
-#   ss://YWVzLTEyOC1nY206dGVzdA@192.168.100.1:8888
115
-#
116
-# You can define 2 dialers here: telegram and default. Telegram dialer
117
-# is used to connect to Telegram servers only. Default is used for other
118
-# purposes, like accessing ifconfig.co to obtains public address (DNS is
119
-# resolved via DoH)
120
-#
121
-# Please also be aware that dialers are only doing TCP. If UDP is
122
-# required (for statsd for example), then these dialers are going to be
123
-# ignored.
124
-#
125
-# If telegram dialer is not defined, a default one is going to be used.
126
-[network.dialers]
127
-telegram = ""
128
-default = ""
129
-
130 104
 # FakeTLS can compare timestamps to prevent probes. Each message has
131 105
 # encrypted timestamp. So, mtg can compare this timestamp and decide if
132 106
 # we need to proceed with connection or not.
@@ -154,8 +128,9 @@ enabled = true
154 128
 # that we can go over this limit for 10-20% under some conditions and
155 129
 # architectures.
156 130
 max-size = "16mb"
157
-# TTL for each cache record.
158
-ttl = "8h"
131
+# we use stable bloom filters for anti-replay cache. This helps
132
+# to maintain a desired error ratio.
133
+error-rate = 0.0001
159 134
 
160 135
 # statsd statistics integration.
161 136
 [stats.statsd]

+ 1
- 0
go.mod 查看文件

@@ -3,6 +3,7 @@ module github.com/9seconds/mtg/v2
3 3
 go 1.16
4 4
 
5 5
 require (
6
+	github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15
6 7
 	github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5
7 8
 	github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6
8 9
 	github.com/kr/pretty v0.1.0 // indirect

+ 3
- 0
go.sum 查看文件

@@ -1,3 +1,5 @@
1
+github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 h1:AUNCr9CiJuwrRYS3XieqF+Z9B9gNxo/eANAJCF2eiN4=
2
+github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
1 3
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
2 4
 github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
3 5
 github.com/babolivier/go-doh-client v0.0.0-20201028162107-a76cff4cb8b6 h1:4NNbNM2Iq/k57qEu7WfL67UrbPq1uFWxW4qODCohi+0=
@@ -24,6 +26,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
24 26
 github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
25 27
 github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
26 28
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
29
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
27 30
 github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
28 31
 github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
29 32
 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=

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

@@ -2,6 +2,4 @@ package mtglib
2 2
 
3 3
 import "errors"
4 4
 
5
-var (
6
-	ErrSecretEmpty = errors.New("secret is empty")
7
-)
5
+var ErrSecretEmpty = errors.New("secret is empty")

+ 3
- 3
mtglib/secret.go 查看文件

@@ -58,10 +58,10 @@ func (s *Secret) UnmarshalText(data []byte) error {
58 58
 }
59 59
 
60 60
 func (s Secret) Base64() string {
61
-    data := append([]byte{238}, s.Key...) // 238 = hex ee
62
-    data = append(data, s.Host...)
61
+	data := append([]byte{238}, s.Key...) // 238 = hex ee
62
+	data = append(data, s.Host...)
63 63
 
64
-    return base64.RawURLEncoding.EncodeToString(data)
64
+	return base64.RawURLEncoding.EncodeToString(data)
65 65
 }
66 66
 
67 67
 func (s Secret) String() string {

Loading…
取消
儲存