关于获取用户真实 ip 问题,下面代码可靠性 ok 吗?

2019-09-04 11:18:14 +08:00
 Bruin
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'];
}

2355 次点击
所在节点    程序员
10 条回复
glacer
2019-09-04 11:33:06 +08:00
我可以通过伪造 HTTP_X_FORWARDED_FOR 来实现无限 IP 了
Bruin
2019-09-04 11:39:07 +08:00
@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 的,
Bruin
2019-09-04 11:39:40 +08:00
@glacer HTTP_X_FORWARDED_FOR 伪造现在是无效的了
gstqc
2019-09-04 11:43:03 +08:00
@Bruin 你贴的代码,明明可以随便伪造 #3
zhengwenk
2019-09-04 11:43:25 +08:00
如果你的应用的请求没有经过可靠的转发,HTTP_X_FORWARDED_FOR 是不可靠的
ChristopherWu
2019-09-04 11:51:44 +08:00
@Bruin 可以看看我写的文章,https://www.v2ex.com/t/543304

用 nginx 的 real ip 模块功能好了,就不用造轮子。
Bruin
2019-09-04 12:08:37 +08:00
@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 这个不能被伪造吧?
leo108
2019-09-04 12:20:34 +08:00
先不说你 XFF 处理得对不对,HTTP_CLIENT_IP 这段不照样有风险?
ChristopherWu
2019-09-04 12:59:11 +08:00
@Bruin #7 看代码,好像你是跟我文章的做法差不多。这么说吧,问题是不大的,或者说,我文章里面别人评论的 nginx real ip 模块,做法也不外乎如是:

本质就是叠加 remote_addr ( ip 包里的 ip 地址)到 x-forwarded-ip,一直过滤。

只要别人不是自己重新实现 ip 协议,remote_addr 就肯定是真实的。
maxbon
2019-09-07 17:07:01 +08:00
除非直接对接用户,拿 remote_addr,是最真实的,其他的都可以伪造,如果自己走了代理,最好还是自定义头传真实 IP 过来

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/597794

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX