linux 获取经过N层Nginx转发的访问来源真实IP

2017-09-11 11:30:09

通常系统出于安全考虑,需要进行权限(账号、密码)和IP白名单控制。如何获取访问来源真实的IP,如果公司网络入口设置负载,自己系统设置nginx代理等操作,会使你达到目的不那么简单直接。

通常情况下我们使用request.getRemoteAddr()就可以获取到客户端ip,但是当我们使用了nginx作为反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址。如果我们想要在web端获得用户的真实ip,就必须在nginx这里作一个赋值操作,如下:
proxy_set_header            X-real-ip $remote_addr;
其中这个X-real-ip是一个自定义的变量名,这样用户的真实ip就被放在X-real-ip这个变量里了,然后,在web端可以这样获取:request.getAttribute("X-real-ip")。但是如果中间经过N次代理过来的请求,X-real-ip就只能获得到前一层代理的IP(10.6.61.14)了,下面是我的解决方案:



红色部分IP是使用X-Forwarded-For(简称XFF头)获取的:,它代表客户端,也就是HTTP的请求端真实的IP,只有在通过了HTTP 代理或者负载均衡服务器时才会添加该项(没有经过的获取为空)标准格式如下:
X-Forwarded-For: client1, proxy1, proxy2
从标准格式可以看出,X-Forwarded-For头信息可以有多个,中间用逗号分隔,第一项为真实的客户端ip,剩下的就是曾经经过的代理或负载均衡的ip地址,经过几个就会出现几个。
我的Nginx具体配置如下:


关于参数含义:
proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
意思是增加(不是覆盖一个$proxy_add_x_forwarded_for到X-Forwarded-For里去。
举个例子,有一个web应用,在它之前通过了两个nginx转发。在第一台nginx中,使用
proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
现在的$proxy_add_x_forwarded_for变量的"X-Forwarded-For"部分是空的,所以只有$remote_addr,而$remote_addr的值是用户的ip,于是赋值以后,X-Forwarded-For变量的值就是用户的真实的ip地址了。
到了第二台nginx,使用
proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;
现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了“用户的真实ip,第一台nginx的ip”。

所以我在程序中使用request.getHeader("x-forwarded-for").toString().split(",")[0]就能获取到访问客户的真实IP,不用担心前面有几层转发啦。



  • 2019-09-26 21:48:15

    解决UEditor超出最大字数后只提示不限制的问题

    最近项目用到百度额UEditor文本编辑器,今天测试向我提出了一个问题。就是在输入的文字超过默认的最大字数限制之后,虽然提示“字数超过最大范围,服务器可能拒绝保存”,但是仍然可以点击保存按钮进行保存。

  • 2019-09-27 14:49:33

    Google Guava介绍和体检

    JDK提供的String还不够好么?也许还不够友好,至少让我们用起来还不够爽,还得操心!举个栗子,比如String提供的split方法,我们得关心空字符串吧,还得考虑返回的结果中存在null元素吧,只提供了前后trim的方法(如果我想对中间元素进行trim呢)。

  • 2019-09-28 00:03:21

    shiro的session共享,持久化

     shiro的session创建与session的查询、更新、过期、删除中,shiro对session的操作基本都讲到了,但还缺一个session共享没有讲解;session共享的原理其实在自定义session管理一文已经讲过了,本文不讲原理,只看看shiro的session共享的实现。

  • 2019-09-28 08:00:30

    Java.io.tmpdir介绍

    System.getproperty(“java.io.tmpdir”)是获取操作系统缓存的临时目录,不同操作系统的缓存临时目录不一样,