背景,在处理一个神奇的IP查询BUG时,发现有用户伪造IP地址,具体方案就是添加 x-forwarded-for
的头,达到伪造的目的,这个问题在之前已经处理过了,不过又出现了,可能和迁移到k8s有关系。
伪造方式:
curl -H"x-forwarded-for: 100.14.144.11, 14.2.2.4" "https://www.baidu.com"
服务端会收到如下内容:
$_SERVER[HTTP_X_ORIGINAL_FORWARDED_FOR]: 100.14.144.11, 14.2.2.4, 11.123.11.244
$_SERVER[HTTP_X_FORWARDED_FOR]: 100.14.144.11
$_SERVER[HTTP_X_REAL_IP]: 100.14.144.11
$_SERVER[HTTP_X_FORWARDED_FOR]: 100.14.144.11
$_SERVER[HTTP_X_REAL_IP]: 100.14.144.11
现实很残酷:HTTP_X_FORWARDED_FOR
得到了一个错误的IP地址,而我需要的11.123.11.244
IP则存在于HTTP_X_ORIGINAL_FORWARDED_FOR
中。于是开始排查问题。
- 检查代理是否有单独设置变量【正常】
- 检查容器是否有设置变量【正常】
- 检查入口SLB和Nginx是否设置变量【正常】
- 检查Ingress是否有设置变量【不正常】 很不客气的设置了
X-Original-Forwarded-For
- 检查Ingress使用错误IP的原因:
set_real_ip_from 0.0.0.0/0;
于是问题找到,然后开始安心修BUG,几个项目一个一个替换HTTP_X_FORWARDED_FOR
为HTTP_X_ORIGINAL_FORWARDED_FOR
, 然后使用了变态的修正方案
<?php
if (isset($_SERVER['HTTP_X_ORIGINAL_FORWARDED_FOR'], $_SERVER['HTTP_X_FORWARDED_FOR'])
&& strpos($_SERVER['HTTP_X_ORIGINAL_FORWARDED_FOR'], $_SERVER['HTTP_X_FORWARDED_FOR']) !== false) {
// 修正 HTTP_X_FORWARDED_FOR 不是原始值的问题
$_SERVER['HTTP_X_FORWARDED_FOR_BACKUP'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
$_SERVER['HTTP_X_FORWARDED_FOR'] = $_SERVER['HTTP_X_ORIGINAL_FORWARDED_FOR'];
}
if (isset($_SERVER['HTTP_X_ORIGINAL_FORWARDED_FOR'], $_SERVER['HTTP_X_FORWARDED_FOR'])
&& strpos($_SERVER['HTTP_X_ORIGINAL_FORWARDED_FOR'], $_SERVER['HTTP_X_FORWARDED_FOR']) !== false) {
// 修正 HTTP_X_FORWARDED_FOR 不是原始值的问题
$_SERVER['HTTP_X_FORWARDED_FOR_BACKUP'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
$_SERVER['HTTP_X_FORWARDED_FOR'] = $_SERVER['HTTP_X_ORIGINAL_FORWARDED_FOR'];
}
当前还没有任何评论