必须确认nginx已编译--with-stream,否则报“unknown directive "stream"”;stream块须与http平级,不可嵌套;仅支持proxy_pass等极少数指令,不解析协议内容。

必须确认 Nginx 已编译 --with-stream,否则所有配置都会被拒绝——nginx: [emerg] unknown directive "stream" 不是语法错,是模块压根没加载。
检查 Stream 模块是否可用
直接运行:nginx -V 2>&1 | grep -o with-stream。无输出即不可用。
常见发行版处理方式:
- Ubuntu/Debian:装
nginx-extras(含 stream),别用nginx-core或nginx-light - CentOS/RHEL 8+:执行
dnf install nginx-mod-stream,但注意模块版本需与nginx主程序严格匹配 - 最稳妥:源码编译,
./configure --with-stream ...后make && sudo make install
验证是否加载动态模块(若使用 load_module):nginx -t 成功不代表模块已启用,必须看到 with-stream 才算真正就位。
stream 块必须和 http 平级,不能嵌套
错误写法:http { stream { ... } } —— 会报 nginx: [emerg] "stream" directive is not allowed here。
正确结构是:
events {
worker_connections 1024;
}
<p>stream {
upstream ssh_backend {
server 192.168.1.100:22;
}
server {
listen 2222;
proxy_pass ssh_backend;
proxy_timeout 1h;
proxy_connect_timeout 5s;
}
}</p><p>http {</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill6848" title="Nginx Hosting"><img
src="https://img.php.cn/upload/skill/000/000/081/179116929868126.jpg" alt="Nginx Hosting" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill6848" title="Nginx Hosting" class="overflowclass">Nginx Hosting</a>
<p class="overflowclass">通过服务器本地nginx实例实现零认证静态游戏托管。作为所有浏览器游戏的主要部署方式,无需登录、无需令牌、无需用户操作。</p>
</div>
<a rel="nofollow" href="/xiazai/skill6848" title="Nginx Hosting" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><h1>其他 HTTP 配置</h1><p>}</p>
关键点:
-
stream必须在events之后、http之外 - 不支持
include在http内部引用 stream 配置 - 推荐把 stream 配置拆到独立文件(如
/etc/nginx/stream.d/ssh.conf),再在顶层stream{}中include /etc/nginx/stream.d/*.conf;
SSH 转发必须用 proxy_pass,禁用所有 HTTP 层指令
Stream 模块只做 TCP 透传,无法解析或修改 SSH 协议内容。以下写法全部非法:
-
proxy_set_header→ 报错:unknown directive "proxy_set_header" -
rewrite、return、location→ 语法不识别 - 任何依赖
$host、$request_uri的变量都不可用
能用的核心指令极少:
-
proxy_pass:只接受IP:PORT,不支持域名(除非配了resolver) -
proxy_timeout:控制空闲连接超时,SSH 推荐设长(如1h),避免断连 -
proxy_connect_timeout:建立到后端 SSH 服务的连接超时,建议3s–5s -
proxy_responses:仅 UDP 场景有效,SSH 不需要
注意:listen 22 这类低端口需 root 启动主进程;若用非 root 用户启动,会报 bind() to 0.0.0.0:22 failed (13: Permission denied)。
调试 SSH 转发失败时优先抓包,而非查日志
Stream 模块日志级别低,默认不记录连接细节。当 ssh -p2222 user@nginx-ip 连不上时:
- 先用
tcpdump -i any port 2222 -w ssh.pcap抓包,确认请求是否到达 Nginx - 再在后端 SSH 服务器上抓
tcpdump -i any port 22,看转发是否发出 -
nginx -t通过 ≠ 配置生效;systemctl reload nginx后务必ss -tlnp | grep :2222确认监听已启动 - 防火墙常被忽略:
iptables -L -n | grep 2222或firewall-cmd --list-ports
真正容易被绕过的点:Nginx 主进程权限、底层网络策略(如云厂商安全组)、以及 stream 模块本身是否被静态链接进二进制——有些精简版镜像(如 Alpine 的 nginx:alpine)默认不含 stream,得自己重编或换基础镜像。










