X-Forwarded-For 与nginx,$proxy_add_x_forwarded_for

一般来说,X-Forwarded-For是用于记录代理信息的,每经过一级代理(匿名代理除外),代理服务器都会把这次请求的来源IP追加在X-Forwarded-For中
X-Forwarded-For确实是一般的做法
1. 在正向(如squid)反向(如nginx)代理中都是标准用法,而正向代理中是没有x-real-ip相关的标准的,也就是说,如果用户访问你的 nginx反向代理之前,还经过了一层正向代理,你即使在nginx中配置了x-real-ip,取到的也只是正向代理的IP而不是客户端真实IP
2. 大部分nginx反向代理配置文章中都没有推荐加上x-real-ip,而只有x-forwarded-for,因此更通用的做法自然是取x-forwarded-for
3. 多级代理很少见,只有一级代理的情况下二者是等效的
4. 如果有多级代理,x-forwarded-for效果是大于x-real-ip的,可以记录完整的代理链路

在nginx里

$proxy_add_x_forwarded_for是用来获取所有请求上游的请求头的remote_add的集合,以逗号分隔,
上游的请求如果未设置的话 $proxy_add_x_forwarded_for=$remote_addr,$http_x_forwarded_for用获取请求头里的X-Forwarded-For的,不设置就没有

 

实操
客户端ip:10.1.1.115
proxy1:10.88.1.79
proxy2:10.88.1.250
server:10.88.1.142

请求访问方式
client->proxy1->proxy2->server

proxy1配置

location ^~  /proxy{
        proxy_pass http://10.88.1.250;
        proxy_set_header Host $proxy_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Real-Port $remote_port;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
    }
    location =/proxy/v1{
        default_type text/html;
        return 200  host:$host<br>remote_addr:$remote_addr<br>remote_port:$remote_port<br>proxy_add_x_forwarded_for:$proxy_add_x_forwarded_for<br>http_x_forwarded_for:$http_x_forwarded_for;
    }

proxy2配置

location ^~  /proxy{
                proxy_pass http://10.88.1.142;
                proxy_set_header Host $proxy_host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Real-Port $remote_port;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        }
    location =/proxy/v2{
        default_type text/html;
        return 200  host:$host<br>remote_addr:$remote_addr<br>remote_port:$remote_port<br>proxy_add_x_forwarded_for:$proxy_add_x_forwarded_for<br>http_x_forwarded_for:$http_x_forwarded_for;
    }

server里

location =/proxy/v3{
        default_type text/html;
        return 200  host:$host<br>remote_addr:$remote_addr<br>remote_port:$remote_port<br>proxy_add_x_forwarded_for:$proxy_add_x_forwarded_for<br>http_x_forwarded_for:$http_x_forwarded_for;
    }

分别访问/proxy/v1,/proxy/v2,/proxy/v3

在proxy1里
host:10.88.1.79
remote_addr:10.1.1.115
remote_port:44433
proxy_add_x_forwarded_for:10.1.1.115
http_x_forwarded_for:
------------------------------------- 在proxy2里 host:
10.88.1.250 remote_addr:10.88.1.79 remote_port:51511 proxy_add_x_forwarded_for:10.1.1.115, 10.88.1.79 http_x_forwarded_for:10.1.1.115
---------------------------------------------
在server host:10.88.1.142 remote_addr:10.88.1.250 remote_port:60978 proxy_add_x_forwarded_for:10.1.1.115, 10.88.1.79, 10.88.1.250 http_x_forwarded_for:10.1.1.115, 10.88.1.79

 

 

client->proxy1->proxy2->server
当proxy1里
只设置
proxy_pass http://proxy2的ip;
proxy2里只设置
proxy_pass http://server的ip;
在proxy2,server里获取 $http_x_forwarded_for 均为空
$proxy_add_x_forwarded_for等同$remote_addr

---------------------------------
当只在proxy1里的设置里新增
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy2里能获取到$http_x_forwarded_for 为proxy1里设置的X-Forwarded-For
$proxy_add_x_forwarded_for为 "clientip,proxy1的ip"
在server里
$http_x_forwarded_for为clientip
$proxy_add_x_forwarded_for为"clientip,proxy2的ip"