活力39282
在线时间13640 小时
阅读权限200
管理员
自由的灵魂
- 积分
- 107434
- 主题
- 5630
- 回帖
- 26661
- 注册时间
- 2003-4-10
- 最后登录
- 2026-10-2
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1、问题缘起
在评估 TMDB 插件安全风险时,发现 config_global.php 末尾有一段关于 HTTP_X_FORWARDED_FOR 的代码:
- // 信任代理 IP(雷池)
- if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
- $list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
- $_SERVER['REMOTE_ADDR'] = $list[0];
- }
复制代码
由于雷池 WAF 已开启“清空并重写 X-Forwarded-For”,且 Nginx 已禁用 XFF 传递给 PHP,初步判断这段代码已失效,建议删除。
但在实测验证中发现了相反的结果:
| 状态 | REMOTE_ADDR | HTTP_X_FORWARDED_FOR | | 保留代码 | 真实 IP(如 52.167.144.238) | 真实 IP | | 删除代码 | 127.0.0.1(雷池回源地址) | 真实 IP |
结论:这段代码依然有效,它将 HTTP_X_FORWARDED_FOR 的值写入了 REMOTE_ADDR。
2、你的解决方案
(1)简要技术分析
一句话概括:在 PHP 入口处手动从 HTTP_X_FORWARDED_FOR 提取第一个 IP 覆盖 REMOTE_ADDR,确保后续所有代码(包括第三方插件)都能通过 $_SERVER['REMOTE_ADDR'] 获取真实访问者 IP。
(2)修改/涉及文件列表
| 文件 | 操作 | 说明 | | /config/config_global.php | 保留(原拟删除,实测后决定保留) | XFF→REMOTE_ADDR 转换 | | /source/module/forum/forum_viewthread.php | 临时添加(已移除) | 测试用日志代码 |
(3)关键代码段
文件:config/config_global.php(末尾,THE END 之前)
- // 从 X-Forwarded-For 中提取真实 IP(雷池已做清空并重写,取第一个即可)
- if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
- $list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
- $_SERVER['REMOTE_ADDR'] = trim($list[0]);
- }
- // 隐藏 API Key
- $_config['tmdb_api_key'] = '6f3d8c9d8c902a3d284f5f956c64ea9b';
- // ------------------- THE END -------------------- //
复制代码
3、最终实现效果
| 验证场景 | REMOTE_ADDR | HTTP_X_FORWARDED_FOR | 论坛记录 IP | | 保留代码 | 真实 IP | 真实 IP | 真实 IP ✅ | | 删除代码 | 127.0.0.1 | 真实 IP | 真实 IP ✅ |
结论:两种配置论坛都能正确记录用户 IP,但保留代码的兼容性更好——第三方插件如果直接读取 $_SERVER['REMOTE_ADDR'] 也能拿到真实 IP。
4、重要技术沉淀(需更新固化摘要)
踩坑点:
即使雷池开启了“清空并重写 X-Forwarded-For”、Nginx 禁用了 XFF 传递,PHP 中的 HTTP_X_FORWARDED_FOR 依然有值。这是因为雷池在转发请求时仍然会添加该 Header,只是 Nginx 不再将其作为 fastcgi 参数传递?实测表明它仍然存在。
需要更新到 env-base 固化摘要的内容:
IP 获取机制(2026-05-11 确认)
| 层级 | 配置 | 说明 | | 雷池 WAF | 开启“清空并重写 X-Forwarded-For” | 丢弃客户端伪造的 XFF,写入真实 IP | | Nginx | 已禁用 fastcgi_param HTTP_X_FORWARDED_FOR | 但 XFF 仍会通过其他方式传递到 PHP | | PHP(config_global.php) | 手动提取 HTTP_X_FORWARDED_FOR 第一个 IP 覆盖 REMOTE_ADDR | 确保 $_SERVER['REMOTE_ADDR'] 为真实 IP |
关键代码(保留在 config_global.php 末尾):
- if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
- $list = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
- $_SERVER['REMOTE_ADDR'] = trim($list[0]);
- }
复制代码
5、进一步优化的可能性
| 构想 | 说明 | 优先级 | | 提取为通用函数 | 将 XFF 解析逻辑封装为 get_real_ip(),统一供全站调用 | 低(当前够用) | | 增加 IPv6 支持 | 当前 explode(',') 对 IPv6 地址同样有效,无需修改 | 已支持 | | 记录原始 XFF 到日志 | 在调试模式下记录完整 XFF 链,便于排查代理链路问题 | 极低 |
当前无立即优化必要。 |
|