【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除
背景
上篇 blog
【Ubuntu】【Gitlab】拉出内网 Web 服务:Gitlab 配置审视(六)
通过修改本地 hosts 文件,模拟 DNS 行为,演示了在浏览器请求中,Host 是域名[非默认端口]的事实,然后分析了 Nginx 对于 server_name 配置项的匹配规则,下面继续
Nginx 配置审视
回到这个官方文档 How nginx processes a request 的描述

之前 blog 提到,Nginx 只看 HTTP 请求头里的 Host 字段,并且如果没有匹配到 server_name 的话,就会交给 default_server 默认处理器处理,下面就这个 default_server 继续分析
- 首先第一种情况,对于下面这种,没有指定
default_server的场景
bash
server {
listen 80;
server_name example.org www.example.org;
...
}
server {
listen 80;
server_name example.net www.example.net;
...
}
server {
listen 80;
server_name example.com www.example.com;
...
}
Nginx 会默认使用写在最前面的那个 server 块,也就是
bash
server {
listen 80;
server_name example.org www.example.org;
...
}
这是 Nginx 的标准默认行为,只要没有显示指定 default_server 块,第一个 server 就会被当成兜底的默认站点
- 第二种场景,也可以显示指定哪个 server 是默认服务器,只要在 listen 指令中加上
default_server描述参数,比如下面这种情况
bash
server {
listen 80 default_server;
server_name example.net www.example.net;
...
}
此时这个 server 块被明确标记为了 80 端口的默认服务器,即使它不是第一个,即使它的 server_name 是一个普通的站点 example.net,只要其他请求 80 端口的 Host 不匹配任何站点,就会交给它处理
最后总结一下,Nginx 通过 Host 头匹配 server_name,匹配失败时,就会用 default_server 处理请求,这个 default_server 要么是第一个 server 块,要么是用 listen 80 default_server; 显式指定的那个 server 块
在实际使用时,为了避免安全风险,比如别人用 IP 直接访问 Web 服务器而看到某个网站,建议显式定义一个空的 default_server,比如
bash
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name "";
return 444; # 关闭连接,不返回任何内容
}
这里有两个点:
- 首先,是定义了两个
default_server
bash
listen 80 default_server;
listen [::]:80 default_server;
这里 listen 80; 监听 IPv4 的 80 端口,listen[::]:80; 监听 IPv6 的 80 端口,这里 [::] 是 IPv6 中任意地址的简写,相当于 IPv4 的 0.0.0.0 ,现代操作系统和网络环境同时支持 IPv4 和 IPv6,如果只写 listen 80;,当用户通过 IPv4 访问这个 IP(无效域名)时,可以匹配到这个 default_server,然后关闭连接;但如果用户通过 IPv6 访问时,就会匹配不到,然后 Nginx 用另一个默认 server 处理(绕过了显式指定的 default_server),所以为了全面兜底,必须同时监听 IPv4 和 IPv6,做到完整兼容
- 然后第二个点,
server_name "";这里指定server_name为空表示匹配空 Host 头(HTTP/1.0 客户端的请求没有 Host 头),或者无效 Host,但更重要的是,表示这里只是个占位符 ,因为这里真正依赖的是default_server,而不是server_name,这个 server 块被选中,不是因为server_name匹配了某个域名,而是因为它是default_server,换句话说,无论 Host 是example.com,1.2.3.4,还是xxx.yyy,还是根本没有,只要没有其他 server 块匹配,Nginx 就会用这个default_server,此时server_name ""几乎不起作用,只是语法上必须存在,因为 Nginx 要求每个 server 至少有一个server_name,这个server_name也可以写成server_name _;,server_name invalid;,效果都一样,因为根本不会靠它来匹配
OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog
【Ubuntu】【Gitlab】拉出内网 Web 服务:Gitlab 配置审视(八)