nginx的real_ip_header和X-Forwarded-For似乎是错误的

HTTP头X-Forwarded-For的维基百科描述是:

X-Forwarded-For:client1,proxy1,proxy2,…

指令real_ip_headernginx文档部分读取:

该指令设置用于传送replaceIP地址的标题的名称。
在X-Forwarded-For的情况下,该模块使用X-Forwarded-For报头中的最后一个 IP进行replace。 [强调我的]

这两个描述看起来不一致。 在我们的场景中, X-Forwarded-For头部与描述的完全相同 – 客户端的“真实”IP地址是最左边的条目。 同样,nginx的行为是使用最右边的值 – 显然,这只是我们的代理服务器之一。

我对X-Real-IP理解是,它应该被用来确定实际的客户端IP地址 – 而不是代理。 我错过了什么,或者这是一个在Nginx的错误?

而且,除此之外,有没有人有任何build议如何使X-Real-IP头显示最左边的值,如X-Forwarded-For

    我相信,在多个IP链接时解决X-Forwarded-For困境的关键是最近引入的configuration选项real_ip_recursive (添加在nginx 1.2.1和1.3.0中)。 从nginx的realip文档 :

    如果启用recursionsearch,则与请求标头字段中发送的最后一个不可信地址相匹配的原始客户端地址与其中一个可信地址匹配。

    nginx默认是抓取链中的最后一个IP地址,因为那是唯一被假定为可信的IP地址。 但是,启用新的real_ip_recursive并使用多个set_real_ip_from选项,可以定义多个可信代理,并取得最后一个不可信的IP。

    例如,用这个configuration:

     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不会select最左边的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 config,nginx只会将最后两个地址信任为代理。 这意味着nginx会正确select123.123.123.123作为IP地址,尽pipe欺骗IP实际上是最左边的。

    X-Forwarded-For头文件的parsing在nginx real_ip模块中确实存在缺陷。

     len = r->headers_in.x_forwarded_for->value.len; ip = r->headers_in.x_forwarded_for->value.data; for (p = ip + len - 1; p > ip; p--) { if (*p == ' ' || *p == ',') { p++; len -= p - ip; ip = p; break; } } 

    它从头部string的最右侧开始,只要它看到空格或逗号,就会停止查找,并将该部分粘贴到IPvariables中的空格或逗号的右侧。 所以,它将最近的代理地址视为原始的客户端地址。

    根据规范,这不是很好玩。 这是在RFC中没有明确expression的危险。

    除此之外:很难在格式上find一个很好的主要来源,最初由squid定义 – 通过他们的文档挖掘证实了sorting; 最左边是原始客户端,最右边是最近的追加。 我非常想在wikipedia页面上添加一个[引用需要] 。 一个匿名编辑似乎是互联网在这个问题上的权威。

    如果可能的话,你可以让你的中间代理停止将自己添加到头部的末尾,只留下真正的客户端地址?

    X-Real-IP是服务器正在与之通话的实际客户机(服务器的“真实”客户机)的IP地址,在代理连接的情况下,该IP地址是代理服务器。 这就是为什么X-Real-IP将包含X-Forwarded-For报头中的最后一个IP。