一、端口转发与隧道:内网穿透的两把钥匙
现实里常遇到:数据库、后台管理页、开发服务只监听内网,想从公网/家里访问;或想通过一台公网服务器把流量转发到内网某服务。这就是端口转发与 SSH 隧道。端口转发在"Nginx/iptables 层"做目标地址/端口改写;SSH 隧道则通过加密的 SSH 连接建立安全的"管道",分本地转发、远程转发、动态转发三种。下面分别讲透,并给出常见落地场景。
二、Nginx 端口转发(stream 模块)
非 HTTP 的 TCP 流量(如 MySQL 3306、MongoDB)用 Nginx 的 stream 层转发最方便:
# /etc/nginx/nginx.conf 主配置顶部(stream 块与 http 平级)
stream {
upstream mysql_backend {
server 10.0.0.5:3306;
}
server {
listen 3306;
proxy_pass mysql_backend;
proxy_connect_timeout 5s;
}
}
sudo nginx -t && sudo systemctl reload nginx
这样外部访问该机的 3306 即被转到内网 10.0.0.5:3306。配 stream 要注意:stream 块和多的是 separate,不能用 http 的 location;同时转发 MySQL 这类敏感服务务必限制来源 IP + 结合防火墙与 fail2ban。它适合"跳板机帮内网服务对外暴露"的场景。
三、iptables DNAT 端口转发
更"底层"的是 iptables 的 NAT 转发,把公网端口映射到内网主机(需开启内核转发):
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
# 把本机公网 2080 转发到内网 10.0.0.5:80
sudo iptables -t nat -A PREROUTING -p tcp --dport 2080 \
-j DNAT --to-destination 10.0.0.5:80
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.0.0.5 --dport 80 \
-j MASQUERADE
# 放行并持久化(RHEL 系 service iptables save)
sudo iptables -L -t nat -n
关键点:PREROUTING 做 DNAT(改目标),POSTROUTING 做 MASQUERADE(改源,保证回包能回来)。iptables 转换针对"路由转发"场景,和 Nginx stream 思路不同——前者是内核网络层,后者是用户态代理。二选一依据你的管理习惯与拓扑。
四、SSH 本地转发:把远程服务"拉到本地"
手机/笔记本在外网想访问家里/办公网的某端口,可用 SSH 本地转发:
# 把远程服务器上的 3306(数据库)映射到本地 13306 ssh -L 13306:127.0.0.1:3306 user@server_ip # 之后本地 127.0.0.1:13306 即通向 server 的 3306 # 挂在后台且不死(-f 后台 -N 不执行命令 -n 禁 stdin) ssh -f -N -L 13306:127.0.0.1:3306 user@server_ip
图上示意:本机 13306 ←→ 隧道 ←→ server 的 3306。它用加密 SSH 把"远端网络"完整连到本机,适合安全访问开发库而不用把端口暴露公网。
五、SSH 远程转发与跳板
反向场景:把"位于防火墙后面、无法被连入"的内网机器,通过一台公网服务器反向暴露:
# 在内网机器上执行:让公网 Nginx/端口 转发到本机 80 ssh -R 8080:localhost:80 user@publicserver # 访问 publicserver:8080 即到达内网机原 80 服务 # 动态转发:把 SSH 客户端所在机器作为 SOCKS 代理 ssh -D 1080 user@server_ip # 之后浏览器 HTTP 代理指向 127.0.0.1:1080 即可借该服务器上网
远程转发(-R)常在"家/内网主机主动连向公网"场景用于内网穿透;动态转发(-D)则把该连接变成 SOCKS 代理,是临时科学上网、调试内网的利器。三者本质都一样:建立加密隧道,区别只在于"数据从哪端进入隧道"。性能上 SSH 隧道有加解密开销,高吞吐场景可考虑 WireGuard(见前文)更专业。
六、安全与防呆建议
- 最小暴露:只转发业务需要的端口,敏感服务锁来源 IP。
- 结构清晰:用注释标明每条约道的用途,别堆积一堆说不清规则的转发。
- SSH 密钥:隧道自动连接用密钥免密,别挂明文密码到脚本。
- 防火墙配合:转发的目标端口用 firewalld/iptables 限制,结合 fail2ban 防爆破。
- 端口冲突:先 `ss -tlnp | grep :端口` 确认没被占。
- 生命周期:隧道断开会自动退出,监控脚本可建议 `ServerAliveInterval` 保持连接。
写在最后
端口转发与 SSH 隧道是运维里"把不在手边的服务接到手上"的核心技能。总结:对外提供服务选 Nginx stream 或 iptables DNAT;安全访问内部服务选 SSH 本地转发;内网方向选 SSH 远程转发;代理上网选动态转发。实践上从"本地转发访问一个开发库"起步,逐步扩展到跳板和转发链路。记住"最小暴露 + 加密 + 防火墙收紧"三条原则,你就能安全地把内网、公网、多台服务器灵活地串起来。


