MailABC是科普电子邮件知识的个人Blog,接受交换友链。您可以关注公众号mailabc留言,或邮件联系feedback@mailabc.cn 。

HTTP协议透传源IP:X-Forwarded-For

邮箱运维 小胡子大魔王 2周前 (09-04) 33次浏览 0个评论

什么是X-Forwarded-For

X-Forwarded-For (简称XFF)是一个 HTTP 扩展头部,用于表示 HTTP 请求的真实 IP 地址。HTTP/1.1(RFC 2616)协议中并没有对它进行定义,该功能最初由缓存代理软件 Squid 引入。如今,它已成为事实上的标准,广泛应用于各种 HTTP 代理和负载均衡服务中,并被纳入了 RFC 7239(Forwarded HTTP Extension)标准。

X-Forwarded-For 请求头格式如下:

X-Forwarded-For: client, proxy1, proxy2

X-Forwarded-For请求头是由「英文逗号 + 空格」隔开的多个部分组成,最开始的是离服务端最远的设备 IP,然后是每一级代理设备的 IP。

如下图所示,每经过一层代理服务器,X-Forwarded-For中的IP会做一次追加。

x-forwarded-for

代理服务器对X-Forwarded-For的处理

注:为了方便测试X-Forwarded-For的运作原理,这里以最常用的反向代理软件Nginx为例。

在Nginx配置中,有几个关键变量的含义需要了解一下:

  • $http_x_forwarded_for:表示X-Forwarded-For值。
  • $remote_addr:表示访问来源的IP地址。
  • proxy_add_x_forwarded_for:表示“$http_x_forwarded_for”+ “,”+“$remote_addr”,如果$http_x_forwarded_for为空,则这个值与$remote_addr相同。

如果本机Nginx作为反向代理,处理X-Forwarded-For的配置如下:

location / {
      proxy_pass http://backend;
      proxy_set_header        X-FORWARDED-FOR $proxy_add_x_forwarded_for;
      proxy_set_header        X-FORWARDED-PROTO $scheme;
}

上述配置中将$proxy_add_x_forwarded_for 内容设置到X-FORWARDED-FOR属性中,传递给下一个节点(代理服务器或者web服务器)。

WEB服务器对X-FORWARDED-FOR处理

注:WEB服务器以tomcat为例说明。

在Tomcat中,一般通过下面的配置来获取X-FORWARDED-FOR中的IP信息:

<Valve className="org.apache.catalina.valves.RemoteIpValve"
         remoteIpHeader="X-FORWARDED-FOR"
         protocolHeader="X-FORWARDED-PROTO"
         internalProxies="127\.0\.0\.1|2\.2\.2\.2|3\.3\.3\.3"/>

参数解释如下:

  • className: 指定了使用的类名。在这个例子中,org.apache.catalina.valves.RemoteIpValve 类用于处理客户端 IP 地址的重写。
  • remoteIpHeader: 指定了包含原始客户端 IP 地址的 HTTP 头名称。通常反向代理会将原始客户端的 IP 地址放入 X-FORWARDED-FOR 头中,因此这里设置为 X-FORWARDED-FOR
  • protocolHeader: 指定了包含原始协议(HTTP 或 HTTPS)的 HTTP 头名称。X-FORWARDED-PROTO 通常被用于指示原始请求是通过 HTTP 还是 HTTPS 进行的。
  • internalProxies: 用于指定一系列内部代理服务器的 IP 地址(通过正则表达式定义)。这些代理服务器会被认为是可信的,并且他们转发的 X-FORWARDED-FOR 头会被 Tomcat 认为是可信的客户端 IP 地址。在这个配置中,internalProxies 列出了三个 IP 地址:
    • 127.0.0.1: 本地回环地址
    • 2.2.2.2, 3.3.3.3: 假设这些是其他可信任的内部代理服务器的 IP 地址。

基于上述配置,Tomcat会针对X-FORWARDED-FOR传递过来的内容从右向左进行逐个检查,如果地址在internalProxies中将去除该IP;如果地址不在internalProxies中则取这个IP作为remoteip。正常来说所有代理服务器的IP应该包含在internalProxies,否则最终可能取到代理服务器的IP。

以文中示例图所示,从1.1.1.1经过2.2.2.2、3.3.3.3两层代理,WEB服务器(4.4.4.4)最终接收到的X-FORWARDED-FOR值为“1.1.1.1, 2.2.2.2, 3.3.3.3”,如果internalProxies=”127\.0\.0\.1|2\.2\.2\.2″,则Tomcat取到的remoteip是3.3.3.3,而不会取到1.1.1.1 。

如何测试?

可以通过curl做X-FORWARDED-FOR模拟测试:

curl -H "X-Forwarded-For: 203.0.113.195, 192.168.17.19" https://www.mailabc.cn

在Nginx配置中,可以针对输出的日志属性进行定义,加入$http_x_forwarded_for变量内容输出,如下示例所示:

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
            '$status $body_bytes_sent "$http_referer" '
            '"$http_user_agent" "$http_x_forwarded_for" '
            '$upstream_response_time $request_time ';

这样就可以通过日志查看上游代理节点传递的X-FORWARDED-FOR值具体是什么。当然也可以通过网络抓包分析。

注意事项

X-FORWARDED-FOR 可以在数据传输过程中被修改,属于不可信数据。配置过程中需要注意做好代理节点IP信任控制,防止恶意攻击。


未标注来源的文章均为原创作品,版权所有,转载请注明出处。非原创文章均已标注来源,如有侵权请告知。 如您喜欢本站,可以收藏加关注(扫码关注右上角微信公众号mailabc)。
喜欢 (1)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址