获取客户端ip其实不是个简单的活儿,因为存在Ip欺骗,和代理问题,所以获取客户端的IP的真实性会打折扣的,不能百分百准确.但是我们还是尽量找一个比较完善的获取客户端真正ip方法.使用php获取IP的方法能找到很多.
getIp
- function getIp() {
- if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown")) $ip = getenv("HTTP_CLIENT_IP");
- else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown")) $ip = getenv("HTTP_X_FORWARDED_FOR");
- else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown")) $ip = getenv("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);
- }
现在需要对这段代码进行解释,这里用到了两个函数,getenv()和strcasecmp(),前一个函数获取得系统的环境变量,如果能取到值,则返回该值,不能则返回false.
$_SERVER是服务器超级全局变量数组,用$_SERVER['REMOTE_ADDR']同样可以获取到客户端的IP地址.二者的区别在于,getenv不支持IIS的isapi方式运行的php.
strcasecmp(string1,string2)字符串函数的用法是把string1和string2进行比较,如果相等返回0,如果string1大于string2,返回大于0的数,小于则返回小于0的数.
函数先使用客户IP,如果不成立尝试用代理的方法,如果不行,再使用REMOTE_ADDR.还看到过一个检测IP更详细的方法,考虑了IP的欺骗,和多重代理代码.方法相类似.
- function getip() {
- $unknown = 'unknown';
- if (isset($_SERVER['HTTP_X_FORWARDED_FOR']) && $_SERVER['HTTP_X_FORWARDED_FOR'] && strcasecmp($_SERVER['HTTP_X_FORWARDED_FOR'], $unknown)) {
- $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
- }
- elseif(isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], $unknown)) {
- $ip = $_SERVER['REMOTE_ADDR'];
- }
- /*
- 处理多层代理的情况
- 或者使用正则方式:$ip = preg_match("/[\d\.]{7,15}/", $ip, $matches) ? $matches[0] : $unknown;
- */
- if (false !== strpos($ip, ',')) $ip = reset(explode(',', $ip));
- return $ip;
- }
REMOTE_ADDR = 客户端IP
HTTP_X_FORWARDED_FOR = 没数值或不显示
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 客户端真实 IP (经过多个代理服务器时,这个值类似:221.5.252.160, 203.98.182.163, 203.129.72.215)
这类代理服务器还是将客户端真实的IP发送给了访问对象,无法达到隐藏真实身份的目的.
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP (经过多个代理服务器时,这个值类似:203.98.182.163, 203.98.182.163, 203.129.72.215)
这种情况下隐藏了客户端的真实IP,但是向访问对象透露了客户端是使用代理服务器访问它们的.
REMOTE_ADDR = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP(经过多个代理服务器时,这个值类似:220.4.251.159, 203.98.182.163, 203.129.72.215)
这种情况下同样透露了客户端是使用了代理服务器,但编造了一个虚假的随机IP(220.4.251.159)代替客户端的真实IP来欺骗它.
REMOTE_ADDR = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 没数值或不显示
无论是REMOTE_ADDR还是HTTP_FORWARDED_FOR,这些头消息未必能够取得到,因为不同的浏览器不同的网络设备可能发送不同的IP头消息.因此PHP使用$_SERVER["REMOTE_ADDR"] 、$_SERVER["HTTP_X_FORWARDED_FOR"] 获取的值可能是空值也可能是“unknown”值.
-----------------------------------------------------------------------------------------测试例子----------------------------------------------------------------------------------------------------
REMOTE_ADDR 是你的客户端跟你的服务器“握手”时候的IP。如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP。
HTTP_CLIENT_IP 是代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回none值。同样,REMOTE_ADDR也会被替换为这个代理服务器的IP。
$_SERVER['REMOTE_ADDR']; //访问端(有可能是用户,有可能是代理的)IP
$_SERVER['HTTP_CLIENT_IP']; //代理端的(有可能存在,可伪造)
$_SERVER['HTTP_X_FORWARDED_FOR']; //用户是在哪个IP使用的代理(有可能存在,也可以伪造)
下面是测试代码:
服务端获取IP地址 http://ip.itlearner.com/ 其代码如下:
$s_onlineip = getenv(‘HTTP_CLIENT_IP’);
echo “HTTP_CLIENT_IP:”.$s_onlineip.”
\n”;
$s_onlineip = getenv(‘HTTP_X_FORWARDED_FOR’);
echo “HTTP_X_FORWARDED_FOR:”.$s_onlineip.”
\n”;
$s_onlineip = getenv(‘REMOTE_ADDR’);
echo “REMOTE_ADDR:”.$s_onlineip.”
\n”;
$s_onlineip = $_SERVER['REMOTE_ADDR'];
echo “\$_SERVER['REMOTE_ADDR']:”.$s_onlineip.”
\n”;
客户端代码:
伪造IP测试:
$url = ‘http://ip.itlearner.com/’;
$data_string = ‘test=test’;
$URL_Info = parse_url($url);
$request = ”;
if (!isset($URL_Info["port"]))
$URL_Info["port"]=80;
$request.=”POST “.$URL_Info["path"].” HTTP/1.1\n”;
$request.=”Host: “.$URL_Info["host"].”\n”;
$request.=”Referer: “.$URL_Info["host"].”\n”;
$request.=”Content-type: application/x-www-form-urlencoded\n”;
$request.=”X-Forwarded-For:192.168.1.4\n”;//HTTP_X_FORWARDED_FOR的值
$request.=”client_ip:192.168.1.5\n”;//HTTP_CLIENT_IP的值
$request.=”Content-length: “.strlen($data_string).”\n”;
$request.=”Connection: close\n”;
$request.=”\n”;
$request.=$data_string.”\n”;$fp = fsockopen($URL_Info["host"], $URL_Info["port"]);
fputs($fp, $request);
$result = ”;
while(!feof($fp)) {
$result .= fgets($fp, 1024);
}
fclose($fp);
echo $result;
输出:
HTTP_CLIENT_IP:192.168.1.5
HTTP_X_FORWARDED_FOR:192.168.1.4
REMOTE_ADDR:127.0.0.1
$_SERVER['REMOTE_ADDR']:127.0.0.1
代理IP测试:
$cUrl = curl_init();
curl_setopt($cUrl, CURLOPT_URL, $url);
curl_setopt($cUrl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($cUrl, CURLOPT_HEADER, 1);
curl_setopt($cUrl, CURLOPT_USERAGENT, “Mozilla/99.99″);
//curl_setopt($cUrl, CURLOPT_TIMEOUT, 10);
curl_setopt($cUrl, CURLOPT_PROXY, ’125.77.194.103:80′);
$c = curl_exec($cUrl);
curl_close($cUrl);
echo $c;
输出:
HTTP_CLIENT_IP:
HTTP_X_FORWARDED_FOR:
REMOTE_ADDR:125.77.194.103
$_SERVER['REMOTE_ADDR']:125.77.194.103
--------------------------------------------------------------------------------------------------伪造2--------------
伪造IP来源对于php来说是很简单的一件事情,我们只要利用了php curl即可实现伪造IP来源哦,IP地址你可以随便写哦。
实例
代码如下 | 复制代码 |
$ch = curl_init(); |
2.php代码:
代码如下 | 复制代码 |
function getClientIp() { 用1.php 请求 2.php,输出结果: IP:8.8.8.8 referer:http://www.hzhuti.com |
伪造成功,这是不是给采集的朋友提供了很好的换IP的方案!!当然防被刷的朋友也要注意了
PHP中的CURL函数库(Client URL Library Function)
curl_close — 关闭一个curl会话
curl_copy_handle — 拷贝一个curl连接资源的所有内容和参数
curl_errno — 返回一个包含当前会话错误信息的数字编号
curl_error — 返回一个包含当前会话错误信息的字符串
curl_exec — 执行一个curl会话
curl_getinfo — 获取一个curl连接资源句柄的信息
curl_init — 初始化一个curl会话
curl_multi_add_handle — 向curl批处理会话中添加单独的curl句柄资源
curl_multi_close — 关闭一个批处理句柄资源
curl_multi_exec — 解析一个curl批处理句柄
curl_multi_getcontent — 返回获取的输出的文本流
curl_multi_info_read — 获取当前解析的curl的相关传输信息
curl_multi_init — 初始化一个curl批处理句柄资源
curl_multi_remove_handle — 移除curl批处理句柄资源中的某个句柄资源
curl_multi_select — Get all the sockets associated with the cURL extension, which can then be "selected"
curl_setopt_array — 以数组的形式为一个curl设置会话参数
curl_setopt — 为一个curl设置会话参数
curl_version — 获取curl相关的版本信息
curl_init()函数的作用初始化一个curl会话,curl_init()函数唯一的一个参数是可选的,表示一个url地址。
curl_exec()函数的作用是执行一个curl会话,唯一的参数是curl_init()函数返回的句柄。
curl_close()函数的作用是关闭一个curl会话,唯一的参数是curl_init()函数返回的句柄。
---------------------------------------------相关阅读--------------------------------------------------------
我粗略列举6种PHP业内、国际各大开源系统获取用户真实IP的案例(包括Magento Zencart Zend Framework Yii...国内的就不提了吧!通杀!):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
function
GetIP(){
if
(!
empty
(
$_SERVER
[
"HTTP_CLIENT_IP"
])){
$cip
=
$_SERVER
[
"HTTP_CLIENT_IP"
];
}
elseif
(!
empty
(
$_SERVER
[
"HTTP_X_FORWARDED_FOR"
])){
$cip
=
$_SERVER
[
"HTTP_X_FORWARDED_FOR"
];
}
elseif
(!
empty
(
$_SERVER
[
"REMOTE_ADDR"
])){
$cip
=
$_SERVER
[
"REMOTE_ADDR"
];
}
else
{
$cip
=
"无法获取!"
;
}
return
$cip
;
}
echo
GetIP();
?>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
error_reporting
(E_ERROR | E_WARNING | E_PARSE);
if
(
$HTTP_SERVER_VARS
[
"HTTP_X_FORWARDED_FOR"
]){
$ip
=
$HTTP_SERVER_VARS
[
"HTTP_X_FORWARDED_FOR"
];
}
elseif
(
$HTTP_SERVER_VARS
[
"HTTP_CLIENT_IP"
]){
$ip
=
$HTTP_SERVER_VARS
[
"HTTP_CLIENT_IP"
];
}
elseif
(
$HTTP_SERVER_VARS
[
"REMOTE_ADDR"
]){
$ip
=
$HTTP_SERVER_VARS
[
"REMOTE_ADDR"
];
}
elseif
(
getenv
(
"HTTP_X_FORWARDED_FOR"
)){
$ip
=
getenv
(
"HTTP_X_FORWARDED_FOR"
);
}
elseif
(
getenv
(
"HTTP_CLIENT_IP"
)){
$ip
=
getenv
(
"HTTP_CLIENT_IP"
);
}
elseif
(
getenv
(
"REMOTE_ADDR"
)){
$ip
=
getenv
(
"REMOTE_ADDR"
);
}
else
{
$ip
=
"Unknown"
;
}
echo
$ip
;
?>
|
1
2
3
4
|
$iipp
=
$_SERVER
[
"REMOTE_ADDR"
];
echo
$iipp
;
?>
|
1
2
3
4
5
|
$user_IP
= (
$_SERVER
[
"HTTP_VIA"
]) ?
$_SERVER
[
"HTTP_X_FORWARDED_FOR"
] :
$_SERVER
[
"REMOTE_ADDR"
];
$user_IP
= (
$user_IP
) ?
$user_IP
:
$_SERVER
[
"REMOTE_ADDR"
];
echo
$user_IP
?>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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
(!
eregi
(
"^(10|172\.16|192\.168)\."
,
$ips
[
$i
])){
$ip
=
$ips
[
$i
];
break
;
}
}
}
return
(
$ip
?
$ip
:
$_SERVER
[
'REMOTE_ADDR'
]);
}
echo
get_real_ip();
?>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
if
(
getenv
(
'HTTP_CLIENT_IP'
)){
$onlineip
=
getenv
(
'HTTP_CLIENT_IP'
);
}
elseif
(
getenv
(
'HTTP_X_FORWARDED_FOR'
)){
$onlineip
=
getenv
(
'HTTP_X_FORWARDED_FOR'
);
}
elseif
(
getenv
(
'REMOTE_ADDR'
)){
$onlineip
=
getenv
(
'REMOTE_ADDR'
);
}
else
{
$onlineip
=
$HTTP_SERVER_VARS
[
'REMOTE_ADDR'
];
}
echo
$onlineip
;
?>
|
客官看完了业界常用的获取用户真实IP方法后,发现有个共同规律,主要核心就是
不同的演变,只是代码兼容性罢了!
问:如果可以伪造模拟HTTP_CLIENT_IP,伪造模拟HTTP_X_FORWARDED_FOR,伪造模拟REMOTE_ADDR,不就可以达到追踪不到用户真实IP的目的了么?
答:楼上理解完全正确!如果做到这样完全可以通杀99%的获取用户真实IP,以用户IP为标识的系统!
支招【LET采集技巧】(curl、socket、fsocketopen、stream_socket_client):
1
2
3
|
curl_setopt(
$curl
, CURLOPT_HTTPHEADER,
array
(
'Client_Ip: '
.mt_rand(0, 255).
'.'
.mt_rand(0, 255).
'.'
.mt_rand(0, 255).
'.'
.mt_rand(0, 255),
));
//优点:伪造成本低,通杀90%系统
|
1
2
3
|
curl_setopt(
$curl
, CURLOPT_HTTPHEADER,
array
(
'X-Forwarded-For: '
.mt_rand(0, 255).
'.'
.mt_rand(0, 255).
'.'
.mt_rand(0, 255).
'.'
.mt_rand(0, 255),
));
//优点:伪造成本低,通杀90%系统
|
1
2
3
|
curl_setopt(
$curl
, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curl_setopt(
$curl
, CURLOPT_PROXY,
'1.1.1.1:8080'
);
//自行百度获得普匿代理IP即可,高匿代理IP更佳!
//优点:通杀100%系统
|