在Nginx 443端口隐匿部署Telegram MTProxy
本文旨在解决系统管理员和开发者面临的一个关键挑战:如何在不干扰现有Nginx管理的Web服务的前提下,在标准的HTTPS 443端口上部署Telegram MTProxy。这种配置通过将代理流量伪装成常规Web流量,显著增强了代理抵御检测和封锁的能力。主要难点在于Nginx如何正确路由请求,在同一端口上区分目标HTTP/HTTPS站点和MTProxy。本指南将详细阐述Nginx stream 模块的运行机制及其与 mtprotoproxy 的集成,以创建一个强大而隐蔽的解决方案。
Nginx Stream 模块如何实现多路复用
为了让MTProxy和Nginx能在443端口上成功共存,一个智能的路由机制至关重要。Nginx的stream模块在TCP/UDP层运行,能够在完整的应用层处理之前分析初始连接数据。一个关键点是,TLS ClientHello消息中的服务器名称指示(SNI)字段即使在加密连接中也是以明文传输的。这使得Nginx无需解密整个SSL流即可读取请求的主机名。
所提出的解决方案采用以下逻辑:
- HTTPS主机的端口重分配: 所有先前监听443端口的现有Nginx HTTPS虚拟主机都将迁移到一个内部端口,例如4443。这为集中式处理器腾出了443端口。
- Nginx Stream 作为中央路由器: 在现在可用的443端口上配置一个Nginx
stream服务器。该服务器使用ssl_preread on指令从传入的SSL连接中提取SNI。 - 动态路由: 根据提取到的SNI,Nginx
stream做出决策:
* 如果SNI与为MTProxy选择的域名(例如 myprovider.ru)匹配,则连接将被转发到MTProxy(MTProxy将监听一个本地端口,例如7788)。
* 如果SNI与任何其他域名匹配,则连接将被重定向回Nginx,但会重定向到内部端口4443,在那里由标准的HTTPS虚拟主机进行处理。
- 保留真实IP: 为了准确的日志记录、流量分析以及Nginx后端应用程序的正常运行,使用了
proxy_protocol。这允许真实的客户端IP地址沿着代理链传递。
这种方法使得MTProxy能够伪装成常规的HTTPS流量,与Web服务器使用相同的端口。这显著提高了其抵御检测和封锁的能力,使其流量与标准Web连接无法区分。
配置Nginx以实现共存
第一步是修改所有现有Nginx HTTPS虚拟主机的配置。您需要将其监听端口从443更改为内部端口,例如 127.0.0.1:4443。这确保了Nginx在 stream 模块重定向请求后能够处理这些请求。
示例 server 块修改:
server {
server_name mywebsite.ru;
listen 127.0.0.1:4443 ssl http2 proxy_protocol;
set_real_ip_from 127.0.0.1; # 信任localhost作为PROXY协议源
real_ip_header proxy_protocol; # 从PROXY协议头中提取IP
real_ip_recursive on; # 递归应用以正确确定IP
# ... 您的服务器块的其他指令 ...
ssl_certificate /etc/letsencrypt/live/mywebsite.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebsite.ru/privkey.pem;
# ... 其他SSL/TLS设置 ...
}
listen 中的 proxy_protocol 指令指示Nginx期望接收PROXY协议头。set_real_ip_from 和 real_ip_header 对于Nginx正确识别并传递客户端的真实IP地址至关重要,而不是Nginx Stream将使用的本地主机IP(127.0.0.1)。如果没有这些设置,所有对您站点的请求都将显示为源自 127.0.0.1,这可能会扰乱应用程序功能、日志记录和安全系统。
下一步是为Nginx stream 模块创建一个新的配置文件。建议将其放置在 /etc/nginx/conf.d/stream.conf 或其他能确保Nginx加载它的合适位置。
stream {
log_format stream '$remote_addr [$time_local] host=$ssl_preread_server_name '
'prot=$protocol status=$status out=$bytes_sent in=$bytes_received';
# 可选:启用日志以进行调试
#access_log /var/log/nginx/stream_access.log stream;
#error_log /var/log/nginx/stream_error.log;
map $ssl_preread_server_name $backend_name {
myprovider.ru tg_proxy; # 选定MTProxy域名的流量
default nginx_https; # 所有其他HTTPS流量
}
upstream nginx_https {
server 127.0.0.1:4443; # 重定向到Nginx的内部端口
}
upstream tg_proxy {
server 127.0.0.1:7788; # 重定向到MTProxy的本地端口
}
server {
listen 443 reuseport; # 监听主443端口
proxy_pass $backend_name;
ssl_preread on; # 启用SNI读取以确定主机名
proxy_protocol on; # 启用PROXY协议以传递真实IP
}
}
在此块中,map 用于将SNI($ssl_preread_server_name)与后端名称关联起来。$backend_name 将根据请求的域名是 tg_proxy 还是 nginx_https。upstream 指令定义了每个后端流量的转发位置。listen 443 reuseport 允许多个Nginx进程监听同一端口,从而提高性能和容错能力。ssl_preread on 是一个关键指令,它使Nginx无需解密整个SSL流量即可获取SNI。
如果您的当前Nginx安装不支持 stream 模块(例如,它是最小化构建),则需要安装它。在Debian/Ubuntu上,可以使用以下命令完成:
sudo apt install nginx-full
完成所有更改后,您必须验证Nginx配置并重新启动它:
nginx -t && sudo systemctl restart nginx
在基于systemd的系统上,使用 systemctl restart 而不是 service nginx restart 是更现代和推荐的方法。
MTProxy安装与配置
在此设置中实现MTProxy,我们将使用alexbers开发的高效Python实现 mtprotoproxy,它与Nginx proxy_protocol 良好集成,并支持所需的TLS伪装模式。
安装过程包括克隆仓库并切换到适当的分支:
(cd /opt || sudo mkdir /opt && sudo chown $(whoami):$(whoami) /opt) && cd /opt
git clone https://github.com/alexbers/mtprotoproxy.git
cd mtprotoproxy
# 重要提示:在撰写本文时,此配置在master分支上可实现稳定运行
git checkout master
接下来,为MTProxy生成一个密钥(secret)。此密钥将用于Telegram客户端的身份验证,并且必须是唯一的:
head -c 16 /dev/urandom | xxd -ps
生成的32位十六进制值应该保存下来。现在,您需要在 mtprotoproxy 目录中创建或编辑 config.py 文件:
# /opt/mtprotoproxy/config.py
PORT = 7788 # Nginx Stream将重定向流量到的本地端口
LISTEN_ADDR_IPV4 = "127.0.0.1" # 为安全起见绑定到localhost
LISTEN_ADDR_IPV6 = None # 如果不需要或未配置,则禁用IPv6
# 用户及其密钥的字典。可以为不同的组创建多个。
USERS = {
"tg_user_1": "YOUR_GENERATED_SECRET_HERE",
# "tg_user_2": "0123456789abcdef0123456789abcdef", # 额外密钥示例
}
# MTProxy运行模式
MODES = {
"classic": False, # 经典模式,易于检测
"secure": False, # 改进模式,但伪装效果不佳
"tls": True # TLS伪装模式,最能抵抗检测
}
# TLS模式的域名。MTProxy将在启动时检查其可用性。
# 使用您在Nginx Stream配置中选择的域名。
TLS_DOMAIN = "myprovider.ru" # 将用于MTProxy的域名
PROXY_PROTOCOL = True # 与Nginx Stream配合工作的强制设置
# AD_TAG = "GET_YOUR_AD_TAG_FROM_@MTProxybot" # 可选:用于广告标签
这里的关键设置包括:LISTEN_ADDR_IPV4 = "127.0.0.1" 确保MTProxy只能通过同一服务器上的Nginx访问,从而增强安全性。MODES = {"tls": True} 激活TLS伪装模式,使MTProxy流量与常规HTTPS无法区分。TLS_DOMAIN 必须与Nginx Stream map 指令中指定的域名匹配,以便Nginx正确识别和转发流量。最后,PROXY_PROTOCOL = True 允许MTProxy从Nginx接收客户端的真实IP地址,这对于正常运行和日志记录至关重要。
验证与自动化启动
在配置Nginx和MTProxy之后,彻底验证整个系统的功能至关重要。
验证MTProxy和Nginx功能
- 手动启动MTProxy: 导航到
/opt/mtprotoproxy目录,手动启动MTProxy进行初步检查:
```bash
python3 mtprotoproxy.py
```
控制台应显示一行代理连接参数,例如:
```
tg_user_1: tg://proxy?server=YOUR_VM_IP&port=7788&secret=LONG_SECRET
```
重要提示: 这里显示的密钥将带有 ee 前缀,并包含 config.py 中指定的编码 TLS_DOMAIN。这是TLS伪装机制的一部分。复制此链接。
- 使用Telegram客户端测试:
* 在复制的链接中,将端口从 7788 更改为 443。
* 将生成的链接发送到Telegram的“收藏夹”或“保存的消息”中。
* 点击链接并选择“连接”。
* 如果一切配置正确,Telegram应该能通过代理成功连接。为了进行额外检查,您可以向任何机器人(例如 @MTProxybot)发送 /ping 命令——应返回一条包含当前代理延迟的消息。
- 验证HTTPS伪装: 为确认MTProxy正确伪装成常规网站,请执行以下检查:
* 将以下行添加到您的本地 hosts 文件中(对于Linux/macOS,是 /etc/hosts;对于Windows,是 %SystemRoot%\System32\drivers\etc\hosts):
```
YOUR_VM_IP myprovider.ru
```
* 将 YOUR_VM_IP 替换为您的服务器实际IP地址。
* 在浏览器中打开 https://myprovider.ru。
* 如果一切正常,您应该能看到 myprovider.ru 的内容(您的提供商网站或您在 TLS_DOMAIN 中指定的任何其他域名)。这证实了Nginx Stream将请求重定向到MTProxy,并且MTProxy识别为非Telegram流量后,透明地将其代理到原始Web资源,从而展示了成功的TLS伪装。
* 验证后请务必删除 hosts 文件中添加的行。
将MTProxy设置为Systemd服务
为确保MTProxy在系统启动时自动启动并持续运行,建议将其配置为 systemd 服务。
- 停止 手动运行的MTProxy(
Ctrl+C)。 - 创建 一个
systemd单元文件,路径为/etc/systemd/system/mtprotoproxy.service:
```ini
[Unit]
Description=MTProto Proxy
After=network.target
[Service]
Type=simple
User=nobody
Group=nogroup
WorkingDirectory=/opt/mtprotoproxy
ExecStart=/usr/bin/python3 /opt/mtprotoproxy/mtprotoproxy.py
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
```
在这里,User=nobody 和 Group=nogroup 通过以最小权限运行服务来增强安全性。WorkingDirectory 指向 mtprotoproxy.py 脚本所在的目录。
- 重新加载
systemd配置,启用服务并启动它:
```bash
sudo systemctl daemon-reload
sudo systemctl enable mtprotoproxy.service
sudo systemctl start mtprotoproxy.service
```
- 检查 服务状态:
```bash
systemctl status mtprotoproxy.service
```
输出应显示服务处于 active (running) 状态。
- 查看日志: 用于调试或监控,请使用:
```bash
journalctl -u mtprotoproxy.service -e
```
这种全面的设置允许您在443端口上使用Telegram MTProxy,有效地将其伪装成常规HTTPS流量,同时保留同一服务器上现有网站的全部功能。
重要提示:
- 在Nginx Stream中使用
ssl_preread可以在不解密的情况下基于SNI进行流量路由,这对于在单个端口上分离MTProxy和HTTPS流量至关重要。 - 在Nginx和MTProxy中配置
proxy_protocol确保了客户端真实IP地址的传输,这对于日志记录和安全性至关重要。 - MTProxy配置为
tls: True模式并指定了TLS_DOMAIN,使得代理流量与到该域名的常规HTTPS连接无法区分。 - 将MTProxy绑定到
127.0.0.1通过限制直接外部访问来增强安全性。 systemd服务确保MTProxy的自动启动和监控,保证其持续运行。
— Editorial Team
暂无评论。