一、前言
虚拟主机是 Nginx 最基础也最常用的功能------它允许一台 Nginx 服务器在同一个端口上处理多个域名的请求。本文将完整演示 5 种 server_name 匹配规则及其优先级,并附上完整的验证方法。
二、为什么需要虚拟主机?
生产场景
你在工作中会遇到以下场景:
| 场景 | 说明 |
|---|---|
| 多域名接入 | 一台 Nginx 同时接入 www.example.com、api.example.com、m.example.com |
| PC 端 vs 手机端 | 根据域名 pc.example.com 和 m.example.com 分发到不同后端 |
| 默认兜底 | 防止恶意 IP 扫描,不认识域名直接断开 |
| SSL 证书分离 | 不同域名使用不同证书(SNI) |
工作原理
Nginx 根据 HTTP 请求头中的 Host 字段来匹配 server_name:
用户请求 http://www.example.com
→ 请求头中包含 Host: www.example.com
→ Nginx 遍历所有 server block,匹配 server_name
→ 匹配到对应的 server block → 处理请求
三、5 种 server_name 匹配规则
优先级排序
① 精确匹配(最高优先级)
↓
② 通配符前缀(* 开头)
↓
③ 通配符后缀(* 结尾)
↓
④ 正则匹配(~ 开头)
↓
⑤ 默认兜底(最低优先级)
完整配置
nginx
# ① 精确匹配(最高优先级)
server {
listen 8080;
server_name site1.nginx.demo;
# 仅当 Host = site1.nginx.demo 时匹配
}
# ② 通配符前缀(第二优先级)
server {
listen 8080;
server_name *.nginx.demo;
# 匹配任何以 .nginx.demo 结尾的域名
# 如 api.nginx.demo、www.nginx.demo
}
# ③ 通配符后缀(第三优先级)
server {
listen 8080;
server_name site1.*;
# 匹配任何以 site1. 开头的域名
# 如 site1.abc.com、site1.xyz.com
}
# ④ 正则匹配(第四优先级)
server {
listen 8080;
server_name ~^www\.(?!nginx\.demo$).+\.demo$;
# 以 ~ 开头表示正则
# 匹配 www.xxx.demo 但不匹配 www.nginx.demo
}
# ⑤ 默认兜底(最低优先级)
server {
listen 8080 default_server;
server_name _;
# 所有未匹配的域名都走这里
# _ 只是一个占位符,不代表任何实际域名
}
匹配规则流程图
收到请求,Host = www.nginx.demo
│
▼
是否有精确匹配(server_name 完全一致)?
├── 是 → 使用该 server block
└── 否 → 继续
│
▼
是否有通配符前缀(*.nginx.demo)?
├── 是 → 使用该 server block
└── 否 → 继续
│
▼
是否有通配符后缀(site1.*)?
├── 是 → 使用该 server block
└── 否 → 继续
│
▼
是否有正则匹配(~^www\\....)?
├── 是 → 使用该 server block
└── 否 → 继续
│
▼
使用 default_server
四、实操验证
环境准备
bash
# 创建各虚拟主机的根目录
mkdir -p /var/www/nginx-review/vhost-{exact,wildcard-prefix,wildcard-suffix,regex}
# 写入标记文件,用于验证匹配结果
echo "Exact Match: site1.nginx.demo" > /var/www/nginx-review/vhost-exact/index.html
echo "Wildcard Prefix: *.nginx.demo" > /var/www/nginx-review/vhost-wildcard-prefix/index.html
echo "Wildcard Suffix: site1.*" > /var/www/nginx-review/vhost-wildcard-suffix/index.html
echo "Regex Match" > /var/www/nginx-review/vhost-regex/index.html
测试命令
bash
# 测试 1:精确匹配
curl -sI -H "Host: site1.nginx.demo" http://localhost:8080/ | grep X-Match-Rule
# 输出:X-Match-Rule: exact: site1.nginx.demo
# 测试 2:通配符前缀
curl -sI -H "Host: api.nginx.demo" http://localhost:8080/ | grep X-Match-Rule
# 输出:X-Match-Rule: wildcard-prefix: *.nginx.demo
# 测试 3:通配符后缀
curl -sI -H "Host: site1.abc.com" http://localhost:8080/ | grep X-Match-Rule
# 输出:X-Match-Rule: wildcard-suffix: site1.*
# 测试 4:正则匹配
curl -sI -H "Host: www.test.demo" http://localhost:8080/ | grep X-Match-Rule
# 输出:X-Match-Rule: regex match
# 测试 5:默认兜底
curl -sI -H "Host: unknown.xxx" http://localhost:8080/ | grep X-Match-Rule
# 输出:X-Match-Rule: default: _
测试结果汇总
| 请求 Host | 匹配规则 | 结果 |
|---|---|---|
site1.nginx.demo |
精确匹配 | ✅ 匹配 exact |
api.nginx.demo |
通配符前缀 *.nginx.demo |
✅ 匹配 wildcard-prefix |
www.nginx.demo |
通配符前缀 *.nginx.demo |
✅ 匹配 wildcard-prefix |
site1.abc.com |
通配符后缀 site1.* |
✅ 匹配 wildcard-suffix |
www.test.demo |
正则 ~^www\\.(?!nginx\\.demo$).+\\.demo$ |
✅ 匹配 regex |
unknown.xxx |
无匹配 → 默认 | ✅ 匹配 default |
五、F5 工程师看虚拟主机
F5 概念 Nginx 对应
────────────────────────────────────
Virtual Server server block
Destination IP:Port listen 80
Destination Domain server_name
Pool upstream
SNAT proxy_set_header
iRule location / rewrite
关键区别: F5 的 Virtual Server 绑定 IP:Port,不同域名可以走不同 VS。Nginx 的 server block 绑定的是 listen + server_name,多个域名共享同一个 IP:Port。
六、生产建议
- 精确匹配优先于通配符,性能最好的匹配方式
- 通配符不能跨级 ,
*.example.com不匹配www.api.example.com - 正则匹配性能最低,生产环境尽量少用
- default_server 必须配置,防止恶意 IP 扫描
- 多个 server_name 可以写在一起 :
server_name site1.nginx.demo site2.nginx.demo;
下一篇: Nginx 反向代理与 5 种负载均衡策略详解