nginx stream模块可四层代理ssh流量,仅tcp转发且不解析协议;需先确认启用(nginx -v | grep with-stream),再通过端口映射实现多台内网服务器统一接入,并支持ip白名单等基础安全控制。

Nginx 的 Stream 模块能以四层方式代理 SSH 流量,不解析协议内容,只做 TCP 转发。它本身不支持按用户名或目标主机名路由(SSH 协议无 Host 字段),但可通过端口区分、负载均衡或前置跳板实现多台内网机器的统一接入。
确认 Stream 模块已启用
这是前提,缺一不可:
- 运行
nginx -V 2>&1 | grep with-stream,有输出说明已编译支持; - 若无结果,需重新编译 Nginx 并添加
--with-stream参数; - Debian/Ubuntu 用户可直接安装
nginx-full包,通常自带 Stream 支持; - CentOS/RHEL 用户建议使用官方源或手动编译,避免
nginx默认包缺失该模块。
用端口映射法管理多台 SSH 服务器
最简单可靠的方式:为每台内网机器分配独立监听端口,Nginx 按端口转发。
例如:
- 公网
2201→ 内网192.168.1.10:22(服务器 A) - 公网
2202→ 内网192.168.1.11:22(服务器 B) - 公网
2203→ 内网192.168.1.12:22(服务器 C)
配置示例(写在 nginx.conf 顶层,与 http { } 同级):
stream {
upstream ssh_a {
server 192.168.1.10:22;
}
upstream ssh_b {
server 192.168.1.11:22;
}
upstream ssh_c {
server 192.168.1.12:22;
}
server {
listen 2201;
proxy_pass ssh_a;
proxy_timeout 1h;
proxy_connect_timeout 5s;
}
server {
listen 2202;
proxy_pass ssh_b;
proxy_timeout 1h;
proxy_connect_timeout 5s;
}
server {
listen 2203;
proxy_pass ssh_c;
proxy_timeout 1h;
proxy_connect_timeout 5s;
}
}
加基础安全控制,缩小暴露面
Stream 层虽不加密,但能强化访问边界:
- 配合
allow/deny指令做 IP 白名单(放在server块内):allow 203.0.113.5; allow 2001:db8::1; deny all;
- 设置
proxy_timeout 1h防止空闲断连(SSH 自身控制会话超时,Nginx 不应干预); -
proxy_responses 1可提升首次握手成功率,尤其对部分老旧客户端有效; - 避免监听标准 22 端口,改用非标端口(如 2201–2299),降低自动化扫描命中率。
需要按用户路由?得加跳板逻辑
纯 Stream 无法识别 SSH 登录用户名。若必须“ssh user@proxy 自动分发到对应机器”,需额外组件:
- 在 Nginx 后接一个轻量跳板服务(如
sshservice、bore或自研脚本); - 该服务监听 Nginx 转发来的连接,读取 SSH 协议协商阶段的用户名(如
SSH_MSG_USERAUTH_REQUEST); - 根据用户名查表,再建立到对应后端的 TCP 连接;
- Nginx 此时只做最外层入口,不再承担路由决策。
不复杂但容易忽略。











