PHP 获取客户端真实 IP

验证 IP 地址有效性及区分 IPv4/IPv6 地址

IPv4 和 IPv6 地址的字符串长度

IPv4 地址: 最大长度为 15 个字符
IPv6 地址: 最大长度为 63 个字符

IPv4 采用  32 位地址长度    xxx.xxx.xxx.xxx
IPv6 采用 128 位地址长度    FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF

PHP 获取客户端真实 IP 地址

方法一

通过 HTTP_CLIENT_IPHTTP_X_FORWARDED_FORREMOTE_ADDR 获取客户端 IP, 并过滤私有 IP 地址

function get_real_ip() {
    $ip = false;
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        $ip = $_SERVER['HTTP_CLIENT_IP'];
    }
    if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $ips = explode(', ', $_SERVER['HTTP_X_FORWARDED_FOR']);
        if ($ip) {
            array_unshift($ips, $ip);
            $ip = false;
        }
        for ($i = 0; $i < count($ips); $i++) {
            if (!preg_match('/^(10|172.16|192.168)./', $ips[$i])) {
                $ip = $ips[$i];
                break;
            }
        }
    }
    return ($ip ? $ip : $_SERVER['REMOTE_ADDR']);
}

方法二

通过不同的服务器变量获取 IP 地址 (HTTP_X_FORWARDED_FORHTTP_CLIENT_IPREMOTE_ADDR)

function get_real_ip() {
    static $realip;
    if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $realip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $realip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
            $realip = $_SERVER['REMOTE_ADDR'];
        }
    } else {
        if (getenv('HTTP_X_FORWARDED_FOR')) {
            $realip = getenv('HTTP_X_FORWARDED_FOR');
        } else if (getenv('HTTP_CLIENT_IP')) {
            $realip = getenv('HTTP_CLIENT_IP');
        } else {
            $realip = getenv('REMOTE_ADDR');
        }
    }
    return $realip;
}

方法三

Discuz 代码示例, 通过 is_ip 函数判断 IP 是否有效

function getIp() {
    $ip = '未知IP';
    if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
        return is_ip($_SERVER['HTTP_CLIENT_IP']) ? $_SERVER['HTTP_CLIENT_IP'] : $ip;
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        return is_ip($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $ip;
    } else {
        return is_ip($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : $ip;
    }
}

function is_ip($str) {
    $ip = explode('.', $str);
    for ($i = 0; $i < count($ip); $i++) {
        if ($ip[$i] > 255) {
            return false;
        }
    }
    return preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $str);
}

方法四

我目前在使用的

function getRealIp() {
    static $realip;
    if (isset($_SERVER)) {
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
            $realip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        } else if (isset($_SERVER['HTTP_CLIENT_IP'])) {
            $realip = $_SERVER['HTTP_CLIENT_IP'];
        } else {
            $realip = $_SERVER['REMOTE_ADDR'];
        }
    } else {
        if (getenv('HTTP_X_FORWARDED_FOR')) {
            $realip = getenv('HTTP_X_FORWARDED_FOR');
        } else if (getenv('HTTP_CLIENT_IP')) {
            $realip = getenv('HTTP_CLIENT_IP');
        } else {
            $realip = getenv('REMOTE_ADDR');
        }
    }

    if (filter_var($realip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE)) {
        return $realip;
    } elseif (filter_var($realip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
        return $realip;
    } else {
        return -1;
    }
}

判断 IP 是否为有效 IP 地址

PHP 自带的 filter_var 函数可用于 IP 地址有效性验证, 以下为几种验证方式

判断是否为合法 IP 地址

if (filter_var($ip, FILTER_VALIDATE_IP)) {
    // 是合法 IP
} else {
    // 不是合法 IP
}

判断是否为合法 IPv4 地址

if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
    // 是合法 IPv4
} else {
    // 不是合法 IPv4 地址
}

判断是否为公共 IPv4 地址 (排除私有 IP 地址)

192.168.1.1 这类的私有IP地址将会排除在外

if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE)) {
    // 是公共 IPv4 地址
} else {
    // 不是合法 IPv4 地址
}

判断是否为合法 IPv6 地址

if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_RES_RANGE)) {
    // 是合法 IPv6 地址
} else {
    // 不是合法 IPv6 地址
}

判断是否为公共 IPv4 或 IPv6 地址

if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
    // 是公共 IP 地址
} else {
    // 不是公共 IP
}

判断客户端连接的 IP 版本 (IPv4/IPv6)

可以通过检查 IP 地址字符串中是否包含 : 符号来区分 IPv4 和 IPv6

function ipVersion($txt) {
    return strpos($txt, ":") === false ? 4 : 6;
}

原文

php获取客户端真实ip地址的三种方法
php如何判断IP为有效IP地址
php – 如何检查是否有人通过IPv6/IPv4连接
How to know which version of the Internet Protocol (IP) a client is using when connecting to my server?
Ipv4和Ipv6的地址字符串长度
一个完整的IPv6显示在TextBox里面, 它到底占用多少个字符?

最后更新于 2019-06-05
使用 Hugo 构建
主题 StackJimmy 设计