没有与主机外部的 Docker 容器的 IPv6 连接

qnm*_*qnm 5 networking iptables ipv6 docker

我有一个 IPv6 本机容器,在端口 8000 上运行一个小型 Web 应用程序。

在 Docker 主机上,我可以使用全局 IP 访问 Web 服务,但从另一台主机连接时收到“连接被拒绝”。但是,可以从其他主机对容器执行 ping 操作。

容器中的服务有效

# curl "http://[2a01:4f8:10a:2cc5:0:242:ac11:2]:8000"
I'm b6032b33bc12
Run Code Online (Sandbox Code Playgroud)

但是,从另一台主机运行:

{2.1.5p273} curl "http://[2a01:4f8:10a:2cc5:0:242:ac11:2]:8000"
curl: (7) Failed to connect to 2a01:4f8:10a:2cc5:0:242:ac11:2 port 8000: Connection refused
Run Code Online (Sandbox Code Playgroud)

然而,ipv6 地址是可 ping 通的:

{2.1.5p273} ping6 2a01:4f8:10a:2cc5:0:242:ac11:2
PING 2a01:4f8:10a:2cc5:0:242:ac11:2(2a01:4f8:10a:2cc5:0:242:ac11:2) 56 data bytes
64 bytes from 2a01:4f8:10a:2cc5:0:242:ac11:2: icmp_seq=1 ttl=60 time=0.385 ms
64 bytes from 2a01:4f8:10a:2cc5:0:242:ac11:2: icmp_seq=2 ttl=60 time=0.452 ms
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

有关我的环境的更多详细信息:

# docker -
Docker version 17.03.1-ce, build c6d412e
Run Code Online (Sandbox Code Playgroud)

该守护进程使用以下参数来启用 ipv6:

--experimental=true --ipv6 --fixed-cidr-v6=2a01:4f8:10a:2cc5::2/64
Run Code Online (Sandbox Code Playgroud)

主机有一个路由 ipv6/64子网,其中一个 ip 分配给eth0,其余子网分配给docker0

# ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:c8:f8:5c:7b
      inet addr:172.17.0.1  Bcast:0.0.0.0  Mask:255.255.0.0
      inet6 addr: fe80::1/64 Scope:Link
      inet6 addr: fe80::42:c8ff:fef8:5c7b/64 Scope:Link
      inet6 addr: 2a01:4f8:10a:2cc5::1/64 Scope:Global
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:129 errors:0 dropped:0 overruns:0 frame:0
      TX packets:121 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:0
      RX bytes:9536 (9.3 KiB)  TX bytes:11130 (10.8 KiB)

eth0      Link encap:Ethernet  HWaddr 90:1b:0e:c4:3d:a1
      inet addr:88.99.148.135  Bcast:88.99.148.191  Mask:255.255.255.192
      inet6 addr: fe80::921b:eff:fec4:3da1/64 Scope:Link
      inet6 addr: 2a01:4f8:10a:2cc5::2/128 Scope:Global
      UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
      RX packets:107917 errors:0 dropped:0 overruns:0 frame:0
      TX packets:25223 errors:0 dropped:0 overruns:0 carrier:0
      collisions:0 txqueuelen:1000
      RX bytes:143498170 (136.8 MiB)  TX bytes:2953043 (2.8 MiB)
      Interrupt:16 Memory:f7000000-f7020000
Run Code Online (Sandbox Code Playgroud)

容器有全局ipv6

docker exec b6032b33bc12 ifconfig eth0
eth0      Link encap:Ethernet  HWaddr 02:42:ac:11:00:02
      inet addr:172.17.0.2  Bcast:0.0.0.0  Mask:255.255.0.0
      inet6 addr: fe80::42:acff:fe11:2/64 Scope:Link
      inet6 addr: 2a01:4f8:10a:2cc5:0:242:ac11:2/64 Scope:Global
Run Code Online (Sandbox Code Playgroud)

ipv6 的路由已就位,并且似乎可以工作:

# ip -6 route
2a01:4f8:10a:2cc5::2 dev eth0  proto kernel  metric 256
2a01:4f8:10a:2cc5::/64 dev docker0  proto kernel  metric 256
2a01:4f8:10a:2cc5::/64 dev docker0  metric 1024
fe80::/64 dev eth0  proto kernel  metric 256
fe80::/64 dev docker0  proto kernel  metric 256
fe80::/64 dev veth0fbfa39  proto kernel  metric 256
default via fe80::1 dev eth0  metric 1024
Run Code Online (Sandbox Code Playgroud)

主机具有出站连接:

# ping6 google.com
PING google.com(fra16s20-in-x0e.1e100.net) 56 data bytes
64 bytes from fra16s20-in-x0e.1e100.net: icmp_seq=1 ttl=56 time=5.08 ms
Run Code Online (Sandbox Code Playgroud)

和容器一样

# docker exec b6032b33bc12 ping6 google.com
PING google.com(fra16s20-in-x0e.1e100.net) 56 data bytes
64 bytes from fra16s20-in-x0e.1e100.net: icmp_seq=1 ttl=55 time=5.00 ms
64 bytes from fra16s20-in-x0e.1e100.net: icmp_seq=2 ttl=55 time=5.00 ms
Run Code Online (Sandbox Code Playgroud)

我怀疑存在 iptables 问题:

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
Chain FORWARD (policy DROP)
target     prot opt source               destination
DOCKER-ISOLATION  all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate     RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
Chain DOCKER (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             172.17.0.2           tcp dpt:8000
Chain DOCKER-ISOLATION (1 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere
Run Code Online (Sandbox Code Playgroud)

和 ipv6 等效:

# ip6tables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
Run Code Online (Sandbox Code Playgroud)

kas*_*erd 1

仔细查看您的整个配置,我没有发现任何错误。

我从 Hetzner 使用的所有内容都只有链接前缀,没有路由前缀。但我mtr在 Hetzner 网络之外的机器上进行了尝试,输出看起来2a01:4f8:10a:2cc5::/64确实是一个路由前缀。

从您的路由前缀分配单个地址eth0有点不寻常。但由于您确实将其分配为 a ,/128所以它仍然是有效的配置。如果您的服务器仅带有路由前缀而没有链接前缀,那么/128以这种方式分配 a 是一个明智的配置。

由于我在您的配置中找不到任何问题,因此我尝试从我的机​​器上重现该问题,但我做不到。

$ curl "http://[2a01:4f8:10a:2cc5:0:242:ac11:2]:8000"
I'm b6032b33bc12
Run Code Online (Sandbox Code Playgroud)

这使我得出的结论是,问题可能出在您运行该curl命令的计算机上(或它所连接的网络上)。

由于您没有告诉我们有关该机器的任何信息,因此我无法更具体地说问题是什么。您可以尝试比较这两个命令的输出:

traceroute 2a01:4f8:10a:2cc5:0:242:ac11:2
traceroute -p 8000 2a01:4f8:10a:2cc5:0:242:ac11:2
Run Code Online (Sandbox Code Playgroud)

这里我traceroute在 Ubuntu 16.04 上使用该包。其他traceroute版本可能需要不同的参数。