常见的坑有两个:

一、获取的是内网的ip地址。在nginx作为反向代理层的架构中,转发请求到php,java等应用容器上。结果php获取的是nginx代理服务器的ip,表现为一个内网的地址。php获取REMOTE_ADDR就是这样一个情况(内网地址)。

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

为避免伪造,不要使用discuz原来的获取ip函数,里面的判断优先级会使得攻击者容易伪造ip。

php代码:

function getIP() {

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");

} else {

$ip = "unknown";

}

return $ip;

}

说明

在反向代理架构中,不能通过REMOTE_ADDR来获取用户的真实ip!

以前的理解方式有误(更新一下)

一般的方式是这样:

nginx>>(fastcgi方式)>>php引擎

nginx把REMOTE_ADDR传递给了php。代表的是当前与nginx通信的客户端ip,一般情况下(非反向代理),这个客户就是用户的浏览器,所以得到的用户的ip。

假设做了反向代理架构,是下面这样子的:


户>>>>>>>>>>>服务器
a>>>>>>>>>>>>>>>>>>nginx>>>>>>>>>>>>>>
(fastcgi方式通信)>>>>>>>>>>>>php引擎

用户访问一个域名,实际上是通过服务器a做了转发,转发到nginx去(反向代理架构经常会这样部署)

于是,当前与nginx通信的客户端,就是服务器a的地址, REMOTE_ADDR就是a服务器的地址了。

如何判断:nginx的上一层是不是还有一层。像上面的情况就还有一层。所以得到的将会是服务器a的地址。

总结:在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地址。

获取用户的真实ip的更多相关文章

  1. PHP获取用户的真实IP地址

    本文出至:新太潮流网络博客 PHP获取用户的真实IP地址,非代理IP function getClientIP(){ global $ip; if(getenv("HTTP_CLIENT_I ...

  2. 深入nginx之《获取用户的真实IP》

    获取用户的真实IP Nginx会将客户端的IP信息存放在$remote_addr变量里,但这并不意味着它就是客户端的IP,生产环境往往会充满各种代理,让IP的来龙去脉变得扑朔迷离. 目前互联网公司基本 ...

  3. 在PHP中如何获取用户的真实IP

    /** * 获得用户的真实IP地址 * * @access public * @return string */ function real_ip() { static $realip = NULL; ...

  4. Nginx 反向代理时获取用户的真实 IP

    在平时我们开发后端程序的过程中,应该多多少少都会碰到记录客户端 IP 的场景,例如我之前写过的 APP 用户的一个审计功能,就需要获取用户的 IP 地址:还有广告系统里面,也是需要获取用户的 IP 地 ...

  5. 如何获取用户的真实IP

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的.但是在通过了 Apache,Nagix等反向代理软件就不能获取到客户端的真实 ...

  6. 怎么使用PHP获取用户客户端真实IP的解决方案呢?

    function getIp(){if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIE ...

  7. PHP获取用户客户端真实IP的解决方案是怎样呢?

    function getIp(){if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIE ...

  8. PHP获取用户的真实IP地址,非代理IP

    function getClientIP(){ global $ip; if(getenv("HTTP_CLIENT_IP")){ $ip = getenv("HTTP_ ...

  9. F5后端nginx+tomcat应用如何获得用户的真实ip【转】

    根据业务需要要求记录每个通过wap或者客户端访问我们服务器的用户真实ip但是由于业务前端部署了两个3900系列的F5设备导致程序一直获得F5设备自身的ip,所以笔者考虑可能是因为F5导致无法获得用户的 ...

随机推荐

  1. java-cef系列视频第一集:从官方代码编译

    本视频介绍了如何从官方给出步骤编译java-cef代码,生成可运行可移植的发行版. 值得一提的是:截至2016-09-24java-cef代码编译方式有所改变,读者请自行查看bitbucket上关于编 ...

  2. __new__ 的简单应用

    用__new__与__init__不同,通过继承内建类型对象,__new__可以用来创建一个简单的新类型,在__new__加入一些动作以完成创建. class RoundFloat(float): d ...

  3. 写出几种IE6 BUG的解决方法

    1.双边距BUG float引起的  使用display:inline 2.3像素问题 使用多个float和注释引起的 使用dislpay:inline -3px   3.超链接hover 点击后失效 ...

  4. .NET 相关工具

    加密工具,反DUMP,反调试,反编译,加密代码资源内容,混淆流程,变量.Confuser is a protector/obfuscator for .NET, providing great sec ...

  5. Android 优化布局层次结构

    前面介绍过使用HierarchyViewer和Android lint来优化我们的程序,这一篇算是总结性的,借助一个小例子来说用怎么优化应用布局.这个例子是android官网给出的,作者也当一把翻译. ...

  6. linux ckconfig

    linux自定义开机启动服务和chkconfig使用方法 linux自定义开机启动服务和chkconfig使用方法 1. 服务概述在linux操作系统下,经常需要创建一些服务,这些服务被做成shell ...

  7. AppCompat Toolbar控件去掉阴影设置高度

    For Android 5.0, if you want to set it directly into a style use: <item name="android:elevat ...

  8. 【翻译】VSM 和触发器

    原文:The VisualStateManager and Triggers Author:Carole Snyder Silverlight 推出了可视化状态管理器( Visual State Ma ...

  9. Visual Studio 2010 简体中文旗舰、专业版(MSDN原版下载)

    Visual Studio 2010 简体中文旗舰.专业版(MSDN原版下载)(Visual Studio 2010 ultimate professional x86 dvd)2010[光盘镜像]- ...

  10. Asp.net Mvc4 基于Authorize实现的模块权限验证方式

    在MVC中,我们可以通过在action或者controller上设置Authorize[Role="xxx"] 的方式来设置用户对action的访问权限.显然,这样并不能满足我们的 ...