【发布时间】:2011-07-22 05:24:02
【问题描述】:
我确实可以跟踪用户的“真实”IP,如果他有一个发送真实 IP 标头的代理...有没有更好的解决方案,甚至更多的标头?
由于这个函数在脚本中经常使用,它必须非常快,而且它似乎不在那个星座中:/
我提出了一些建议,但无法实现:
- 把标题按顺序排列,什么是最“野外”使用的,以便函数快速完成
- 让 IP 的 pre_match 检测更快
===
function get_real_ip()
{
$proxy_headers = array(
'CLIENT_IP',
'FORWARDED',
'FORWARDED_FOR',
'FORWARDED_FOR_IP',
'HTTP_CLIENT_IP',
'HTTP_FORWARDED',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED_FOR_IP',
'HTTP_PC_REMOTE_ADDR',
'HTTP_PROXY_CONNECTION',
'HTTP_VIA',
'HTTP_X_FORWARDED',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED_FOR_IP',
'HTTP_X_IMFORWARDS',
'HTTP_XROXY_CONNECTION',
'VIA',
'X_FORWARDED',
'X_FORWARDED_FOR'
);
foreach($proxy_headers as $proxy_header)
{
if(isset($_SERVER[$proxy_header]) && preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $_SERVER[$proxy_header])) /* HEADER ist gesetzt und dies ist eine gültige IP */
{
return $_SERVER[$proxy_header];
}
else if(stristr(',', $_SERVER[$proxy_header]) !== FALSE) /* Behandle mehrere IPs in einer Anfrage(z.B.: X-Forwarded-For: client1, proxy1, proxy2) */
{
$proxy_header_temp = trim(array_shift(explode(',', $_SERVER[$proxy_header]))); /* Teile in einzelne IPs, gib die letzte zurück und entferne Leerzeichen */
if(($pos_temp = stripos($proxy_header_temp, ':')) !== FALSE) $proxy_header_temp = substr($proxy_header_temp, 0, $pos_temp); /* Entferne den Port */
if(preg_match("/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/", $proxy_header_temp) return $proxy_header_temp;
}
}
return $_SERVER['REMOTE_ADDR'];
}
【问题讨论】:
-
ereg已弃用。除此之外..您始终需要存储真实 ip 和“代理”ip,因为用户可以简单地自己添加这些标头。 -
谢谢,用(可能更快的)preg_match 替换了 ereg 并添加了一个部分来检测,如果字段中有更多 IP,例如:en.wikipedia.org/wiki/X-Forwarded-For
-
我的真实IP是
192.168.0.81。我很好奇它有什么用吗? -
“在脚本中经常使用”是什么意思?在脚本运行时是否有理由多次运行它?
-
如果字段中有更多 IP,你会选择什么“IP”?为什么?