Nginx实现内网穿透的本质是反向代理中转,而非绕过NAT或防火墙;需依赖公网服务器与内网服务的网络连通(如SSH隧道),再通过proxy_pass将外部请求映射至内网地址,并支持HTTP/HTTPS及stream模块的TCP/UDP转发。

用 Nginx 实现内网穿透,核心不是“穿透”本身(Nginx 无法绕过防火墙或 NAT),而是通过反向代理 + 公网服务器中转,把外部请求“映射”到内网服务上。关键前提是:你有一台带公网 IP 的 Linux 服务器(比如云主机),且内网服务已能被该服务器访问(例如通过内网 IP 或 SSH 端口转发打通网络)。
前提准备:确保网络连通性
这是最容易卡住的一步。Nginx 本身不解决网络可达问题:
- 确认公网服务器能主动访问你的内网服务(如
curl http://192.168.1.100:8080);如果不能,需先建立连接通道——常见方式是用 SSH 反向隧道(ssh -R 8080:localhost:8080 user@public-server),让内网服务“反向暴露”到公网服务器的本地端口 - 确保公网服务器的对应端口(如 80/443 或自定义端口)已在安全组、防火墙(如 ufw/iptables)中放行
- Nginx 需监听在公网可访问的地址(如
listen 80;或listen 0.0.0.0:8080;),而非仅127.0.0.1
基础反向代理配置(HTTP 服务)
适用于内网已有 Web 服务(如 Flask、Node.js、本地网站),且已通过上述方式让公网服务器可访问它:
server {
listen 80;
server_name your-domain.com;
<pre class="brush:php;toolbar:false;">location / {
proxy_pass http://192.168.1.100:8080; # 指向内网服务地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
注意:proxy_pass 后的地址必须是公网服务器能直接解析并访问的(可以是内网 IP、localhost(配合 SSH 隧道)、或 127.0.0.1 上由隧道暴露的端口)。
非 HTTP 流量转发(TCP/UDP)
Nginx 默认只处理 HTTP/HTTPS。如需转发 SSH、MySQL、远程桌面等 TCP 流量,需启用 stream 模块(编译时需带 --with-stream,主流发行版包通常已包含):
在 /etc/nginx/nginx.conf 的顶层(不在 http 块内)添加:
stream {
upstream inner_ssh {
server 192.168.1.100:22; # 内网 SSH 地址
}
<pre class="brush:php;toolbar:false;">server {
listen 2222;
proxy_pass inner_ssh;
proxy_timeout 1s;
}
}
然后重载 Nginx:sudo nginx -t && sudo systemctl reload nginx。此时访问公网服务器的 2222 端口,就会被转发到内网机器的 22 端口。
安全与实用建议
公开暴露内网服务有风险,务必加固:
- 避免直接暴露管理后台、数据库端口;如必须,限制访问来源(
allow 1.2.3.4; deny all;)或加认证(HTTP Basic Auth / SSH 密钥) - 为 HTTP 服务配置 HTTPS(用 Certbot 自动申请 Let’s Encrypt 证书),防止流量被窃听
- 不要用 root 运行 Nginx;用非特权用户启动,必要时用 systemd 的
CapabilityBoundingSet=控制权限 - 日志要开启(
access_log /var/log/nginx/tunnel_access.log;),便于排查和审计
这种方案本质是“代理中转”,不是真正的 P2P 穿透,但稳定、可控、无需第三方服务。只要公网服务器在线,内网服务就能被间接访问。











