PHP获取客户端IP地址 详解

在程序开发过程中,统计用户访问的IP是再正常不过的功能了,今天特意来分享一下PHP获取客户端IP真实地址方法

 

一、PHP获取客户端IP 代码

此示例代码既可以完美实现php获取客户端ipv4与ipv6

前提是只要你的服务器支持ipv6网络访问;

<?php
if ($_SERVER["HTTP_CLIENT_IP"] && strcasecmp($_SERVER["HTTP_CLIENT_IP"], "unknown")) {
    $ip = $_SERVER["HTTP_CLIENT_IP"];
}elseif ($_SERVER["HTTP_X_FORWARDED_FOR"] && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], "unknown")) {
    $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
}elseif ($_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown")) {
    $ip = $_SERVER["REMOTE_ADDR"];
}else{
    $ip = "unknown";
}

 

注意:

1、文章最后面有说明PHP获取客户端IP地址的代码为什么都要依次获取 HTTP_CLIENT_IP 、 HTTP_X_FORWARDED_FOR 与 REMOTE_ADDR?

 

2、如果你要分清楚是IPV4还是IPV6?还需要用正则表达式匹配。例如,匹配IPV4:

$res =  preg_match ( '/[\d\.]{7,15}/', $ip, $matches ) ? $matches [0] : '';
echo $res;

 

二、PHP获取客户端IP 原理

 

PHP获取客户端IP地址有四种方法:

  • HTTP_CLIENT_IP
  • HTTP_X_FORWARDED_FOR
  • REMOTE_ADDR
  • HTTP_VIA

 

$_SERVER['HTTP_CLIENT_IP'] 代理端的(有可能存在,可伪造)

HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回none值。同样,REMOTE_ADDR也会被替换为这个代理服务器的IP。

 

$_SERVER['HTTP_VIA'] 代理端的

HTTP_VIA是代理服务器地址,和HTTP_CLIENT_IP同理;绝大多数情况下,我们是用HTTP_VIA来判断用户是否通过代理访问的?是就会直接退出,不会再继续执行下去,这是保证安全的一项措施。

因此,这里获取IP一般是直接使用 $_SERVER['HTTP_CLIENT_IP'] ,没必要再使用 $_SERVER['HTTP_VIA'] 了。

 

$_SERVER['HTTP_X_FORWARDED_FOR'] 用户是在哪个IP使用的代理(有可能存在,也可以伪造)

 

$_SERVER['REMOTE_ADDR'] 访问端(有可能是用户,有可能是代理的)IP

REMOTE_ADDR是你的客户端跟你的服务器“握手”时候的IP。如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP。

 

1、没有使用代理服务器的情况:

REMOTE_ADDR = 您的 IP

HTTP_VIA = 没数值或不显示

HTTP_X_FORWARDED_FOR = 没数值或不显示

 

2、使用透明代理服务器的情况:Transparent Proxies

REMOTE_ADDR = 最后一个代理服务器 IP

HTTP_VIA = 代理服务器 IP

HTTP_X_FORWARDED_FOR = 您的真实 IP ;经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

 

这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。

 

3、使用普通匿名代理服务器的情况:Anonymous Proxies

REMOTE_ADDR = 最后一个代理服务器 IP

HTTP_VIA = 代理服务器 IP

HTTP_X_FORWARDED_FOR = 代理服务器 IP ;经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

 

隐藏了您的真实IP,但是向访问对象透露了您是使用代理服务器访问他们的。

 

4、使用欺骗性代理服务器的情况:Distorting Proxies

REMOTE_ADDR = 代理服务器 IP

HTTP_VIA = 代理服务器 IP

HTTP_X_FORWARDED_FOR = 随机的 IP ;经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

 

告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。

 

5、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)

REMOTE_ADDR = 代理服务器 IP

HTTP_VIA = 没数值或不显示

HTTP_X_FORWARDED_FOR = 没数值或不显示 ;经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。

 

完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象。

 

三、PHP获取客户端IP 其它问题

 

1、关于 REMOTE_ADDR

这个变量获取到的是《直接来源》的 IP 地址,所谓《直接来源》指的是直接请求该地址的客户端 IP 。这个 IP 在单服务器的情况下,很准确的是客户端 IP ,无法伪造。当然并不是所有的程序都一定是单服务器,比如在采用负载均衡的情况(比如采用 haproxy 或者 nginx 进行负载均衡),这个 IP 就是转发机器的 IP ,因为过程是客户端->负载均衡->服务端。是由负载均衡直接访问的服务端而不是客户端。

 

2、关于 HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP

基于《一》,在负载均衡的情况下直接使用 REMOTE_ADDR 是无法获取客户端 IP 的,这就是一个问题,必须解决。于是就衍生出了负载均衡端将客户端 IP 加入到 HEAD 中发送给服务端,让服务端可以获取到客户端的真实 IP 。当然也就产生了各位所说的伪造,毕竟 HEAD 除了协议里固定的那几个数据,其他数据都是可自定义的。

 

3、为何网上找到获取客户端 IP 的代码都要依次获取 HTTP_CLIENT_IP 、 HTTP_X_FORWARDED_FOR 和 REMOTE_ADDR?

基于《一》和《二》以及对程序通用性的考虑,所以才这样做。 假设你在程序里直接写死了 REMOTE_ADDR ,有一天你们的程序需要做负载均衡了,那么,你有得改了。当然如果你想这么做也行,看个人爱好和应用场景。也可以封装一个只有 REMOTE_ADDR 的方法,等到需要的时候改这一个方法就行了。

 

总结:

php获取客户端ip地址到此就算全部结束了,php获取客户端真实ip地址其实就是这么的简单。

大家只需要知道两点:

1、REMOTE_ADDR 得到的是客户端真实IP地址,并且IP不可伪造(虽然有时候得到的IP也是代理的)

2、HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP 得到的是代理端的IP地址,是可以伪造的

    A+
发布日期:2020年12月13日 17:01:42  所属分类:PHP
最后更新时间:2020-12-13 17:01:42
评分: (2 票;平均数3.00 ;最高评分 5 ;用户总数2;总得分 6;百分比60.00)
付杰
Python爬虫教程:零基础上手Scrapy分布爬虫
  • ¥ 388.0元
  • 市场价:388.0元
服务器管理面板/主机控制面板“安装”服务
服务器管理面板/主机控制面板“安装”服务
  • ¥ 49.9元
  • 市场价:99.9元
JAVA从入门到精通视频教程(实战)
  • ¥ 99.0元
  • 市场价:99.0元
PHP零基础入门到精通视频教程
  • ¥ 199.0元
  • 市场价:199.0元

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: