WEB应用

惊现Haproxy重复添加X-Forwarded-For问题(附官方解决办法)

Jager · 4月12日 · 2019年 · 4414次已读

最近在配置 Haproxy 代理的时候发现一个很有意思的事情:Haproxy 在代理 http 请求会无脑加一个 X-Forwarded-For(后文简称 XFF),而不是将自身的 IP 地址加到已存在的 XFF 列表之后,WTF!还有这种神操作?

确认无误之后,我到 Haproxy 的 github 开了一个 issue 反馈了这个 BUG(issue 地址),最终了解到了 Haproxy 就是这样设计的,并得到了解决方案,而且这个 issue 的回复很有意思,特来博客分享下。惊现Haproxy重复添加X-Forwarded-For问题(附官方解决办法)

刚开始,我的 issue 提到 Haproxy 没有将自身 IP 地址 append 到已有的 XFF 列表之后,而是无脑又加了一个,这应该是个 BUG:惊现Haproxy重复添加X-Forwarded-For问题(附官方解决办法)

官方开发 GG 回复让我升级到最新稳定版,我说升级了也是一样的,结果人家又回复我说 Haproxy 本来就是这样设计的:惊现Haproxy重复添加X-Forwarded-For问题(附官方解决办法)

我接着回复说 Haproxy 这样设计会导致很多开源程序获取真实 IP 异常,比如 Twisted 和 packetbeat,但是官方说 Haproxy 的设计 100%符合 HTTP 协议标准 balabala....既然都这样说了,我能说啥呢?只好用官方给的建议选项 if none 来拒绝 Haproxy 添加 XFF,先解决我程序获取源 IP 错误的问题。

本以为这样就结束了,结果高潮来了!

一位很酷的法国大胡子发起了热心支援:惊现Haproxy重复添加X-Forwarded-For问题(附官方解决办法)

他的大概意思是说,既然 Haproxy 100% 符合 HTTP 标准,那为啥没有遵循 XFF 的标准约定,将自身的 IP 地址添加到已存在的 XFF 列表末尾??也提到了多个 XFF 会导致很多程序无法读取,比如 tomcat-8.5。为啥不加一个选项来选择使用多个 XFF 还是使用一个 XFF 等等 balabala 一顿说...

接着官方在 HTTP 标准上发起反驳解释(一大堆内容,此处不表),并在最后说明这样做是为了提高 Haproxy 性能,如果先判断是否存在 XFF 在高并发情况下性能大概下降 2-3 倍(非特指 Haproxy)。

当然,官方最终还是给了一个解决办法,能够让 Haproxy 也像 Nginx 那样将自己的 IP 地址加到已有 XFF 之后,只需在 Haproxy 新增如下配置即可:

http-request replace-value x-forwarded-for ^ "%[hdr(x-forwarded-for)], %[sr]"

虽然官方给的答复可以解决问题,不过法国大胡子最后回复的一段话我觉得说得非常好:惊现Haproxy重复添加X-Forwarded-For问题(附官方解决办法)

大致意思是,我已经知道如何通过配置来解决,但是为啥 option forwardfor 这个选项没有和大部分人预期那样来设计与开发,而且搞得巨复杂?

然后直接给出他认为更好的开发设计,比如用 option forwardfor force 替代:

http-request del-header x-forwarded-for
option forwardfor

实现强制覆盖 XFF,又比如用 option forwardfor append 来替代:

http-request replace-value x-forwarded-for ^ "%[hdr(x-forwarded-for)], %[src]"

实现将自身 IP 地址加到已有的 XFF 之后。很明显,这样的设计才更有可读性,更好理解!他在最后还提到了,Apache/Nginx/Tomcat/Jetty/F5 等等都是将自身 IP 地址添加到 XFF 之后,难道你 Haproxy 认为这些软件的使用率还不够高??喷得大快人心,再次赞一下法国大胡子!

总之,真的是很有意思的一个 issue,同时也解决了问题,发现同样问题的朋友可以参考解决!

7 条回应
  1. qq下载 2019-4-29 · 8:59

    支持你,原创博客,向你学习,我一直都坚持不下来,

  2. 攸一随心笔记 2019-5-1 · 14:56

    很有技术性,先收藏后看,哈哈,谢谢Jager

  3. 心灵博客 2019-8-11 · 9:49

    这也解决 了我的一大问题。

  4. 道处长 2019-8-13 · 23:28

    这样看haproxy官方很二b

  5. Ginone 2019-8-17 · 16:05

    请问option forwardfor不支持append 参数如何解决
    parsing [/etc/haproxy/haproxy.cfg:14] : 'option forwardfor' only supports optional values: 'except', 'header' and 'if-none'
    系统:centros7.6
    内核:4.4.189-1.el7.elrepo.x86_64
    ha版本:2.0.4
    编译时的参数:make TARGET=generic PREFIX=/usr/local/haproxy USE_PCRE=1 USE_ZLIB=1 USE_OPENSSL=1 USE_CPU_AFFINITY=1 ADDLIB=-ldl

    • avatar
      Jager 2019-9-25 · 19:54

      文章中已经给了解决方案了,细读一下。不过我实测貌似没啥效果,官方感觉也是水

      • Ginone 2019-9-25 · 19:55

        已解决