想把 3306 端口从公网转到内网数据库,在 nginx.conf 里加了 proxy_pass,执行 nginx -t 却报 unknown directive stream 或 stream directive is not allowed here。先别怀疑语法,stream 是独立模块,放错层级或者没编译进去都会这样。

stream 块不能放进 http 里

nginx stream 处理的是 TCP 或 UDP 四层转发,配置要写在最外层,和 http 平级,不能塞进 http、server 里面。一个最小例子:

stream { upstream mysql_backend { server 10.0.0.12:3306; } server { listen 13306; proxy_pass mysql_backend; } }

保存后先 nginx -t,看到 syntax is ok 再 nginx -s reload。改错配置别直接重启生产机,先备份原文件,失败时能马上换回去。

先确认模块在不在

运行 nginx -V,输出里找 --with-stream。没有这个参数,说明当前二进制没带 stream 模块,改配置也没用,需要换带模块的包或重新编译。用发行版自带的 nginx 时,模块拆包很常见,安装对应的 stream 模块包后再试。版本号不同,包名也不一样,别照着旧文章抄。

端口和防火墙要一起放行

listen 13306 只是 Nginx 在听,系统防火墙和云安全组没放行,外部照样连不上。用 ss -lntp 看端口是否真的起来,再在本机 telnet 127.0.0.1 13306 测试。数据库账号还要允许来源地址,只开 Nginx 的地址,不要把 root 放开给所有主机。

UDP 和长连接的细节

转发 DNS 这类 UDP 服务,写成 listen 53 udp;,并在 proxy_responses 里按响应数量设置。数据库这种长连接,可以调 proxy_timeout,默认值偏短时会被断开。stream 只做四层转发,看不到 URL 路径,别指望用它按域名分流 HTTP 请求,那种需求还是放 http 块。

值不值得用 Nginx 转

临时暴露一个内网端口,stream 够用;要按用户、路径做细粒度控制,应该交给专门的网关或数据库代理。上线前把 nginx -T 的完整配置导出来核对,确认没有重复监听,再观察连接数和错误日志。nginx stream 配起来不复杂,难的是模块、防火墙和权限三处都对齐。