sleep3r/mtproto.zig
sleep3r/mtproto.zig has 2,203 GitHub stars and 71 forks. GitHot measured +7 stars in 24 hours and +9 in 7 days. Last checked 2026-11-12 16:44 UTC. Last push 2026-10-01.
让你爱的人始终保持联系——一款小巧的 Telegram 代理,可自行部署并隐匿于普通 HTTPS 流量中
实测星标增长
- 24小时
- +7
- 7天
- +9
- 15天
- 正在收集历史
- 1个月
- 正在收集历史
各周期内的星标净变化,周期相互重叠,并非每日新增。缺失的测量保持空白。星标代表关注度,不代表软件质量。
README.zh.md
原文mtproto.zig
让你所爱的人始终保持联系。
一个运行在你自己服务器上的小巧 Telegram 代理。它隐藏在普通的 HTTPS 流量之中,让审查无从发现 —— 你的家人也不会再失去它。一条命令即可部署,一个链接即可分享。
177 KB · under 1 MB RAM · 0 dependencies —— 没错,它就是这么精简 (详见下文 ↓)
技术上讲:一个用 Zig 编写、零依赖的小巧 MTProto 代理,能将 Telegram 流量伪装成标准的 TLS 1.3 HTTPS。
为何选它? · 安装 · 更新 · 命令 · 路由 · 配置 · 监控面板 · 构建 · Docker · 信任 · 兼容性 · FAQ
适用人群
- 你所在的地方 Telegram 被限速或被封锁,而你只想把它找回来。
- 你是家人遇事会求助的那个人 —— 你希望用一个只需点一次、之后再也无需操心的链接,保护你的父母和朋友。
它运行在你自己的服务器上 —— 你的消息绝不会经过我们的服务器,也无需注册任何账号。基于 MIT 开源;代理刻意从不记录密钥,也不记录谁连接过。
为什么不直接用 VPN?
VPN 会暴露自己 —— 审查者能识别其协议并加以封锁,而全设备 VPN 既慢又耗电。本项目看起来就像一个普通的 HTTPS 网站,只承载 Telegram 流量,而你分享给的人无需安装任何东西:他们点一下链接,剩下的交给 Telegram。它足够小巧,能跑在你能租到的最便宜的 VPS 上,启动即用,无需任何额外设置。
与其他 MTProto 代理的对比
大多数 MTProto 代理体积庞大、依赖繁多、占用大量内存。本项目则截然不同:
| 代理 | 语言 | 二进制大小 | 基准 RSS | 启动时间 | 依赖 |
|---|---|---|---|---|---|
| mtproto.zig | Zig | 177 KB | 0.75 MB | < 10 ms | 0 |
| 官方 MTProxy | C | 524 KB | 8.0 MB | < 10 ms | openssl, zlib |
| Telemt | Rust | 15 MB | 12.1 MB | ~ 5-6 s | 423 个 crate |
| mtg | Go | 13 MB | 11.6 MB | ~ 30 ms | 78 个模块 |
| MTProtoProxy | Python | N/A | ~ 30 MB | ~ 300 ms | python3, cryptography |
| JSMTProxy | Node.js | N/A | ~ 45 MB | ~ 400 ms | nodejs, openssl |
为什么选 Zig?
我们选择 Zig,是因为它提供了 C 那样的原始性能和极小的体积,却没有内存不安全问题,也没有构建系统的噩梦:
- 无任意分配: 所有连接槽和缓冲区都在启动时预先分配。没有垃圾回收器在高负载下丢帧。
- 封闭式交叉编译: 在 macOS 上运行
zig build,就能产出一个静态链接的 Linux 二进制文件。无需 Docker,也没有glibc版本不匹配的问题。 - Comptime(编译期计算): 协议定义映射、字节序转换以及
mtbuddy的双语字符串查找等昂贵操作都在编译期完成,从而实现瞬时启动。
下面这些名词你完全不用懂 —— 默认安装会为你全部开启。 在底层,本代理叠加的反审查技术比任何其他 MTProto 代理都多,并且会随着封锁手段变得更聪明而持续适配:
| 技术 | 作用 |
|---|---|
| Fake TLS 1.3 | 在 DPI 看来,连接就像普通的 HTTPS |
| DRS | 模仿 Chrome/Firefox 的 TLS 记录大小 |
| 主动探测伪装 | 如果审查者主动探测你的服务器,它会从本地 Web 后端获得一次真实的 TLS 握手(如果你拥有该域名则用真实证书,否则用自签名证书),而不是一个会暴露身份、沉默不语的代理。可选:为 single-round-x25519 域名直接前置真实的 tls_domain:443 |
| TCPMSS=88 | 将 ClientHello 分片到 6 个 TCP 包中,破坏 DPI 的重组 |
| nfqws TCP desync | 发送伪造数据包 + TTL 受限的分片,迷惑有状态的 DPI |
| Split-TLS | 使用 1 字节的 Application 记录,挫败被动特征匹配 |
| VPN 隧道 | 在 DC 被封锁时,通过显式的套接字策略路由(SO_MARK)经 WireGuard/AmneziaWG 转发 |
| IPv6 跳变 | 检测到被封时,通过 Cloudflare API 从 /64 段自动轮换 IPv6 地址 |
| 防重放 | 拒绝重放的握手 + 检测 ТСПУ Revisor 主动探测 |
| 多用户 | 每个用户拥有独立的密钥 |
| MiddleProxy | ME 传输,自动刷新 Telegram 元数据 |
推广标签(promotion tag)以及非 Premium 账号的媒体内容都需要 MiddleProxy。没有它,非 Premium 账号上的照片、视频、故事及其他媒体应被视为不可用,而非时好时坏。本代理不支持 Telegram 通话:Telegram 只通过 SOCKS 风格的路径路由通话,而暴露的 SOCKS 流量无法被 mtproto.zig 伪装成普通的 HTTPS。
安装
所有的安装、更新和管理都通过 mtbuddy 完成 —— 这是一个随代理一同发布的原生 Zig 命令行工具。
一条命令
curl -fsSL https://raw.githubusercontent.com/sleep3r/mtproto.zig/main/deploy/bootstrap.sh | sudo bash
# Explicitly allow unsigned bootstrap mode (not recommended)
curl -fsSL https://raw.githubusercontent.com/sleep3r/mtproto.zig/main/deploy/bootstrap.sh | sudo bash -s -- --insecure
# or: MTPROTO_INSECURE=1
这会下载最新的 mtbuddy 二进制文件,从 GitHub Release 验证 minisign 签名 + SHA-256 校验和,然后运行 mtbuddy --help。接着安装代理:
# Minimal — auto-generates a secret, enables all DPI bypass modules
sudo mtbuddy install --port 443 --domain rutube.ru --yes
# Bring your own secret and username
sudo mtbuddy install --port 443 --domain rutube.ru --secret <32-hex> --user alice --yes
# Disable all DPI modules (bare proxy only)
sudo mtbuddy install --port 443 --domain rutube.ru --no-dpi --yes
# Install using an existing config file (auto-maps port and domain)
sudo mtbuddy install --config /path/to/config.toml --yes
# Explicitly allow unsigned mode (not recommended)
sudo mtbuddy install --insecure --port 443 --domain rutube.ru --yes
最后,mtbuddy 会打印一条可直接使用的 tg:// 连接链接。
把它分享给你所爱的人。 把下面这段话连同链接一起发给他们: “我为我们搭了一扇通往 Telegram 的私人之门。点一下这个链接,选择「连接」,Telegram 就又能用了 —— 无需安装、无需付费,而且只属于我们。”
交互式向导
如果你更希望有人一步步引导你完成设置:
sudo mtbuddy --interactive
演示:交互式安装程序
安装过程做了什么
- 从 GitHub Releases 下载预编译的代理二进制文件(自动检测 CPU:
x86_64_v3→x86_64→aarch64) - 生成一个随机密钥(或使用
--secret) - 创建一个 systemd 服务(
mtproto-proxy) - 在
ufw中开放端口(如果 ufw 已启用) - 应用 TCPMSS=88 的 iptables 规则
- 设置 Nginx 伪装 + nfqws TCP desync(除非使用
--no-dpi) - 打印
tg://链接
安装选项
| 选项 | 默认值 | 说明 |
|---|---|---|
--port, -p |
443 |
代理监听端口 |
--public-port |
— | 在生成的 Telegram 链接中公布的端口 |
--domain, -d |
rutube.ru |
TLS 伪装域名(⚠️ 不可更改 —— 见下方注意事项) |
--secret, -s |
auto | 用户密钥(32 个十六进制字符) |
--user, -u |
user |
config.toml 中的用户名 |
--config, -c |
— | 使用现有的 config.toml 文件 |
--yes, -y |
— | 跳过确认提示 |
--max-connections <N> |
512 |
最大代理连接数 |
--bind, -b |
— | 绑定到指定 IP(默认:所有网络接口) |
--no-masking |
— | 禁用 Nginx 伪装 |
--no-nfqws |
— | 禁用 nfqws TCP desync |
--no-tcpmss |
— | 禁用 TCPMSS 钳制 |
--tcpmss <n> |
88 |
TCPMSS 钳制值(强制 ClientHello 分片) |
--no-dpi |
— | 禁用所有 DPI 模块 |
--middle-proxy |
— | 启用 Telegram MiddleProxy 中继 |
--ipv6-hop |
— | 启用 IPv6 自动跳变 |
--version, -v <tag> |
latest |
要安装的发布版本 |
--insecure |
— | 允许未签名的文件(不推荐) |
⚠️
--domain只能选定一次。 tg:// 链接中嵌入了tls_domain,因此在已上线的部署上更改它 (包括通过mtbuddy setup masking --domain …)会使你已经分享出去的每一个链接 全部失效。 参见 ARCHITECTURE.md / COMPATIBILITY.md。
更新
# Update to latest release (verifies minisign + checksum, checks CPU compat, auto-rollback on failure)
sudo mtbuddy update
# Pin to a specific version
sudo mtbuddy update --version v0.11.1
# Explicitly allow unsigned mode (not recommended)
sudo mtbuddy update --insecure
其他 mtbuddy 命令
# Show proxy and module status
sudo mtbuddy status
# Validate and inspect config
sudo mtbuddy config validate
sudo mtbuddy config doctor
sudo mtbuddy config doctor --network
sudo mtbuddy config print-effective
# Print Telegram proxy links from config.toml (FakeTLS ee by default; +dd when fake_tls_only=false; sensitive output)
sudo mtbuddy links
sudo mtbuddy links --server proxy.example.com --config /opt/mtproto-proxy/config.toml
# Generate a fresh 32-hex user secret
mtbuddy secret
# Hot-reload config (SIGHUP, reloadable settings only)
sudo mtbuddy reload
# Setup DPI modules after the fact
sudo mtbuddy setup masking --domain rutube.ru
sudo mtbuddy setup nfqws
sudo mtbuddy setup recovery
# 可选的内核级每 IP SYN 速率限制(防洪水,默认关闭)。
# 在 accept() 之前就在内核里丢弃滥用性的首个 SYN 突发;用独立的 systemd
# oneshot 实现,因此从不授予代理 CAP_NET_ADMIN。默认预设对 CGNAT 更安全。
sudo mtbuddy setup syn-limit --preset soft # soft 2/s·5 | medium 1/s·3 | hard 1/s·1
sudo mtbuddy setup syn-limit --status
sudo mtbuddy setup syn-limit --remove
# WEB 代理中继(Telegram Desktop 7.1+,MTProto 承载在普通 HTTPS 站点内)。
# 需要你拥有的域名,并把 A 记录指向本机。
sudo mtbuddy setup web --domain relay.example.com
sudo mtbuddy setup web --remove
# Install web monitoring dashboard
sudo mtbuddy setup dashboard
# VPN tunnel (for servers where Telegram DCs are blocked)
sudo mtbuddy setup tunnel /path/to/awg0.conf
sudo mtbuddy setup tunnel 'vpn://...'
sudo mtbuddy setup tunnel --iface awg1 /path/to/awg1.conf
# 通过 VPN 分享链接出口 — 为 代理→Telegram 跳转提供干净、难以封锁的上游。
# vless:// vmess:// trojan:// ss:// -> 本地 sing-box TUN 隧道(type=tunnel;VLESS-Reality 将跳转伪装为真实 TLS)。
# wireguard:// -> 原生内核 WG 隧道(等同 `setup tunnel`)。
# 多个链接 -> urltest 故障转移池。
sudo mtbuddy setup egress 'vless://...@host:443?security=reality&pbk=...&sni=...&flow=xtls-rprx-vision'
# vless / vmess / trojan / ss / hysteria2 — hysteria2 is QUIC, so measure UDP to the endpoint first
sudo mtbuddy setup egress 'wireguard://<privkey>@host:51820?publickey=...&address=10.0.0.2/32'
# IPv6 hopping
sudo mtbuddy ipv6-hop --check
sudo mtbuddy ipv6-hop --auto --prefix 2a01:abcd:ef00:: --threshold 5
# Update Cloudflare DNS A record
sudo mtbuddy update-dns 1.2.3.4 proxy.example.com
# Full help
mtbuddy --help
mtbuddy --lang ru --help
服务管理
sudo systemctl status mtproto-proxy
sudo journalctl -u mtproto-proxy -f
sudo systemctl reload mtproto-proxy # SIGHUP hot-reload (where possible)
sudo systemctl restart mtproto-proxy
上游路由
本代理支持多种方式将出站连接路由到 Telegram DC 服务器。
路由模式
[upstream].type |
工作方式 | 适用场景 |
|---|---|---|
auto(默认) |
直接出站,不带隧道策略标记 | 大多数部署 |
direct |
从主机直接连接 Telegram DC | 服务器可直达 DC |
tunnel |
直接连接,通过 SO_MARK=200 经 VPN 隧道池进行策略路由 |
DC 被 ISP 封锁 |
socks5 |
通过外部 SOCKS5 代理路由,可选认证 | 已有代理基础设施 |
http |
通过 HTTP CONNECT 代理路由,可选认证 | 企业代理环境 |
VPN 隧道
如果你的 VPS 位于 Telegram DC 在网络层被封锁的地区,你可以通过带显式套接字策略路由的 VPN 隧道池来路由代理流量。代理运行在主机命名空间中;只有被代理标记(SO_MARK=200)的套接字才会经由路由表 200 转发。mtbuddy 会让该路由表始终指向配置顺序中第一个健康的隧道。
当前支持的 VPN 类型:
- AmneziaWG —— 抗 DPI 的 WireGuard 分支(推荐用于俄罗斯/伊朗)
- WireGuard —— 标准 WireGuard(计划中)
Client → mtproto-proxy (host namespace)
│
SO_MARK=200
│
Linux policy routing table 200
│
awg0 / awg1 / ... (pool)
│
Telegram DC servers
sudo mtbuddy setup tunnel /path/to/awg0.conf
# or paste an Amnezia share link directly
sudo mtbuddy setup tunnel 'vpn://...'
# Add or replace a specific pool member
sudo mtbuddy setup tunnel --iface awg1 /path/to/awg1.conf
在 mtbuddy 的交互式菜单中,隧道设置会先询问 VPN 类型(目前为 AmneziaWG),然后显示当前的隧道池。选择 Create new tunnel 可追加下一个空闲的 awgN,或选择某个现有接口来替换该隧道池成员的配置。
mtbuddy 会保持 [general].use_middle_proxy 不变,只配置传输方式([upstream].type = "tunnel")。
设置完成后,它会安装 mtproto-tunnel-pool.timer,校验通往 Telegram DC 地址段的策略路由(mark 200),并打印操作命令。隧道池控制器会通过每条隧道探测 Telegram,并用 ip route replace 重写路由表 200;自动故障切换不会重启 mtproto-proxy。
你也可以在 config.toml 中显式配置隧道接口:
[upstream]
type = "tunnel"
[upstream.tunnel]
interface = "awg0"
interfaces = ["awg0", "awg1"]
pinned_interface = "" # optional; empty means priority auto-failback
SOCKS5 代理
通过外部 SOCKS5 代理路由 DC 连接。支持 RFC 1928 认证。
[upstream]
type = "socks5"
[upstream.socks5]
host = "127.0.0.1"
port = 1080
username = "admin" # optional, omit for no-auth
password = "secret"
HTTP CONNECT 代理
通过 HTTP CONNECT 代理路由 DC 连接。支持 Basic 认证。
[upstream]
type = "http"
[upstream.http]
host = "127.0.0.1"
port = 8080
username = "admin" # optional, omit for no-auth
password = "secret"
注意: 通往 DC 的中继流量以及 MiddleProxy 元数据刷新(
getProxyConfig/getProxySecret)会使用所配置的上游。伪装(掩护)连接始终直连。依赖说明: “零依赖”的说法适用于默认的
auto/direct出站方式。在socks5、http或tunnel上游模式下,MiddleProxy 元数据刷新会调用外部的curl,因此主机上必须安装curl(标准安装程序会自动安装它)。
配置
配置文件位于 /opt/mtproto-proxy/config.toml。MTBuddy 会在安装时生成它;你也可以手动编辑后重启:
[general]
use_middle_proxy = true # ME mode for promo-channel parity
[upstream]
type = "auto" # auto | direct | tunnel | socks5 | http
# allow_direct_fallback = false # fail-closed by default for socks5/http misconfig
[server]
port = 443
# public_ip = "proxy.example.com" # Inbound IP/domain used in client links
# public_port = 443 # Link port when behind HAProxy/Nginx
# middle_proxy_nat_ip = "203.0.113.10" # Outbound IPv4 seen by Telegram MiddleProxy
max_connections = 512
# workers = 1 # SO_REUSEPORT epoll workers: 1 = single-threaded (default); 0 = one per CPU; N spreads load across cores
idle_timeout_sec = 120
# client_silence_close_sec = 0 # Close a relay whose server reply went unanswered by the client for N sec (breaks an iOS bad_salt wedge where "Updating" hangs ~90-120s) → instant clean reconnect. 0 = off; best-effort, can occasionally close a healthy conn — ~10-15 if you enable it
handshake_timeout_sec = 15
# dc_connect_timeout_sec = 10 # 连接到某个 Telegram DC 端点的每端点 TCP-connect 截止时间;让被黑洞的端点快速失败,从而(在 handshake_timeout_sec 内)让故障转移推进到下一个。0 = 关闭;从不影响健康连接(<1 秒)
graceful_shutdown_timeout_sec = 15
log_level = "info" # debug | info | warn | err
rate_limit_per_subnet = 0 # 0 = disabled (default; avoids carrier-NAT false positives). Set e.g. 30 for non-NAT hosts
handshake_flood_guard_enabled = false
handshake_flood_guard_threshold = 20
handshake_flood_guard_window_sec = 30
handshake_flood_guard_block_sec = 120
tag = "" # Optional: promotion tag from @MTProxybot
[censorship]
tls_domain = "rutube.ru"
mask = true
# mask_target = "host.docker.internal" # Optional: custom masking backend host (Docker/remote Nginx)
mask_port = 8443 # 8443 = local Nginx backend (what mtbuddy installs); 443 = front the real tls_domain (opt-in, single-round-x25519 domains only)
fast_mode = true # Recommended: delegates S2C AES to the DC, saves CPU/RAM
drs = true # Dynamic Record Sizing (mimics Chrome/Firefox)
[access.users]
alice = "00112233445566778899aabbccddeeff"
bob = "ffeeddccbbaa99887766554433221100"
[access.direct_users]
alice = true # bypass MiddleProxy for this user
完整配置参考
| 配置项 | 默认值 | 说明 |
|---|---|---|
[upstream].type |
auto |
出站模式:auto(直连)、direct、tunnel(通过套接字策略路由走 VPN)、socks5 或 http |
[upstream] allow_direct_fallback |
false |
若为 true,则在上游不可用时允许 socks5/http 模式回退到直接出站 |
[upstream.tunnel] interface |
"awg0" |
旧版单隧道接口 / SO_MARK 路由的回退项 |
[upstream.tunnel] interfaces |
["awg0"] |
有序的隧道池;第一个健康的接口优先生效 |
[upstream.tunnel] pinned_interface |
— | 可选的手动优先项,在其健康时优先于有序隧道池使用 |
[upstream.socks5] host |
— | SOCKS5 代理地址 |
[upstream.socks5] port |
— | SOCKS5 代理端口 |
[upstream.socks5] username |
— | SOCKS5 用户名(留空 = 无认证) |
[upstream.socks5] password |
— | SOCKS5 密码 |
[upstream.http] host |
— | HTTP CONNECT 代理地址 |
[upstream.http] port |
— | HTTP CONNECT 代理端口 |
[upstream.http] username |
— | HTTP 代理用户名(留空 = 无认证) |
[upstream.http] password |
— | HTTP 代理密码 |
[general] use_middle_proxy |
false |
针对 DC1..5 的 ME 模式(推荐,以与推广功能保持一致) |
[general] ad_tag |
— | [server].tag 的别名 |
[server] port |
443 |
TCP 监听端口 |
[server] bind_address |
— | 用于绑定监听套接字的指定 IP(默认:所有网络接口) |
[server] public_ip |
auto | 在客户端链接中显示的入站 IP/域名。使用 VPN 隧道时必填;若客户端在 IPv6 链接上连接失败,请显式设置 IPv4 |
[server] public_port |
[server].port |
在客户端链接中显示的端口;当 HAProxy/Nginx 对外暴露不同的公共端口时很有用 |
[server] middle_proxy_nat_ip |
auto | 用于 MiddleProxy 密钥派生的出站 IPv4;与 public_ip 相互独立地自动检测,当 DC 流量经 VPN/NAT IP 出站时请显式设置 |
[server] backlog |
4096 |
TCP 监听队列深度 |
[server] max_connections |
512 |
并发连接上限,会根据 RAM 和 RLIMIT_NOFILE 自动钳制 |
[server] workers |
1 |
SO_REUSEPORT epoll 工作线程数。1 = 单线程;0 = 每个 CPU 一个;N 将中继/加密负载分散到多个核心。当 >1 时,SIGHUP 配置重载需要重启 |
[server] idle_timeout_sec |
120 |
连接空闲超时 |
[server] idle_timeout_jitter_pct |
15 |
对空闲超时施加每连接 ±% 的抖动,避免固定值成为指纹(0 表示禁用) |
[server] dc_connect_timeout_sec |
10 |
连接到某个 Telegram DC 端点的每端点 TCP-connect 截止时间。被过滤/黑洞的端点不会发送 RST,因此内核会在 SYN_SENT 状态停留约 2 分钟;handshake_timeout_sec 虽已对整个握手设上限,但那是全局的,所以一个慢的首个端点会让其余的故障转移挨饿。该项让单个失效端点快速失败并推进到下一个(在 handshake_timeout_sec 上限之内)。保持低于 handshake_timeout_sec。0 = 关闭;健康连接在 <1 秒内完成,因此从不受其影响 |
[server] client_silence_close_sec |
0 |
当服务器最后一条回复已 N 秒未被客户端应答时关闭该已建立中继,触发即时(~450 毫秒)干净重连。修复 iOS MtProtoKit 卡死:盐过期被拒后客户端丢弃盐、停止发送,"更新中"卡住 ~90-120 秒直到 DC 关闭套接字。仅当最后一个负载是 server→client 时才触发(最后一次动作是自身 ping/ack 的健康空闲连接不受影响)。尽力而为的权宜之计:低于最慢合法响应的值偶尔也会关掉健康连接(仅 450ms 重连)。0 = 关闭(默认);如启用,10–15 为合理起点,自行调整 |
[server] handshake_timeout_sec |
15 |
握手完成超时 |
[server] graceful_shutdown_timeout_sec |
15 |
强制关闭前 SIGTERM 排空超时 |
[server] middleproxy_buffer_kb |
1024 |
ME 每连接缓冲区(KiB)。低于 1024 在媒体流量下可能导致溢出 |
[server] tag |
— | 来自 @MTProxybot 的 32 个十六进制字符推广标签 |
[server] log_level |
"info" |
debug / info / warn / err |
[server] rate_limit_per_subnet |
0 |
每个 /24(IPv4)或 /48(IPv6)每秒最大新建连接数。0 = 禁用(默认,对 NAT 友好);非 NAT 主机可设为如 30 |
[server] handshake_flood_guard_enabled |
false |
临时拒绝那些反复 MTProto 握手失败的具体源 IP(默认关闭 —— 对 NAT/VPN 安全) |
[server] handshake_flood_guard_threshold |
20 |
每个源 IP 触发临时拒绝前所允许的错误握手/限速/预算事件数 |
[server] handshake_flood_guard_window_sec |
30 |
handshake_flood_guard_threshold 的滚动时间窗口 |
[server] handshake_flood_guard_block_sec |
120 |
对喧闹源 IP 的临时拒绝时长 |
[server] unsafe_override_limits |
false |
禁用对 max_connections 的自动钳制 |
[monitor] host |
"127.0.0.1" |
面板绑定地址 |
[monitor] port |
61208 |
面板端口 |
[metrics] enabled |
false |
启用内置的 Prometheus /metrics 端点 |
[metrics] host |
"127.0.0.1" |
指标绑定地址 |
[metrics] port |
9400 |
指标端口 |
[censorship] tls_domain |
"google.com" |
要冒充的域名 |
[censorship] mask |
true |
将未认证的客户端转发到 tls_domain |
[censorship] unknown_sni_action |
"mask" |
对未知 SNI 的 ClientHello 的处理方式:mask(转发)、reject(像拒绝连接的服务器那样返回致命 TLS 警报)或 drop |
[censorship] mask_target |
unset | 被伪装客户端的可选后端主机 |
[censorship] mask_port |
443 |
本地伪装端口(Nginx zero-RTT 时使用 8443) |
[censorship] desync |
true |
Split-TLS:1 字节的 Application 记录 |
[censorship] drs |
false |
动态记录大小调整(Dynamic Record Sizing) |
[censorship] fast_mode |
false |
将 S2C 加密委托给 DC(推荐) |
[web] enabled |
false |
启用 WEB 代理中继(Telegram Desktop 7.1+) |
[web] only |
false |
仅提供 WEB:除中继外的直连 MTProto 一律转入伪装后端;需要 mask = true,未 enabled 时忽略 |
[web] domain |
未设置 | tg://webproxy 链接中的公开主机名 —— 分发链接后不可更改 |
[web] listen |
"127.0.0.1" |
中继绑定地址(TLS 在其前端终止) |
[web] port |
8081 |
中继端口 |
[web] backend |
127.0.0.1:<server.port> |
中继为每条逻辑流拨号的 MTProxy |
[web] ws_path |
"/api/v1/socket" |
桥接页面的同源 WebSocket 端点 |
[web] trust_forwarded_for |
true |
从 X-Forwarded-For 取客户端地址 |
[web] check_origin |
true |
升级时要求 Origin: https://<domain> |
[web] max_sessions |
64 |
并发桌面客户端数 |
[web] max_streams |
32 |
每客户端的逻辑 MTProto 套接字数 |
[web] relay_sources |
[] |
额外允许使用 dd 传输的 IP(loopback 始终允许) |
[web] cert / [web] key |
未设置 | 为中继 vhost 自备证书,替代 Let's Encrypt(由 mtbuddy setup web 读取) |
[access.users] <name> |
— | 每个用户的 32 个十六进制字符密钥 |
[access.direct_users] <name> |
— | 为该用户绕过 ME |
[access.user_max_conns] <name> |
— | 每个用户的并发连接上限(更改需重启) |
[access.user_expirations] <name> |
— | 每个用户的到期日期 "YYYY-MM-DD"(更改需重启) |
[access.user_max_ips] <name> |
— | 每个用户同时使用该链接的不同客户端网络(IPv4 地址 / IPv6 /64)数量上限(更改需重启) |
生成密钥:
mtbuddy secret或openssl rand -hex 16显式打印客户端链接:
sudo mtbuddy links。默认情况下它只打印 FakeTLS(ee...domain)链接;当启用dd传输(fake_tls_only = false)时,它也会打印安全填充(dd...)链接。运行时的代理日志会刻意隐藏密钥和代理链接。
dd(“安全”/填充)传输默认被拒绝([censorship].fake_tls_only = true)—— 它是纯粹混淆的 MTProto,没有任何 TLS 伪装,可被 DPI 直接识别为 MTProto 特征。默认情况下代理只接受 FakeTLS(ee),且mtbuddy links只打印ee链接。若要发放dd链接(低 DPI / 兼容性场景),请设置fake_tls_only = false。参见 THREAT_MODEL.md。两个滥用防护默认均关闭,以免大型运营商 NAT、VPN 出口或共享办公网络(许多合法客户端共用一个源 IP/子网)被误判并一起拦截:每子网的新建连接速率限制(
rate_limit_per_subnet = 0)与精确 IP 的握手洪水防护(handshake_flood_guard_enabled = false)。访问本就已由每用户密钥、全局握手在途预算以及max_connections把关。在遭受真实滥用的单租户 / 非 NAT 主机上,请将它们开启:设置rate_limit_per_subnet(如30)并设handshake_flood_guard_enabled = true(调整handshake_flood_guard_threshold/ 窗口 / 拦截时长)。上述两者都在 accept() 之后运行(它们在代理进程内)。如果还需要一个内核级的层级,在滥用性的首个 SYN 突发耗费 socket/accept() 之前就将其丢弃,可使用一个可选的每源 IP SYN 速率限制器:
sudo mtbuddy setup syn-limit --preset soft。它是一条 iptables hashlimit 规则,作为独立的 mtproto-syn-limit.service oneshot 安装,因此从不授予代理 CAP_NET_ADMIN。同样默认关闭,并受同样的运营商 NAT 注意事项约束(soft 2/s·burst-5 预设是对 CGNAT 更安全的默认值);用 --remove 撤销,drop 计数与状态见 mtbuddy status。更改代理端口后请重新运行它。
WEB 代理(Telegram Desktop 7.1+)
Telegram Desktop 7.1 新增了第四种代理类型 WEB。它仍然是普通的 MTProxy,但载体是浏览器:客户端根本不打开
MTProto 套接字。隐藏的原生 WebView 加载 https://<你的域名>/?bridge=<capability>,页面通过同源 WebSocket
把复用帧转发给中继,中继再为每条逻辑流拨号到普通 MTProxy —— 也就是本项目。
Telegram Desktop → 隐藏 WebView → https://relay.example.com/ ← 真实浏览器对真实站点的 TLS 握手
→ mtproto-web-relay → mtproto-proxy → Telegram
审查者看到的是真实的浏览器指纹、真实的 CA 证书链和随后的 HTTP —— 因为它本来就是。没有可能对不上的 FakeTLS ServerHello,链路上也没有 MTProto 握手。
sudo mtbuddy setup web --domain relay.example.com
sudo mtbuddy links # 现在也会打印 tg://webproxy 链接
需要你拥有的域名,并把 A 记录指向本机;mtbuddy 会通过 HTTP-01 申请 Let's Encrypt 证书(因此会开放 80 端口)
并安装续期钩子。
--mode mask(默认):中继通过代理自身的 masking 后端提供服务 —— 本地 Nginx 上按 SNI 选择的第二个 vhost, 不需要额外的公开端口。--mode behind:中继监听普通 HTTP,由 Cloudflare、另一台主机或备用 IP 终止 TLS。
WEB 链接携带与 FakeTLS 链接相同的 16 字节密钥,只是编码为 dd…(Telegram Desktop 认为 ee FakeTLS 密钥
对 WEB 代理不受支持)。fake_tls_only 保持开启:只有中继自身的源地址被允许通过该闸门,且判定依据是 accept()
报告的地址。中继会用 PROXY 协议头转发真实客户端地址,因此按 IP 的统计与限流仍然准确。
限制: 仅桌面端(7.1+),不支持通话,且比直连更受 RTT 影响。它是直连链接被封锁时的备用通道,而不是替代品。
监控面板
一个轻量级的 Web 面板(约 30 MB RAM)展示实时连接、CPU/内存、网络吞吐、代理统计、隧道池健康/故障切换状态、用户管理以及流式日志。
该面板直接内嵌在 mtbuddy 二进制文件中 —— 无需任何额外文件。
# Install the dashboard on the server
sudo mtbuddy setup dashboard
# Open via SSH tunnel (binds to 127.0.0.1:61208 by default)
ssh -L 61208:localhost:61208 root@<server_ip>
# → http://localhost:61208
该面板需要 HTTP Basic 认证(用户名:任意;密码自动生成于 /opt/mtproto-proxy/monitor/dashboard.token —— 在服务器上 cat 查看)。它是一个具有 root 权限的控制平面,因此请将其保留在回环/SSH 隧道路径上,切勿将明文 HTTP 暴露到公网 —— 如确有需要,请在其前面加上 HTTPS + 反向代理。
演示:监控面板
Prometheus 指标
mtproto-proxy 可以在专用端口上暴露一个内置的、兼容 Prometheus 的指标端点。
若需要一套完整的、基于 Docker 的监控栈(包含 mtproto-zig、Prometheus、Grafana 以及可导入的仪表盘),请参见 hack/docker/README.md。
[metrics]
enabled = true
host = "127.0.0.1"
port = 9400
该端点为明文 HTTP,提供:
GET /metrics
典型的 Docker 用法:
docker run --rm \
-p 443:443 \
-p 9400:9400 \
-v "$PWD/config.toml:/etc/mtproto-proxy/config.toml:ro" \
mtproto-zig
它会暴露代理计数器,以及诸如 RSS、虚拟内存、CPU 时间和已打开文件描述符等进程指标。
本地构建
需要 Zig 0.16.0。
git clone https://github.com/sleep3r/mtproto.zig.git
cd mtproto.zig
make build # cross-compile ReleaseFast binaries for Linux x86_64_v3+aes
make test # run Zig tests
make e2e # run E2E/integration harness
make fmt # format Zig sources
make deploy # build + deploy to SERVER (see Makefile)
make dashboard # SSH tunnel for web dashboard (localhost:61208)
# optional performance checks
zig build bench
zig build soak
发布构建者如有需要,可以覆盖默认固定的 minisign 密钥:
zig build -Dminisign_pubkey=RW... -Doptimize=ReleaseFast -Dtarget=x86_64-linux
在 macOS 上交叉编译 Linux 版本:
zig build -Doptimize=ReleaseFast -Dtarget=x86_64-linux -Dcpu=x86_64_v3+aes
scp zig-out/bin/mtproto-proxy root@<SERVER>:/opt/mtproto-proxy/
Docker
提供 Docker 支持是为了测试、打包实验,以及只需要代理二进制文件的简单部署。本项目主要面向由 mtbuddy 管理的原生 Linux 主机:DPI 模块、隧道池故障切换、策略路由、Nginx 伪装、nfqws 以及恢复定时器都是主机级别的集成,容器无法完整体现这些功能。
docker pull ghcr.io/sleep3r/mtproto.zig:latest
docker run --rm \
-p 443:443 \
-v "$PWD/config.toml:/etc/mtproto-proxy/config.toml:ro" \
ghcr.io/sleep3r/mtproto.zig:latest
MiddleProxy 的媒体/推广流量对其加密握手中使用的出站源 IP:port 很敏感。对于需要 MiddleProxy 的 Docker 部署,建议使用主机网络(--network host)或原生的 mtbuddy 安装。[server].public_ip 只是显示给客户端的入站地址;如果出站 DC 流量经由 VPN/NAT IP 出去,请将 [server].middle_proxy_nat_ip 设置为该出站 IPv4。会重写源端口的桥接或远程 NAT 仍可能破坏 MiddleProxy 握手。
本地构建:
docker build -t mtproto-zig .
# multi-arch
docker buildx build --platform linux/amd64,linux/arm64 -t your-registry/mtproto-zig:latest --push .
发布的 linux/amd64 镜像使用可移植的 CPU 配置(-Dcpu=x86_64)构建,以避免在较旧的 VPS CPU 上出现 Illegal instruction 崩溃。
对于生产环境的反审查部署,请优先使用原生的
mtbuddy install流程。操作系统级别的缓解措施(iptables TCPMSS、nfqws、隧道策略路由、伪装/恢复单元)不会在容器内应用;容器中只运行代理二进制文件。
信任与安全
- SECURITY.md - 漏洞报告政策与响应流程
- THREAT_MODEL.md - 安全目标、非目标、对手模型、残余风险
- CONTRIBUTING.md - 开发工作流(
fmt/test/e2e/bench)与 PR 期望 - CHANGELOG.md - 发布历史
- LICENSE - MIT 许可证条款
仓库治理:
.github/CODEOWNERS.github/ISSUE_TEMPLATE下的 issue 模板
已知限制与兼容性
完整模型请参见 THREAT_MODEL.md。以下是简要的运行要点:
- 已知限制
- 这是一个用于加固传输的代理,而非匿名网络。
- 随着 DPI 策略不断演进,绕过效果可能会下降。
- 面板/指标默认为明文;未经认证/TLS 时切勿公开暴露。
- Telegram 通话无法通过本代理使用。通话需要 Telegram 的 SOCKS 风格通话路径,这超出了 MTProto/TLS 伪装模型的范围,在此无法被干净地伪装成普通 HTTPS。
- 没有 MiddleProxy(
[general].use_middle_proxy = true),非 Premium 账号上的媒体内容将无法加载。照片、视频、故事和推广标签都需要 MiddleProxy。
- 特定地区注意事项
- ISP 的行为因国家/地区而异;配置无法通用移植。
- IPv6 与 AAAA 的处理在不同服务商之间差异很大,可能影响 iOS/桌面端的连接延迟。
- 隧道路由取决于主机的策略路由以及该地区所允许的 VPN 协议。
- Telegram 客户端兼容性
- 官方 Telegram Android/iOS/桌面端:预期在当前版本上可正常工作。
- 第三方客户端:仅尽力而为。
- 内核/操作系统兼容性矩阵
- Linux
x86_64:支持(主要目标) - Linux
aarch64:支持 - Linux 上的 Docker:有保留地支持(操作系统级别的 DPI 模块在主机侧)
- macOS/Windows 运行时:不支持(仅支持 Linux 运行时目标)
- Linux
- Telegram/DC 变更后可能出问题的地方
- MiddleProxy 元数据与端点行为
- 较新 Telegram 客户端中的握手预期
- DC/媒体路由的边缘情况(例如 DC203 的行为)
故障排查 — 卡在 “Updating...”
1. 存在 AAAA 记录,但服务器上的 IPv6 不可用。 DNS 中有 AAAA → iOS 会先尝试 IPv6 → 超时 → 缓慢回退到 IPv4。 解决:在 IPv6 路由完全配置好之前移除 AAAA 记录。
dig +short proxy.example.com AAAA
ip -6 route
2. 家庭 Wi-Fi 封锁了服务器的 IPv4。 移动网络通常可用(它们使用 IPv6)。家用路由器常常会封锁目标 IPv4。 解决:在你的路由器上启用 IPv6 前缀委派(IA_PD)。
3. VPN 正在丢弃 MTProto 流量。 商业 VPN 常常会对流量做 DPI 并丢弃代理流量。 解决:更换 VPN 协议,或使用自建的 AmneziaWG。
4. 同一服务器上同时部署了 WireGuard/Docker。
Docker 的网桥会丢弃来自 VPN 子网的数据包。
解决:iptables -I DOCKER-USER -s 172.29.172.0/24 -p tcp --dport 443 -j ACCEPT
5. 非 Premium 客户端上 DC203 媒体连接被重置。
检查日志:journalctl -u mtproto-proxy | grep -E "dc=203|Middle"。
代理会在启动时从 Telegram 自动刷新 DC203 元数据。如果 core.telegram.org 不可达,它会使用内置的回退地址。
在 [upstream].type = "socks5" 或 "http" 下,元数据刷新会使用该上游;运行 sudo mtbuddy config doctor --network 以验证代理端点和 Telegram 元数据获取路径。
许可证
MIT © 2026 Aleksandr Kalashnikov
探索相关项目
trimstray/the-book-of-secret-knowledge
汇集各类启发灵感的清单、手册、速查表、博客、技巧、单行命令、CLI/Web 工具等内容。
257,935 星标Hack-with-Github/Awesome-Hacking
面向黑客、渗透测试人员与安全研究人员的各类 Awesome 清单合集。
125,254 星标swisskyrepo/PayloadsAllTheThings
一份用于 Web 应用安全以及渗透测试/CTF 的实用 payload 与绕过方法列表。
82,623 星标caddyserver/caddy
快速、可扩展的跨平台 HTTP/1-2-3 Web 服务器,支持自动 HTTPS
79,020 星标