应为每个租户显式定义 default_server 并配置独立兜底 HTTPS server,使用仅含 IP 的自签名证书并返回 444,同时禁用未命名 SSL 上下文复用、分离证书存储、启用 SNI 日志标记。

在多租户 Nginx 环境中(例如:SaaS 平台、托管服务、内网反向代理集群),多个域名共用同一台 Nginx 实例时,SSL 证书配置若未隔离,极易引发两类关键问题:一是不同租户的证书在 IP 直连场景下相互“串出”,暴露非目标域名;二是默认 server 块响应未匹配的 SNI 请求,导致源站 IP 被扫描工具(如 Censys、Shodan)关联到无关域名,绕过 CDN 或防火墙防护。
为每个租户显式定义 default_server
当客户端仅用 IP 访问 https://192.168.1.100:443(不带 Host 或 SNI),Nginx 会返回第一个被加载的 HTTPS server 块——这往往不是你期望的租户站点,而是某个测试域名或管理后台。解决方式是:为每个租户的 server 块明确指定 server_name,并单独设置一个“兜底” server 作为 default_server,且该兜底块使用独立的、无业务含义的证书(如仅含 IP 的自签名证书):
- 在
http{}块顶部或单独 conf 文件中添加:
# 兜底 HTTPS server(仅响应 IP 直连)
server {
listen 443 ssl default_server;
server_name _;
ssl_certificate /etc/nginx/ssl/ip-only.crt;
ssl_certificate_key /etc/nginx/ssl/ip-only.key;
return 444; # 静默关闭连接,不返回任何响应
}
- 所有租户 server 块均不加
default_server标识,仅靠server_name example-tenant.com匹配; - 兜底证书必须不含任何真实租户域名(CN 和 SAN 均设为服务器公网/内网 IP),避免泄露业务信息。
禁用未命名 SSL 上下文的证书复用
Nginx 默认允许未指定 server_name 的 HTTPS server 复用首个可用证书,这是证书“泄漏”的根源。需确保:
- 每个
server { listen 443 ssl; }块都包含明确的server_name(哪怕只是通配符*.tenant-a.com); - 移除所有无
server_name的 HTTPS server 块; - 验证配置加载顺序:将兜底块放在所有租户块之前(按文件字典序或 include 顺序),确保它真正成为 default。
分离证书存储与权限控制
多租户环境下,证书文件若混放同一目录且权限宽松,存在越权读取或误配风险:
- 为每个租户建立独立子目录:
/etc/nginx/ssl/tenant-a/、/etc/nginx/ssl/tenant-b/; - 证书与私钥权限设为
600,所属用户限定为 nginx 运行用户(如www-data或nginx); - 避免在配置中使用通配路径(如
ssl_certificate /etc/nginx/ssl/*.crt),必须写绝对路径; - 可配合
include按租户分片管理:include /etc/nginx/tenants/*.conf;,便于自动化部署与审计。
启用 SNI 强制校验与日志标记
通过日志识别异常 SNI 行为,辅助发现配置遗漏或扫描行为:
- 在全局或租户 server 块中添加:
log_format tenant_ssl '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$ssl_server_name" "$ssl_protocol" "$ssl_cipher"'; - 当
$ssl_server_name为空或为 IP 时,说明客户端未发送有效 SNI——这类请求应由兜底块处理,若出现在租户块日志中,即表明配置有误或存在恶意探测; - 结合
fail2ban监控连续空 SNI 请求,自动封禁可疑 IP。


















