daa*_*aku 7 ipv6 containers docker
我的目标是为我的每个 docker 容器拥有一个可路由的公共 IPv6 地址。我希望能够使用 IPv6 协议连接进出我的容器。
我正在使用 Linode 并且我被分配了一个公共 IPv6 池:
2600:3c01:e000:00e2:: / 64 routed to 2600:3c01::f03c:91ff:feae:d7d7
Run Code Online (Sandbox Code Playgroud)
该“路由到”地址是由 dhcp 自动配置的:
# ip -6 addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
inet6 2600:3c01::f03c:91ff:feae:d7d7/64 scope global mngtmpaddr dynamic
valid_lft 2591987sec preferred_lft 604787sec
inet6 fe80::f03c:91ff:feae:d7d7/64 scope link
valid_lft forever preferred_lft forever
Run Code Online (Sandbox Code Playgroud)
我设置了 AAAA 记录,ipv6.daaku.org以便更轻松地使用:
# nslookup -q=AAAA ipv6.daaku.org
ipv6.daaku.org has AAAA address 2600:3c01:e000:e2::1
Run Code Online (Sandbox Code Playgroud)
为了测试,我手动分配了该地址:
# ip -6 addr add 2600:3c01:e000:00e2::1/64 dev eth0
# ip -6 addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
inet6 2600:3c01:e000:e2::1/64 scope global
valid_lft forever preferred_lft forever
inet6 2600:3c01::f03c:91ff:feae:d7d7/64 scope global mngtmpaddr dynamic
valid_lft 2591984sec preferred_lft 604784sec
inet6 fe80::f03c:91ff:feae:d7d7/64 scope link
valid_lft forever preferred_lft forever
Run Code Online (Sandbox Code Playgroud)
我现在可以从启用了 IPv6 的家庭网络 ping 这个:
# ping6 -c3 ipv6.daaku.org
PING6(56=40+8+8 bytes) 2601:9:400:12ab:1db7:a353:a7b4:c192 --> 2600:3c01:e000:e2::1
16 bytes from 2600:3c01:e000:e2::1, icmp_seq=0 hlim=54 time=16.855 ms
16 bytes from 2600:3c01:e000:e2::1, icmp_seq=1 hlim=54 time=19.506 ms
16 bytes from 2600:3c01:e000:e2::1, icmp_seq=2 hlim=54 time=17.467 ms
--- ipv6.daaku.org ping6 statistics ---
3 packets transmitted, 3 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 16.855/17.943/19.506/1.133 ms
Run Code Online (Sandbox Code Playgroud)
我删除了地址,因为我只想要它在容器中,然后回到原来的状态:
# ip -6 addr del 2600:3c01:e000:00e2::1/64 dev eth0
# ip -6 addr show eth0
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qlen 1000
inet6 2600:3c01::f03c:91ff:feae:d7d7/64 scope global mngtmpaddr dynamic
valid_lft 2591987sec preferred_lft 604787sec
inet6 fe80::f03c:91ff:feae:d7d7/64 scope link
valid_lft forever preferred_lft forever
Run Code Online (Sandbox Code Playgroud)
我在另一个终端中启动了一个没有网络的 docker 容器:
# docker run -it --rm --net=none debian bash
root@b96ea38f03b3:/#
Run Code Online (Sandbox Code Playgroud)
将其 pid 卡在一个变量中以便于使用:
CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' b96ea38f03b3)
Run Code Online (Sandbox Code Playgroud)
为该 pid 设置 netns:
# mkdir -p /run/netns
# ln -s /proc/$CONTAINER_PID/ns/net /run/netns/$CONTAINER_PID
Run Code Online (Sandbox Code Playgroud)
创建了一个新设备,为其分配了 IP:
# ip link add container0 link eth0 type macvlan
# ip link set container0 netns $CONTAINER_PID
# ip netns exec $CONTAINER_PID ip link set dev container0 name eth0
# ip netns exec $CONTAINER_PID ip link set eth0 up
# ip netns exec $CONTAINER_PID ip addr add 2600:3c01:e000:00e2::1/64 dev eth0
Run Code Online (Sandbox Code Playgroud)
回到我启动容器的另一个终端:
# ip -6 addr show eth0
22: eth0@gre0: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500
inet6 2600:3c01::a083:1eff:fea5:5ad2/64 scope global dynamic
valid_lft 2591979sec preferred_lft 604779sec
inet6 2600:3c01:e000:e2::1/64 scope global
valid_lft forever preferred_lft forever
inet6 fe80::a083:1eff:fea5:5ad2/64 scope link
valid_lft forever preferred_lft forever
# ip -6 route
2600:3c01::/64 dev eth0 proto kernel metric 256 expires 2591976sec
2600:3c01:e000:e2::/64 dev eth0 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
default via fe80::1 dev eth0 proto ra metric 1024 expires 67sec
Run Code Online (Sandbox Code Playgroud)
这不起作用,我无法从容器连接(ping6 ipv6.google.com用作我的测试),也无法从我的家庭网络通过 Internet ping 容器(ping6 ipv6.daaku.org用作我的测试)。
更新:我设法通过这样做使传出IPv6 工作:
ip -6 addr add 2600:3c01:e000:00e2::1111:1/112 dev docker0 &&
ip6tables -P FORWARD ACCEPT &&
sysctl -w net.ipv6.conf.all.forwarding=1 &&
sysctl -w net.ipv6.conf.all.proxy_ndp=1
CONTAINER_PID=$(docker inspect -f '{{.State.Pid}}' 4fd3b05a04bb)
mkdir -p /run/netns &&
ln -s /proc/$CONTAINER_PID/ns/net /run/netns/$CONTAINER_PID &&
ip netns exec $CONTAINER_PID ip -6 addr add 2600:3c01:e000:00e2::1111:20/112 dev eth0 &&
ip netns exec $CONTAINER_PID ip -6 route add default via 2600:3c01:e000:00e2::1111:1 dev eth0
Run Code Online (Sandbox Code Playgroud)
主机上的 IPv6 路由:
# ip -6 r
2600:3c01::/64 dev eth0 proto kernel metric 256 expires 2582567sec
2600:3c01:e000:e2::1111:0/112 dev docker0 proto kernel metric 256
2600:3c01:e000:e2::/64 dev eth0 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
fe80::/64 dev docker0 proto kernel metric 256
fe80::/64 dev veth1775864 proto kernel metric 256
fe80::/64 dev veth102096c proto kernel metric 256
fe80::/64 dev vethdf3a55b proto kernel metric 256
Run Code Online (Sandbox Code Playgroud)
容器中的 IPv6 路由:
# ip -6 r
2600:3c01:e000:e2::1111:0/112 dev eth0 proto kernel metric 256
fe80::/64 dev eth0 proto kernel metric 256
default via 2600:3c01:e000:e2::1111:1 dev eth0 metric 1024
Run Code Online (Sandbox Code Playgroud)
仍然无法从我的家用机器 ping 它。
我认为你的问题与路由有关。问题是您已被分配了一套公寓/64,但您已决定对 . 进行子网划分/112。这对于出站流量来说很好,因为您的容器主机知道所有单独的子子网,但是当您的 ISP 来处理返回数据包时,他们不知道您已经进行了分段2600:3c01:e000:e2::1111:0/112并且应该通过2600:3c01:e000:00e2::1. 他们只是希望整个系统2600:3c01:e000:00e2::/64都坐在那里,直接连接并通过单播访问。
问题在于,没有任何机制可以告诉您的 ISP 您已决定开始划分子网(实际上,这是一个谎言,有很多方法 - 但它们都需要您的 ISP 的合作)。最简单的选择可能是停止将流量路由到容器,并开始桥接它。
我无法确切地告诉你该怎么做。我尝试过,有几个人善意地指出我错了。希望有人能澄清一下。但问题仍然是,您需要将容器桥接到下一跳路由,反之亦然,而不是路由它们。