X-Forwarded-For 和 X-Real-IP 标头之间的差异

2024-04-19

我使用 Nginx 作为反向代理。

这些标头有什么区别:

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

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

它们看起来很相似,所以我想了解它们有何不同以及我是否需要同时使用两者。


这些标头有什么区别?

你检查了吗$proxy_add_x_forwarded_for多变的文档 https://nginx.org/en/docs/http/ngx_http_proxy_module.html#var_proxy_add_x_forwarded_for?

the X-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

并且您的请求来自 IP198.51.100.17, 新的X-Forwarded-For标头值(要传递到上游)将是

X-Forwarded-For: 203.0.113.195, 150.172.238.178, 198.51.100.17

如果传入的请求不包含X-Forwarded-Forheader,这个 header 将被传递到上游

X-Forwarded-For: 198.51.100.17

另一方面,X-Real-IP按照您在问题中显示的方式设置的标题将始终等于$remote_addrnginx 内部变量,在本例中它将是

X-Real-IP: 198.51.100.17

(除非ngx_http_realip_模块 http://nginx.org/en/docs/http/ngx_http_realip_module.html将参与将该变量值更改为实际远程对等地址之外的其他值;阅读模块文档以了解所有详细信息;this https://stackoverflow.com/questions/48433490/x-real-ip-header-confusion-in-nginx所以问题也有一些有用的例子/额外的细节。)

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

您的第一个问题应该是“我是否需要将这些标头添加到发送到后端的请求中?”这实际上取决于您的后端应用程序。它依赖于这些标头中的任何一个吗?这些标头值实际上会对应用程序行为产生任何影响吗?您的后端应用程序如何处理这些标头值?如您所见,请求来源假定为来自X-Forwarded-For地址列表。另一方面,该标头很容易被欺骗,因此某些服务器设置可能允许仅将该标头用于受信任的源,否则将其删除。如果您设置X-Real-IP由您的服务器设置标头,它将始终包含实际的远程对等地址;如果你不这样做,并且你收到了一个欺骗性的请求X-Real-IP标头已经存在于其中,它将按原样传递到您的后端,如果您的应用程序更喜欢依赖该标头而不是,这可能非常糟糕X-Forwarded-For一。不同的后端应用程序可能表现不同;你可以检查this https://github.com/akka/akka-http/issues/1670GitHub 问题讨论以获取想法。

总结一下这一切。

如果您确实知道后端应用程序实际可以处理哪些标头以及如何完成,则应该根据处理它们的方式设置必需的标头并跳过非必需的标头以最小化代理负载。如果您不这样做,并且您不知道您的应用程序是否会被错误的欺骗X-Forwarded-For标头,并且您的 nginx 实例前面没有受信任的代理服务器,最安全的方法是根据实际的远程对等地址进行设置:

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

如果您确定您的后端应用程序不会被错误的欺骗X-Forwarded-ForHTTP 标头,并且您希望向其提供原始请求中获得的所有信息,请使用您在问题中显示的示例:

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

一些附加的技术信息。

其实那些X-Forwarded-...HTTP 标头是某种非标准标头。根据 MDN,假设传输此类信息的标准标头是Via https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Via,描述于RFC7230 https://www.rfc-editor.org/rfc/rfc7230.html#section-5.7.1, and Forwarded https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded,描述于RFC7239 https://www.rfc-editor.org/rfc/rfc7239#section-4。但是,那X-Forwarded-For https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For, X-Forwarded-Host https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host and X-Forwarded-Proto https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto成为替代版本和事实上的标准版本。而不是使用X-Forwarded-Host,这可能会或可能不会被您的后端应用程序解释,更可靠的方法是显式设置Host https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Host使用以下任一方式的代理请求的 HTTP 标头

proxy_set_header Host $host;

or

proxy_set_header Host $http_host;

or even

proxy_set_header Host $server_name;

(你可以检查之间的区别$host https://nginx.org/en/docs/http/ngx_http_core_module.html#var_host, $http_host https://nginx.org/en/docs/http/ngx_http_core_module.html#var_http_ and $server_name https://nginx.org/en/docs/http/ngx_http_core_module.html#var_server_nameNginx 内部变量here https://serverfault.com/questions/706438/what-is-the-difference-between-nginx-variables-host-http-host-and-server-na.) 另一方面X-Forwarded-Proto经常用于告诉后端应用程序原始请求是否是通过加密的 HTTPS 协议发出的。有时你甚至可以看到X-Forwarded-Proxy配置中使用的标头;对我来说,这看起来毫无意义,因为后端应用程序的行为不应根据您实际使用的反向代理软件而有所不同;但是我相信有一些网络应用程序确实可以以某种有用的方式处理这个问题。 MDN 没有提到X-Real-IP根本没有标题;然而,该应用程序应该提供相当多的网络应用程序。

还有一个技术细节。与其他一些反向代理服务器一样,nginx 会“折叠”多个X-Forwarded-For标头合并为一个标头,因此

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

and the

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

配置片段的行为相同,传递单个X-Forwarded-For后端应用程序的标头,无论使用什么配置都相同。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

X-Forwarded-For 和 X-Real-IP 标头之间的差异 的相关文章

随机推荐