Nginx 的 server_name 通配符与 catch-all 怎么配?
Nginx server_name 通配(*.example.com)、正则与 catch-all(server_name _ + default_server)配置方法;匹配优先级规则、泛域名证书搭配与 FAQ。
三种写法:前缀通配 *.example.com 匹配所有子域;正则 ~^(?<sub>.+)\.example\.com$ 可捕获子域名;catch-all 用 listen 80 default_server; server_name _; 兜住一切未匹配的请求。
1. 通配符匹配所有子域
server {
listen 80;
server_name *.example.com; # 匹配 www./blog./shop. 等一切一级子域
root /var/www/wildcard;
...
}
*.example.com只匹配一级子域;example.com本身不匹配,需要并列写上:server_name example.com *.example.com;。- 开头通配(
*.)是合法位置;www.*.com这种中间通配不合法。 - 另一种等价写法:
.example.com(点开头)同时匹配裸域和一级子域。
2. 正则 server_name(要捕获子域时)
server {
listen 80;
server_name ~^(?<tenant>.+)\.example\.com$;
root /var/www/tenants/$tenant; # 捕获组可直接当变量用
}
多租户 SaaS 的经典用法:acme.example.com → /var/www/tenants/acme。
3. Catch-all(兜底 server)
server {
listen 80 default_server; # 这个 listen 地址的默认 server
server_name _; # "_" 只是个占位无效名,不是真正的通配
return 444; # 直接断连;或 return 301 到主站
}
原理澄清:让某 server 成为兜底的关键是 default_server,不是 server_name _。当请求的 Host 没匹配到任何 server_name 时,该 listen 地址的默认 server 接管。return 444 是 Nginx 特有的"无响应关闭连接",常用于丢弃扫描器/非法 Host 流量。
匹配优先级
同一 listen 地址上多个 server 块时:
精确名 > 前通配(*.example.com)> 后通配(www.example.*)> 正则 > default_server
nginx -T 可以确认实际加载的 server 块及顺序。
配套:泛域名证书
HTTPS 场景下通配 server_name 需搭配泛域名证书(*.example.com)。Let's Encrypt 的泛域名证书只能走 DNS-01 验证(certbot 配 DNS 插件自动续期)。
观测云对照
catch-all 块的流量日志是金矿——里面全是"你不知道谁在访问你"的请求:扫描器、错误 DNS 指向、盗链。把 Nginx 访问日志接入观测云,按 host 聚合,非业务域名的访问量、UA 分布一目了然;非法 Host 的突增可配告警,盗链和恶意扫描无所遁形。
常见问题(FAQ)
Q:server_name _ 里的下划线有特殊含义吗?
A:没有。它只是个不可能合法的域名,用来占住"永远不会被主动匹配"的位置;真正起兜底作用的是 default_server。
Q:正则 server_name 有什么性能开销吗?
A:有,每次请求都要跑正则。高并发站点尽量用精确名和前通配,正则留给确实需要的场景。
Q:一个 server 块能写多个 server_name 吗?
A:可以,空格分隔:server_name example.com www.example.com *.example.net;,混合精确与通配都行。