nginx中server_name支持~*(忽略大小写)或~(大小写敏感)开头的正则匹配泛域名,需转义点号、锚定结尾,避免混用通配符语法;推荐结合map指令提升性能与可维护性。

在 Nginx 中,server_name 支持正则表达式匹配泛域名,但需注意语法规范和性能影响。核心是用波浪线 ~ 开头表示开启大小写敏感正则匹配,或用 ~* 表示忽略大小写;泛域名逻辑需靠正则自身实现,Nginx 不识别 *.example.com 这类通配符语法(那是非正则的通配符写法)。
正确写法:用 ~* 匹配泛二级域名
例如,要匹配 foo.example.com、api.example.com、test123.example.com,但不匹配 example.com 或 sub.foo.example.com:
server {
listen 80;
server_name ~* ^([a-zA-Z0-9\-]+)\.example\.com$;
# 后续配置...
}- 必须以
~*(或~)开头,否则 Nginx 当作字面量或通配符处理 -
\.要转义点号,$锚定结尾,避免误匹配如example.com.hacker.ru - 括号捕获组可配合
$1在rewrite或root中使用,例如:root /var/www/$1;
匹配多级子域名(如 a.b.example.com)
若需支持任意深度的子域名(常见于 SaaS 多租户),可用更宽松的正则:
server_name ~* ^([a-zA-Z0-9\-\.]+)\.example\.com$;
-
[a-zA-Z0-9\-\.]+允许子域名中含点和连字符(如us-west.api) - 注意:这种写法可能匹配到
evil..example.com(双点),建议加边界控制或用^([a-zA-Z0-9\-]+(?:\.[a-zA-Z0-9\-]+)*)\.example\.com$更严谨 - 正则越复杂,每次请求的匹配开销越大,生产环境建议优先用静态
server_name+map指令做分流
避免常见错误
- 不要混用通配符和正则:如
*.example.com是通配符语法,不是正则;写成~*.example.com会报错 - 不要遗漏分号:正则结尾必须有分号,否则 Nginx 启动失败
- 测试正则是否生效:用
nginx -t检查语法;用curl -H "Host: test.example.com" http://your-ip验证路由 - 注意优先级:Nginx 按「精确匹配 > 长度最长的通配符前缀 > 长度最长的通配符后缀 > 正则顺序第一」匹配,正则按配置中出现顺序执行,建议把最常用的正则放前面
替代方案:用 map 提升可维护性
当泛域名规则复杂或需关联不同后端时,推荐结合 map 指令解耦逻辑:
map $host $backend {
~*^([a-zA-Z0-9\-]+)\.example\.com$ $1;
default "default";
}
<p>server {
listen 80;
server_name ~* .example.com$;
location / {
proxy_pass <a href="https://www.php.cn/link/cd9c60b899bb18ff270d69e637cf90a0">https://www.php.cn/link/cd9c60b899bb18ff270d69e637cf90a0</a>;
}
}</p>- 主
server_name只做粗筛(如所有子域名),具体提取和路由交给map -
map支持缓存结果,比重复正则匹配更高效 - 便于扩展条件(如按子域名白名单放行、记录日志等)











