在互联网上,有各种代理服务器介入转发HTTP请求,但是也修改了报文格式,因此增加了额外的字段包含原始信息。
2014年,RFC7239 中定义了Forwarded这个http首部1字段,标准化了其格式和含义。
但是在这之前互联网上的代理服务器已经大量使用了X-Forwarded-* 系列首部,比如 X-Forwarded-For 、 X-Forwarded-Host 以及X-Forwarded-Proto这三个首部,其含义已经成为既成标准
Forwarded 首部中包含了代理服务器的客户端的信息,即由于代理服务器在请求路径中的介入而被修改或丢失的信息。
这个消息首部会被用来进行调试和统计,以及生成基于位置的定制化内容,按照设计的目的,它会暴露一定的隐私和敏感信息,比如客户端的IP地址。所以在应用此消息首部的时候,需要将用户的隐私问题考虑在内。
Forwarded: by=
; for= ; host= ; proto=
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
在mozilla网站2上找到这个定义Html
X-Forwarded-For (XFF) 在客户端访问服务器的过程中如果需要经过HTTP代理或者负载均衡服务器,可以被用来获取最初发起请求的客户端的IP地址,这个消息首部成为事实上的标准。在消息流从客户端流向服务器的过程中被拦截的情况下,服务器端的访问日志只能记录代理服务器或者负载均衡服务器的IP地址。如果想要获得最初发起请求的客户端的IP地址的话,那么 X-Forwarded-For 就派上了用场。
这个消息首部会被用来进行调试和统计,以及生成基于位置的定制化内容,按照设计的目的,它会暴露一定的隐私和敏感信息,比如客户端的IP地址。所以在应用此消息首部的时候,需要将用户的隐私问题考虑在内。
HTTP 协议中的 Forwarded 是这个消息首部的标准化版本。
X-Forwarded-For 也是一个电子邮件相关协议中用到的首部,用来表示一封电子邮件是从其他账户转发过来的。
X-Forwarded-For:
, ,
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这个首部用的较少,我们在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没有定义
如果应用、服务器或是代理支持标准格式的 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]"
https://en.wikipedia.org/wiki/List_of_HTTP_header_fields ↩︎
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Forwarded ↩︎ ↩︎
https://docs.aws.amazon.com/elasticloadbalancing/latest/classic/x-forwarded-headers.html#x-forwarded-port ↩︎