V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Bruin
V2EX  ›  程序员

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

  •  
  •   Bruin · 2019-09-04 11:18:14 +08:00 · 2339 次点击
    这是一个创建于 1667 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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'];
    }
    
    
    10 条回复    2019-09-07 17:07:01 +08:00
    glacer
        1
    glacer  
       2019-09-04 11:33:06 +08:00
    我可以通过伪造 HTTP_X_FORWARDED_FOR 来实现无限 IP 了
    Bruin
        2
    Bruin  
    OP
       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
        3
    Bruin  
    OP
       2019-09-04 11:39:40 +08:00
    @glacer HTTP_X_FORWARDED_FOR 伪造现在是无效的了
    gstqc
        4
    gstqc  
       2019-09-04 11:43:03 +08:00 via Android
    @Bruin 你贴的代码,明明可以随便伪造 #3
    zhengwenk
        5
    zhengwenk  
       2019-09-04 11:43:25 +08:00
    如果你的应用的请求没有经过可靠的转发,HTTP_X_FORWARDED_FOR 是不可靠的
    ChristopherWu
        6
    ChristopherWu  
       2019-09-04 11:51:44 +08:00
    @Bruin 可以看看我写的文章,https://www.v2ex.com/t/543304

    用 nginx 的 real ip 模块功能好了,就不用造轮子。
    Bruin
        7
    Bruin  
    OP
       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
        8
    leo108  
       2019-09-04 12:20:34 +08:00
    先不说你 XFF 处理得对不对,HTTP_CLIENT_IP 这段不照样有风险?
    ChristopherWu
        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 就肯定是真实的。
    maxbon
        10
    maxbon  
       2019-09-07 17:07:01 +08:00
    除非直接对接用户,拿 remote_addr,是最真实的,其他的都可以伪造,如果自己走了代理,最好还是自定义头传真实 IP 过来
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   962 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 20:35 · PVG 04:35 · LAX 13:35 · JFK 16:35
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.