在 Nginx 中,通過(guò) server_name
區(qū)分同一端口下不同域名/主機(jī)名的請(qǐng)求,核心是利用虛擬主機(jī)(Server Block) 機(jī)制,按以下邏輯匹配:
1. 匹配優(yōu)先級(jí)規(guī)則
Nginx 收到請(qǐng)求后,先提取 Host
頭(請(qǐng)求的域名/IP:端口),按以下順序找對(duì)應(yīng) server
:
| | | |
---|
| server_name example.com www.abc.com; | | |
| server_name *.example.com; | | |
| server_name mail.*; | | |
| server_name ~^api\d+\.example\.com$; | | |
| server_name _; | | |
示例:
server {
listen 80;
server_name example.com www.example.com; # 精確匹配
...
}
server {
listen 80;
server_name *.example.com; # 匹配 blog.example.com 等子域
...
}
server {
listen 80;
server_name ~^api\d+\.example\.com$; # 正則匹配 api1.example.com 等
...
}
server {
listen 80;
server_name _; # 其他未匹配的請(qǐng)求走這里
return 404;
}
2. 關(guān)鍵配置細(xì)節(jié)
(1)listen
端口與 IP 綁定
若需區(qū)分同一端口但不同 IP(服務(wù)器多網(wǎng)卡場(chǎng)景),可在 listen
指定 IP:
server {
listen 192.168.1.10:80; # 僅處理 192.168.1.10 的 80 端口請(qǐng)求
server_name site1.com;
...
}
server {
listen 192.168.1.20:80; # 僅處理 192.168.1.20 的 80 端口請(qǐng)求
server_name site2.com;
...
}
(2)Host
頭缺失的處理
若請(qǐng)求無(wú) Host
頭(或非法值),Nginx 會(huì)找默認(rèn) server(同端口下,第一個(gè) server
或顯式標(biāo)記 default_server
的):
server {
listen 80 default_server; # 標(biāo)記為默認(rèn),處理無(wú) Host 或不匹配的請(qǐng)求
server_name _;
return 400; # 直接返回錯(cuò)誤
}
(3)HTTPS 場(chǎng)景的 SNI 支持
TLS 握手時(shí),瀏覽器通過(guò) SNI(Server Name Indication) 傳遞 server_name
,Nginx 需開啟支持(默認(rèn)開啟,舊版本需編譯時(shí)加 --with-http_ssl_module
):
server {
listen 443 ssl;
server_name site1.com;
ssl_certificate /etc/nginx/certs/site1.crt;
ssl_certificate_key /etc/nginx/certs/site1.key;
...
}
server {
listen 443 ssl;
server_name site2.com;
ssl_certificate /etc/nginx/certs/site2.crt;
ssl_certificate_key /etc/nginx/certs/site2.key;
...
}
3. 調(diào)試與驗(yàn)證
(1)檢查配置語(yǔ)法
nginx -t # 驗(yàn)證配置文件是否正確
(2)查看請(qǐng)求匹配日志
在 error_log
開啟 debug
級(jí)別(臨時(shí)調(diào)試用,別長(zhǎng)期開):
error_log /var/log/nginx/error.log debug;
重啟 Nginx 后,請(qǐng)求日志會(huì)顯示 server_name
匹配過(guò)程。
(3)用 curl
模擬請(qǐng)求
指定 Host
頭測(cè)試不同域名:
curl -H "Host: example.com" http://127.0.0.1 # 匹配 example.com 的 server
curl -H "Host: blog.example.com" http://127.0.0.1 # 匹配 *.example.com 的 server
4. 常見問題
問題1:修改 server_name
后不生效
→ 原因:瀏覽器緩存/未重啟 Nginx
→ 解決:nginx -s reload
重啟,或用 curl
繞開瀏覽器緩存測(cè)試。
問題2:通配符/正則匹配失效
→ 原因:語(yǔ)法錯(cuò)誤(如通配符 *.com
不匹配 a.b.com
,需寫成 *.b.com
或正則)
→ 解決:嚴(yán)格按通配符/正則規(guī)則寫,正則用 ~
標(biāo)記并轉(zhuǎn)義 .
(如 ~^www\.example\.com$
)。
問題3:HTTPS 提示證書錯(cuò)誤
→ 原因:SNI 未生效(舊瀏覽器/客戶端不支持),或證書綁定錯(cuò)誤
→ 解決:確認(rèn)客戶端支持 SNI,檢查 ssl_certificate
與 server_name
對(duì)應(yīng)關(guān)系。
通過(guò) server_name
配合 listen
,可精準(zhǔn)區(qū)分同一端口的不同域名請(qǐng)求,核心是利用 Nginx 的虛擬主機(jī)匹配規(guī)則。調(diào)試時(shí)重點(diǎn)抓 Host
頭和日志,就能快速定位問題~
閱讀原文:原文鏈接
該文章在 2025/7/1 23:29:42 編輯過(guò)