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

获取客户 ip 这件事情,有解么?

  •  
  •   xeis · 2017-03-11 16:31:08 +08:00 via Android · 6658 次点击
    这是一个创建于 2601 天前的主题,其中的信息可能已经有所发展或是发生改变。
    试了好多,都不行。。。
    20 条回复    2017-03-13 23:54:02 +08:00
    GoBeyond
        1
    GoBeyond  
       2017-03-11 16:49:00 +08:00 via Android
    $_SERVER['REMOTE_ADDR']
    xeis
        2
    xeis  
    OP
       2017-03-11 17:02:45 +08:00 via Android
    @GoBeyond 拿到的是 cdn 地址
    mooncakejs
        3
    mooncakejs  
       2017-03-11 17:07:07 +08:00 via iPhone
    cdn 一般给 X_real_ip
    bianhua
        4
    bianhua  
       2017-03-11 17:07:46 +08:00
    @xeis

    一些 CDN 会在 CDN 回源请求加 HTTP 头信息,其中可能包含访客的“真实 IP ”。具体要看是哪家 CDN ,比如 Cloudflare 是 CF-Connecting-IP 。
    Mazda
        5
    Mazda  
       2017-03-11 18:42:41 +08:00 via iPhone
    自己看你用的 cdn 的文档呗,这个是最基本的
    peesefoo
        6
    peesefoo  
       2017-03-11 19:05:10 +08:00 via Android
    X-Forwarded-For
    cnwtex
        7
    cnwtex  
       2017-03-11 19:30:17 +08:00
    mytsing520
        8
    mytsing520  
       2017-03-11 23:03:11 +08:00
    X-Forwarded-For
    X-Real-IP
    liangmishi
        9
    liangmishi  
       2017-03-12 00:33:11 +08:00 via Android
    如果用了 cdn ,那么一般在 headers 里有真实的 ip 。
    如果使用了 ngnix 反向代理的话可以配置一下 nginx ,就可以在请求头里拿到 ip
    Allianzcortex
        10
    Allianzcortex  
       2017-03-12 00:40:36 +08:00
    OpenResty 的内置变量里 remote_addr 在单台机器上可以用,如果做了负载均衡的话就用 http_x_forwarded_for ,来应对访问网络里有多层代理的情况。这个问题应该偏运维多一点?
    jitongxi
        11
    jitongxi  
       2017-03-12 07:49:28 +08:00
    你访问以下,
    然后把 header 里面的信息打印出来就知道了.
    阿里是"Ali-Cdn-Real-Ip"
    changwei
        12
    changwei  
       2017-03-12 09:45:10 +08:00 via Android
    @peesefoo X-Forwarded-For 听说有被客户端伪造的风险
    Reign
        13
    Reign  
       2017-03-12 10:08:15 +08:00
    @bianhua 我可能用的假 cloudflare 了, CF-Connecting-IP 哪里出现在 cloudflare 的 response headers 里面了???
    lavasing
        14
    lavasing  
       2017-03-12 10:32:07 +08:00 via Android
    @Reign 付费版本才有
    bianhua
        15
    bianhua  
       2017-03-12 10:59:40 +08:00
    @Reign

    不是 Response Header ,而是 Request Header 。

    https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-

    如果你使用 PHP 的话,头信息应该在储存在$_SERVER['HTTP_CF_CONNECTING_IP']。

    当然如果这样还不行,同时你在用 Nginx 的话,你可以按照
    https://support.cloudflare.com/hc/en-us/articles/200170706-How-do-I-restore-original-visitor-IP-with-Nginx-
    的“ Restoring the original visitor IP for your web application ”小结来配置你的 Nginx ,这样你就能直接用 REAL_IP 这个头来读取 IP 了。

    如果上面都不行,仍然有解决方案:
    你可以自己在程序里解析那几个 XFF 头信息(参考你的 CDN 具体给你返回了哪个 XFF ,比如 X-Forwarded-For 或者 X-Forwarded 等等)。
    首先检查 REMOTE_ADDR ,看访问是否来自 CDN ,如果不是则直接使用 REMOTE_ADDR ,否则按照下面的方式解析 XFF :
    把 XFF 读出来之后,从最后一台经过的服务器开始检查,看 IP 地址是否属于 CDN ,如果是则检查前一台。循环这个过程直到找到一台非 CDN 的 IP 地址,然后将这个 IP 地址作为客户端的“真实” IP 地址。
    注意:这个解决方案需要详细的配置你的程序,确保它能够准确判断访问 IP 是否来自 CDN 。否则访客可以伪造 XFF ,造成任意伪造 IP 地址的问题。(同时其实也要确保你用的 CDN 是安全可信的,乱填 XFF 头也会造成安全问题)
    hasdream
        16
    hasdream  
       2017-03-12 11:06:57 +08:00
    cdn 获取远程地址 X-Forwarded-For 格式: X-Forwarded-For: client1, proxy1, proxy2 。 第一个永远是客户端地址 这个头可以伪造 但是大部分网站使用 CDN 都是用这个头取客户端 IP 的。 阿里云 CDN 和腾讯 CDN 这个值都可以获取到客户端的真实地址
    参考: https://imququ.com/post/x-forwarded-for-header-in-http.html
    ioioioioioioi
        17
    ioioioioioioi  
       2017-03-12 13:03:12 +08:00
    先获取 CDN 地址,然后判断:
    if ($_SERVER['REMOTE_ADDR'] == '47.1.1.1' or $_SERVER['REMOTE_ADDR'] == '120.1.1.1' ) {
    return $ip = strtok($_SERVER['HTTP_X_FORWARDED_FOR'], ',') ?: $_SERVER['REMOTE_ADDR'];
    }

    return $ip = $_SERVER['REMOTE_ADDR'];
    phantomer
        18
    phantomer  
       2017-03-12 17:50:51 +08:00
    ```php
    function get_client_ip($type = 0,$adv=false) {
    $type = $type ? 1 : 0;
    static $ip = NULL;
    if ($ip !== NULL) return $ip[$type];
    if($adv){
    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]);
    $ip = trim($arr[0]);
    }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
    $ip = $_SERVER['HTTP_CLIENT_IP'];
    }elseif (isset($_SERVER['REMOTE_ADDR'])) {
    $ip = $_SERVER['REMOTE_ADDR'];
    }
    }elseif (isset($_SERVER['REMOTE_ADDR'])) {
    $ip = $_SERVER['REMOTE_ADDR'];
    }
    // IP 地址合法验证
    $long = sprintf("%u",ip2long($ip));
    $ip = $long ? array($ip, $long) : array('0.0.0.0', 0);
    return $ip[$type];
    }
    ```
    henbf
        19
    henbf  
       2017-03-13 11:34:20 +08:00 via iPhone
    nginx 的 Realip 模块
    gouchaoer
        20
    gouchaoer  
       2017-03-13 23:54:02 +08:00 via Android
    老老实实的去 js 获取 ip ,然后上传
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1043 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 19:31 · PVG 03:31 · LAX 12:31 · JFK 15:31
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.