博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
获取用户的真实ip
阅读量:4943 次
发布时间:2019-06-11

本文共 1980 字,大约阅读时间需要 6 分钟。

 

常见的坑有两个:

 

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

posted on
2016-03-04 11:31 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/ldms/p/5241457.html

你可能感兴趣的文章
SQL 将一个表中的所有记录插入到一个临时表中
查看>>
nmea协议
查看>>
js 中对象的特性
查看>>
hdoj3714【三分】
查看>>
嵌入式开发入门(4)—驱动入门之时序图分析【20121211修改,未完】
查看>>
Python 使用字符串
查看>>
Quartz Core之CALayer
查看>>
java:一个项目的开发过程(转)
查看>>
express框架学习笔记
查看>>
操作系统下载路径
查看>>
网站开发 关于图片压缩 以及图片使用
查看>>
hive的count(distinct id)测试--慎用
查看>>
第九周周总结
查看>>
Logistic Regression
查看>>
8lession-基础类型转化
查看>>
FlashCS5作成SWC,在Flex4中使用(1)
查看>>
vue-cli目录结构及说明
查看>>
JS 数据类型转换
查看>>
WeQuant交易策略—RSI
查看>>
osgearth将视点绑定到一个节点上
查看>>