HTTP的X-Forwarded-*系列header

简介

在互联网上,有各种代理服务器介入转发HTTP请求,但是也修改了报文格式,因此增加了额外的字段包含原始信息。

2014年,RFC7239 中定义了Forwarded这个http首部1字段,标准化了其格式和含义。

但是在这之前互联网上的代理服务器已经大量使用了X-Forwarded-* 系列首部,比如 X-Forwarded-For 、 X-Forwarded-Host 以及X-Forwarded-Proto这三个首部,其含义已经成为既成标准


Forwarded2

Forwarded 首部中包含了代理服务器的客户端的信息,即由于代理服务器在请求路径中的介入而被修改或丢失的信息。

这个消息首部会被用来进行调试和统计,以及生成基于位置的定制化内容,按照设计的目的,它会暴露一定的隐私和敏感信息,比如客户端的IP地址。所以在应用此消息首部的时候,需要将用户的隐私问题考虑在内。

语法

Forwarded: by=<identifier>; for=<identifier>; host=<host>; proto=<http|https>

  1. <identifier>
    一个 identifier 显示了在使用代理的过程中被修改或者丢失的信息。它们可以是以下几种形式:
    一个IP地址(V4 或 V6,端口号可选,ipv6 地址需要包含在方括号里面,同时用引号括起来),
    语意不明的标识符(比如 “_hidden” 或者 “_secret”),
    或者是 “unknown”,当当前信息实体不可知的时候(但是你依然想要说明请求被进行了转发)。
  2. by=<identifier>
    该请求进入到代理服务器的接口。
  3. for=<identifier>
    发起请求的客户端以及代理链中的一系列的代理服务器。
  4. host=<host>
    代理接收到的 Host 首部的信息。
  5. proto=<http|https>
    表示发起请求时采用的何种协议(通常是 “http” 或者 “https”)。

示例


Forwarded: for="_mdn" 

# 大小写不敏感
Forwarded: For="[2001:db8:cafe::17]:4711"

# for proto by 之间可用分号分隔
Forwarded: for=192.0.2.60; proto=http; by=203.0.113.43

# 多值可用逗号分隔
Forwarded: for=192.0.2.43, for=198.51.100.17

X-Forwarded-*

X-Forwarded-For (XFF)

在mozilla网站2上找到这个定义Html

X-Forwarded-For (XFF) 在客户端访问服务器的过程中如果需要经过HTTP代理或者负载均衡服务器,可以被用来获取最初发起请求的客户端的IP地址,这个消息首部成为事实上的标准。在消息流从客户端流向服务器的过程中被拦截的情况下,服务器端的访问日志只能记录代理服务器或者负载均衡服务器的IP地址。如果想要获得最初发起请求的客户端的IP地址的话,那么 X-Forwarded-For 就派上了用场。

这个消息首部会被用来进行调试和统计,以及生成基于位置的定制化内容,按照设计的目的,它会暴露一定的隐私和敏感信息,比如客户端的IP地址。所以在应用此消息首部的时候,需要将用户的隐私问题考虑在内。

HTTP 协议中的 Forwarded 是这个消息首部的标准化版本。

X-Forwarded-For 也是一个电子邮件相关协议中用到的首部,用来表示一封电子邮件是从其他账户转发过来的。

语法

X-Forwarded-For: <client>, <proxy1>, <proxy2>

指令

  1. <client>
    客户端的IP地址。
  2. <proxy1>, <proxy2>
    如果一个请求经过了多个代理服务器,那么每一个代理服务器的IP地址都会被依次记录在内。也就是说,最右端的IP地址表示最近通过的代理服务器,而最左端的IP地址表示最初发起请求的客户端的IP地址。

示例

X-Forwarded-For: 2001:db8:85a3:8d3:1319:8a2e:370:7348

X-Forwarded-For: 203.0.113.195

X-Forwarded-For: 203.0.113.195, 70.41.3.18, 150.172.238.178

其他非标准形式:

# Used for some Google services
X-ProxyUser-Ip: 203.0.113.19

X-Forwarded-Port

X-Forwarded-Port这个首部用的较少,我们在aws3网站上找到了定义

The X-Forwarded-Port request header helps you identify the destination port that the client used to connect to the load balancer.

oracle 网站上也有

X-Forwarded-Port
Identifies the listener port number that the client used to connect to the load balancer. For example:

X-Forwarded-Port: 443

意思是说字段是代理的目的端口。但是对于金山云的LB后端转发,这个字段一直是代表客户端原始的端口号

在 https://github.com/http-party/node-http-proxy/issues/341 还找到2012年修改过这个问题

My understanding is that x-forwarded-port should be set to the server port that the request came in on: 80, 443, etc.

If that's the case, it's not happening. req.connection.remotePort is the requesting client's remote port. I didn't see an obvious way to get the server from the request, but it seems easy enough to determine it from the host header/protocol.

Assuming I'm understanding x-forwarded-port correctly, I've got a branch that fixes the issue here:

https://github.com/blahed/node-http-proxy/compare/x-forwarded-port

还有https://github.com/envoyproxy/envoy/issues/3732 种也有人对这个字段含义提出异议。

因为AWS是云计算的事实标准,所以大部分都根据这个来了, 但是AWS只定义了 X-Forwarded-For/X-Forwarded-Proto/X-Forwarded-Port,X-Forwarded-Host没有定义


从 X-Forwarded-For 到 Forwarded 的迁移

如果应用、服务器或是代理支持标准格式的 Forwarded 的首部的话,那么 X-Forwarded-For 可以被替换。需要注意的是,在 Forwarded 中 ipv6 地址需要包含在方括号里面,同时用引号括起来。

X-Forwarded-For: 123.34.567.89
Forwarded: for=123.34.567.89

X-Forwarded-For: 192.0.2.43, 2001:db8:cafe::17
Forwarded: for=192.0.2.43, for="[2001:db8:cafe::17]"


  1. https://en.wikipedia.org/wiki/List_of_HTTP_header_fields ↩︎

  2. https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Forwarded ↩︎ ↩︎

  3. https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html#x-forwarded-port ↩︎

猜你喜欢

转载自blog.csdn.net/juewuer/article/details/104850405