如何用Nginx Stream单端口基于域名代理多台SSH服务器?
解决方案:基于域名的Nginx Stream SSH代理
问题根源
SSH协议本身不支持SNI(Server Name Indication),你之前用的ssl_preread依赖SNI字段识别目标域名,这就是配置失效的核心原因。要实现基于域名的转发,需要让客户端先发起带SNI的SSL连接,将SSH流量封装在SSL隧道中传输,Nginx通过ssl_preread读取SNI后转发到对应上游服务器。
正确的Nginx Stream配置
stream { # 映射域名到对应MongoDB容器的SSH端口 map $ssl_preread_server_name $ssh_upstream { ssh1.srv.domain.com mongodb-server-1:22; ssh2.srv.domain.com mongodb-server-2:22; ssh3.srv.domain.com mongodb-server-3:22; ssh4.srv.domain.com mongodb-server-4:22; ssh5.srv.domain.com mongodb-server-5:22; # 默认 fallback(可选,避免无匹配域名时的无效连接) default unix:/dev/null; } server { listen 2323 ssl; # 加载你的泛域名SSL证书 ssl_certificate /etc/letsencrypt/com/domain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/com/domain.com/privkey.pem; # 启用SNI预读取,获取客户端发送的目标域名 ssl_preread on; # 转发流量到映射的上游SSH服务器 proxy_pass $ssh_upstream; # 适配SSH长会话特性的超时配置 proxy_connect_timeout 10s; proxy_timeout 1h; } }
客户端连接方法
1. CLI SSH连接
使用openssl s_client作为代理,强制发送SNI到Nginx,命令格式如下:
ssh -o ProxyCommand="openssl s_client -connect ssh1.srv.domain.com:2323 -servername ssh1.srv.domain.com" \ -i ~/.ssh/private_key \ root@localhost
localhost仅为占位符,实际流量会通过SSL隧道转发到目标MongoDB容器的SSH服务器- 替换
ssh1.srv.domain.com为对应域名,root为你的SSH用户名
2. MongoDB Compass连接
在Compass的SSH隧道配置面板中:
- SSH Hostname:填写
localhost - SSH Port:填写
22 - SSH Username:填写你的SSH用户名
- SSH Identity File:选择本地私钥文件
- Proxy:选择
Custom,填入以下命令:openssl s_client -connect ssh1.srv.domain.com:2323 -servername ssh1.srv.domain.com - 完成后正常填写MongoDB连接地址(如
mongodb://localhost:27017,对应容器内的MongoDB端口)
配置验证
- 重启Nginx加载新配置:
nginx -s reload - 先测试CLI连接是否能正常登录目标服务器
- 再验证MongoDB Compass是否能通过SSH隧道成功连接MongoDB
内容的提问来源于stack exchange,提问作者BurakBey
相关产品推荐
相关产品推荐

