konakona
PHP获取IP地址方法及原理
PHP获取IP地址方法及原理

此文属转载,写得不错。但konakona有话要说:php是无法获得代理后的真实ip的,文章中也很好的说了“如果代理商就是不留下任何记号,你始终无法知道它的真实ip”。但我更在意的是ip138和51la获取真实ip的方法!同时它们2个都是asp……

小问题中包含大学问。

在谷歌中搜索“PHP中获取地址的方法”,肯定能得到不少的结果。简单点的,只需要

 

复杂点的,可能就需要判断更多,比如,(来自discuz代码)

那么,隐藏在这复杂判断情形之下的原理是什么?为什么要这么判断?现在让我们一一揭开。

其实,浏览器访问PHP服务器时,假设服务器使用Apache,那么Apache会负责在_SERVER变量中设置环境变量。设置的内容遵从CGI/1.1定义(你可以查看http://bitsucker.com/index.php/archives/61获取更多关于CGI/1.1的说明)。那么来看这几个可能遇到的_SERVER变量:

REMOTE_ADDR

The IP address of the agent sending the request to the server. Not necessarily that of the client.对服务器发起访问的代理的IP地址。不一定是客户端的。IP地址遵从格式:REMOTE_ADDR = hostnumber;hostnumber = digits “.” digits “.” digits “.” digits;digits = 1*digit

也就是说,这个存放的是IP地址,但是有可能是用户使用的代理的IP地址,不一定是真实的用户地址。那么直接使用这个变量来获取地址的话,还真不好意思说方法名是getRealIP。那么有没有办法确认代理呢?继续看。

HTTP_*

These variables are specific to requests made with HTTP.Environment variables with names beginning with “HTTP_” contain header data read from the client, if the protocol used was HTTP.The server is not required to create environment variables for all the headers that it receives. In particular, it might remove any headers carrying authentication information, such as `Authorization’.以HTTP_开头的变量描述HTTP请求的具体环境,它包含客户端发送的头信息。但是,不要求服务器设置接收到的所有头信息,服务器可以有选择的取舍。(特别是,服务器可以去掉头信息中还有的验证部分。)

HTTP_X_FORWARDED_FOR,HTTP_CLIENT_IP

这一类的变量(以HTTP_开头的)并不是CGI/1.1规范严格定义的。它们可以有客户端自由定义(,至少根据规范的描述来说)。所幸,如果用户使用代理,一般HTTP_X_FORWARDED_FOR或HTTP_CLIENT_IP变量会被设置;在此种情况下,HTTP_X_FORWARDED_FOR或HTTP_CLIENT_IP变量代表了客户端的真实IP,而REMOTE_ADDR则代表此代理的IP地址。那么一般情况下就可以根据此特征获取用户的真实IP地址以及是否使用了代理。

为什么说一般呢?因为这里还有点问题。第一是用户使用多层代理。此时,REMOTE_ADDR代表最后一个使用的代理的IP,而HTTP_X_FORWARDED_FOR会依次设置为这样的形式:你的真实IP地址、第一层代理IP、第二层代理IP、等等,地址之间使用逗号分隔;此时HTTP_X_FORWARDED_FOR相当于代表了真实的客户端到到达最终的服务器之前经过的所有路径点的IP列表;然后HTTP_CLIENT_IP会被代理设置为客户端的真实IP。(所以,用户只使用一层代理的情况下,HTTP_X_FORWARDED_FOR与HTTP_CLIENT_IP相同只是使用多层代理的特殊情况。)再一个问题是代理的邪恶:代理可以依据自己的喜好标准选择是否设置HTTP_X_FORWARDED_FOR与HTTP_CLIENT_IP,设置成什么样的值,设置全部还是部分。因此代理可以提交完整的设置,提交部分设置的数据,提交伪造的IP地址数据,甚至什么也不设置伪装成没有使用代理。(你可以参考这篇文章了解一下更多的内容。下面摘抄了部分关键内容)

 

 

 

总结起来,

REMOTE_ADDR 是你的客户端跟服务器“握手”时候的IP。如果使用代理,REMOTE_ADDR将显示代理服务器的IP。
HTTP_CLIENT_IP 是代理服务器设置发送的HTTP头,代表你的客户端的真实IP。当然,人家可以选择设置与否以及设置成什么样。
HTTP_X_FORWARDED_FOR 是用户到达最终访问地时经过的路径访问点(包括自身和使用的多层代理)的IP列表。依然取决于代理的设置,可以伪造。

知道了以上的情况,我们就可以写出比较完整的获取IP地址的方法。但是鉴于IP地址还是有可能被某些代理伪造,所以叫做getRealIP还是稍显底气不足。

 

 

赞赏
https://secure.gravatar.com/avatar/3b712b34a0e1b689cfb524c9c6bcdc47?s=256&r=g

团哥

文章作者

继续玩我的CODE,让别人说去。 低调,就是这么自信。

发表评论

textsms
account_circle
email

konakona

PHP获取IP地址方法及原理
php是无法获得代理后的真实ip的,文章中也很好的说了“如果代理商就是不留下任何记号,你始终无法知道它的真实ip”。但我更在意的是ip138和51la获取真实ip的方法!同时它们2个都是asp……
扫描二维码继续阅读
2011-08-29