问题陈述
通过以下配置,在默认/主网络命名空间和名为 的 netns 之间创建一个 veth 对ns1
。
该配置还创建了第二个 veth 对:veth2 在 netns 中ns1
,而 veth3 在 netns 中ns2
,这会加入ns1
创建ns2
链:default netns-veth0 <-> veth1-ns1-veth2 <-> veth3-ns2
。
sudo ip link add veth0 type veth peer name veth1
sudo ip -6 addr add CCFF::0/127 peer CCFF::1/127 dev veth0
sudo ip link set up dev veth0
sudo ip netns add ns1
sudo ip link set veth1 netns ns1
sudo ip -n ns1 -6 addr add CCFF::1/127 peer CCFF::0/127 dev veth1
sudo ip -n ns1 link set up dev veth1
sudo ip -n ns1 -6 route add default via CCFF::0
sudo ip link add veth2 type veth peer name veth3
sudo ip link set veth2 netns ns1
sudo ip -n ns1 -6 addr add CCFF::2/127 peer CCFF::3/127 dev veth2
sudo ip -n ns1 link set up dev veth2
sudo ip -n ns1 -6 route add CCFF::/64 via CCFF::3
sudo ip netns add ns2
sudo ip link set veth3 netns ns2
sudo ip -n ns2 -6 addr add CCFF::3/127 peer CCFF::2/127 dev veth3
sudo ip -n ns2 link set up dev veth3
sudo ip -n ns2 -6 route add default via CCFF::2
sudo ip -6 r add CCFF::/64 via CCFF::1
从默认网络,我可以 ping 位于同一网络的 veth0。从默认网络,我可以 ping 位于 中的 veth1 和 veth2 ns1
。从默认网络,我无法 ping 位于 中的 veth3 ns2
。
如果我按如下方式扩展更改,即在 中添加 veth4ns2
并在 中添加 veth5,ns3
则会出现同样的问题。我可以从 中的任何接口 pingns1
到 中的任何接口ns2
,但无法到达 中的任何接口ns3
。
sudo ip link add veth4 type veth peer name veth5
sudo ip link set veth4 netns ns2
sudo ip netns exec ns2 ip -6 addr add CCFF::4/127 peer CCFF::5/127 dev veth4
sudo ip netns exec ns2 ip link set up dev veth4
sudo ip netns exec ns2 ip -6 route add CCFF::/64 via CCFF::5
sudo ip netns add ns3
sudo ip link set veth5 netns ns3
sudo ip netns exec ns3 ip -6 addr add CCFF::5/127 peer CCFF::4/127 dev veth5
sudo ip netns exec ns3 ip link set up dev veth5
sudo ip netns exec ns3 ip -6 route add default via CCFF::4
看来我只能 ping 到与我 ping 的直接“相邻”/“连接”网络中的接口。我无法 ping 过网络命名空间链。路由全部有效;默认网络可以 ping 中的任何接口,ns1
但不能进一步 ping, 中的接口ns1
可以 ping 默认网络中的任何接口或ns2
但不能 ping 中的任何接口ns3
,并且ns3
可以 ping 中的任何内容ns2
但不能pingns1
或默认网络之外的内容。
这是网络命名空间的限制吗?
故障排除
IPv6 转发已启用,ip6tables 仅设置为“允许所有”,我不确定还要检查什么。
$ip -6 r
ccff::1 dev veth0 proto kernel metric 256 pref medium
ccff::/127 dev veth0 proto kernel metric 256 pref medium
ccff::/64 via ccff::1 dev veth0 metric 1024 pref medium
fe80::/64 dev veth0 proto kernel metric 256 pref medium
$sudo ip -n ns1 -6 r
ccff:: dev veth1 proto kernel metric 256 pref medium
ccff::/127 dev veth1 proto kernel metric 256 pref medium
ccff::3 dev veth2 proto kernel metric 256 pref medium
ccff::2/127 dev veth2 proto kernel metric 256 pref medium
ccff::/64 via ccff::3 dev veth2 metric 1024 pref medium
fe80::/64 dev veth1 proto kernel metric 256 pref medium
fe80::/64 dev veth2 proto kernel metric 256 pref medium
default via ccff:: dev veth1 metric 1024 pref medium
$sudo ip -n ns2 -6 r
ccff::2 dev veth3 proto kernel metric 256 pref medium
ccff::2/127 dev veth3 proto kernel metric 256 pref medium
ccff::5 dev veth4 proto kernel metric 256 pref medium
ccff::4/127 dev veth4 proto kernel metric 256 pref medium
ccff::/64 via ccff::5 dev veth4 metric 1024 pref medium
fe80::/64 dev veth3 proto kernel metric 256 pref medium
fe80::/64 dev veth4 proto kernel metric 256 pref medium
default via ccff::2 dev veth3 metric 1024 pref medium
$sudo ip -n ns3 -6 r
ccff::4/127 dev veth5 proto kernel metric 256 linkdown pref medium
default via ccff::4 dev veth5 metric 1024 linkdown pref medium
$cat /proc/sys/net/ipv6/conf/all/forwarding
1
$cat /proc/sys/net/ipv6/conf/default/forwarding
1
$sudo ip6tables-save
# Generated by ip6tables-save v1.8.4 on Wed Nov 17 22:02:48 2021
*filter
:INPUT ACCEPT [76565:173401906]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [50440:6536664]
COMMIT
# Completed on Wed Nov 17 22:02:48 2021
$lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.3 LTS
Release: 20.04
Codename: focal
$uname -a
Linux l13-ubuntu 5.11.0-40-generic #44~20.04.2-Ubuntu SMP Tue Oct 26 18:07:44 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
答案1
已启用 IPv6 转发
可能不是:当我在我的系统上尝试使用问题开头给出的命令时,我也无法达到veth3
:
$ ping -6 CCFF::3
PING CCFF::3(ccff::3) 56 data bytes
^C
--- CCFF::3 ping statistics ---
13 packets transmitted, 0 received, 100% packet loss, time 12290ms
但是,当我在ns1
echo 1 | sudo ip netns exec ns1 tee /proc/sys/net/ipv6/conf/all/forwarding
有用:
$ ping -6 CCFF::3
PING CCFF::3(ccff::3) 56 data bytes
64 bytes from ccff::3: icmp_seq=1 ttl=63 time=0.112 ms
64 bytes from ccff::3: icmp_seq=2 ttl=63 time=0.054 ms
因此,您可能也没有在 中启用 IPv6 转发ns1
。(请记住,转发是每个命名空间;您是否在主命名空间中启用了它,但没有在ns1
?)
我通过tcpdump
在每个接口上执行此操作来调试这个问题;ping 没有到达,veth2
表明转发未启用。
如果您想知道“但是为什么veth2
如果没有启用转发,我可以 ping 通”:Linux 将所有本地地址视为相同,因此您可以从任何接口访问任何本地地址。这与转发完全无关。
顺便说一句,它可以帮助你们xterm
在每个命名空间中运行;这使得调试变得容易得多。
答案2
我得出了与 @dirkt 相同的完全有效的结论,每个命名空间本身都是一个网络主机,包括它是否像路由器一样运行的设置(默认为关闭)。/proc/sys/net 设置对于每个命名空间都是独立的。解析是独立的,接口链接是独立的(但主机名不是,为此您必须创建 UTS 命名空间)。所以基本上这就是您的答案。
无论如何,我都不会贬低它,但为了将来参考,我会添加一些内容并稍微重新安排和简化它。您实际上不需要默认命名空间中的路由设置,除非您想将外部流量路由到这些命名空间或反之亦然。
总结一下默认命名空间和 ns1 加 ns2 的构造。
# create namespaces
ip netns add ns1
ip netns add ns2
# loopbacks, nice to have
ip -n ns1 link set lo up
ip -n ns2 link set lo up
# make veth pairs for each new namespace
ip link add veth0 type veth peer name veth1
ip link add veth2 type veth peer name veth3
# add interfaces to their namespaces
ip link set veth1 netns ns1
ip link set veth2 netns ns1
ip link set veth3 netns ns2
# assign addresses
ip -6 addr add CCFF::0/127 dev veth0
ip -n ns1 -6 addr add CCFF::1/127 dev veth1
ip -n ns1 -6 addr add CCFF::2/127 dev veth2
ip -n ns2 -6 addr add CCFF::3/127 dev veth3
# set the new links to up
ip link set up dev veth0
ip -n ns1 link set up dev veth1
ip -n ns1 link set up dev veth2
ip -n ns2 link set up dev veth3
# namespaces that should forward
ip netns exec ns1 sysctl -w net.ipv6.conf.all.forwarding=1
# route any ip6 outward towards host through namespace 1
ip -n ns2 -6 route add default via CCFF::2
# route any ccff ip6 inward from host
# to a more inner space through namespace 1
ip -6 r add CCFF::/64 via CCFF::1
然后你可以进行一些测试:
ip netns list
ip netns exec ns2 ping6 ccff::0
ip netns exec ns2 ping6 ccff::1
ip netns exec ns2 ping6 ccff::3
# Or put your shell (e.g. bash) in the namespace ns2
ip netns exec ns2 /bin/bash
ping6 ccff::0
exit
您还可以进行一些解析和主机文件更改
# Setup a resolver
# (replace with your own DNS, does not work with a loopback resolver)
mkdir -p /etc/netns/ns2
echo nameserver dns-ip > /etc/netns/ns2/resolv.conf
# Maybe give it its own hosts file, to do edits
cp /etc/hosts /etc/netns/ns2/hosts