如何通过Nginx实现不同虚拟主机分别仅提供HTTPS与SSH服务(无流复用)
如何通过Nginx实现不同虚拟主机分别仅提供HTTPS与SSH服务(无流复用)
我完全get你的需求——不想搞复杂的流复用,就想干干净净让不同域名对应纯单一服务:web.myserver.com只走HTTPS,ssh.myserver.com只走SSH,还得尽量避免额外的流量开销。你之前的尝试遇到400错误,问题出在没利用SNI(服务器名称指示)区分域名流量,也没正确配置Nginx的stream模块来识别TLS握手信息。
下面给你一套直接可行的方案:
核心思路
利用Nginx的stream模块配合ssl_preread功能,读取TLS握手包中的SNI字段,根据不同域名把流量转发到对应的后端服务——SSH后端或HTTPS后端,全程不需要流复用,每个域名的流量直接对应单一服务,没有额外开销。
具体配置步骤
1. Stream模块配置(处理流量路由)
在Nginx配置的stream块中添加如下内容,用来区分两个域名的流量并转发:
stream { # 定义SSH服务的后端(替换成你实际运行SSH的服务器IP和端口) upstream ssh_backend { server 192.168.1.5:22; } # 定义HTTPS服务的后端(选一个和443不冲突的端口,比如4443) upstream https_backend { server 192.168.1.5:4443; } # 处理ssh.myserver.com的流量:转发到SSH后端 server { listen 443; listen [::]:443; proxy_pass ssh_backend; # 关键配置:开启ssl_preread读取TLS握手里的SNI信息 ssl_preread on; # 匹配目标域名 server_name ssh.myserver.com; } # 处理web.myserver.com的流量:转发到HTTPS后端 server { listen 443; listen [::]:443; proxy_pass https_backend; ssl_preread on; server_name web.myserver.com; } }
2. HTTP模块配置(处理HTTPS服务)
在Nginx的http块中配置你的HTTPS服务,监听刚才指定的4443端口:
http { server { listen 4443 ssl; listen [::]:4443 ssl; server_name web.myserver.com; # 替换成你的SSL证书和密钥路径 ssl_certificate /path/to/your/web-cert.pem; ssl_certificate_key /path/to/your/web-key.pem; # 常规Web服务配置,比如网站根目录、路由规则等 root /var/www/web-root; index index.html index.htm; } }
为什么之前的配置失败?
你之前的stream块只配置了一个监听443的server,既没开启ssl_preread,也没根据域名区分流量。当你用SSH客户端连接443端口时,Nginx无法识别这是SSH流量,反而把它当成了不符合格式的HTTP请求,所以返回了400 Bad Request错误——这就是你日志里看到的内容。
注意事项
- 确保
ssh.myserver.com和web.myserver.com的DNS解析都指向你的Nginx服务器IP; ssl_preread on是核心,它让Nginx在不终止TLS连接的前提下读取SNI信息,才能正确路由;- HTTPS后端的监听端口(比如4443)不能和stream模块监听的443端口冲突;
- 连接SSH时需要指定443端口:
ssh -p 443 your-user@ssh.myserver.com,如果想让SSH用默认22端口,只需要把stream里对应ssh.myserver.com的server监听端口改成22即可。
备注:内容来源于stack exchange,提问作者Panayotis
相关产品推荐
相关产品推荐

