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

WP主题Bug提交 WP主题Bug提交 主题:1067 回复:2226

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

晚风撩人 发布于 2017-09-13 字数 332 浏览 1042 回复 3

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

支持 Markdown 语法,需要帮助?

评论(3

浮生未歇 2017-09-29 3 楼

给你个封装好的函数:

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'];
}

偏爱自由 2017-09-28 2 楼

我看过一本书。叫<nginx实战>作者是张宴。这里有提到过使用ngxin作为反向代理服务器获取用户真实ip。需要通过代理服务器header什么东东来获取。这里我也不记得了。当我没说。建议你看下这本书。在负载均衡这一章。

想挽留 2017-09-23 1 楼

下面的代码用于获得真实的客户端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 Proxies
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来欺骗它.
五、使用高匿名代理服务器的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”值.