if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
$pos = array_search('unknown',$arr);
if(false !== $pos) unset($arr[$pos]);
foreach ($arr as $k => $v) {
if(preg_match("/^10\.|^19\d{1}\.|^17\d{1}\./", trim($v))) {
unset($arr[$k]);
}
}
if(!count($arr)) throw new \Exception('ip 获取失败', 403);
// 过滤完数据 获取最后一个地址
$ip = trim(end($arr));
} elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (isset($_SERVER['REMOTE_ADDR'])) {
$ip = $_SERVER['REMOTE_ADDR'];
}
1
glacer 2019-09-04 11:33:06 +08:00
我可以通过伪造 HTTP_X_FORWARDED_FOR 来实现无限 IP 了
|
2
Bruin OP @glacer 60.177.121.18 - - [03/Sep/2019:18:52:06 +0800] "POST /v2/api/service/vote/testip HTTP/1.1" 200 93 "-" "PostmanRuntime/7.16.3" "60.177.121.199, 60.177.121.18" 这个 199 是我伪造的 ip,上面是我已经改造了的代码,获取的 ip 是 ok 的,
|
4
0ZXYDDu796nVCFxq 2019-09-04 11:43:03 +08:00 via Android
@Bruin 你贴的代码,明明可以随便伪造 #3
|
5
zhengwenk 2019-09-04 11:43:25 +08:00
如果你的应用的请求没有经过可靠的转发,HTTP_X_FORWARDED_FOR 是不可靠的
|
6
ChristopherWu 2019-09-04 11:51:44 +08:00
|
7
Bruin OP @gstqc postman 测试
Content-Type:application/x-www-form-urlencoded X-Forwarded-For: 60.177.121.199,60.177.121.20,18883331 获取的的 ip 结果,跟我本机的地址是一致的 "POST /v2/api/service/vote/testip HTTP/1.1" 200 45 "-" "PostmanRuntime/7.16.3" "60.177.121.199,60.177.121.20,18883331, 183.128.232.50, 172.18.168.233, 172.18.168.233, 172.18.168.233, 172.18.168.233, 172.18.168.233" 机器上 X-Forwarded-For 获取的地址,过滤内网 ip ['60.177.121.199','60.177.121.20','18883331','183.128.232.50'] 最后这个才是 ip 取得最后一个 ip 这个不能被伪造吧? |
8
leo108 2019-09-04 12:20:34 +08:00
先不说你 XFF 处理得对不对,HTTP_CLIENT_IP 这段不照样有风险?
|
9
ChristopherWu 2019-09-04 12:59:11 +08:00
@Bruin #7 看代码,好像你是跟我文章的做法差不多。这么说吧,问题是不大的,或者说,我文章里面别人评论的 nginx real ip 模块,做法也不外乎如是:
本质就是叠加 remote_addr ( ip 包里的 ip 地址)到 x-forwarded-ip,一直过滤。 只要别人不是自己重新实现 ip 协议,remote_addr 就肯定是真实的。 |
10
maxbon 2019-09-07 17:07:01 +08:00
除非直接对接用户,拿 remote_addr,是最真实的,其他的都可以伪造,如果自己走了代理,最好还是自定义头传真实 IP 过来
|