IETF RFC 2616 第 4.2 节允许请求包含具有相同字段名称的多个标头,只要插入的时间顺序保持不变,并且它们的值可以转换为具有逗号分隔的值列表的单个标头。
https://www.rfc-editor.org/rfc/rfc2616#section-4.2
当且仅当该标头字段的整个字段值定义为逗号分隔列表 [即 #(values)] 时,具有相同字段名称的消息标头字段才可以出现在消息中。必须能够将多个标头字段组合成一个“字段名称:字段值”对,而无需更改消息的语义,方法是将每个后续字段值附加到第一个字段值,每个字段值都用逗号分隔。因此,接收具有相同字段名称的标头字段的顺序对于组合字段值的解释非常重要,因此代理在转发消息时不得更改这些字段值的顺序。F5 不会覆盖任何现有的 X-Forwarded-For。它也不会将现有的 X-Forwarded-For 连接成单个逗号分隔的值。相反,它将在集合的尾端插入一个额外的 X-Forwarded-For。
但是,对于具有多个客户端、代理、CDN、流量管理器和参与操作收集的服务器的环境来说,情况又如何呢X-Forwarded-For
?
执行统一的做法似乎有好处。但最佳做法是什么?
X-Forwarded-For
F5 BIG-IP 默认 http 配置文件插入标头在请求的预先存在的 XFF 标头集合末尾累积额外的标头,以保持顺序。
AWS ELB 鼓励将传入请求的多个合并X-Forwarded-For
到单个标头中,该标头包含以逗号分隔的 XFF IP 列表以及用户主机地址,并保持顺序。
其他设备可能采用其他变化。
是否存在针对异构环境的一致建议或事实上的标准?
此外,是否提供了任何时间戳数据,以便代码能够X-Forwarded-For
按照添加的时间顺序对标题进行明确排序,以防之前对 XFF 标题的操作存在怀疑。
答案1
是的,有一个标准:根本不要使用X-Forwarded-For。
RFC 7239定义 Forwarded 标头,其语义与 X-Forwarded-For 截然不同,新的实现应该使用它。不幸的是,它存在您在此处发现的 X-Forwarded-For 的相同问题:它可能在请求中定义两次或包含逗号分隔的值列表。代理也可以完全删除它。
是的,有一个最佳做法:在内部使用不同的标题名称。
请记住,X-Forwarded-For 及其替代 Forwarded 包含不受信任的输入。客户端可以很轻松地将他们想要的任何内容放入这样的标头中。如果您确实需要知道连接到服务器的任何内容的公共 IP 地址,请将其放在不同的标头中。例如,CloudFlare 为此目的使用了 CF-Connecting-IP。我还看到 nginx 中使用了 Client-IP 和 X-Real-IP(您可以在其中定义任何内容)。无论使用什么名称,您的负载均衡器都应该以一些除 X-Forwarded-For 或 Forwarded 之外的标头。