63、【Ubuntu】【Gitlab】拉出内网 Web 服务:Gitlab 配置审视(七)

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如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 配置审视(八)

相关推荐
子兮曰4 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰4 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万4 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝4 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
三十而立洋4 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
卡布鲁4 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
汉堡大王95274 天前
Jev:不是聊天机器人, 而是一个智能 if 语句
前端·人工智能·后端
梦想很大很大4 天前
从运行事实到回归证据:Workrun 的 Telemetry 与 Evaluation 实践
前端·人工智能·后端
计算机魔术师4 天前
Meta Muse agent 接入 Shopify 的 Shop Pay 实现代理式购物
前端
沙蒿同学4 天前
我用 Go 搭了一条 AI Agent 流水线:从 1 张商品图到一整套淘宝详情页
前端·javascript·后端