Nginx获取真实ip之X-Forwarded-For

Nginx获取真实ip之X-Forwarded-For

前言

生产环境下使用nginx时最常见的基础架构就是nginx反向代理了,他的原理是这样的:”当客户端发起请求时,此时代理服务器来接收客户端的请求,然后根据代理服务器的location规则进行匹配,将请求转给对应的后端服务器,后端服务器收到了代理服务器的请求后,将数据发给代理服务器,然后代理服务器再将取到的内容返回给客户端,而在客户端看来,整个过程都是透明化的.”  那么由反向代理引出的问题是此时后端服务器上日志上记载的远程ip已然不是客户端的真实ip了.取而代之的是nginx反向代理服务器的Ip,那么如何让后端服务器获取到真正的客户端ip呢? X-Forwrded-For就是用来干这个,下面我和大家一起来学习.

什么是remote_addr

remote_addr代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的(可以理解就近原则)当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问这个代理,然后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP。

什么是X-Forwarded-For

X-Forwarded-For 是一个 HTTP 扩展头部。HTTP/1.1(RFC 2616)协议并没有对它的定义,它最开始是由 Squid 这个缓存代理软件引入,用来表示 HTTP 请求端真实 IP。如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。

X-Forwarded-For的原理

当你使用了代理时,web服务器就不知道你的真实IP了,为了避免这个情况,代理服务器通常会增加一个叫做X-Forwarded-For的头信息,把连接它的客户端IP(即你的上网机器IP)加到这个头信息里,这样就能保证网站的web服务器能获取到真实IP

原理: 这个x-forwarded-for是在代理服务器上配置,因为只有他才有机会和客户端ip直接建立连接,然后记录这个ip到x-forwarded-for 头信息.

如何配置?

1. 由于Nginx是代理服务器,所有客户端请求都从Nginx转发到Tomcat,如果Nginx不把客户端真实IP、域名、协议、端口告诉Tomcat,那么Tomcat应用是永远不会知道这些信息的,所以需要Nginx配置一些HTTP Header来将这些信息告诉被代理的Tomcat; 
2. Tomcat这一端,不能按照默认的获取直接和它连接的客户端(也就是Nginx代理)的信息,而是要从Nginx传递过来的HTTP Header中获取客户端信息

综上,我们需要既在nginx代理服务器上配置,也需要在后端真实服务器去引用新的配置.

  • proxy_set_header X-Forwarded-For $remote_addr;

#他代表的意思只记载代理服务器的ip地址,丢失了客户端真实ip和任意中间代理ip

  • proxy_set_header X-Forwarded-For “$httpd_x_forwarded_for,$remote_addr”;

#如上配置既记录了代理服务器ip 又记录了真实ip

  • proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;

#$proxy_add_x_forwarded_for 可以实现第二中种功能, 他是第二中的内置变量的结合,一般推荐直接引用该变量进行配置.

完整配置如下:

  • 情形一: nginx代理+后端tomcat

Nginx代理服务器配置:

proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;

后端Tomcat服务器配置:

在server.xml中的host元素加入即可

<Valve className=”org.apache.catalina.valves.RemoteIpValve” />

  • 情形二:nginx代理+后端nginx

Nginx代理服务器配置不变,后端nginx需要修改http字段中的log_format信息(也可以新增加一个log_format 名为wangtingwei)

log_format wangtingwei  ‘$remote_addr $remote_user [$time_local] “$request” ‘
‘$status $body_bytes_sent “$http_referer” ‘
‘$http_user_agent $http_x_forwarded_for $request_time $upstream_response_time $upstream_addr $upstream_status’;

然后在定义日志的时候指定引用名为wangtingwei的日志格式

默认是:   access_log    logs/wp_access.log  main;

修改为 :access_log    logs/wp_access.log wangtingwei;

蓝色标记为引用哪个日志格式.

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Loading...