Nginx使用server_name正则时,如何正确获取请求域名捕获变量?
Nginx动态子域名SSL证书加载问题解决
问题根源
你遇到的核心问题是SSL证书加载时机早于server块正则变量捕获时机:
- Nginx在SSL握手阶段就需要确定使用的证书,这一步发生在server块匹配之前;
- 你通过
server_name ~^(?<custom_domain>[^.]+)\.捕获的$custom_domain变量,要到server块匹配完成后才会被赋值,所以加载证书时这个变量是空的; - 用
$host返回正则表达式,是因为Nginx还没完成域名解析就尝试读取证书,此时$host并未指向实际请求的域名。
修复方案
要实现动态加载子域名证书,得用map模块提前从请求域名提取子域名,同时依赖SNI(Nginx 0.9.8+默认支持)来在握手阶段匹配证书:
1. 全局添加map配置
在http块(所有server块外面)添加map,从$host里提取第一个子域名:
http { # 其他全局配置... map $host $custom_domain { ~^(?<sub>[^.]+)\. $sub; default ""; } # 下面放你的server块 }
2. 修改server块配置
调整server块的匹配规则和证书路径:
server { listen 80; listen 443 ssl; # 匹配所有带点的域名(覆盖子域名场景) server_name ~^[^.]+\..+$; # 用map提取的变量加载证书 ssl_certificate /var/www/faqnation-server/issued_certs/${custom_domain}__issued_cert.pem; ssl_certificate_key /var/www/faqnation-server/issued_certs/${custom_domain}__issued_cert.key; # 可选:开启OCSP stapling优化SSL性能 ssl_stapling on; ssl_stapling_verify on; resolver 8.8.8.8 8.8.4.4 valid=300s; resolver_timeout 5s; location / { proxy_pass http://127.0.0.1:4178; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } }
3. 验证步骤
- 检查配置语法:
nginx -t - 重载Nginx:
systemctl reload nginx - 确保证书目录权限正确:执行
chown -R nginx:nginx /var/www/faqnation-server/issued_certs/让Nginx能读取证书文件
内容的提问来源于stack exchange,提问作者Ashu Sharma
相关产品推荐
相关产品推荐

