`

两种方式获得nginx真实地址

阅读更多

去年虽做过这方面的获取客户端的地址,但说得不够清楚,今天看到一篇有关xff的科普,讲得很清晰,就转过来了。

 

问题背景:

在实际应用中,我们可能需要获取用户的ip地址,比如做异地登陆的判断,或者统计ip访问次数等,通常情况下我们使用request.getRemoteAddr()就可以获取到客户端ip,但是当我们使用了nginx作为反向代理后,使用request.getRemoteAddr()获取到的就一直是nginx服务器的ip的地址,那这时应该怎么办? 

part1:解决方案

我在查阅资料时,有一本名叫《实战nginx》的书,作者张晏,这本书上有这么一段话“经过反向代理后,由于在客户端和web服务器之间增加了中间层,因此web服务器无法直接拿到客户端的ip,通过$remote_addr变量拿到的将是反向代理服务器的ip地址”。这句话的意思是说,当你使用了nginx反向服务器后,在web端使request.getRemoteAddr()(本质上就是获取$remote_addr),取得的是nginx的地址,即$remote_addr变量中封装的是nginx的地址,当然是没法获得用户的真实ip的,但是,nginx是可以获得用户的真实ip的,也就是说nginx使用$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")

这样就明白了吧。

part2:原理介绍

这里我们将nginx里的相关变量解释一下,通常我们会看到有这样一些配置

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. server {  
  2.         listen       88;  
  3.         server_name  localhost;  
  4.         #charset koi8-r;  
  5.         #access_log  logs/host.access.log  main;  
  6.         location / {  
  7.             root   html;  
  8.             index  index.html index.htm;  
  9.             proxy_pass                  http://backend;   
  10.             proxy_redirect              off;  
  11.             proxy_set_header            Host $host;  
  12.             proxy_set_header            X-real-ip $remote_addr;  
  13.             proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;  
  14. }  

 

我们来一条条的看

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. 1. proxy_set_header    X-real-ip $remote_addr;  

 

这句话之前已经解释过,有了这句就可以在web服务器端获得用户的真实ip。但是,实际上要获得用户的真实ip,不是只有这一个方法,下面我们继续看。 

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. 2.  proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;  

 

我们先看看这里有个X-Forwarded-For变量,这是一个squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,如果有做X-Forwarded-For设置的话,每次经过proxy转发都会有记录,格式就是client1, proxy1, proxy2,以逗号隔开各个地址,由于他是非rfc标准,所以默认是没有的,需要强制添加,在默认情况下经过proxy转发的请求,在后端看来远程地址都是proxy端的ip 。也就是说在默认情况下我们使用request.getAttribute("X-Forwarded-For")获取不到用户的ip,如果我们想要通过这个变量获得用户的ip,我们需要自己在nginx添加如下配置:

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;  

 

意思是增加一个$proxy_add_x_forwarded_for到X-Forwarded-For里去,注意是增加,而不是覆盖,当然由于默认的X-Forwarded-For值是空的,所以我们总感觉X-Forwarded-For的值就等于$proxy_add_x_forwarded_for的值,实际上当你搭建两台nginx在不同的ip上,并且都使用了这段配置,那你会发现在web服务器端通过request.getAttribute("X-Forwarded-For")获得的将会是客户端ip和第一台nginx的ip。 

那么$proxy_add_x_forwarded_for又是什么?

$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For"与$remote_addr两部分,他们之间用逗号分开。

举个例子,有一个web应用,在它之前通过了两个nginx转发,即用户访问该web通过两台nginx。

在第一台nginx中,使用

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. 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,使用

 

[cpp] view plaincopy在CODE上查看代码片派生到我的代码片
 
  1. 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”,这样就清楚了吧。 最后我们看到还有一个$http_x_forwarded_for变量,这个变量就是X-Forwarded-For,由于之前我们说了,默认的这个X-Forwarded-For是为空的,所以当我们直接使用proxy_set_header            X-Forwarded-For $http_x_forwarded_for时会发现,web服务器端使用request.getAttribute("X-Forwarded-For")获得的值是null。如果想要通过request.getAttribute("X-Forwarded-For")获得用户ip,就必须先使用proxy_set_header            X-Forwarded-For $proxy_add_x_forwarded_for;这样就可以获得用户真实ip。

转自:http://blog.csdn.net/kai_ding/article/details/39575255

分享到:
评论

相关推荐

    nginx实战-张晏

    1. Nginx安装与配置:介绍如何在Linux环境下安装Nginx,包括源码编译安装和使用包管理器安装两种方式。配置文件结构解析,讲解如何配置监听端口、日志记录、虚拟主机等基本设置。 2. Nginx工作原理:深入理解Nginx...

    java非常强的获取客户端真实IP的两种方法

    ### Java获取客户端真实IP的两种方法详解 #### 一、问题背景 在Web开发中,经常需要获取客户端的真实IP地址来进行一系列的操作,比如统计访问来源、进行地理定位、安全防护等。然而,在实际应用场景中,客户端请求...

    跟我学Nginx+Lua开发.pdf

    《跟我学Nginx+Lua开发》是一本针对Nginx与Lua结合使用的教程书籍,旨在帮助读者理解如何利用这两种技术进行高效且灵活的Web应用开发。Nginx作为一款广泛使用的高性能HTTP服务器和反向代理服务器,在处理高并发连接...

    nginx-0.9.2.zip

    Nginx 主要有两种工作模式:Master-Worker 模式和 Event 模式。 1. **Master-Worker 模式**:主进程(Master)负责管理和调度工作进程(Worker),工作进程则处理实际的网络连接和请求。这种模式保证了 Nginx 在...

    前端开发需要了解的Nginx知识1

    反向代理方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。...

    反向代理及Nginx示例.docx

    2. 节约了有限的 IP 地址资源,企业内所有的网站共享一个在 internet 中注册的 IP 地址,这些服务器分配私有地址,采用虚拟主机的方式对外提供服务; 3. 保护了真实的 web 服务器,web 服务器对外不可见,外网只能...

    基于Nginx的高校图书馆站群开源架构应用研究.docx

    - **增强安全性**:通过Nginx的反向代理功能屏蔽了后端服务器的真实IP地址,减少了直接攻击的风险。 - **提升可用性**:双机热备方案确保即使一台服务器出现故障,也能迅速切换至另一台,实现无缝服务。 - **优化...

    使用Nginx实现HTTPS双向验证的方法

    在HTTP的安全通信中,涉及了单向和双向两种不同的身份验证方式,本文将主要讨论如何使用Nginx实现HTTPS的双向验证,以及单向和双向验证的区别和相关知识。 单向验证指的是客户端验证服务器端证书的有效性,确保通信...

    nginx+vue.js实现前后端分离的示例代码

    Nginx在这里扮演了反向代理的角色,将请求转发给后端服务器,同时隐藏了真实的后端服务器信息,从而绕过跨域限制。 前端模板引擎和后端模板引擎的区别主要在于应用场景和性能需求。后端模板引擎适合在服务器端渲染...

    JSP 获取用户的真实IP两种实现方法详解

    以下是两种在JSP中获取真实IP地址的方法的详细说明: 方法一:使用X-Forwarded-For头信息 在多数情况下,真实客户端的IP地址会被包含在名为“X-Forwarded-For”的HTTP请求头中。这个头部由代理服务器在转发客户端...

    2021最新版运维面试题.pdf

    redis持久化有RDB和AOF两种方式。哨兵模式用于监控主服务器状态,并在故障时自动将从服务器提升为主服务器。 18. MongoDB相关知识点: MongoDB是一个基于分布式文件存储的开源NoSQL数据库,具有高性能、高可用性等...

    C# 获取IP及判断IP是否在区间

    通过这两种方法,开发者可以轻松地在应用程序中处理与IP相关的逻辑,例如限制访问权限、统计用户地理位置等。在实际开发中,还需要考虑边缘情况,比如IP地址的合法性验证、异常处理等,以确保代码的健壮性。

    translate-wechat-mini-program-master-百度翻译api实现微信翻译小程序.zip

    zh是中文,en是英文,很遗憾,这个url这可以播报中文和英文的语音,其他的小语种不可以这也是我的小程序只可以有中文和英文两种语言的语音的原因,第二个参数是text就是要播报的文本是什么效果图如下:...

    PHP秒杀系统 高并发高性能的极致挑战-

    这两种算法可以帮助我们有效地控制秒杀活动中的流量,防止系统因过载而崩溃。 #### 五、实战案例分析 在具体实现过程中,可以通过以下几个步骤来搭建一个简单的秒杀系统: 1. **环境准备**:搭建PHP运行环境,...

    高性能mysql

    MySQL以其高性能、高可靠性和易用性,在电子商务和互联网服务领域中得到了广泛应用。 一、MySQL的市场占有率 MySQL在全球范围内的安装数量超过了1100万次,日下载量超过五万次。据第三方市场调查机构Evans Data ...

    1000道 互联网Java工程师面试题 485页_PDF密码解除.pdf

    - **ZAB协议:**ZooKeeper的基本协议,分为两种模式:恢复模式和广播模式。 - **恢复模式:**用于在新领导人选举后重新同步状态。 - **广播模式:**用于正常状态下的数据更新。 **4. 四种类型的数据节点Znode** - ...

    javapms门户网站源码

    系统基于 Java语言开发,配合Tomcat、Nginx构建,数据库默认采用Mysql, 可在各种操作系统上平稳运行,采用 B/S 架构的管理方式,无论在什么地方,只要能上网就能轻松管理系统。 3.1. 硬件配置 CPU:Intel(R) Xeon ...

    MySQL Tomcat Apache优化

    Apache有两种主要的工作模式:`prefork`和`worker`。 - **prefork**模式适用于简单的静态内容服务,每个请求都会创建一个新的进程来处理。这种模式简单易用,但在处理大量并发请求时效率较低。 - **worker**模式...

Global site tag (gtag.js) - Google Analytics