$remote_addr

代表客户端IP。注意,这里的客户端指的是直接请求Nginx的客户端,非间接请求的客户端。假设用户请求过程如下:

用户客户端--发送请求->Nginx1 --转发请求-->Nginx2->后端服务器

那么,默认情况下,针对Nginx1而言,​​$remote_addr​​​为用户客户端IP,对Nginx2而言,​​$remote_addr​​则为Nginx1的IP。此时如果希望Nginx2也可以获取用户客户端IP,那要怎么处理呢?答案如下:

在Nginx1配置文件中使用​​proxy_set_header​​为转发请求设置请求头

proxy_set_header X-Real-IP $remote_addr; // X-Real-IP 为请求头名称,可自定义

然后,在Nginx2 配置文件中通过​​$http_x_real_ip​​​来获取​​X-Real-IP​​请求头的值来获取真实客户端IP.

此时,如果要求“后端服务器”也要获取用户客户端IP,咋处理呢?做法和上述类似,在Nginx2配置文件中,使用​​proxy_set_header​​做同样的配置,即:

proxy_set_header X-Real-IP $remote_addr; 

然后,“后端服务器”获取请求头“X-Real-IP”的值即为用户客户端IP。

很多HTTP代理会在HTTP协议头中添加​​X-Forwarded-For​​​头,用来追踪请求的来源。​​X-Forwarded-For​​的格式如下:

​X-Forwarded-For​​​包含多个IP地址,每个值通过逗号+空格分开,最左边(client1)是最原始客户端的IP地址,中间如果有多层代理,每一层代理会将连接它的客户端IP追加在​​X-Forwarded-For​​右边。

$proxy_add_x_forwarded_for

代表附加​​$remote_addr​​​变量的客户端请求头​​X-Forwarded-For​​ ,其值如果包含多个地址,用逗号+空格分隔,标准格式如下:

X-Forwarded-For: clientIP, proxyIP1, proxyIP2 # 最左边的clientIp即为客户端真实IP

如果​​X-Forwarded-For​​​字段没出现在客户端请求头,​​$proxy_add_x_forwarded_for​​​ 等同于​​$remote_addr​​ 变量。

这里,假设用户请求过程和上文所述一样,如下:

用户客户端--发送请求->Nginx1 --转发请求-->Nginx2->后端服务器

假设,仅在Nginx1配置文件中进行了以下配置

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

那么,Nginx2配置的​​X-Forwarded-For​​​请求头的值即为​​clientIP​​,当然,这个结论的前提是,客户端IP没有配置​​X-Forwarded-For​​请求头,因为如上所述,客户端没有出现这个请求头时,​​$proxy_add_x_forwarded_for​​ 的值即为​​$remote_addr​​ 变量的值,否则,则是客户端为​​X-forwarded-for​​请求头的实际值

接着,假设Nginx2配置文件也进行以下配置

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

那么,“后端服务器”获取的​​X-Forwarded-For​​​请求头的值将为​​clientIP, Nginx1IP​​​。也就是说以上命令的执行是个叠加的过程(类似Python的列表的​​append​​方法的处理过程),可以简单理解为如果存在上级代理,执行以上命令时,会把上级代理IP追加到X-Forwarded-For请求头总,否则把客户端IP ​​$remote_addr​​、或者客户端​​X-Forwarded-For​​请求头的值(如果有的话)追加到X-Forwarded-For请求头中。

参考连接:

​https://nginx.org/en/docs/http/ngx_http_core_module.html#var_remote_addr​

​https://nginx.org/en/docs/http/ngx_http_proxy_module.html#var_proxy_add_x_forwarded_for​