php 如何取得反向代理的真实ip?

摘要:前端Nginx反向代理配置成功,参数传递正常。我后端用的是lighttpd,php程序获取IP用的是$_SERVER['REMOTE_ADDR'],所以取得的是反代服务器的IP,我知道可以改动php程序来实现,但现在php程序是加密的,因此我想问不改动php程序把X-REAL-IP或HTTP_X_FORWARDED_FOR赋值到REMOTE_ADDR或其他方法来实现,另外前后端为独立服务器,且前端服务器不提供php?...

作者:LoveCode标签:php,ip,真实ip

前端Nginx反向代理配置成功,参数传递正常。我后端用的是lighttpd,php程序获取IP用的 是$_SERVER['REMOTE_ADDR'],所以取得的是反代服务器的IP,我知道可以改动php程序来实现,但现在php程序是加密的,因此我 想问不改动php程序把X-REAL-IP或HTTP_X_FORWARDED_FOR赋值到REMOTE_ADDR或其他方法来实现,另外前后端为独立 服务器,且前端服务器不提供php?


下面的代码用于获得真实的客户端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;
}


需要做下简单解释:

一、没有使用代理服务器的PHP获取客户端IP情况
REMOTE_ADDR = 客户端IP
HTTP_X_FORWARDED_FOR = 没数值或不显示


二、使用透明代理服务器的情况:Transparent Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 客户端真实 IP (经过多个代理服务器时,这个值类似:221.5.252.160, 203.98.182.163, 203.129.72.215)
这类代理服务器还是将客户端真实的IP发送给了访问对象,无法达到隐藏真实身份的目的.


三、使用普通匿名代理服务器的PHP获取客户端IP情况:Anonymous Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_X_FORWARDED_FOR = 代理服务器 IP (经过多个代理服务器时,这个值类似:203.98.182.163, 203.98.182.163, 203.129.72.215)
这种情况下隐藏了客户端的真实IP,但是向访问对象透露了客户端是使用代理服务器访问它们的.


四、使用欺骗性代理服务器的情况:Distorting ProxiesREMOTE_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来欺骗它.


五、使用高匿名代理服务器的PHP获取客户端IP情况:High Anonymity Proxies (Elite proxies)
REMOTE_ADDR = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 没数值或不显示
无 论是REMOTE_ADDR还是HTTP_FORWARDED_FOR,这些头消息未必能够取得到,因为不同的浏览器不同的网络设备可能发送不同的IP头 消息.因此PHP使用$_SERVER["REMOTE_ADDR"] 、$_SERVER["HTTP_X_FORWARDED_FOR"] 获取的值可能是空值也可能是“unknown”值


封装好的函数:

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])) 
    {
        return $_SERVER[$proxy_header];
    }
    else if(stristr(',', $_SERVER[$proxy_header]) !== FALSE)
    {
      $proxy_header_temp = trim(array_shift(explode(',', $_SERVER[$proxy_header]))); 
      if(($pos_temp = stripos($proxy_header_temp, ':')) !== FALSE) $proxy_header_temp = substr($proxy_header_temp, 0, $pos_temp); 

      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'];
}
CopyRight © 2017 荒山本的官方网站 粤ICP备16049175号 All Right Service 网站地图(xml) 网站地图(html)