• 获取用户的真实ip


    常见的坑有两个:

    一、获取的是内网的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地址。

  • 相关阅读:
    ORACLE 查看进程数,已执行任务数, 剩余任务数,删除指定任务
    ORACLE 收集统计整个用户数据
    解决Hystrix dashboard Turbine 一直 Loading…… 及其他坑
    利用 Maven 构造 Spring Cloud 微服务架构 模块使用 spring Boot构建
    AES加解密
    JAVA POI XSSFWorkbook导出扩展名为xlsx的Excel,附带weblogic 项目导出Excel文件错误的解决方案
    JAVA 文件的上传下载
    shell启停服务脚本模板
    JAVA 设计模式之 原型模式详解
    JAVA 设计模式之 工厂模式详解
  • 原文地址:https://www.cnblogs.com/wangtao_20/p/4582701.html
Copyright © 2020-2023  润新知