解决Nginx多SSL配置中未匹配域名的默认回退问题
· 阅读需 2 分钟
问题现象
我给 nginx 配置了多个server,分别设置了 ssl 代理,但是当其中一个服务未启动是,会访问到第一个 server 的内容。
server {
listen 443 ssl;
server_name a.domain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://xxxx:10010;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 443 ssl;
server_name b.domain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://xxxx:10086;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
当 10086 端口的服务未启动时,访问 https://b.domain.com 时,会出现 10010端口的服务的内容。 也就是 nginx 只会访问第一个
server 的内容。经过一番查找,发现是因为没有设置 default_server
。
解决方案
添加一个下面的 server 配置
server {
listen 443 ssl default_server;
server_name _;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
return 444; # 立即关闭连接
}
问题剖析
Nginx 请求匹配机制
- 端口监听优先级:Nginx优先匹配
listen
指令相同的配置 - 域名精确匹配:在相同监听端口中,
server_name
最精确匹配的配置生效 - 默认回退机制:当没有匹配的server_name 时,自动选择:
- 第一个定义的 server 块(未显式声明 default_server 时)
- 标记为
default_server
的配置块
问题根源
当后端服务不可达时,Nginx 的请求处理流程:
- 客户端请求
b.domain.com
- Nginx正确匹配到
b.domain.com
的 server 块 - 尝试代理到
http://xxxx:10086
时发现连接失败 - 错误配置导致匹配降级,回退到默认 server 块(第一个定义的
a.domain.com
)