从网络命名空间

时间:2016-04-05 22:20:28

标签: networking ipv6 linux-containers

我需要从网络名称空间访问外部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

感谢您阅读此问题。建议欢迎:)

编辑:

主机中的路由表:

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

1 个答案:

答案 0 :(得分:4)

ULA不可路由

您已向网络命名空间指定了唯一的本地地址(fc00 :: 2):此IP地址在全球互联网中不可路由,但仅限于您的本地网络。

当您的ISP收到来自该地址的ICMP数据包时,它将丢弃它。即使此数据包成功到达ipv6.google.com,它也无法将答案发回给您,因为此{IP地址为there is no announced route

路由表问题(NDP通知)

由于以下行,您会收到NDP通知:

ip netns exec ns1 ip -6 route add default dev vpeer1

告诉内核(在netns中)vpeer1接口上的所有IP地址直接连接。内核认为这个IP地址存在于以太网链路上:这就是它试图用NDP解析其MAC地址的原因。

相反,你想说通过给定的路由器可以访问它们(在你的情况下,路由器是你的主机):

ip netns exec ns1 ip -6 route add default dev vpeer1 via $myipv6

解决方案

你可以:

  • 公共IPv6地址(公共IPv6前缀)与您的网络相关联,并在主机上设置NDP代理地址;

  • 将您的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