从网络名称空间 Ping 外部 IPv6 地址
Ping external IPv6 address from a network namespace
我需要从网络命名空间访问外部 IPv6 地址。
在我的主机中,我设置了一个 SIT 隧道 (IPv6-in-IPv4),它对 IPv6 数据包进行隧道传输并通过默认接口 (eth0) 发送它。 SIT 隧道依赖于 Hurricane Electric 隧道代理服务。我可以从主机 ping 外部 IPv6 地址。
$ ping6 ipv6.google.com
PING ipv6.google.com(lis01s13-in-x0e.1e100.net) 56 data bytes
64 bytes from lis01s13-in-x0e.1e100.net: icmp_seq=1 ttl=57 time=98.1 ms
64 bytes from lis01s13-in-x0e.1e100.net: icmp_seq=2 ttl=57 time=98.7 ms
以下是有关隧道的一些详细信息:
$ ip -6 route sh
2001:470:1f14:10be::/64 dev he-ipv6 proto kernel metric 256
default dev he-ipv6 metric 1024
有趣的部分来了。由于超出此问题范围的原因,我需要从网络名称空间内执行相同的操作 (ping ipv6.google.com)。
以下是我创建和设置网络名称空间的方法:
ns1.sh
#!/bin/bash
set -x
if [[ $EUID -ne 0 ]]; then
echo "You must run this script as root."
exit 1
fi
# Create network namespace 'ns1'.
ip netns del ns1 &>/dev/null
ip netns add ns1
# Create veth pair.
ip li add name veth1 type veth peer name vpeer1
# Setup veth1 (host).
ip -6 addr add fc00::1/64 dev veth1
ip li set dev veth1 up
# Setup vpeer1 (network namespace).
ip li set dev vpeer1 netns ns1
ip netns exec ns1 ip li set dev lo up
ip netns exec ns1 ip -6 addr add fc00::2/64 dev vpeer1
ip netns exec ns1 ip li set vpeer1 up
# Make vpeer1 default gw.
ip netns exec ns1 ip -6 route add default dev vpeer1
# Get into ns1.
ip netns exec ns1 /bin/bash --rcfile <(echo "PS1=\"ns1> \"")
然后我 运行 ns1.sh
并从 'ns1'.
ping veth1 (fc00::1) vpeer1 (fc00::2)
ns1> ping6 fc00::1
PING fc00::1(fc00::1) 56 data bytes
64 bytes from fc00::1: icmp_seq=1 ttl=64 time=0.075 ms
^C
ns1> ping6 fc00::2
PING fc00::2(fc00::2) 56 data bytes
64 bytes from fc00::2: icmp_seq=1 ttl=64 time=0.056 ms
但是,如果我尝试 ping 外部 IPv6 地址:
ns1> ping6 2a00:1450:4004:801::200e
PING 2a00:1450:4004:801::200e(2a00:1450:4004:801::200e) 56 data bytes
^C
--- 2a00:1450:4004:801::200e ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1008ms
所有数据包都丢失了。
我用 tcpdump 打开 veth1 并检查发生了什么。我看到的是 Neighbor Solicitation 数据包正在到达接口。这些数据包正在尝试解析 IPv6 目标地址的 MAC 地址:
$ sudo tcpdump -qns 0 -e -i veth1
IPv6, length 86: fc00::2 > ff02::1:ff00:200e: ICMP6, neighbor solicitation,
who has 2a00:1450:4004:801::200e, length 32
IPv6, length 86: fc00::2 > ff02::1:ff00:200e: ICMP6, neighbor solicitation,
who has 2a00:1450:4004:801::200e, length 32
我真的不明白为什么会这样。我也在主机中启用了 IPv6 转发,但没有效果:
$ sudo sysctl -w net.ipv6.conf.default.forwarding=1
感谢阅读这个问题。欢迎提出建议:)
编辑:
主机中的路由table:
2001:470:1f14:10be::/64 dev he-ipv6 proto kernel metric 256
fc00::/64 dev veth1 proto kernel metric 256
default dev he-ipv6 metric 1024
我在主机中添加了一个 NDP 代理,解决了 NDP 请求。仍然无法从 nsnet 访问该地址(对此进行调查):
sudo sysctl -w net.ipv6.conf.all.proxy_ndp=1
sudo ip -6 neigh add proxy 2a00:1450:4004:801::200e dev veth1
ULA 不是 routable
您已经为网络命名空间提供了一个唯一本地地址 (fc00::2):此 IP 地址不是全球互联网中的 routable,而是仅在您的本地网络中。
当您的 ISP 收到来自该地址的 ICMP 数据包时,它将丢弃它。即使此数据包成功到达 ipv6.google.com,它也不可能将答案发送回给您,因为此 IP 地址为 there is no announced route。
路由 table 问题(NDP 通知)
您收到 NDP 通知是因为这条线:
ip netns exec ns1 ip -6 route add default dev vpeer1
告诉内核(在 netns 中)所有 IP 地址都 直接连接 在 vpeer1
接口上。内核认为此 IP 地址存在于以太网 link 上:这就是它试图用 NDP 解析其 MAC 地址的原因。
相反,您想说它们可以通过给定的路由器访问(在您的情况下,路由器是您的主机):
ip netns exec ns1 ip -6 route add default dev vpeer1 via $myipv6
解决方案
您可以:
将 public IPv6 地址(属于您的 public IPv6 前缀)关联到您的 netns 并在此 地址的主机;
将您的 IPv6 前缀划分为子网并将子网路由到您的主机(如果可以);
使用 NAT(不好,丑陋,不要那样做)。
您应该能够使用如下方法实现第一个:
#!/bin/bash
set -x
myipv6=2001:470:1f14:10be::42
peeripv6=2001:470:1f14:10be::43
#Create the netns:
ip netns add ns1
# Create and configure the local veth:
ip link add name veth1 type veth peer name vpeer1
ip -6 address add $myipv6/128 dev veth1
ip -6 route add $peeripv6/128 dev veth1
ip li set dev veth1 up
# Setup vpeer1 in the netns:
ip link set dev vpeer1 netns ns1
ip netns exec ns1 ip link set dev lo up
ip netns exec ns1 ip -6 address add $peeripv6/128 dev vpeer1
ip netns exec ns1 ip -6 route add $myipv6/128 dev vpeer1
ip netns exec ns1 ip link set vpeer1 up
ip netns exec ns1 ip -6 route add default dev vpeer1 via $peeripv6
# IP forwarding
sysctl -w net.ipv6.conf.default.forwarding=1
# NDP proxy for the netns
ip -6 neigh add proxy $myipv6 dev veth1
我需要从网络命名空间访问外部 IPv6 地址。
在我的主机中,我设置了一个 SIT 隧道 (IPv6-in-IPv4),它对 IPv6 数据包进行隧道传输并通过默认接口 (eth0) 发送它。 SIT 隧道依赖于 Hurricane Electric 隧道代理服务。我可以从主机 ping 外部 IPv6 地址。
$ ping6 ipv6.google.com
PING ipv6.google.com(lis01s13-in-x0e.1e100.net) 56 data bytes
64 bytes from lis01s13-in-x0e.1e100.net: icmp_seq=1 ttl=57 time=98.1 ms
64 bytes from lis01s13-in-x0e.1e100.net: icmp_seq=2 ttl=57 time=98.7 ms
以下是有关隧道的一些详细信息:
$ ip -6 route sh
2001:470:1f14:10be::/64 dev he-ipv6 proto kernel metric 256
default dev he-ipv6 metric 1024
有趣的部分来了。由于超出此问题范围的原因,我需要从网络名称空间内执行相同的操作 (ping ipv6.google.com)。
以下是我创建和设置网络名称空间的方法:
ns1.sh
#!/bin/bash
set -x
if [[ $EUID -ne 0 ]]; then
echo "You must run this script as root."
exit 1
fi
# Create network namespace 'ns1'.
ip netns del ns1 &>/dev/null
ip netns add ns1
# Create veth pair.
ip li add name veth1 type veth peer name vpeer1
# Setup veth1 (host).
ip -6 addr add fc00::1/64 dev veth1
ip li set dev veth1 up
# Setup vpeer1 (network namespace).
ip li set dev vpeer1 netns ns1
ip netns exec ns1 ip li set dev lo up
ip netns exec ns1 ip -6 addr add fc00::2/64 dev vpeer1
ip netns exec ns1 ip li set vpeer1 up
# Make vpeer1 default gw.
ip netns exec ns1 ip -6 route add default dev vpeer1
# Get into ns1.
ip netns exec ns1 /bin/bash --rcfile <(echo "PS1=\"ns1> \"")
然后我 运行 ns1.sh
并从 'ns1'.
ns1> ping6 fc00::1
PING fc00::1(fc00::1) 56 data bytes
64 bytes from fc00::1: icmp_seq=1 ttl=64 time=0.075 ms
^C
ns1> ping6 fc00::2
PING fc00::2(fc00::2) 56 data bytes
64 bytes from fc00::2: icmp_seq=1 ttl=64 time=0.056 ms
但是,如果我尝试 ping 外部 IPv6 地址:
ns1> ping6 2a00:1450:4004:801::200e
PING 2a00:1450:4004:801::200e(2a00:1450:4004:801::200e) 56 data bytes
^C
--- 2a00:1450:4004:801::200e ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 1008ms
所有数据包都丢失了。
我用 tcpdump 打开 veth1 并检查发生了什么。我看到的是 Neighbor Solicitation 数据包正在到达接口。这些数据包正在尝试解析 IPv6 目标地址的 MAC 地址:
$ sudo tcpdump -qns 0 -e -i veth1
IPv6, length 86: fc00::2 > ff02::1:ff00:200e: ICMP6, neighbor solicitation,
who has 2a00:1450:4004:801::200e, length 32
IPv6, length 86: fc00::2 > ff02::1:ff00:200e: ICMP6, neighbor solicitation,
who has 2a00:1450:4004:801::200e, length 32
我真的不明白为什么会这样。我也在主机中启用了 IPv6 转发,但没有效果:
$ sudo sysctl -w net.ipv6.conf.default.forwarding=1
感谢阅读这个问题。欢迎提出建议:)
编辑:
主机中的路由table:
2001:470:1f14:10be::/64 dev he-ipv6 proto kernel metric 256
fc00::/64 dev veth1 proto kernel metric 256
default dev he-ipv6 metric 1024
我在主机中添加了一个 NDP 代理,解决了 NDP 请求。仍然无法从 nsnet 访问该地址(对此进行调查):
sudo sysctl -w net.ipv6.conf.all.proxy_ndp=1
sudo ip -6 neigh add proxy 2a00:1450:4004:801::200e dev veth1
ULA 不是 routable
您已经为网络命名空间提供了一个唯一本地地址 (fc00::2):此 IP 地址不是全球互联网中的 routable,而是仅在您的本地网络中。
当您的 ISP 收到来自该地址的 ICMP 数据包时,它将丢弃它。即使此数据包成功到达 ipv6.google.com,它也不可能将答案发送回给您,因为此 IP 地址为 there is no announced route。
路由 table 问题(NDP 通知)
您收到 NDP 通知是因为这条线:
ip netns exec ns1 ip -6 route add default dev vpeer1
告诉内核(在 netns 中)所有 IP 地址都 直接连接 在 vpeer1
接口上。内核认为此 IP 地址存在于以太网 link 上:这就是它试图用 NDP 解析其 MAC 地址的原因。
相反,您想说它们可以通过给定的路由器访问(在您的情况下,路由器是您的主机):
ip netns exec ns1 ip -6 route add default dev vpeer1 via $myipv6
解决方案
您可以:
将 public IPv6 地址(属于您的 public IPv6 前缀)关联到您的 netns 并在此 地址的主机;
将您的 IPv6 前缀划分为子网并将子网路由到您的主机(如果可以);
使用 NAT(不好,丑陋,不要那样做)。
您应该能够使用如下方法实现第一个:
#!/bin/bash
set -x
myipv6=2001:470:1f14:10be::42
peeripv6=2001:470:1f14:10be::43
#Create the netns:
ip netns add ns1
# Create and configure the local veth:
ip link add name veth1 type veth peer name vpeer1
ip -6 address add $myipv6/128 dev veth1
ip -6 route add $peeripv6/128 dev veth1
ip li set dev veth1 up
# Setup vpeer1 in the netns:
ip link set dev vpeer1 netns ns1
ip netns exec ns1 ip link set dev lo up
ip netns exec ns1 ip -6 address add $peeripv6/128 dev vpeer1
ip netns exec ns1 ip -6 route add $myipv6/128 dev vpeer1
ip netns exec ns1 ip link set vpeer1 up
ip netns exec ns1 ip -6 route add default dev vpeer1 via $peeripv6
# IP forwarding
sysctl -w net.ipv6.conf.default.forwarding=1
# NDP proxy for the netns
ip -6 neigh add proxy $myipv6 dev veth1