【问题标题】:HAProxy tcp mode source client ipHAProxy tcp模式源客户端ip
【发布时间】:2019-08-15 07:19:30
【问题描述】:

我在 HAProxy 中有以下设置

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

defaults
    log global
    retries 2
    option  dontlognull
    timeout connect 10000
    timeout server 600000
    timeout client 600000

frontend https
    bind 5.x.x.x:443
    default_backend https

backend https
    mode tcp
    balance roundrobin
    option tcp-check
    server traefik 192.168.128.5:9443 check fall 3 rise 2

它按预期工作,后端服务器“traefik”正在对请求进行 SSL 终止。

问题是我在后端服务器中获得的客户端源 IP 是 HAProxy 的 IP,我想将源 IP 传递给后端服务器。

有可能吗?因为我尝试了我在互联网上看到的所有选项。

谢谢。

【问题讨论】:

  • 我是 HAProxy 的忠实拥护者,因此请不要将此误解为对 HAProxy 的负面评论:如果 traefik 正在终止 SSL,而您正在 TCP 模式下运行 HAProxy,那么有什么意义呢?完全使用 HAProxy 吗?我看不出有什么优势,除非它是您尚未解释的更大计划的一部分。
  • 是的,traefik 运行在一个服务器不公开的 kubernetes 集群中,只有 HAProxy 可以访问内部网络和互联网

标签: linux networking haproxy


【解决方案1】:

最后解决方案是使用https://www.haproxy.com/blog/haproxy/proxy-protocol/,因为它受到 HAProxy 和 traefik 的支持。

global
    log /dev/log    local0
    log /dev/log    local1 notice
    chroot /var/lib/haproxy
    stats socket /run/haproxy/admin.sock mode 660 level admin
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

defaults
    log global
    retries 2
    option  dontlognull
    timeout connect 10000
    timeout server 600000
    timeout client 600000

frontend https
    bind 5.x.x.x:443
    default_backend https

backend https
    mode tcp
    balance roundrobin
    option tcp-check
    server traefik 192.168.128.5:9443 check fall 3 rise 2 send-proxy

并启用 traefik 的入口点代理协议,如下所述:https://docs.traefik.io/configuration/entrypoints/#proxyprotocol

【讨论】:

  • 这是一个很好的解决方案。然而,我的情况略有不同,我的haproxy 位于不支持代理协议的 cloudflare 后面。在这种情况下,haproxy 正在代理 cloudflare 的 IP 地址,而不是客户端 IP。似乎无法找到让traefik 使用实际客户端 IP 而不是 cloudflare 的 IP 添加 x-real-ip 标头的方法。你有同样的情况吗,如果有,你解决了吗?
  • 当然,只要有一种方法可以让traefik 能够从特定的 http 标头获取客户端 ip,例如cf-connecting-ip。我想我得四处看看traefik 是否最终支持这一点。
  • 基于这个answer,看起来 traefik 在v1.7v2.1 之间没有变化,因为它仍然从remoteAddr 获得x-real-ip。这意味着traefik 不能根据其他一些标头设置x-real-ip