Nginx通过启用stream模块实现TCP层内网穿透和端口转发,适用于SSH、数据库等非HTTP服务;需确认编译含--with-stream、在顶层stream块中配置upstream和server监听,配合防火墙限制访问并验证连通性。

用 Nginx 做 TCP 层的内网穿透和端口转发,核心是启用 stream 模块,并在独立的上下文中配置代理规则。它不处理 HTTP 协议,而是直接转发原始 TCP 流量,适合 SSH、数据库、游戏服务等非 HTTP 场景。
确认 Nginx 编译时启用了 stream 模块
Nginx 默认不开启 stream 功能,需检查是否已编译进二进制文件:
- 运行
nginx -V 2>&1 | grep -o with-stream,若输出with-stream,说明支持 - 若无输出,需重新编译 Nginx,添加
--with-stream参数 - 部分发行版(如 Ubuntu 20.04+ 的官方包)已默认包含该模块
配置 stream 块实现端口转发
在主配置文件(如 /etc/nginx/nginx.conf)的顶层(http 块之外)添加 stream 块:
stream {
upstream remote_db {
server 192.168.1.100:3306; # 内网 MySQL 地址
}
<pre class="brush:php;toolbar:false;">server {
listen 3307; # 公网暴露端口
proxy_pass remote_db;
proxy_timeout 1h;
proxy_responses 1;
}}
-
listen必须监听在公网可访问的 IP 和端口(如0.0.0.0:3307或1.2.3.4:3307) -
proxy_timeout防止长连接被中间设备断开,建议设为较大值 -
proxy_responses 1表示只等待一个响应包后即转发,适用于多数 TCP 服务
结合防火墙与安全加固
仅靠 Nginx 转发不等于安全暴露,还需限制访问来源:
- 用
iptables或ufw限制listen端口仅允许可信 IP 连接 - 避免监听
0.0.0.0,改用具体公网 IP(如1.2.3.4:3307),减少扫描面 - 若需多用户隔离,可搭配
auth_http模块或前置认证网关(Nginx stream 本身不支持用户级鉴权) - 禁止将管理端口(如 Redis 的 6379、MySQL 的 3306)直接映射到公网,应加 SSH 隧道或 TLS 终止层
验证与排错要点
启动后快速验证是否生效:
- 执行
nginx -t确保语法正确;systemctl reload nginx重载配置 - 用
ss -tlnp | grep :3307确认 Nginx 正在监听目标端口 - 从外部机器执行
telnet your-server-ip 3307,能连通表示 TCP 层通了 - 若连接成功但服务无响应,检查内网目标服务是否允许该 IP 连接、是否有本地防火墙拦截










