对于一个web程序来说,每天会提供给网路上的很多用户访问,那么有一些有心的站长或者企业级的web用户都会记录一下client-ip,这样做是多方面的,首先是为了追踪访问,再者是安全问题。
在php程式下面,我想很容易做到,使用一个全局变量即可,$_SERVER[‘REMOTE_ADDE’],这个变量会打印出来client的IP。Okay,从理论上来说,这一点错都没有,可是如果我是一个使用proxy(代理)上网或者负载均衡访问web数据的用户呢。这个IP得到的是谁的IP呢?这个ip代理的IP。那这里就要来和大家解释一下,我们在使用代理(一级代理的情况下)上网的时候,首先客户端会和代理连接,之后代理再和请求服务器连接,也就是说请求服务器看到的是代理的IP,而不是客户端的。那如何正确得到客户端的IP呢。
首先我们来讲一个老生常谈的web问题,那就是HTTP的报文头,这个头就是我们常说的HEADER,在你请求一个网路资源的时候,我们会发送一个HTTP的header给服务器,服务器会根据你的header的相关选项来返回内容,当然包括响应的header。举例来说我可以在一个php文件顶部写入:
[php]header(‘Client-Ip:123.456.78.99’);
header(‘Referer:http://www.xiaotiejiang.com’);[/php]
这个就是告诉服务器我的客户端IP是多少,我的来路页面是哪一个喽。
对于其他的标准RFC2616定义的header的选项,大家可以去官网查看。那其实我们常常会使用发送虚假头部的方法去访问被屏蔽IP的网站,例如,
[php]$header[‘Client-IP’] = ‘123.23.65.42’;
$header[‘X-Forwarded-For’] = ‘345.56.65.63’;
$header[‘Host’] = ‘http://xiaotiejiang.com’;
$Head = array();
foreach($header as $key => $value){
$Head[] = $key.’:’.$value;
}
ob_start();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, ‘http://xiaotiejiang.com ‘);
curl_setopt($ch, CURLOPT_HEADER, $Head);
curl_setopt($ch, CURLOPT_REFERER, ‘http://xiaotiejiang.com’);
curl_exec($ch);
curl_close($ch);
$content = ob_get_contents();
echo $content;[/php]
其实这样的方法是不奏效的,在此不多说。
那现在我们提及一个很好的东西XFF,也就是X-Forwarded-For,可能很多同学都会有一些疑问,这个东东见的蛮少耶。哦,那就对了。这个也是header的一部分,但不是标准的。这个请求首部是由squid的开发人员提出来的。Squid大家都知道,是一个代理服务器和web缓存服务器。
那么这个首部的作用简言之就是会显示客户真是的IP,只有再使用了代理连接入网路的时候才能出现此变量$_SERVER[‘X-Forwarded-For’],这个http头的格式如下
[shell]X-Forwarded-For: client1, proxy1, proxy2[/shell]
其中最左边的是客户真实的IP,后面的都是代理的IP,其中最后一层经过的代理IP不会显示。那因此我们可以在在服务器端使用php来判断是否有$_SERVER[‘X-Forwarded-For’]这个变量来判断用户的真实IP。
那么我们可以通过配置apache的,让apache来记录这个XFF的信息,在httpd.conf中的log-format配置如下:
[shell]%{X-Forwarded-For}i[/shell]
这样在apache的日志中就会看到通过代理来访问web的客户。
如果server端使用了多级的反向代理,这个XFF的可信性就值得商榷了。在Nginx这个反向代理服务器中我们会和这个X-Forwarded-For有很多接触的。