在平时我们开发后端程序的过程中,应该多多少少都会碰到记录客户端 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. oh-my-zsh 安装及使用

    什么是 oh-my-zsh oh-my-zsh 是基于 zsh 的功能做了一个扩展,方便的插件管理.主题自定义,以及漂亮的自动完成效果. oh-my-zsh 安装及插件安装 查看系统中 zsh 及版本 ...

  2. “全栈2019”Java多线程第二十四章:等待唤醒机制详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  3. 根据已有的Jar包 一键生成对应的mavenpom.xml信息

    根据已有的jar包信息一键生成对应的maven坐标信息 .想一个问题 假如 我有一个SSH的项目, jar包是配置在lib中, 我现在想把它做成maven格式的SSH项目  ,那么这些jar包在mav ...

  4. Python 将一个列表里面的元素拼接成一个字符串

    item1 = ["lowman", "isbusy"] item2 = ",".join(item1) # 根据实际需要使用相应的分隔符连 ...

  5. Good Bye 2017 C. New Year and Curling

    Carol is currently curling. She has n disks each with radius r on the 2D plane. Initially she has al ...

  6. AndroidManifest.xml文件安全探索

    本文作者:i春秋签约作家——icq8756c1a2 最近在做一些apk的安全检测,对AndroidManifest.xml文件进行了研究和探讨,介绍AndroidManifest.xml文件的作用和架 ...

  7. Apache Log4j配置说明

    1.Log4j简介 Log4j是Apache的一个开源项目,它允许开发者以任意间隔输出日志信息.Log4j主要由三大类组件构成: 1)Logger-负责输出日志信息,并能够对日志信息进行分类筛选,即决 ...

  8. fluentd 推送 mariadb audit log

    说明: mariadb audit log是 mariadb 的审计日志 目的是把日志拆分成 tab 键分隔的字段 直接附上 fluentd 配置文件 <system> log_level ...

  9. hexo安装总结

    博客原文地址:Claiyre的个人博客 如需转载,请在文章开头注明原文地址 hexo真心是一个不错的东西呢,安装简单(然而对博主来说并不是这样,伤心脸),主题样式简洁优雅,还有多种选择. 流程如下 安 ...

  10. yii2之前端资源引入

     PS:因新项目后端使用yii2框架,不在使用纯html模板的方式搭建页面(前后端不分离模式)使用yii2的内置boostart封装模板,遂研究了一番yii2 通过yii2官方下载的基础文件结构 其中 ...