nginx反向代理后,在应用中取得的ip都是反向代理服务器的ip,取得的域名也是反向代理配置的url的域名,解决该问题,需要在nginx反向代理配置中添加一些配置信息,目的将客户端的真实ip和域名传递到应用程序中。

①:php获取REMOTE_ADDR就是这样一个情况(内网地址)。

②:获取的是攻击者伪造的ip地址。攻击者可以随便伪造一个头部信息,随便填写一个ip放到头部发过来,php获取到HTTP_CLIENT_IP就是这样一个情况。伪造的ip,导致我们数据库存储是假的ip,无从真实去判断攻击者的来源。比如批量注册帐号的注册ip,登录的ip等。

配置如下:

location ~* \.(jpg|png|gif)$ {
proxy_set_header X-Forwarded-For $remote_addr;
#proxy_pass http://....
}
location ~ \.php$ {
proxy_set_header X-Forwarded-For $remote_addr;
#proxy_pass http://....
}

PHP代码:

function getIP() {
$ip = "unknown";
if (getenv("HTTP_X_FORWARDED_FOR")) {
//这个提到最前面,作为优先级,nginx代理会获取到用户真实ip,发在这个环境变量上,必须要nginx配置这个环境变量HTTP_X_FORWARDED_FOR
$ip = getenv("HTTP_X_FORWARDED_FOR");
} else if (getenv("REMOTE_ADDR")) {
//在nginx作为反向代理的架构中,使用REMOTE_ADDR拿到的将会是反向代理的的ip,即拿到是nginx服务器的ip地址。往往表现是一个内网ip。
$ip = getenv("REMOTE_ADDR");
} else if ($_SERVER['REMOTE_ADDR']) {
$ip = $_SERVER['REMOTE_ADDR'];
} else if (getenv("HTTP_CLIENT_IP")) {
//HTTP_CLIENT_IP攻击者可以伪造一个这样的头部信息,导致获取的是攻击者随意设置的ip地址。
$ip = getenv("HTTP_CLIENT_IP");
}
return $ip;
}

总结

在nginx作为反向代理的架构中,php的REMOTE_ADDR(其他语言也是类似的名称)拿到的将会是nginx代理的ip地址。拿不到用户的真实ip,拿到是nginx反向代理服务器地址。

REMOTE_ADDR本意就是远程的地址,nginx是代理层,转发请求到php,php获取到的远程地址实际上是nginx反向代理服务器ip,这是符合协议规则的。

但是,可以让nginx帮助我们拿到用户的真实ip,写到一个环境变量中,然后转发给我们,只要按照某个约定的名称即可,比如约定名称为HTTP_X_FORWARD_FOR(也可以约定其他名称,关键看nginx中配置,可以全公司考虑统一)。

nginx配置类似于这样:

fastcgi_param  HTTP_X_FORWARD_FOR  $remote_addr;

上一句的目的是,将HTTP_X_FORWARD_FOR的值设置为$remote_addr的值。也就是将用户真实的ip(或用户使用代理的ip)放到HTTP_X_FORWARD_FOR中去。

$remote_addr是nginx的内置变量,这个变量它得到是用户真实的ip地址(用户使用了代理,则就是代理的ip地址)。

于是在php端通过getenv("HTTP_X_FORWARDED_FOR")就可以获取到nginx传递过来的值,是用户真实的ip地址。

php获取用户IP地址的三个属性的区别

下面分析获得IP的几种情况。

一、没有使用代理服务器的情况:
REMOTE_ADDR = 您的 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示

二、使用透明代理服务器的情况:Transparent Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 您的真实 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
这类代理服务器还是将您的信息转发给您的访问对象,无法达到隐藏真实身份的目的。

三、使用普通匿名代理服务器的情况:Anonymous Proxies
REMOTE_ADDR = 最后一个代理服务器 IP
HTTP_VIA = 代理服务器 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_VIA = 代理服务器 IP
HTTP_X_FORWARDED_FOR = 随机的 IP ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
告诉了访问对象您使用了代理服务器,但编造了一个虚假的随机IP代替您的真实IP欺骗它。

五、使用高匿名代理服务器的情况:High Anonymity Proxies (Elite proxies)
REMOTE_ADDR = 代理服务器 IP
HTTP_VIA = 没数值或不显示
HTTP_X_FORWARDED_FOR = 没数值或不显示 ,经过多个代理服务器时,这个值类似如下:203.98.182.163, 203.98.182.163, 203.129.72.215。
完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象。

返回一个ip

public static function getIP() {
if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
$cip = $_SERVER["HTTP_CLIENT_IP"];
} else if (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$cip = $_SERVER["HTTP_X_FORWARDED_FOR"];
} else if (!empty($_SERVER["REMOTE_ADDR"])) {
$cip = $_SERVER["REMOTE_ADDR"];
} else {
$cip = '';
}
preg_match("/[\d\.]{7,15}/", $cip, $cips);
$cip = isset($cips[]) ? $cips[] : 'unknown';
unset($cips); return $cip;
}

最新文章

  1. ASP.NET MVC 的 WebGrid 的 6 个重要技巧 【已翻译100%】
  2. LeetCode 119 Pascal's Triangle II
  3. 怎么解决xp系统不能安装NET Framework4.0?
  4. js⑧
  5. Protobuf - 使用scons编译proto文件
  6. 【USACO 1.2】Name That Number
  7. LoadRunner关联之学习笔记
  8. RedHat5.1下安装Seismic Unix44R1
  9. B - Network - uva 315(求割点)
  10. 【Ruby on Rails学习二】在线学习资料的整理
  11. 如果让莎士比亚、海明威编写JavaScript代码
  12. [LeetCode290]Word Pattern
  13. 在centOS上搭建wordpress博客系统
  14. .net4.5中HttpClient使用注意点
  15. TP5 路由使用
  16. 使用kafka connect,将数据批量写到hdfs完整过程
  17. (二) V4L2引入(含浅析UVC)
  18. 第2章 Java并发机制的底层实现原理
  19. PHP 合并有序数组
  20. HTML5与相关类的扩充

热门文章

  1. 利用vanitygen生成比特币个性地址的教程
  2. 重温MFC
  3. 1.JavaScript 教程:基础语法
  4. Arrays.sort解析
  5. jsp页面取值
  6. 【转】DELL R710服务器可以安装的VMWare ESX Server 4.1 全套下载带注册码
  7. CSS<img>与<a href>字体同行显示方法与对齐
  8. python监控微信报警
  9. 使用localhost可以访问,但使用本地ip+端口号无法访问
  10. MySQL密码重置(root用户)