9seconds/mtg
GitHub: 9seconds/mtg
一款专注于流量伪装和隐私保护的极简 Telegram MTProto 代理服务。
Stars: 2656 | Forks: 316
# mtg
高度主观(去除了废话)的 MTPROTO 代理,专为
[Telegram](https://telegram.org/) 设计。
[](https://github.com/9seconds/mtg/actions/workflows/ci.yaml)
[](https://codecov.io/gh/9seconds/mtg)
[](https://pkg.go.dev/github.com/9seconds/mtg/v2)
**如果您使用的是 v1.0 或升级导致代理失效,请阅读
[版本 2](#version-2) 章节**
如果您想要一个 _支持 adtag_ 的代理(通过特殊的 Telegram bot 推广频道的可能性),我建议使用
[telemt](https://github.com/telemt/telemt) 项目。mtg 的 v1 版本支持它,
但我看不到使用它的任何合理理由:adtag 需要通过一组脆弱的中间代理进行通信,
需要复杂的设置并暴露公共 IP,且带宽和延迟较低。
mtg 的理念很简单:极简、无臃肿的代理,能够处理约 1-2 万个并发连接的合理规模,
没有用户管理,但勾选了与其主要意图相关的所有复选框:提供使用 Telegram 的方法。
## 理念
目前有多种可用于 Telegram MTPROTO 的代理。以下是最著名的几个:
* [官方](https://github.com/TelegramMessenger/MTProxy)
* [Python](https://github.com/alexbers/mtprotoproxy)
* [Erlang](https://github.com/seriyps/mtproto_proxy)
* [Telemt (Rust)](https://github.com/telemt/telemt)
您可以使用其中任何一个。它们都很棒,并且所有实现在功能上现已对等。这包括对 adtag、重放攻击保护、域前置、faketls 等的支持。mtg 也有类似的目标:在受限的、受审查的环境中提供连接到 Telegram 的可能性。但它在细节上略有不同,这些细节可能很重要。
* **域前置 (Domain fronting)**
多年来 mtg 一直支持域前置。这种技术意味着如果请求失败,它会回退到访问真实网站。失败的原因可能有很多:反重放保护、意外访问网络服务器或请求过期。无论如何,如果 mtg 拒绝此请求,它不会断开连接。它会连接到网站并复刻客户端发送的所有内容,然后按原样代理回去。用户将看到来自真实网站的响应,与真实网络位置的响应 _字节级一致_。
* **Doppelganger (伪装分身)**
mtg 也是其前置网站的 doppelganger(分身)。当然,如果出问题,通过域前置用户将看到真实网站的回复。
但是,如果 _一切正常_ 呢?
在这种情况下,mtg 会尽可能紧密地模仿 TLS 连接的统计特征。不同的应用程序有不同的流量模式统计。大型 CDN 稳定地传输数据,小型网站则以短小、易于压缩的流量块突发传输。
mtg 人工模拟这些延迟,使其在统计上与真实网站无法区分,即使它掩盖了特定应用程序的连接。
它还遵循 2 种最常见的流量分块模式,因此审查者将不得不投入更多资源来发现我们这里有 Telegram,而不是由 nginx 提供服务的 hookah 网店。
* **资源高效**
它必须是资源高效的。这并不意味着您会看到最小的内存使用量。这意味着它将尝试以零浪费模式使用分配的资源,尽可能多地重用内存等。
* **易于部署**
我坚信 Telegram 代理应该走 [ShadowSocks](https://shadowsocks.org) 的路子:推广频道在我看来是一种奇怪的商业模式。我认为唯一可行的方法是拥有一个可以轻松在任何地方恢复的代理。
* **支持 proxy protocol v1/v2**
通过支持 [通信协议](https://www.haproxy.org/download/2.3/doc/proxy-protocol.txt),这使得与 HAProxy 和 ELB 等负载均衡器的集成成为一等公民。
* **单一密钥**
我认为多个密钥解决不了任何问题,只会增加软件的复杂性。我也相信,对于一次性代理来说,这个功能是无用的奢侈品。
* **无 adtag 支持**
请阅读 [版本 2](#version-2) 章节。
* **无管理 WebUI**
这是一个简单轻量级代理的实现。我不会做那个。
* **代理链**
mtg 支持 [SOCKS5](https://en.wikipedia.org/wiki/SOCKS) 代理。因此,理论上,您可以将此代理作为前端运行,并通过 [v2ray](https://www.v2ray.com/)、[Gost](https://docs.ginuerzh.xyz/gost/)、[Trojan](https://trojan-gfw.github.io/trojan/) 或您喜欢的任何其他项目路由流量。
* **原生封锁列表支持**
以前,这被委托给 [FireHOL](https://firehol.org/) 项目或类似的跟踪攻击并发布潜在危险 IP 列表的项目。mtg 原生支持此类封锁列表。
* **可用作库**
mtg v2 经过重新设计,可以以最小的代价嵌入到您的软件(用 Golang 编写)中 + 您可以根据需要替换某些部分。
也请阅读关于 [最佳实践](https://github.com/9seconds/mtg/blob/master/BEST_PRACTICES.md) 的内容。
### 版本 2
如果您以前使用过 1.x 版本,您可能注意到了一些主要的向后不兼容细节:
1. 配置文件
2. 移除了对 adtag 的支持
关于配置文件,请查看本仓库中的完整示例。它有大量注释,大多数选项都是可选的。我们只有 `secret` 和 `bind-to` 部分是强制性的。示例配置文件中的其他部分已填充默认值。
Adtag 支持已被完全移除。这样做是为了给 mtg 瘦身并保持其简单和直观。希望这个目标已经实现,并且源代码足够干净和直接。
我一直对 adtag 持相当怀疑的态度。在我看来,作为一个拥有数百名客户端的庞大连接点的代理是一种错觉。如果您在审查环境中工作,权威机构做的第一件事就是 IP 封锁。对我们来说,这意味着那些可以从固定频道中受益的大型代理将在一分钟内被封锁。
代理必须是私密的。它应该在一个小群体内共享,比如家庭或大学朋友。它应该有少量的连接,并且从不公开宣布其存在。它必须在雷达下飞行。如果代理被检测到,您需要能够尽快在新 IP 地址上重生。我不认为为此用例设置一些特殊频道有任何意义。
但是其他细节,如重放攻击保护、域前置、精确的 FakeTLS 实现、IP 黑名单和代理链在这里很重要。如果您在受审查的边界内工作,比如受 [GFW](https://en.wikipedia.org/wiki/Great_Firewall)-保护的国家,您可能希望拥有一个 MTPROTO 代理作为前端,通过 [Trojan](https://trojan-gfw.github.io/trojan/)、[Shadowsocks](https://shadowsocks.org)、[v2ray](https://www.v2ray.com/) 或 [Gost](https://docs.ginuerzh.xyz/gost/) 制作的伪装隧道传输流量。这就是为什么您必须将链式支持作为一等公民。
是的,这在可选的 adtag 支持下是可能且可行的。但事实是,Telegram 的 MTPROTO 代理只是一个东西,要么作为普通客户端工作(直接模式),要么在 [TL 语言](https://core.telegram.org/mtproto/TL) 中进行一些 RPC 调用(adtag 支持)。我理解开发者的意图,我也理解他们曾在与 [RKN](https://rkn.gov.ru/) 的高压斗争中,之后又做 TON。没有什么是完美的。但对于代理来说,这意味着源代码中充满了复杂且非平凡的代码,而这些代码仅用于支持我们几乎不需要的功能。
因此,为了拥有一个合理的 MTPROTO 代理,adtag 支持被移除了。这是我职业生涯中软件 v2 给前一个版本瘦身的罕见机会。感觉真好 :)
### 版本 1 和 2
我会继续支持版本 1 和 2。但模式不同。
版本 1 现在正式处于维护模式。这意味着我不会在那里制作任何新功能或改进。您可以将其视为功能冻结。除了关键错误外,不会修复任何错误。不过欢迎 PR。目标是让它保持运行。它将获得一些周期性更新,如更新到新版本的 Golang 或依赖项版本升级,但主要就是这些。
**如果您想拥有 _adtag 支持_ 的 mtg,请使用版本 1**。
版本 2 将获得我所有的关爱、积极支持、错误修复等。它正处于积极的开发和维护中。
该项目有几个主要分支
1. [`master`](https://github.com/9seconds/mtg/tree/master) 分支包含前沿内容。它可能包含一些会破坏您的源代码的功能。
2. [`stable`](https://github.com/9seconds/mtg/tree/stable) 分支包含当我们认为“稳定”时 master 分支的转储。这可能是您想要选择的分支。
3. [`v2`](https://github.com/9seconds/mtg/tree/v2) 包含 v2.x 版本的开发。理论上它现在与 `master` 相同,但当我们有 v3.x 时这会改变。
4. [`v1`](https://github.com/9seconds/mtg/tree/v1) 包含 1.x 版本。
## 入门指南
### 下载 mise
mtg 使用 [mise](https://mise.jdx.dev/) 来维护其开发依赖 + 替代 make 来构建东西。请先 [安装](https://mise.jdx.dev/getting-started.html) 它。
### 下载工具
#### 下载二进制文件
可以从发布页面下载二进制文件。此外,您还可以下载 docker 镜像。
对于当前版本,请像这样下载
```
docker pull nineseconds/mtg:2
```
对于版本 1:
```
docker pull nineseconds/mtg:1
```
您也可以查看 [Docker Hub](https://hub.docker.com/r/nineseconds/mtg/tags) 和 [Github Registry](https://github.com/users/9seconds/packages/container/package/mtg)。
如果您想避免意外,请不要选择 `latest` 或 `stable`。始终选择某个版本标签。
此外,如果您安装了 `go`,您始终可以使用 `go get` 下载此工具:
```
go install github.com/9seconds/mtg/v2@latest
```
#### 从源代码构建
```
git clone https://github.com/9seconds/mtg.git
cd mtg
mise install
mise tasks run build
```
或者对于 docker 镜像:
```
mise tasks run image
```
### 生成密钥
如果您已经有 Base64 格式的密钥或以 `ee` 开头的密钥,您可以跳过本章。否则:
```
$ mtg generate-secret google.com
7ibaERuTSGPH1RdztfYnN4tnb29nbGUuY29t
```
或
```
$ mtg generate-secret --hex google.com
ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d
```
使用 docker 的等效命令:
```
$ docker run --rm nineseconds/mtg:2 generate-secret google.com
7ibaERuTSGPH1RdztfYnN4tnb29nbGUuY29t
$ docker run --rm nineseconds/mtg:2 generate-secret --hex google.com
ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d
```
此密钥是代理的基石,也是您客户端的密码。您需要保证其安全。
我们建议明智地选择主机名。这里我们使用了 _google.com_,但实际上,所有提供商都可以轻松检测到这不是 Google。Google 拥有其正式使用的网络列表,而您的 IP 地址可能不属于它。隐藏在与此 IP 地址有一定关系的某个域后面是一个好主意。
例如,您从 [Digital Ocean](https://www.digitalocean.com/) 购买了 VPS。那么为 _digitalocean.com_ 生成密钥可能是一个好主意。
### 简单运行模式
mtg 支持 2 种模式:简单和正常。简单模式允许使用您通常想要修改的一小部分配置选项启动代理。这对于您可以复制粘贴而无需操心外部文件的单行命令非常适用。
让我们来看看:
```
Usage: mtg simple-run
Run proxy without config file.
Arguments:
A host:port to bind proxy to.
Proxy secret.
Flags:
-h, --help Show context-sensitive help.
-v, --version Print version.
-d, --debug Run in debug mode.
-c, --concurrency=8192 Max number of concurrent connection to proxy.
-b, --tcp-buffer="4KB" Size of TCP buffer to use.
-i, --prefer-ip="prefer-ipv6" IP preference. By default we prefer IPv6 with fallback to IPv4.
-p, --domain-fronting-port=443 A port to access for domain fronting.
-n, --doh-ip=1.1.1.1 IP address of DNS-over-HTTP to use.
-t, --timeout=10s Network timeout to use
-a, --antireplay-cache-size="1MB" A size of anti-replay cache to use.
```
因此,如果您只想使用 CLI 启动代理,您可以这样做
```
$ mtg simple-run -n 1.1.1.1 -t 30s -a 512kib 127.0.0.1:3128 7hBO-dCS4EBzenlKbdLFxyNnb29nbGUuY29t
```
其余配置将从默认值中获取。但如果您没有任何特殊要求或精细调整,简单运行模式就可以了。如果您需要,请查看配置文件。
### 准备配置文件
请查看示例配置文件。除了 `secret` 和 `bind-to` 之外的所有选项都是可选的。您可以安全地拥有这个最小配置文件:
```
secret = "ee473ce5d4958eb5f968c87680a23854a0676f6f676c652e636f6d"
bind-to = "0.0.0.0:443"
```
这足以运行整个应用程序。所有其他选项对于几乎任何规模的应用程序都已有合理的默认值。
哦,配置是采用 [TOML 格式](https://toml.io/en/) 完成的。
### 运行代理
将二进制文件和配置文件放入您的网络服务器。举个例子,二进制文件放在 `/usr/local/bin/mtg`,配置文件放在 `/etc/mtg.toml`。
现在您可以创建一个 systemd 单元:
```
$ cat /etc/systemd/system/mtg.service
[Unit]
Description=mtg - MTProto proxy server
Documentation=https://github.com/9seconds/mtg
After=network.target
[Service]
ExecStart=/usr/local/bin/mtg run /etc/mtg.toml
Restart=always
RestartSec=3
DynamicUser=true
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
$ sudo systemctl daemon-reload
$ sudo systemctl enable mtg
$ sudo systemctl start mtg
```
或者您可以运行 docker 镜像
```
docker run -d -v $PWD/config.toml:/config.toml -p 443:3128 --name mtg-proxy --restart=unless-stopped nineseconds/mtg:2
```
其中 _443_ 是主机端口(您想从客户端连接的端口),_3128_ 是您在 `bind-to` 部分的配置中拥有的端口。
### 访问代理
现在您可以生成一些有用的链接:
```
$ mtg access /etc/mtg.toml
{
"ipv4": {
"ip": "x.y.z.a",
"port": 3128,
"tg_url": "tg://proxy?...",
"tg_qrcode": "https://api.qrserver.com/v1/create-qr-code?data...",
"tme_url": "https://t.me/proxy?...",
"tme_qrcode": "https://api.qrserver.com/v1/create-qr-code?data..."
},
"secret": {
"hex": "...",
"base64": "..."
}
}
```
或者如果您正在使用 docker:
```
$ docker exec mtg-proxy /mtg access /config.toml
```
## Doppelganger (伪装分身)
mtg 可以模仿真实网站,请查看示例配置文件中的相关部分。
mtg 附带了一些来自 [ok.ru](https://ok.ru/) 的非常好的预收集统计数据。这并不意味着您必须通过假装 mtg 是 _ok.ru_ 来掩盖自己。**不要那样做:ok.ru 来自非常特定的 ASN,而不是您将要使用的 VPS 提供商。** 我想说的是,默认值已经足够好,可以按原样使用,因为 ok.ru 的公共页面具有非常通用的 TLS 数据包延迟配置文件。
但为了获得更好的结果,建议让 mtg 了解您将用作域前置的网站。为此,您需要指定来自该网站的 URL。只需访问它,打开 WebDeveloper 控制台并选择随机 URL。为了获得更好的结果,它们必须 **来自您打算用作伪装的同一个域名**,但要提供轻度和重度内容:页面、图像等。不要使用太多,2-3 个可能就行。
mtg 会定期抓取这些页面,积累统计数据并随着您的使用而使用它。
```
[defense.doppelganger]
urls = [
"https://lalala.com/index.html",
"https://lalala.com/contacts.html",
]
```
这不是非常必要的。请记住这些规则:
1. 如果您不确定这是怎么回事,什么也不做。默认值很好。
2. 所有 URL 必须是 HTTPS
3. 所有 URL 应来自同一个域名(但这不是规则)
4. 不要使用大量页面。使用 _不同的_ 页面。mtg 最终会在积累足够数据后开始使用这些统计数据。
5. 这些 URL该可以直接从 mtg 访问,无需任何代理
6. 不要制造巨大的突袭。mtg 会在突袭中重复抓取,进行 N 次重复。不要使用高 N,您不想引起注意。
7. 突袭之间的延迟很小是没有意义的。通常,网络服务器不会每小时更新其 TLS 设置。
8. 如果您对网络服务器是否使用 [TLS Dynamic Record Sizing](https://blog.cloudflare.com/optimizing-tls-over-tcp-to-reduce-latency/) 有特定了解,您可以使用非常特定的设置。这些包括 Cloudflare、Go 标准网络服务器、[caddy](https://caddyserver.com/) 和 [H2O](https://h2o.examp1e.net/)。如果是这样,您可以启用 `drs` 设置。
9. **如果您不确定,什么也别碰!**
## 指标
开箱即用,mtg 支持 [statsd](https://github.com/statsd/statsd) 和 [Prometheus](https://prometheus.io/)。请查看配置文件示例以了解如何设置此集成。
以下是指标列表及其类型,但不带前缀。
| 名称 | 类型 | 标签 | 描述 |
|-----------------------------|---------|----------------------------------|-------------------------------------------------------------------------------------|
| client_connections | gauge | `ip_family` | 正在处理的客户端连接数。 |
| telegram_connections | gauge | `telegram_ip`, `dc` | 到 Telegram 服务器的连接数。 |
| domain_fronting_connections | gauge | `ip_family` | 到前置域的连接数。 |
| iplist_size | gauge | `ip_list` | 正在使用的允许列表或封锁列表的大小。 |
| telegram_traffic | counter | `telegram_ip`, `dc`, `direction` | 传输到/来自 Telegram 的字节数。 |
| domain_fronting_traffic | counter | `direction` | 传输到/来自前置域的字节数。 |
| domain_fronting | counter | – | 域前置事件计数。 |
| concurrency_limited | counter | – | 因并发限制而拒绝客户端连接的事件计数。 |
| ip_blocklisted | counter | `ip_list` | 因 IP 在封锁列表中而拒绝客户端连接的事件计数。 |
| replay_attacks | counter | – | 检测到的重放攻击计数。 |
标签含义:
| 名称 | 值 | 描述 |
|-------------|----------------------------|----------------------------------------|
| ip_family | `ipv4`, `ipv6` | IP 协议的版本。 |
| dc | | 连接的 Telegram DC 编号。 |
| telegram_ip | | Telegram 服务器的 IP 地址。 |
| direction | `to_client`, `from_client` | 流量流动的方向。 |
| ip_list | `allowlist`, `blocklist` | IP 列表的类型。 |
标签:EVTX分析, Faketls, Golang, IP 地址批量处理, Linux运维, MTPROTO代理, Python安全, Telegram代理, 中间人攻击防御, 内核驱动, 反审查, 域前置, 安全合规, 安全编程, 底层编程, 日志审计, 网络代理, 网络协议, 网络安全, 网络通信, 翻墙, 自定义请求头, 请求拦截, 重放攻击保护, 隐私保护