Score:0

Can't chain more than one network namespace together

de flag

Problem Statement

With the below configuration a veth pair is created between the default/main net namespace and a netns called ns1.

The config also creates a second veth pair: veth2 is in netns ns1 and veth3 is in netns ns2, this joins ns1 to ns2 creating the chain: 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

From the default netns I can ping veth0 which is in the same netns. From the default netns I can ping veth1 and veth2 which are both in ns1. From the default netns I can't pint veth3 which is in ns2.

If I extend the change as follows, by adding veth4 in ns2 and veth5 in ns3 I have the same problem. I can ping from any interface in ns1 to any interface in ns2, but can't reach any interface in 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

It seems I am only able to ping an interface in a directly "neighboring" / "connected" netns to the one I am pinging from. I am unable to ping through a chain of net namespaces. The routing is all valid; default netns can ping any interface in ns1 but nothing further, interfaces in ns1 can ping any interface in the default netns or ns2 but nothing in ns3, and ns3 can ping anything in ns2 but nothing beyond in ns1 or the default netns.

Is this a limitation of network namespacaes?

Troubleshooting

IPv6 forwarding is enabled, ip6tables is just set to "allow all", I'm not sure what else to check.

$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
Score:2
in flag

IPv6 forwarding is enabled

Probably not: When I tried this on my system with the commands given at the beginning of the question, I also cannot reach 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

However, when I enable forwarding in ns1

echo 1 | sudo ip netns exec ns1 tee /proc/sys/net/ipv6/conf/all/forwarding

it works:

$ 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

So it's likely you also do not have IPv6 forwarding enabled in ns1. (And remember forwarding is per namespace; did you enable it in the main namespace, but not in ns1?)


I debugged this by doing a tcpdump on each interface; that the pings did not reach veth2 was a sign that forwarding was not enabled.

And if you are wondering "but why can I ping veth2 if forwarding is not enabled": Linux treats all local addresses the same, so you can reach any local address from any interface. This is completely unrelated to forwarding.

BTW, it helps a lot of you run an xterm in each namespace; that makes debugging a lot easier.

jwbensley avatar
de flag
I thought that setting `/proc/sys/net/ipv6/conf/default/forwarding` in the default ns would be inherited into any new ns created. What a fool I have been. Thanks @dirkt.
Score:1
cn flag

I came to the same totally valid conclusion as @dirkt did, each namespace is a network host by itself, including the setting whether it behaves like a router or not (which defaults to off). /proc/sys/net settings are separate for each namespace. resolving is separate, interface links are separate (but hostname isn't, for that you have to create UTS namespaces). So basically that is your answer.

Not to detract in anyway, but for future reference, I will add some things and rearrange and simplify this slightly. You don't actually need the routing setting in your default namespace, unless you would want to route outside traffic to these namespaces or vice versa.

To sum up a construction for default namespace and ns1 plus 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

Some tests you can then do:

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

You can also do some resolving and hosts file changes

# 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
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.