能否让NGINX Stream基于同端口区分多域名并路由请求?
基于SNI的NGINX Stream多域名转发配置
你的需求完全可以实现,但需要利用**SNI(Server Name Indication)**提取HTTPS请求中的域名——因为Stream层处理的是原始TCP流量,必须解析TLS握手阶段的SNI明文字段,才能获取请求的子域名并完成路由。
关键前提
确保你的NGINX编译时启用了stream_ssl_preread模块,大部分官方预编译包已包含该模块;若自行编译,需添加编译参数:--with-stream_ssl_preread_module
完整配置示例
# 定义域名与后端服务器的映射关系 map $ssl_preread_server_name $backend_server { sub1.yourdomain.com 192.168.1.10:443; sub2.yourdomain.com 192.168.1.20:443; # 可选:设置未匹配域名的默认处理规则 default 192.168.1.30:443; # 或用 "unix:/dev/null;" 直接拒绝连接 } stream { server { listen 443; # 开启SNI读取功能,这是获取域名的核心配置 ssl_preread on; # 根据映射结果转发请求 proxy_pass $backend_server; # 可选:添加TCP转发优化参数 proxy_connect_timeout 10s; proxy_timeout 30m; } }
配置说明
map块:使用$ssl_preread_server_name作为匹配变量,该变量由ssl_preread on指令生成,存储了TLS握手时客户端发送的目标域名。ssl_preread on:必须开启此指令,NGINX才会在不终止TLS连接的前提下,读取SNI字段内容,全程无需接触后端服务器的证书。- 证书处理:NGINX仅做TCP层转发,不会解密HTTPS流量,所有证书验证逻辑由目标后端服务器自行处理,完全符合你“NGINX无法访问证书”的要求。
注意事项
- 若客户端不支持SNI(极少数老旧设备),
$ssl_preread_server_name会为空,此时会触发default规则。 - 域名匹配默认大小写不敏感,若需要精确大小写匹配,可在
map指令后添加strict参数:map $ssl_preread_server_name $backend_server strict { ... }
内容的提问来源于stack exchange,提问作者Manuel Amador
相关产品推荐
相关产品推荐

