X-Forwarded-For和X-Real-IP头部之间的区别

44

我正在使用 Nginx 作为反向代理。

这些头部信息之间有什么区别:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP       $remote_addr;

在一些文档/教程中,我看到两者都被使用,而在另一些文档中只使用第一个。

它们看起来相似,因此我想要了解它们的区别以及是否需要同时使用两者。

1个回答

55
这些头部之间有什么区别?
你是否查看了$proxy_add_x_forwarded_for变量的documentationX-Forwarded-For客户端请求头字段带有以逗号分隔的$remote_addr变量附加在其后。如果客户端请求头中没有X-Forwarded-For字段,则$proxy_add_x_forwarded_for变量等于$remote_addr变量。
如果传入请求已经包含X-Forwarded-For头部,比如说
X-Forwarded-For: 203.0.113.195, 150.172.238.178

如果你的请求来自 IP 地址 198.51.100.17,新的 X-Forwarded-For 头信息(将要传递给上游服务器)将是:

X-Forwarded-For: 203.0.113.195, 150.172.238.178, 198.51.100.17

如果传入的请求没有包含 X-Forwarded-For 头部,该头部将会被传递到上游。
X-Forwarded-For: 198.51.100.17

另一方面,按照您在问题中展示的方式设置X-Real-IP头信息将始终等于$remote_addr nginx内部变量,在此情况下,它将是:
X-Real-IP: 198.51.100.17

除非ngx_http_realip_module介入并将该变量值更改为除实际远程对等地址以外的其他内容;阅读模块文档以了解所有详细信息;this这些SO问题也有一些有用的示例/附加详细信息。

我是否需要同时使用两者?

你的第一个问题应该是“我是否需要添加任何这些标题到发送到我的后端的请求中?”这真的取决于你的后端应用程序。它是否依赖于这些标题之一?这些标头值实际上是否会影响应用程序行为?您的后端应用程序如何处理这些标头值?正如您所看到的,请求来源被假定为来自X-Forwarded-For地址列表的第一个地址。另一方面,该标头可以很容易地伪造,因此某些服务器设置可能允许仅针对受信任的来源使用该标头,否则将其删除。如果您通过服务器设置设置了X-Real-IP标头,则它将始终包含实际的远程对等地址;如果您没有,并且已经存在具有伪造的X-Real-IP标头的伪造请求,它将按原样传递到您的后端,如果您的应用程序更喜欢依赖于该标头而不是X-Forwarded-For,则可能会很糟糕。不同的后端应用程序可能有不同的行为;您可以检查thisGitHub问题讨论以获得想法。

总结所有这些内容。

如果您确切知道您的后端应用程序实际上可以处理哪些标头以及如何处理它们,则应根据将要处理它们的方式设置所需的标头,并跳过非必需的标头以最小化代理有效负载。如果您不知道您的应用程序是否可以使用不正确的X-Forwarded-For标头进行欺骗,并且在您的nginx实例前面没有受信任的代理服务器,则最安全的方法将是根据实际远程对等地址同时设置两者:

proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Real-IP       $remote_addr;

如果您确定您的后端应用程序不能被错误的 X-Forwarded-For HTTP 头欺骗,并且您想要将原始请求中的所有信息提供给它,请使用您在问题中展示的示例:

proxy_set_header X-Forwarded-For $proxy_x_forwarded_for;
proxy_set_header X-Real-IP       $remote_addr;

一些额外的技术信息。

实际上,那些X-Forwarded-... HTTP头是一些非标准头。根据MDN文档,传输这些信息的标准头应该是Via, 在RFC7230中描述,以及Forwarded, 在RFC7239中描述。然而,X-Forwarded-For, X-Forwarded-HostX-Forwarded-Proto 变成了替代品和事实上的标准版本。为了避免使用可能被后端应用程序解释或不解释的X-Forwarded-Host,更可靠的方法是明确地设置Host HTTP头来代理请求。

proxy_set_header Host $host;

或者

proxy_set_header Host $http_host;

甚至
proxy_set_header Host $server_name;

你可以查看$host, $http_host$server_name这些nginx内部变量之间的区别(在这里)。另一方面,X-Forwarded-Proto被广泛用于告诉后端应用程序原始请求是否使用加密的HTTPS协议。有时您甚至可以在配置中看到使用X-Forwarded-Proxy头;对我而言,这似乎是没有意义的,因为后端应用程序不应根据实际使用的反向代理软件而有所不同; 但是我相信可能有一些Web应用程序确实可以以某种有用的方式处理它。MDN根本没有提到X-Real-IP头;但是绝对有很多Web应用程序应该使用它。

还有一个技术细节。像其他一些反向代理服务器一样,nginx将多个X-Forwarded-For头“折叠”成一个头,因此

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Forwarded-For $http_x_forwarded_for;
proxy_set_header X-Forwarded-For $remote_addr;

配置片段将表现相同,将单个X-Forwarded-For头传递给您的后端应用程序,无论使用什么配置,都是相等的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接