获取用户的真实ip

常见的坑有两个:php


 


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


2、获取的是攻击者伪造的ip地址。攻击者能够随便伪造一个头部信息,随便填写一个ip放到头部发过来,php获取到HTTP_CLIENT_IP就是这样一个状况。伪造的ip,致使咱们数据库存储是假的ip,无从真实去判断攻击者的来源。好比批量注册账号的注册ip,登陆的ip等。nginx


     为避免伪造,不要使用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")) {ip


           //在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地址。

相关文章
相关标签/搜索