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

【声明】本博客所有内容均为个人业余时间创作,所述技术案例均来自公开开源项目(如Github,Apache基金会),不涉及任何企业机密或未公开技术,如有侵权请联系删除

背景

上篇 blog
【Ubuntu】【Gitlab】拉出内网 Web 服务:Gitlab 配置审视(八)

分析了安全的 default_server 配置,然后继续分析了 server 块中的 location 配置项,下面继续

Nginx 配置审视

上篇 blog 分析到了配置项 proxy_set_header Host $host; 的作用是把原始请求的 Host 头传递给后端服务,很多 Web 框架会检查 Host 头来生成绝对 URL(重定向场景)

下面就这个重定向场景再详细展开分析下,比如用户登录后的重定向,假设系统架构如下

  • 用户在浏览器输入 http://192.168.1.100/login
  • Nginx 监听 80 端口,并反向代理到 http://localhost:8080
  • 后端是个 Web 应用

登录时,用户提交用户名和密码,后端验证成功后,想把用户重定向到首页 /dashboard,那么问题来了,后端该怎么写这个重定向响应?按照有没有 Host 头划分,有两种情况:

  • 第一种,没 Host 头 :此时后端不知道用户是通过 192.168.1.100 访问的,它可能以为自己直接暴露在 localhost:8080(也就是以为用户直接访问的 localhost:8080),于是返回
bash 复制代码
HTTP/1.1 302 Found
Location: http://localhost:8080/dashboard

然后浏览器跳转到 http://localhost:8080/dashboard,对于私人使用的端口映射远程服务器,这样当然没问题,但是如果是要提供给更多人使用的公用服务器,这么做就有问题了,此时用户会看到无法访问此网站,因为 localhost 是回环地址**,公用场景下,客户端一般不会把自己端口映射出去**,这时用户访问 http://localhost:8080/dashboard,就相当于访问自己的回环地址,那样当然就没有服务了

  • 第二种,有 Host 头 :当 Nginx 设置了 proxy_set_header Host $host;,此时后端收到的请求头包含 Host: 192.168.1.100,于是后端知道,用户是通过 192.168.1.100 访问的,所以生成重定向
bash 复制代码
HTTP/1.1 302 Found
Location: http://192.168.1.100/dashboard

此时浏览器就能正确跳转到 http://192.168.1.100/dashboard

OK,分析完 proxy_set_header Host $host;,继续看下一个

  • proxy_set_header X-Real-IP $remote_addr;:表示将真实客户端 IP 传递给后端,$remote_addr 是 Nginx 变量,表示直接连接 Nginx 的客户端 IP (注意和 $host 区别,$host 表示服务端的域名,remote_addr 表示客户端的 IP),此时后端通过 X-Real-IP 头就能知道真实用户 IP,否则后端看到的来源 IP 永远是 127.0.0.1(本机地址),因为是 Nginx 本地应用在访问后端
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;:用于记录请求经过的代理链 ,如果客户端没发 X-Forwarded-For,那么 $proxy_add_x_forwarded_for 就设为 $remote_addr,表示客户端 IP;如果客户端已经发了(比如 X-Forwarded-For: A, B),就追加当前 IP 上去,最后 X-Forwarded-For 可能呈现为
bash 复制代码
X-Forwarded-For: client-ip, proxy1-ip, proxy2-ip

后端可以通过这个 X-Forwarded-For 追踪原始用户 IP(尤其在多层代理时)

  • proxy_set_header X-Forwarded-Proto $scheme:让后端知道原始请求用的是什么协议(比如 HTTP 还是 HTTPS),这里 $scheme 是 Nginx 变量,值为 http 或 https ,比如有这么一个场景,用户通过 HTTPS 访问 Nginx(比如 https://example.com),但 Nginx 和后端之间走的是 HTTP 协议,此时后端不知道原始请求是 HTTPS,就可能生成 http://... 的链接,会导致混合内容高级或登录失败,通过 $scheme 的传递,可以让用户知道原始请求的协议,进而生成正确的安全链接

最后总结一下,location 字段定义如下功能

  • 请求转发 :proxy_pass 到 localhost:8080
  • 保留原始域名 :Host $host
  • 传递真实 IP :X-Real-IP + X-Forwarded-For
  • 传递原始协议 :X-Forwarded-Proto $scheme

这套反向代理配置适用于大多数 Web 应用


OK,本篇先到这里,如有疑问,欢迎评论区留言讨论,祝各位功力大涨,技术更上一层楼!!!更多内容见下篇 blog

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