在平时我们开发后端程序的过程中,应该多多少少都会碰到记录客户端 IP 的场景,例如我之前写过的 APP 用户的一个审计功能,就需要获取用户的 IP 地址;还有广告系统里面,也是需要获取用户的 IP 地址,有时这个 IP 地址会被用来标识用户的,因此需要比较准确得获取到用户的地址。当然,在开始本文的内容之前还是有必要强调一下我们现在的网络大环境的,在使用 IP 的时候,我们一定要记住有两个东西很关键,一个是网关,一个是代理。

网关其实好理解,说简单一些的就路由器吧,因为 IPv4 的地址空间是有限的,所以就有了局域网共用一个公网 IP 的事实。这在一个集体里面很容易出现,例如家庭、学校,如果我们不加分辨得直接就使用 IP 来记录或者屏蔽,那么很容易出问题,如果将这个问题再扩大化一点,那就是移动端,因为我们知道移动端都是通过连接信号塔进行数据通信的,那么对于一个范围内的同一运营商来说,IP 地址就很可能是一样的,这是移动开发中一个很关键的点;还有就是代理,很多公司对于网络都是封锁得很严厉的,所以所有的对外流量都通过一个代理交流,这也就导致了很多情况下都是同一个代理出来的都是一个 IP,这也是一个非常重要的问题,很容易一棍子打死一船人。

OK,闲话扯完了,回到主题,在后端程序中,一般客户端/前端的流量都不会直接就打到后端的应用上,正常最少都会加一层反向代理,稍复杂一些的还会有负载均衡啥的,这也给我们提取客户端 IP 带来了很大的麻烦,所以我这里就以 Nginx 为例,说说如何更好得获取正确的 IP 值。

下面下来一段我用了好多年的 Nginx 配置,夸张点说就祖传的吧:

这里会出现了好几个和 IP 有关的字段,这也是获取 IP 的关键,对于这些字段如果我们细致得了解了它的来源和原理之后,那么获取相对准确的 IP 也就没那么困难了,下面就一一进行介绍:

Remote Addr

remote_addr 这个字段不是 http 里面的概念,其实是 tcp 的概念,表示的是当前连接的对端的地址,也就是说:

  • 如果在浏览器和 Nginx 之间不存在其他代理,那么这个字段就是真实的 IP
  • 但是,一旦浏览器和 Nginx 之间存在代理,那么这个字段的值就是最后一个代理的地址

X-Real-IP

正如配置中所示,HTTP 中其实不存在这个 Header,但是在 Nginx 中习惯于用来标识用户的真实地址,至于是否真的是客户端的地址,看前面的 remote_addr 的解释我们就清楚了。

X-Forwarded-For

这个就有意思了,X-Forwarded-For 表示在客户端访问 Nginx 的过程中如果需要经过 HTTP 代理或者负载均衡服务器,可以被用来获取最初发起请求的客户端的 IP 地址,这个消息首部成为事实上的标准。怎么说,其实就是一个 HTTP 请求从浏览器发出,每经过一个 HTTP 代理或者负载均衡,都会在这个 Header 里面添加一条记录(当然,这是规定,你不遵守我也没办法),所以对于一个请求来说,X-Forwarded-For Header 的值列表里面的第一个值应该就是客户端的地址,及时经过了 N 多的代理和负载均衡。

但是,这毕竟不是真正的标准,所以我们不能期望 100% 一定有这个,但是根据我的经验,对于一些比较成熟的反向代理软件 例如 Nginx/Squid 都是有的,所以大多数情况下都可以通过这个字段获取到真实值。

X-Forwarded-Host

好吧,这个 Header 是乱入的,它和客户端的 IP 没啥关系,它其实是标识客户端发起请求时的 Host 的地址,我们可以通过这个 Header 来获取客户端是访问的哪个 Host 进来的。

结论

所以通过上面的介绍,我们知道,其实就只有两个东西,分别是 remote_addrX-Forwarded-For,如果中间存在不可控的代理,那么我们应该优先通过 X-Forwarded-For 的第一个值来获取客户端真实 IP;如果中间的代理都是可控的,那么我们优先通过 remote_addr 来获取客户端真实的 IP,而且这个 IP 是不可伪造的。

Nginx 反向代理时获取用户的真实 IP的更多相关文章

  1. nginx做反向代理时获取真实IP

    原文:http://blog.csdn.net/aquester/article/details/48657395 1. 编译 对于client -> nginx reverse proxy - ...

  2. JAVA获取客户端请求的当前网络ip地址(附:Nginx反向代理后获取客户端请求的真实IP)

    1. JAVA获取客户端请求的当前网络ip地址: /** * 获取客户端请求的当前网络ip * @param request * @return */ public static String get ...

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

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

  4. nginx 反向代理时丢失端口的解决方案

        今天,配置nginx反向代理时遇到一个问题,当设置nginx监听80端口时转发请求没有问题.但一旦设置为监听其他端口,就一直跳转不正常:如,访问欢迎页面时应该是重定向到登录页面,在这个重定向的 ...

  5. nginx 反向代理时丢失端口的解决方案(转)

    今天,配置nginx反向代理时遇到一个问题,当设置nginx监听80端口时转发请求没有问题.但一旦设置为监听其他端口,就一直跳转不正常:如,访问欢迎页面时应该是重定向到登录页面,在这个重定向的过程中端 ...

  6. 获取用户的真实ip

    常见的坑有两个: 一.获取的是内网的ip地址.在nginx作为反向代理层的架构中,转发请求到php,java等应用容器上.结果php获取的是nginx代理服务器的ip,表现为一个内网的地址.php获取 ...

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

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

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

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

  9. 使用nginx反向代理时,如何正确获取到用户的真实ip

    在记录日志的的时候,获取用户的信息,比如用户的ip,浏览器等等信息是十分重要的. 但是在使用nginx反向代理的时候,可能经过转发无法获取到用户的真实的ip, 在此情况下需要配置nginx,让其在转发 ...

随机推荐

  1. jQuery基础笔记 each和data(7)

    day56 参考:https://www.cnblogs.com/liwenzhou/p/8178806.html#autoid-1-11-0 each jQuery.each(collection, ...

  2. javascript中创建对象的几种不同方法

    javascript中创建对象的几种不同方法 方法一:最直白的方式:字面量模式创建 <script> var person={ name:"小明", age:20, s ...

  3. java API连接虚拟机上的hbase

    今天用本地的eclipse连接虚拟机上的hbase数据库,代码如下: public static void main(String[] args) throws Exception{ Configur ...

  4. LruCache源码分析

    LRU(Least Recently Used)是一种很常用的资源调度策略,与20/80原则契合,在资源达到上限时倾向保留最近经常访问的资源对象. Android中基于LRU实现了缓存对象,即LruC ...

  5. 【数组】Next Permutation

    题目: Implement next permutation, which rearranges numbers into the lexicographically next greater per ...

  6. 利用ggplot2画出各种漂亮图片详细教程

    1.Why use ggplot2 ggplot2是我见过最human friendly的画图软件,这得益于Leland Wilkinson在他的著作<The Grammar of Graphi ...

  7. Pelican+Github博客搭建详细教程

    操作系统:Mac OS / Linux 工具集: 1.Pelican--基于Python的静态网页生成器 2.马克飞象--Evernote出的Markdown文本编辑器 3.GoDaddy--域名供应 ...

  8. Android JNI初体验

    欢迎转载,转载请注明出处:http://www.cnblogs.com/lanrenxinxin/p/4696991.html 开始接触Android JNI层面的内容,推荐一本不错的入门级的书< ...

  9. springMVC实现json

    很多时候前端都需要调用后台服务实现交互功能,常见的数据交换格式多是JSON或XML,这里主要讲解Spring MVC为前端提供JSON格式的数据并实现与前台交互. 一.概要 JSON(JavaScri ...

  10. 关于js的 for...in 你了解多少

    For...In 声明用于对数组或者对象的属性进行循环/迭代操作. 1. 求value: 对于数组 ,迭代出来的是数组元素,对于对象,迭代出来的是对象的属性值: 1)数组示例 var x var my ...