|
|
@@ -1,545 +1,171 @@
|
|
1
|
|
-# mtg
|
|
|
1
|
+# mtg-multi
|
|
2
|
2
|
|
|
3
|
|
-Highly-opinionated (ex-bullshit-free) MTPROTO proxy for
|
|
4
|
|
-[Telegram](https://telegram.org/).
|
|
|
3
|
+Fork of [9seconds/mtg](https://github.com/9seconds/mtg) with multi-secret support and per-user stats.
|
|
5
|
4
|
|
|
6
|
|
-[](https://github.com/9seconds/mtg/actions/workflows/ci.yaml)
|
|
7
|
|
-[](https://codecov.io/gh/9seconds/mtg)
|
|
8
|
|
-[](https://pkg.go.dev/github.com/9seconds/mtg/v2)
|
|
|
5
|
+[English](#whats-different) | [Русский](#чем-отличается)
|
|
9
|
6
|
|
|
10
|
|
-**If you use v1.0 or upgrade broke you proxy, please read the chapter
|
|
11
|
|
-[Version 2](#version-2)**
|
|
|
7
|
+---
|
|
12
|
8
|
|
|
13
|
|
-If you want to have a proxy that _supports adtag_ (possibility to promote a
|
|
14
|
|
-channel with a special Telegram bot), I recommend to use
|
|
15
|
|
-[telemt](https://github.com/telemt/telemt) project. v1 of mtg supports it
|
|
16
|
|
-but I do not see any reasonable point of using it: adtag requires communication
|
|
17
|
|
-via a fragile set of middle proxies, requires complex setup that must expose
|
|
18
|
|
-a public IPs, has lower bandwidth and latency.
|
|
|
9
|
+## What's different
|
|
19
|
10
|
|
|
20
|
|
-mtg idea is simple: minimal unbloated proxy that can handle a reasonable scale
|
|
21
|
|
-~10-20k simultaneous connections, has no user management, but ticks all
|
|
22
|
|
-checkboxes related to its main intent: provide a way to use Telegram.
|
|
|
11
|
+**Multiple secrets.** Upstream mtg allows only one secret per instance. mtg-multi lets you define named secrets in the config — one per user. All secrets must share the same hostname.
|
|
23
|
12
|
|
|
24
|
|
-## Rationale
|
|
25
|
|
-
|
|
26
|
|
-There are several available proxies for Telegram MTPROTO available. Here
|
|
27
|
|
-are the most notable:
|
|
28
|
|
-
|
|
29
|
|
-* [Official](https://github.com/TelegramMessenger/MTProxy)
|
|
30
|
|
-* [Python](https://github.com/alexbers/mtprotoproxy)
|
|
31
|
|
-* [Erlang](https://github.com/seriyps/mtproto_proxy)
|
|
32
|
|
-* [Telemt (Rust)](https://github.com/telemt/telemt)
|
|
33
|
|
-
|
|
34
|
|
-You can use any of these. They work great and all implementations have
|
|
35
|
|
-feature parity now. This includes support of adtag, replay attack
|
|
36
|
|
-protection, domain fronting, faketls, and so on. mtg has a similar
|
|
37
|
|
-goal: to give a possibility to connect to Telegram in a restricted,
|
|
38
|
|
-censored environment. But it does it slightly differently in details
|
|
39
|
|
-that probably matter.
|
|
40
|
|
-
|
|
41
|
|
-* **Domain fronting**
|
|
42
|
|
-
|
|
43
|
|
- For years mtg supports domain fronting. This technique means that it fallbacks
|
|
44
|
|
- to accessing a real website in case if request fails. It could fail by many
|
|
45
|
|
- reasons: anti-replay protection, accidental access to the webserver or
|
|
46
|
|
- stale request. Anyway, if mtg rejects this request, it does not break a
|
|
47
|
|
- connection. It connects to the websites and replicates everything that client
|
|
48
|
|
- has sent, and simply proxies it back as is. Users will see a response from
|
|
49
|
|
- the real website, _byte-to-byte identical_ to the response of the real netloc.
|
|
50
|
|
-
|
|
51
|
|
-* **Doppelganger**
|
|
52
|
|
-
|
|
53
|
|
- mtg also is a doppelganger of the website it fronts. Sure, with domain fronting
|
|
54
|
|
- users will see replies of the real website in case if something will go wrong.
|
|
55
|
|
- But what about such cases when _everything is fine_?
|
|
56
|
|
-
|
|
57
|
|
- In that case mtg mimics TLS connection statistical characteristics as close as
|
|
58
|
|
- possible. Different application have different statistics of their patterns.
|
|
59
|
|
- Big CDN steadily pumping the data, small websites burst with short easily
|
|
60
|
|
- compressiable chunks of traffic.
|
|
61
|
|
-
|
|
62
|
|
- mtg artificially emulates those delays to be statistically indistinguishable
|
|
63
|
|
- from the real website even if it covers connection of the very specific app.
|
|
64
|
|
- It also follows 2 most common patterns of traffic chunking, so censors
|
|
65
|
|
- will have to put more resources to find out that we have Telegram here
|
|
66
|
|
- but not a hookah webshop served by nginx.
|
|
67
|
|
-
|
|
68
|
|
-* **Resource-efficient**
|
|
69
|
|
-
|
|
70
|
|
- It has to be resource-efficient. It does not mean that you will see
|
|
71
|
|
- the smallest memory usage. It means that it will try to use allocated
|
|
72
|
|
- resources in zero-waste mode, reusing as much memory as possible and
|
|
73
|
|
- so on.
|
|
74
|
|
-
|
|
75
|
|
-* **Easily deployable**
|
|
76
|
|
-
|
|
77
|
|
- I strongly believe that Telegram proxies should follow the way of
|
|
78
|
|
- [ShadowSocks](https://shadowsocks.org): promoted channels is a strange
|
|
79
|
|
- way of doing business I suppose. I think the only viable way is to
|
|
80
|
|
- have a proxy that can be restored anywhere easily.
|
|
81
|
|
-
|
|
82
|
|
-* **Supports proxy protocol v1/v2**
|
|
83
|
|
-
|
|
84
|
|
- This makes integration with loadbalancers like HAProxy and ELB a first class
|
|
85
|
|
- citizen by supporting their
|
|
86
|
|
- [commuication protocols](https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt).
|
|
87
|
|
-
|
|
88
|
|
-* **A single secret**
|
|
89
|
|
-
|
|
90
|
|
- I think that multiple secrets solve no problems and just complex
|
|
91
|
|
- software. I also believe that in the case of throwout proxies, this
|
|
92
|
|
- the feature is a useless luxury.
|
|
93
|
|
-
|
|
94
|
|
- This is very controversial topic. Please read [rationale (in russian)](https://github.com/9seconds/mtg/issues/376#issuecomment-4118726699)
|
|
95
|
|
- and use [mtg-multi](https://github.com/dolonet/mtg-multi) fork if you are disagree with.
|
|
96
|
|
-
|
|
97
|
|
-* **No adtag support**
|
|
98
|
|
-
|
|
99
|
|
- Please read [Version 2](#version-2) chapter.
|
|
100
|
|
-
|
|
101
|
|
-* **No management WebUI**
|
|
102
|
|
-
|
|
103
|
|
- This is an implementation of a simple lightweight proxy. I won't do that.
|
|
104
|
|
-
|
|
105
|
|
-* **Proxy chaining**
|
|
106
|
|
-
|
|
107
|
|
- mtg has the support of [SOCKS5](https://en.wikipedia.org/wiki/SOCKS)
|
|
108
|
|
- proxies. So, in theory, you can run this proxy as a frontend
|
|
109
|
|
- and route traffic via [v2ray](https://www.v2ray.com/),
|
|
110
|
|
- [Gost](https://docs.ginuerzh.xyz/gost/),
|
|
111
|
|
- [Trojan](https://trojan-gfw.github.io/trojan/), or any other project
|
|
112
|
|
- you like.
|
|
113
|
|
-
|
|
114
|
|
-* **Native blocklist support**
|
|
115
|
|
-
|
|
116
|
|
- Previously, this was delegated to the [FireHOL](https://firehol.org/)
|
|
117
|
|
- project or similar ones which track attacks and publish a list of
|
|
118
|
|
- potentially dangerous IPs. mtg has native support of such blocklists.
|
|
119
|
|
-
|
|
120
|
|
-* **Can be used as a library**
|
|
121
|
|
-
|
|
122
|
|
- mtg v2 was redesigned in a way so it can be embedded into your
|
|
123
|
|
- software (written in Golang) with a minimum effort + you can replace
|
|
124
|
|
- some parts with those you want.
|
|
125
|
|
-
|
|
126
|
|
-Please also to read about [best practices](https://github.com/9seconds/mtg/blob/master/BEST_PRACTICES.md).
|
|
127
|
|
-
|
|
128
|
|
-### Version 2
|
|
129
|
|
-
|
|
130
|
|
-If you use version 1.x before, you are probably noticed some major
|
|
131
|
|
-backward non-compatible details:
|
|
132
|
|
-
|
|
133
|
|
-1. Configuration file
|
|
134
|
|
-2. Removed support of adtag
|
|
135
|
|
-
|
|
136
|
|
-For the configuration file, please check out the full example in this
|
|
137
|
|
-repository. It has a lot of comments and most of the options are
|
|
138
|
|
-optional. We do have only `secret` and `bind-to` sections mandatory.
|
|
139
|
|
-Other sections in the example configuration file are filled with default
|
|
140
|
|
-values.
|
|
141
|
|
-
|
|
142
|
|
-Adtag support was removed completely. This was done to debloat mtg and
|
|
143
|
|
-keep it simple and obvious. Hopefully, this goal is achieved and the
|
|
144
|
|
-source code is clean and straightforward enough.
|
|
145
|
|
-
|
|
146
|
|
-I always was quite skeptical about adtag. In my POV, a proxy as a fat
|
|
147
|
|
-big connectivity point for hundreds of clients is an illusion. If you
|
|
148
|
|
-work in a censored environment, the first thing that authority does is
|
|
149
|
|
-IP blocking. For us, it means, those big proxies that can benefit from
|
|
150
|
|
-having a pinned channel are going to be blocked in a minute.
|
|
151
|
|
-
|
|
152
|
|
-Proxy has to be intimate. It has to be shared within a small group as
|
|
153
|
|
-a family or maybe your college friends. It has to have a small number
|
|
154
|
|
-of connections and never publicly announced its presence. It has to fly
|
|
155
|
|
-under the radar. If the proxy is detected, you need to be able to give
|
|
156
|
|
-a rebirth on a new IP address as soon as possible. I do no think that
|
|
157
|
|
-having some special channel for such a use case makes any sense.
|
|
158
|
|
-
|
|
159
|
|
-But other details like replay attack protection, domain fronting,
|
|
160
|
|
-accurate FakeTLS implementation, IP blacklisting, and proxy
|
|
161
|
|
-chaining matter here. If you work in censored perimeter like
|
|
162
|
|
-[GFW](https://en.wikipedia.org/wiki/Great_Firewall)-protected
|
|
163
|
|
-country, you probably want to have an MTPROTO proxy as
|
|
164
|
|
-a frontend that transports traffic via cloaked tunnels
|
|
165
|
|
-made by [Trojan](https://trojan-gfw.github.io/trojan/),
|
|
166
|
|
-[Shadowsocks](https://shadowsocks.org), [v2ray](https://www.v2ray.com/),
|
|
167
|
|
-or [Gost](https://docs.ginuerzh.xyz/gost/). That's why you have to have
|
|
168
|
|
-the support of chaining as a first-class citizen.
|
|
169
|
|
-
|
|
170
|
|
-Yes, this is possible and doable with optional adtag support. But the
|
|
171
|
|
-truth is that the MTPROTO proxy for Telegram is just a thing that either
|
|
172
|
|
-work as a normal client (direct mode) or doing some RPC calls in [TL
|
|
173
|
|
-language](https://core.telegram.org/mtproto/TL) (adtag support). I
|
|
174
|
|
-understand the intention of the developers and I understand that they
|
|
175
|
|
-were under high pressure fighting with [RKN](https://rkn.gov.ru/) and
|
|
176
|
|
-doing TON after that. Nothing is ideal. But for the proxy, it means that
|
|
177
|
|
-source code is full of complex non-trivial code which is required only
|
|
178
|
|
-to support a feature that we barely need.
|
|
179
|
|
-
|
|
180
|
|
-So, to have a reasonable MTPROTO proxy, adtag support was removed. This
|
|
181
|
|
-is a rare chance in my career where software v2 debloats a previous
|
|
182
|
|
-version. It feels so good :)
|
|
183
|
|
-
|
|
184
|
|
-### Version 1 and 2
|
|
185
|
|
-
|
|
186
|
|
-I do continue to support both versions 1 and 2. But in a different mode.
|
|
187
|
|
-
|
|
188
|
|
-Version 1 is now officially in maintenance mode. It means that I won't
|
|
189
|
|
-make any new features or improvements there. You can consider a feature
|
|
190
|
|
-freeze there. No bugs are going to be fixed there except for critical
|
|
191
|
|
-ones. PRs are welcome though. The goal is to keep it working. It will
|
|
192
|
|
-get some periodical updates like updates to the new Golang version of
|
|
193
|
|
-dependencies version bump, but that's mostly it.
|
|
194
|
|
-
|
|
195
|
|
-**If you want to have mtg with _adtag support_, please use version 1**.
|
|
196
|
|
-
|
|
197
|
|
-Version 2 is going to have all my love, active support, bug fixing, etc.
|
|
198
|
|
-It is under active development and maintenance.
|
|
199
|
|
-
|
|
200
|
|
-This project has several main branches
|
|
201
|
|
-
|
|
202
|
|
-1. [`master`](https://github.com/9seconds/mtg/tree/master) branch
|
|
203
|
|
- contains a bleeding edge. It may potentially have some features
|
|
204
|
|
- which will break your source code.
|
|
205
|
|
-2. [`stable`](https://github.com/9seconds/mtg/tree/stable) branch contains
|
|
206
|
|
- dumps of a master branch when we consider it 'stable'. This is a
|
|
207
|
|
- branch you probably want to pick.
|
|
208
|
|
-3. [`v2`](https://github.com/9seconds/mtg/tree/v2) has a development
|
|
209
|
|
- of the v2.x version. In theory, it is the same as `master` but this
|
|
210
|
|
- will change when we have v3.x.
|
|
211
|
|
-4. [`v1`](https://github.com/9seconds/mtg/tree/v1) has a version 1.x.
|
|
212
|
|
-
|
|
213
|
|
-## Getting started
|
|
214
|
|
-
|
|
215
|
|
-### Download mise
|
|
216
|
|
-
|
|
217
|
|
-mtg uses [mise](https://mise.jdx.dev/) to maintain its development
|
|
218
|
|
-dependencies + replaces a make for building things. Please
|
|
219
|
|
-[install](https://mise.jdx.dev/getting-started.html) it first.
|
|
220
|
|
-
|
|
221
|
|
-### Download a tool
|
|
222
|
|
-
|
|
223
|
|
-#### Download binaries
|
|
224
|
|
-
|
|
225
|
|
-Binaries can be downloaded from the release page. Also, you can download
|
|
226
|
|
-docker image.
|
|
227
|
|
-
|
|
228
|
|
-For the current version, please download like
|
|
229
|
|
-
|
|
230
|
|
-```console
|
|
231
|
|
-docker pull nineseconds/mtg:2
|
|
|
13
|
+```toml
|
|
|
14
|
+[secrets]
|
|
|
15
|
+alice = "ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c65617069732e636f6d"
|
|
|
16
|
+bob = "ee0123456789abcdef0123456789abcd9573746f726167652e676f6f676c65617069732e636f6d"
|
|
232
|
17
|
```
|
|
233
|
18
|
|
|
234
|
|
-For version 1:
|
|
|
19
|
+**Stats API.** A lightweight HTTP endpoint that shows live per-user traffic.
|
|
235
|
20
|
|
|
236
|
|
-```console
|
|
237
|
|
-docker pull nineseconds/mtg:1
|
|
|
21
|
+```toml
|
|
|
22
|
+api-bind-to = "127.0.0.1:9090"
|
|
238
|
23
|
```
|
|
239
|
24
|
|
|
240
|
|
-You may also check both [Docker
|
|
241
|
|
-Hub](https://hub.docker.com/r/nineseconds/mtg/tags) and [Github
|
|
242
|
|
-Registry](https://github.com/users/9seconds/packages/container/package/mtg).
|
|
243
|
|
-Please do not choose `latest` or `stable` if you want to avoid
|
|
244
|
|
-surprises. Always choose some version tag.
|
|
245
|
|
-
|
|
246
|
|
-Also, if you have `go` installed, you can always download this tool with `go get`:
|
|
247
|
|
-
|
|
248
|
|
-```console
|
|
249
|
|
-go install github.com/9seconds/mtg/v2@latest
|
|
|
25
|
+```
|
|
|
26
|
+GET /stats
|
|
250
|
27
|
```
|
|
251
|
28
|
|
|
252
|
|
-#### Build from sources
|
|
253
|
|
-
|
|
254
|
|
-```console
|
|
255
|
|
-git clone https://github.com/9seconds/mtg.git
|
|
256
|
|
-cd mtg
|
|
257
|
|
-mise install
|
|
258
|
|
-mise tasks run build
|
|
|
29
|
+```json
|
|
|
30
|
+{
|
|
|
31
|
+ "started_at": "2026-03-29T10:30:00Z",
|
|
|
32
|
+ "uptime_seconds": 3600,
|
|
|
33
|
+ "total_connections": 15,
|
|
|
34
|
+ "users": {
|
|
|
35
|
+ "alice": {
|
|
|
36
|
+ "connections": 8,
|
|
|
37
|
+ "bytes_in": 1048576,
|
|
|
38
|
+ "bytes_out": 2097152,
|
|
|
39
|
+ "last_seen": "2026-03-29T11:25:30Z"
|
|
|
40
|
+ }
|
|
|
41
|
+ }
|
|
|
42
|
+}
|
|
259
|
43
|
```
|
|
260
|
44
|
|
|
261
|
|
-or for the docker image:
|
|
|
45
|
+**Public IP override.** Useful when auto-detection via ifconfig.co is unavailable.
|
|
262
|
46
|
|
|
263
|
|
-```console
|
|
264
|
|
-mise tasks run image
|
|
|
47
|
+```toml
|
|
|
48
|
+public-ipv4 = "1.2.3.4"
|
|
|
49
|
+public-ipv6 = "2001:db8::1"
|
|
265
|
50
|
```
|
|
266
|
51
|
|
|
267
|
|
-### Generate secret
|
|
|
52
|
+Everything else — domain fronting, doppelganger, proxy chaining, blocklists, metrics — works exactly as in upstream. See the [upstream README](https://github.com/9seconds/mtg) for details.
|
|
268
|
53
|
|
|
269
|
|
-If you already have a secret in Base64 format or that, which starts with `ee`,
|
|
270
|
|
-you can skip this chapter. Otherwise:
|
|
|
54
|
+## Quick start
|
|
271
|
55
|
|
|
272
|
|
-```console
|
|
273
|
|
-$ mtg generate-secret google.com
|
|
274
|
|
-7ibaERuTSGPH1RdztfYnN4tnb29nbGUuY29t
|
|
275
|
|
-```
|
|
276
|
|
-
|
|
277
|
|
-or
|
|
|
56
|
+Download a binary from [Releases](https://github.com/dolonet/mtg-multi/releases) or build from source:
|
|
278
|
57
|
|
|
279
|
58
|
```console
|
|
280
|
|
-$ mtg generate-secret --hex google.com
|
|
281
|
|
-ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d
|
|
|
59
|
+git clone https://github.com/dolonet/mtg-multi.git
|
|
|
60
|
+cd mtg-multi
|
|
|
61
|
+mise install && mise tasks run build
|
|
282
|
62
|
```
|
|
283
|
63
|
|
|
284
|
|
-equivalent commands with docker:
|
|
|
64
|
+Generate secrets:
|
|
285
|
65
|
|
|
286
|
66
|
```console
|
|
287
|
|
-$ docker run --rm nineseconds/mtg:2 generate-secret google.com
|
|
288
|
|
-7ibaERuTSGPH1RdztfYnN4tnb29nbGUuY29t
|
|
289
|
|
-
|
|
290
|
|
-$ docker run --rm nineseconds/mtg:2 generate-secret --hex google.com
|
|
291
|
|
-ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d
|
|
|
67
|
+mtg-multi generate-secret --hex storage.googleapis.com
|
|
292
|
68
|
```
|
|
293
|
69
|
|
|
294
|
|
-This secret is a keystone for a proxy and your password for a client.
|
|
295
|
|
-You need to keep it secured.
|
|
296
|
|
-
|
|
297
|
|
-We recommend choosing a hostname wisely. Here we have a _google.com_
|
|
298
|
|
-but in reality, all providers can easily detect that this is not a
|
|
299
|
|
-Google. Google has a list of networks it officially uses and your IP
|
|
300
|
|
-address won't probably belong to it. It is a great idea to hide behind
|
|
301
|
|
-some domain that has some relation to this IP address.
|
|
|
70
|
+Minimal config:
|
|
302
|
71
|
|
|
303
|
|
-For example, you've bought a VPS from [Digital
|
|
304
|
|
-Ocean](https://www.digitalocean.com/). Then it might be a good idea to
|
|
305
|
|
-generate a secret for _digitalocean.com_ then.
|
|
306
|
|
-
|
|
307
|
|
-### Check configuration
|
|
|
72
|
+```toml
|
|
|
73
|
+bind-to = "0.0.0.0:443"
|
|
308
|
74
|
|
|
309
|
|
-There is a special command for secret verification:
|
|
|
75
|
+[secrets]
|
|
|
76
|
+alice = "ee..."
|
|
|
77
|
+bob = "ee..."
|
|
310
|
78
|
|
|
|
79
|
+api-bind-to = "127.0.0.1:9090"
|
|
311
|
80
|
```
|
|
312
|
|
-$ mtg doctor /path/to/my/config.toml
|
|
313
|
|
-Deprecated options
|
|
314
|
|
- ✅ All good
|
|
315
|
|
-Time skewness
|
|
316
|
|
- ✅ Time drift is -607.048µs, but tolerate-time-skewness is 5s
|
|
317
|
|
-Validate native network connectivity
|
|
318
|
|
- ✅ DC 1
|
|
319
|
|
- ✅ DC 2
|
|
320
|
|
- ✅ DC 3
|
|
321
|
|
- ✅ DC 4
|
|
322
|
|
- ✅ DC 5
|
|
323
|
|
- ✅ DC 203
|
|
324
|
|
-Validate network connectivity with proxy socks5://127.0.0.1:1080
|
|
325
|
|
- ✅ DC 1
|
|
326
|
|
- ✅ DC 2
|
|
327
|
|
- ✅ DC 3
|
|
328
|
|
- ✅ DC 4
|
|
329
|
|
- ✅ DC 5
|
|
330
|
|
- ✅ DC 203
|
|
331
|
|
-Validate fronting domain connectivity
|
|
332
|
|
- ✅ xx.xx.xx.xx:yyy is reachable
|
|
333
|
|
-Validate SNI-DNS match
|
|
334
|
|
- ✅ IP address xx.xx.xx.xx matches secret hostname <REDACTED>
|
|
335
|
|
-```
|
|
336
|
|
-
|
|
337
|
|
-It aims to find out possible inconsistencies and problems with your
|
|
338
|
|
-configuration. It makes sense to run it before executing any relevant commands.
|
|
339
|
|
-
|
|
340
|
|
-### Simple run mode
|
|
341
|
81
|
|
|
342
|
|
-mtg supports 2 modes: simple and normal. Simple mode allows starting
|
|
343
|
|
-proxy with a small subset of configuration options you usually want to
|
|
344
|
|
-modify. This is quite good for oneliners that you can copy-paste and do
|
|
345
|
|
-not bother about external files whatsoever.
|
|
346
|
|
-
|
|
347
|
|
-Let's take a look:
|
|
|
82
|
+Run:
|
|
348
|
83
|
|
|
349
|
84
|
```console
|
|
350
|
|
-Usage: mtg simple-run <bind-to> <secret>
|
|
351
|
|
-
|
|
352
|
|
-Run proxy without config file.
|
|
353
|
|
-
|
|
354
|
|
-Arguments:
|
|
355
|
|
- <bind-to> A host:port to bind proxy to.
|
|
356
|
|
- <secret> Proxy secret.
|
|
357
|
|
-
|
|
358
|
|
-Flags:
|
|
359
|
|
- -h, --help Show context-sensitive help.
|
|
360
|
|
- -v, --version Print version.
|
|
361
|
|
-
|
|
362
|
|
- -d, --debug Run in debug mode.
|
|
363
|
|
- -c, --concurrency=8192 Max number of concurrent connection to proxy.
|
|
364
|
|
- -b, --tcp-buffer="4KB" Size of TCP buffer to use.
|
|
365
|
|
- -i, --prefer-ip="prefer-ipv6" IP preference. By default we prefer IPv6 with fallback to IPv4.
|
|
366
|
|
- -p, --domain-fronting-port=443 A port to access for domain fronting.
|
|
367
|
|
- -n, --doh-ip=1.1.1.1 IP address of DNS-over-HTTP to use.
|
|
368
|
|
- -t, --timeout=10s Network timeout to use
|
|
369
|
|
- -a, --antireplay-cache-size="1MB" A size of anti-replay cache to use.
|
|
|
85
|
+mtg-multi run /etc/mtg/config.toml
|
|
370
|
86
|
```
|
|
371
|
87
|
|
|
372
|
|
-So, if you want to startup a proxy with CLI only, you can do something like
|
|
373
|
|
-
|
|
374
|
|
-```console
|
|
375
|
|
-$ mtg simple-run -n 1.1.1.1 -t 30s -a 512kib 127.0.0.1:3128 7hBO-dCS4EBzenlKbdLFxyNnb29nbGUuY29t
|
|
376
|
|
-```
|
|
|
88
|
+See [example.config.toml](example.config.toml) for all available options.
|
|
377
|
89
|
|
|
378
|
|
-The rest of the configuration will be taken from default values. But
|
|
379
|
|
-a simple run is fine if you do not have any special requirements or
|
|
380
|
|
-granular tuning. If you want it, please checkout the configuration
|
|
381
|
|
-files.
|
|
|
90
|
+---
|
|
382
|
91
|
|
|
383
|
|
-### Prepare a configuration file
|
|
|
92
|
+## Чем отличается
|
|
384
|
93
|
|
|
385
|
|
-Please checkout an example configuration file. All options except of
|
|
386
|
|
-`secret` and `bind-to` are optional. You can safely have this minimal
|
|
387
|
|
-configuration file:
|
|
|
94
|
+**Несколько секретов.** В оригинальном mtg — один секрет на инстанс. mtg-multi позволяет задать именованные секреты в конфиге, по одному на пользователя. Все секреты должны использовать один и тот же hostname.
|
|
388
|
95
|
|
|
389
|
96
|
```toml
|
|
390
|
|
-secret = "ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d"
|
|
391
|
|
-bind-to = "0.0.0.0:443"
|
|
|
97
|
+[secrets]
|
|
|
98
|
+alice = "ee367a189aee18fa31c190054efd4a8e9573746f726167652e676f6f676c65617069732e636f6d"
|
|
|
99
|
+bob = "ee0123456789abcdef0123456789abcd9573746f726167652e676f6f676c65617069732e636f6d"
|
|
392
|
100
|
```
|
|
393
|
101
|
|
|
394
|
|
-This is enough to run the whole application. All other
|
|
395
|
|
-options already have sensible defaults for the app at almost any scale.
|
|
396
|
|
-
|
|
397
|
|
-Oh, the configuration is done in [TOML format](https://toml.io/en/).
|
|
398
|
|
-
|
|
399
|
|
-### Run a proxy
|
|
|
102
|
+**Stats API.** HTTP-эндпоинт с live-статистикой трафика по пользователям.
|
|
400
|
103
|
|
|
401
|
|
-Put a binary and a config into your webserver. Just for example,
|
|
402
|
|
-a binary goes to `/usr/local/bin/mtg` and configuration to `/etc/mtg.toml`.
|
|
|
104
|
+```toml
|
|
|
105
|
+api-bind-to = "127.0.0.1:9090"
|
|
|
106
|
+```
|
|
403
|
107
|
|
|
404
|
|
-Now you can create a systemd unit:
|
|
|
108
|
+```
|
|
|
109
|
+GET /stats
|
|
|
110
|
+```
|
|
405
|
111
|
|
|
406
|
|
-```console
|
|
407
|
|
-$ cat /etc/systemd/system/mtg.service
|
|
408
|
|
-[Unit]
|
|
409
|
|
-Description=mtg - MTProto proxy server
|
|
410
|
|
-Documentation=https://github.com/9seconds/mtg
|
|
411
|
|
-After=network.target
|
|
412
|
|
-
|
|
413
|
|
-[Service]
|
|
414
|
|
-ExecStart=/usr/local/bin/mtg run /etc/mtg.toml
|
|
415
|
|
-Restart=always
|
|
416
|
|
-RestartSec=3
|
|
417
|
|
-DynamicUser=true
|
|
418
|
|
-LimitNOFILE=65536
|
|
419
|
|
-AmbientCapabilities=CAP_NET_BIND_SERVICE
|
|
420
|
|
-
|
|
421
|
|
-[Install]
|
|
422
|
|
-WantedBy=multi-user.target
|
|
423
|
|
-$ sudo systemctl daemon-reload
|
|
424
|
|
-$ sudo systemctl enable mtg
|
|
425
|
|
-$ sudo systemctl start mtg
|
|
|
112
|
+```json
|
|
|
113
|
+{
|
|
|
114
|
+ "started_at": "2026-03-29T10:30:00Z",
|
|
|
115
|
+ "uptime_seconds": 3600,
|
|
|
116
|
+ "total_connections": 15,
|
|
|
117
|
+ "users": {
|
|
|
118
|
+ "alice": {
|
|
|
119
|
+ "connections": 8,
|
|
|
120
|
+ "bytes_in": 1048576,
|
|
|
121
|
+ "bytes_out": 2097152,
|
|
|
122
|
+ "last_seen": "2026-03-29T11:25:30Z"
|
|
|
123
|
+ }
|
|
|
124
|
+ }
|
|
|
125
|
+}
|
|
426
|
126
|
```
|
|
427
|
127
|
|
|
428
|
|
-or you can run a docker image
|
|
|
128
|
+**Ручное указание публичного IP.** Для случаев, когда ifconfig.co недоступен с сервера.
|
|
429
|
129
|
|
|
430
|
|
-```console
|
|
431
|
|
-docker run -d -v $PWD/config.toml:/config.toml -p 443:3128 --name mtg-proxy --restart=unless-stopped nineseconds/mtg:2
|
|
|
130
|
+```toml
|
|
|
131
|
+public-ipv4 = "1.2.3.4"
|
|
|
132
|
+public-ipv6 = "2001:db8::1"
|
|
432
|
133
|
```
|
|
433
|
134
|
|
|
434
|
|
-where _443_ is a host port (a port you want to connect to from a
|
|
435
|
|
-client), and _3128_ is the one you have in your config in the `bind-to`
|
|
436
|
|
-section.
|
|
|
135
|
+Всё остальное — domain fronting, doppelganger, цепочки прокси, блоклисты, метрики — работает как в оригинале. Подробности в [README upstream](https://github.com/9seconds/mtg).
|
|
437
|
136
|
|
|
438
|
|
-### Access a proxy
|
|
|
137
|
+## Быстрый старт
|
|
439
|
138
|
|
|
440
|
|
-Now you can generate some useful links:
|
|
|
139
|
+Скачайте бинарник из [Releases](https://github.com/dolonet/mtg-multi/releases) или соберите из исходников:
|
|
441
|
140
|
|
|
442
|
141
|
```console
|
|
443
|
|
-$ mtg access /etc/mtg.toml
|
|
444
|
|
-{
|
|
445
|
|
- "ipv4": {
|
|
446
|
|
- "ip": "x.y.z.a",
|
|
447
|
|
- "port": 3128,
|
|
448
|
|
- "tg_url": "tg://proxy?...",
|
|
449
|
|
- "tg_qrcode": "https://api.qrserver.com/v1/create-qr-code?data...",
|
|
450
|
|
- "tme_url": "https://t.me/proxy?...",
|
|
451
|
|
- "tme_qrcode": "https://api.qrserver.com/v1/create-qr-code?data..."
|
|
452
|
|
- },
|
|
453
|
|
- "secret": {
|
|
454
|
|
- "hex": "...",
|
|
455
|
|
- "base64": "..."
|
|
456
|
|
- }
|
|
457
|
|
-}
|
|
|
142
|
+git clone https://github.com/dolonet/mtg-multi.git
|
|
|
143
|
+cd mtg-multi
|
|
|
144
|
+mise install && mise tasks run build
|
|
458
|
145
|
```
|
|
459
|
146
|
|
|
460
|
|
-or if you are using docker:
|
|
|
147
|
+Генерация секрета:
|
|
461
|
148
|
|
|
462
|
149
|
```console
|
|
463
|
|
-$ docker exec mtg-proxy /mtg access /config.toml
|
|
|
150
|
+mtg-multi generate-secret --hex storage.googleapis.com
|
|
464
|
151
|
```
|
|
465
|
152
|
|
|
466
|
|
-## Doppelganger
|
|
|
153
|
+Минимальный конфиг:
|
|
467
|
154
|
|
|
468
|
|
-mtg can mimic real websites, please take a look at relevant section in example
|
|
469
|
|
-config file.
|
|
|
155
|
+```toml
|
|
|
156
|
+bind-to = "0.0.0.0:443"
|
|
470
|
157
|
|
|
471
|
|
-mtg comes with some very good precollected statistics coming from
|
|
472
|
|
-[ok.ru](https://ok.ru/). It does not mean that you have to cover yourself
|
|
473
|
|
-by pretending that mtg is _ok.ru_. **Do not do that: ok.ru comes from very specific
|
|
474
|
|
-ASNs, but not from VPS providers you are going to use.** What I want to say
|
|
475
|
|
-is that defaults are very good enough to use as is because ok.ru for public
|
|
476
|
|
-pages has a very generic profile of TLS packets delay.
|
|
|
158
|
+[secrets]
|
|
|
159
|
+alice = "ee..."
|
|
|
160
|
+bob = "ee..."
|
|
477
|
161
|
|
|
478
|
|
-But for better results it is recommended to teach mtg about the website you
|
|
479
|
|
-will use as a domain front. In order to do that, you need to specify URLs
|
|
480
|
|
-from this website. Just go to it, open WebDeveloper console and pick up
|
|
481
|
|
-random URLs. For better results they have to be **from the same domain name
|
|
482
|
|
-you are going to use as a disguise** but serve light and heavy content: pages,
|
|
483
|
|
-images etc. Do not use many, 2-3 will probably work.
|
|
|
162
|
+api-bind-to = "127.0.0.1:9090"
|
|
|
163
|
+```
|
|
484
|
164
|
|
|
485
|
|
-mtg will crawl these pages periodically, accumulating statistics and
|
|
486
|
|
-using it as you go.
|
|
|
165
|
+Запуск:
|
|
487
|
166
|
|
|
488
|
|
-```toml
|
|
489
|
|
-[defense.doppelganger]
|
|
490
|
|
-urls = [
|
|
491
|
|
- "https://lalala.com/index.html",
|
|
492
|
|
- "https://lalala.com/contacts.html",
|
|
493
|
|
-]
|
|
|
167
|
+```console
|
|
|
168
|
+mtg-multi run /etc/mtg/config.toml
|
|
494
|
169
|
```
|
|
495
|
170
|
|
|
496
|
|
-This is not very necessary. Keep in mind these rules:
|
|
497
|
|
-
|
|
498
|
|
-1. If you are not sure what is this all about, do nothing. Defaults are good.
|
|
499
|
|
-2. All URLs must be HTTPS
|
|
500
|
|
-3. All URLs should be from the same domain name (but this is not a rule)
|
|
501
|
|
-4. Do not use a lot of pages. Use _different_ pages. mtg will start using this
|
|
502
|
|
- statistics when it will accumulate enough anyway.
|
|
503
|
|
-5. These URLs should be directly accessible from mtg without proxies whatsoever
|
|
504
|
|
-6. Do not create huge raids. mtg will repeatedly crawl in raids, making N repeats.
|
|
505
|
|
- Do not use high N, you do not want to be noticeable.
|
|
506
|
|
-7. It makes no sense to have small delay between raids. Usually webservers
|
|
507
|
|
- do not update their TLS settings each hour.
|
|
508
|
|
-8. If you have some specific knowledge if webserver is using
|
|
509
|
|
- [TLS Dynamic Record Sizing](https://blog.cloudflare.com/optimizing-tls-over-tcp-to-reduce-latency/), you
|
|
510
|
|
- can use a very specific setting. This are Cloudflare, Go standard webservers,
|
|
511
|
|
- [caddy](https://caddyserver.com/) and [H2O](https://h2o.examp1e.net/). If so,
|
|
512
|
|
- you can enable `drs` setting.
|
|
513
|
|
-9. **If you are not sure, touch nothing!**
|
|
514
|
|
-
|
|
515
|
|
-## Metrics
|
|
516
|
|
-
|
|
517
|
|
-Out of the box, mtg works with
|
|
518
|
|
-[statsd](https://github.com/statsd/statsd) and
|
|
519
|
|
-[Prometheus](https://prometheus.io/). Please check configuration file
|
|
520
|
|
-example to get how to set this integration up.
|
|
521
|
|
-
|
|
522
|
|
-Here goes a list of metrics with their types but without a prefix.
|
|
523
|
|
-
|
|
524
|
|
-| Name | Type | Tags | Description |
|
|
525
|
|
-|-----------------------------|---------|----------------------------------|--------------------------------------------------------------------------------------------|
|
|
526
|
|
-| client_connections | gauge | `ip_family` | Count of processing client connections. |
|
|
527
|
|
-| telegram_connections | gauge | `telegram_ip`, `dc` | Count of connections to Telegram servers. |
|
|
528
|
|
-| domain_fronting_connections | gauge | `ip_family` | Count of connections to fronting domain. |
|
|
529
|
|
-| iplist_size | gauge | `ip_list` | A size of either allowlist or blocklist in use. |
|
|
530
|
|
-| telegram_traffic | counter | `telegram_ip`, `dc`, `direction` | Count of bytes, transmitted to/from Telegram. |
|
|
531
|
|
-| domain_fronting_traffic | counter | `direction` | Count of bytes, transmitted to/from fronting domain. |
|
|
532
|
|
-| domain_fronting | counter | – | Count of domain fronting events. |
|
|
533
|
|
-| concurrency_limited | counter | – | Count of events, when client connection was rejected due to concurrency limit. |
|
|
534
|
|
-| ip_blocklisted | counter | `ip_list` | Count of events when client connection was rejected because IP was found in the blocklist. |
|
|
535
|
|
-| replay_attacks | counter | – | Count of detected replay attacks. |
|
|
536
|
|
-
|
|
537
|
|
-Tag meaning:
|
|
538
|
|
-
|
|
539
|
|
-| Name | Values | Description |
|
|
540
|
|
-|-------------|----------------------------|-----------------------------------------------|
|
|
541
|
|
-| ip_family | `ipv4`, `ipv6` | A version of the IP protocol. |
|
|
542
|
|
-| dc | | A number of the Telegram DC for a connection. |
|
|
543
|
|
-| telegram_ip | | IP address of the Telegram server. |
|
|
544
|
|
-| direction | `to_client`, `from_client` | A direction of the traffic flow. |
|
|
545
|
|
-| ip_list | `allowlist`, `blocklist` | A type of the IP list. |
|
|
|
171
|
+Все доступные опции — в [example.config.toml](example.config.toml).
|