我相信,当多个IP链接在一起时,解决X-Forwarded-For问题的关键是最近引入的配置选项real_ip_recursive
(nginx 1.2.1和1.3.0中已添加)。从nginx realip文档:
如果启用了递归搜索,则与请求地址之一匹配的原始客户端地址将替换为在请求标头字段中发送的最后一个不受信任的地址。
默认情况下,nginx会获取链中的最后一个IP地址,因为这是唯一被认为可信任的IP地址。但是real_ip_recursive
启用了新功能并具有多个set_real_ip_from
选项后,您可以定义多个受信任的代理,它将获取最后一个不受信任的IP。
例如,使用此配置:
set_real_ip_from 127.0.0.1;
set_real_ip_from 192.168.2.1;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
X-Forwarded-For标头导致:
X-Forwarded-For: 123.123.123.123, 192.168.2.1, 127.0.0.1
现在,nginx将选择123.123.123.123作为客户端的IP地址。
至于为什么nginx不仅选择最左边的IP地址,还要求您显式定义受信任的代理,这是为了防止简单的IP欺骗。
假设客户的真实IP地址为123.123.123.123
。假设客户的行为不佳,他们试图将其IP地址欺骗为11.11.11.11
。他们使用该标头将请求发送到服务器:
X-Forwarded-For: 11.11.11.11
由于反向代理只是将IP添加到此X-Forwarded-For链中,因此可以说,当nginx到达时,它最终看起来像这样:
X-Forwarded-For: 11.11.11.11, 123.123.123.123, 192.168.2.1, 127.0.0.1
如果您只是抓住最左边的地址,那将使客户端可以轻松地欺骗其IP地址。但是在上面的示例nginx配置中,nginx将仅信任最后两个地址作为代理。这意味着nginx将正确选择123.123.123.123
IP地址,尽管该欺骗IP实际上是最左侧的。