获取客户端IP地址

获取客户端IP地址

函数还是太全面了。🤣

以下是一个PHP函数,用来获取客户端的IP地址,并考虑了不同的HTTP头(包括 HTTP_CLIENT_IPHTTP_X_REAL_IPHTTP_CDN_SRC_IPHTTP_X_FORWARDED_FOR)以及内网请求:

function getClientIp() {
    // 优先级: HTTP_CLIENT_IP > HTTP_X_REAL_IP > HTTP_CDN_SRC_IP > HTTP_X_FORWARDED_FOR
    $client_ip = '';

    // 获取 HTTP_CLIENT_IP
    if (isset($_SERVER['HTTP_CLIENT_IP']) && filter_var($_SERVER['HTTP_CLIENT_IP'], FILTER_VALIDATE_IP)) {
        $client_ip = $_SERVER['HTTP_CLIENT_IP'];
    }
    // 如果没有,获取 HTTP_X_REAL_IP
    elseif (isset($_SERVER['HTTP_X_REAL_IP']) && filter_var($_SERVER['HTTP_X_REAL_IP'], FILTER_VALIDATE_IP)) {
        $client_ip = $_SERVER['HTTP_X_REAL_IP'];
    }
    // 如果没有,获取 HTTP_CDN_SRC_IP
    elseif (isset($_SERVER['HTTP_CDN_SRC_IP']) && filter_var($_SERVER['HTTP_CDN_SRC_IP'], FILTER_VALIDATE_IP)) {
        $client_ip = $_SERVER['HTTP_CDN_SRC_IP'];
    }
    // 如果没有,获取 HTTP_X_FORWARDED_FOR
    elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        // X-Forwarded-For 可以是多个IP,取第一个非内网IP
        $ips = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
        foreach ($ips as $ip) {
            $ip = trim($ip);
            // 排除内网IP范围
            if (!filter_var($ip, FILTER_VALIDATE_IP) || preg_match('/^192\.168\./', $ip) || preg_match('/^10\./', $ip) || preg_match('/^172\.(1[6-9]|2[0-9]|3[01])\./', $ip)) {
                continue;
            }
            $client_ip = $ip;
            break;
        }
    }

    // 如果都没有找到IP,返回REMOTE_ADDR
    if (empty($client_ip) && isset($_SERVER['REMOTE_ADDR'])) {
        $client_ip = $_SERVER['REMOTE_ADDR'];
    }

    return $client_ip;
}

说明:

  1. HTTP_CLIENT_IP:客户端直接提供的IP地址,通常用于代理或虚拟主机环境中。
  2. HTTP_X_REAL_IP:负载均衡器或代理服务器传递的客户端IP地址。
  3. HTTP_CDN_SRC_IP:CDN或反向代理服务器传递的客户端IP。
  4. HTTP_X_FORWARDED_FOR:此头信息通常包含了客户端的原始IP和代理服务器的IP,多个IP由逗号分隔。我们会跳过内网IP(192.168.x.x、10.x.x.x 和 172.16.x.x 到 172.31.x.x)并取第一个有效的IP。
  5. 如果以上都未能找到IP地址,则退回到 REMOTE_ADDR,它通常是直接连接到服务器的客户端IP。

这种方法能处理多种可能的情况,确保获得最准确的客户端IP地址。

发表回复