在 Docker 中使用 HAProxy 通过 IPv6 获取真实客户端 IP

在 Docker 中使用 HAProxy 通过 IPv6 获取真实客户端 IP

我目前在 Docker 容器中运行 HAProxy。Docker 仅在启用了 IPv4 和 IPv6 的一台主机上运行。HAProxy 是唯一共享主机端口的容器,并且只有 80/443 通过外部/公共接口上的防火墙。

目前,网络流量正常。我已forwardfor在 HAProxy 中设置,我的后端获取了用于日志记录和分析的真实 ClientIP……IPv6 除外。尽管端口 80/443 已由 docker 映射/转换,以便 HAProxy 获取 IPv4 上的真实客户端 IP,但 IPv6 上的任何内容都会以某种方式转换为 IPv4!HAProxy 获取私有 172.17.0.1 地址作为所有 IPv6 连接的客户端 IP。

我的daemon.jsonDocker 如下所示:

{
    "tls": true,
    "tlsverify": true,
    "tlscacert": "/etc/docker/ca.pem",
    "tlscert": "/etc/docker/server.crt",
    "tlskey": "/etc/docker/server-key.pem",
    "ipv6": true,
    "fixed-cidr-v6": "2001:19f0:6001:1c12::/80",
    "hosts": ["127.0.0.1:2376", "10.10.6.10:2376", "fd://"]
}

我已经从我的 IPv6 子网中分配了 Docker /80。我使用 Vultr 作为提供商,他们2001:19f0:6001:1c12::为我分配了我的 IPv6 子网和2001:19f0:6001:1c12:5400:01ff:fe49:876e主机 IP 地址(运行 docker 的机器)。我的DEFAULT_FORWARD策略ACCEPT也是ufw,并使用以下配置设置了 ndppd:

proxy ens3 {
  timeout 500
  ttl 30000
  rule 2001:19f0:6001:1c12::/80 {
    static
  }
}

因此,启用 IPv6 后,我发现我的容器都获得了自己的 IPv6 地址。因此,为了让我的 HAProxy 实例获得真正的客户端 IP,我需要将 DNS 指向容器 IPv6 地址并为其打开防火墙规则。但问题是,我需要该地址是静态的。当然,这意味着我不能使用默认的桥接网络,我需要有一个用户定义的网络。

我意识到我应该这样做,然后我想起我的问题是什么。我不断收到以下信息:

.gem/ruby/2.2.0/gems/docker-api-1.33.6/lib/docker/connection.rb:50:in `rescue in request': could not find an available, non-overlapping IPv6 address pool among the defaults to assign to the network (Docker::Error::ServerError)

这是来自 Ruby Docker-API 库,但我使用命令行工具时遇到了完全相同的错误。我尝试了各种 IPv6 子网,但似乎都不起作用,人们告诉我,如果我使用小于 /64 的子网,就会遇到问题。

记住,最初的问题是我无法在我的 Web 服务器日志中获取 IPv6 连接的客户端 IP。如果有更简单的方法可以解决这个问题,我很乐意接受。如果没有,我需要对我的用户定义网络使用什么设置?我希望我可以删除默认网桥并使用其范围,但这似乎不是一个选择。我是否可以阻止默认网桥获取在中定义的 IPv6 子网,daemon.json而是将该范围用于我的用户定义网络(然后静态分配 HAProxy 容器,以便我可以在 DNS/AAAA 记录中使用该容器的 IP?)或者是否有更简单的方法让 IPv6 主机端口直接连接到容器而无需像 IPv4 那样进行转换?

答案1

我最终不得不创建一个用户定义的网络。在我重构了所有内容之后,我发现了一个IPv6 NAT 容器这可能会完成相同的事情,但我很高兴我做对了,而不是尝试使用 IPv6 NAT 来破解它。

首先,我划分了我的 IPv6 范围,因此daemon.json得到以下内容:

"fixed-cidr-v6": "2001:19f0:6001:1c12::1:0:0/96",

我的用户定义网络得到了2001:19f0:6001:1c12::2:0:0/96。我在子网内定义了一个静态 IPv6 地址::2:0:0/96,并在使用 Docker Engine API 创建容器时使用了该 IP:

 ...
 "NetworkingConfig"=>
  {"EndpointsConfig"=>
    {"my-custom-network"=>
      {"IPAMConfig"=>{"IPv6Address"=>"2001:19f0:6001:1c12::2:0:1000"}}}},
 ...

然后我将AAAADNS 中的记录设置为该自定义 IPv6 地址。最后,我确保 HAProxy 使用配置选项bind :::80 v4v6监听IPv4 和 IPv6。bind :::443 v4v6 <insert cert stuff>

相关内容