带SNI和子域名的Nginx反向代理重定向配置异常排查
解决Nginx Stream ssl_preread通配符子域名路由失效问题
你碰到的no host in upstream ""错误,核心是当请求匹配通配符子域名时,$name变量没被正确赋值,导致proxy_pass找不到对应的上游服务。我来帮你梳理下问题和解决方案:
问题根源
你的map配置里用了*.my.domain.com这种通配符写法,但在Nginx Stream模块的map指令中,通配符匹配有时候会因为规则优先级或解析逻辑的问题,无法正确匹配到子域名请求,最终导致$name为空,触发上游找不到的错误。
解决方案:改用正则表达式匹配子域名
把通配符替换成正则表达式,能更可靠地匹配所有my.domain.com的子域名,确保$name被正确赋值。修改后的map配置如下:
map $ssl_preread_server_name $name { ~^.+\.my\.domain\.com$ c; # 匹配所有以.my.domain.com结尾的子域名 a.another.domain.com a; b.another.domain.com b; }
这个正则~^.+\.my\.domain\.com$会精准匹配任何形如xxx.my.domain.com的子域名(比如test.my.domain.com、dev.my.domain.com),完全覆盖你需要的通配符场景。
额外排查步骤
- 确认SNI是否正确获取:查看你的
stream_443.log日志,执行tail -f /var/log/nginx/stream_443.log后发起请求,检查with SNI name字段是否显示了正确的子域名。如果SNI为空,说明ssl_preread没有正常工作,需要确认Nginx编译时包含了--with-stream_ssl_preread_module模块。 - 测试时指定SNI:用curl测试时,要确保请求携带正确的SNI,比如:
有些环境下curl不会自动发送SNI,用curl -v --resolve test.my.domain.com:443:你的Nginx机器IP https://test.my.domain.com--resolve可以强制指定域名对应的IP,确保SNI被正确传递。 - 添加默认规则(可选):为了避免未匹配到的请求报错,可以在
map末尾加一个默认值,比如:map $ssl_preread_server_name $name { ~^.+\.my\.domain\.com$ c; a.another.domain.com a; b.another.domain.com b; default c; # 所有未匹配的请求都走upstream c,或者根据需求调整 }
验证配置
修改完配置后,执行nginx -t检查语法是否正确,然后nginx -s reload重启Nginx,再测试子域名请求,应该就能正常路由到upstream c了。
内容的提问来源于stack exchange,提问作者Zaída De Isidro Navarro
相关产品推荐
相关产品推荐

