zoukankan      html  css  js  c++  java
  • PHP正确获取客户端IP地址

    现状

    目前主流的函数方法:

    <?php
    function getIp()
    {
        if ($_SERVER["HTTP_CLIENT_IP"] && strcasecmp($_SERVER["HTTP_CLIENT_IP"], "unknown")) {
            $ip = $_SERVER["HTTP_CLIENT_IP"];
        } else {
            if ($_SERVER["HTTP_X_FORWARDED_FOR"] && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], "unknown")) {
                $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
            } else {
                if ($_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown")) {
                    $ip = $_SERVER["REMOTE_ADDR"];
                } else {
                    if (isset ($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'],
                            "unknown")
                    ) {
                        $ip = $_SERVER['REMOTE_ADDR'];
                    } else {
                        $ip = "unknown";
                    }
                }
            }
        }
        return ($ip);
    }
    
    echo getIp();
    

    测试

    curl伪造IP请求:

    <?php
    $ch = curl_init('http://localhost/ip.php');
    
    //通用设置
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);//不直接输出
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);//跟踪重定向
    
    //伪造请求头
    $ip = mt_rand(1, 255) . '.' . mt_rand(1, 255) . '.' . mt_rand(1, 255) . '.' . mt_rand(1, 255);
    $header = [
        'CLIENT-IP: ' . $ip,
        'X-FORWARDED-FOR: ' . $ip,
        'X-REAL-IP: ' . $ip,
        'Accept-Language: zh-CN,zh;',
    ];
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    
    $html = curl_exec($ch);
    curl_close($ch);
    echo $html;
    

    输出SERVER数组,发现【HTTP_CLIENT_IP】、【HTTP_X_FORWARDED_FOR】、【HTTP_X_REAL_IP】是随机变动的IP地址。

    主流方法根本不安全!

    分析

    为什么?

    HTTP_CLIENT_IP:存在于http请求的header

    HTTP_X_FORWARDED_FOR:请求转发路径,客户端IP,代理1IP,代理2IP......

    HTTP_X_REAL_IP:这个用得比较少,暂不讨论。

    这三个值都是从HTTP请求头获取的,所以并不可靠!

    REMOTE_ADDR:是直接从TCP中获取的IP,基本不会被伪造!

    返回查看$_SERVER数组,发现【REMOTE_ADDR】显示正确的IP!

    所以直接用 $_SERVER['REMOTE_ADDR'] 就解决问题了?

    其实还不行,如果客户端和服务器之间存在代理服务器,【REMOTE_ADDR】的值是最后一个代理服务器的IP!

    只有第一台接收客户端请求的代理服务器的【REMOTE_ADDR】值才是客户的真实IP地址,要把该值传递下去!

    解决方案

    1. 客户端和服务器直连

    <?php
    function get_client_ip()
    {
        $ip = $_SERVER['REMOTE_ADDR'];
        return $ip;
    }
    

    2. 客户端和服务器存在中间代理

    第一层nginx代理设置:

    proxy_set_header X-Forwarded-For $remote_addr;

    其他层nginx代理设置:

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    PHP代码:

    <?php
    function get_client_ip()
    {
        $ip = null;
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
            $ip = trim(current($ip));
        }
        return $ip;
    }
    
  • 相关阅读:
    eclipse git如何切换分支,拉取代码,合并代码,解决冲突等
    eclipse git提交项目以及down项目大致步骤
    彻底卸载Oracle
    收藏的技术点
    SpringBoot+MyBatis整合报错Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required
    nginx基本配置
    window下命令启动/停止nginx
    springboot 新建的时候 pom 第一行出现红叉,项目可以正常运行
    oracle replace的用法
    启动tomcat出现闪退的原因
  • 原文地址:https://www.cnblogs.com/xiejixing/p/11662158.html
Copyright © 2011-2022 走看看