Fun with Linux Network Namespaces
source link: http://www.linux-admins.net/2015/07/fun-with-linux-network-namespaces.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Fun with Linux Network Namespaces
A feature of the Linux kernel called namespace isolation [1] defines groups of separated processes such that each process cannot "see" resources in the other groups. This is a form of lightweight process virtualization used in some container implementations such as LXC.
There are currently six namespaces implementations:
- mnt: mount points and filesystems isolation
- pid: process isolation
- net: network stack isolation
- ipc: System V IPC isolation
- uts: hostname isolation
- user: user isolation by means of UIDs
In this post I'll show few examples of how to create network namespaces and use them with Open vSwitch.
A network namespace is a separate copy of the network stack - it contains its own routes, network devices and iptables rules. It is defined in include/net/net_namespace.h where each device belongs to only one network namespace.
There's always the default network namespace, called the root namespace where all network interfaces are assigned to:
root@ovs-tests:~# ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether bc:76:4e:11:b5:87 brd ff:ff:ff:ff:ff:ff 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether bc:76:4e:11:b7:85 brd ff:ff:ff:ff:ff:ff root@ovs-tests:~# ip a s 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether bc:76:4e:11:b5:87 brd ff:ff:ff:ff:ff:ff inet 104.130.212.227/24 brd 104.130.212.255 scope global eth0 valid_lft forever preferred_lft forever inet6 2001:4801:7827:101:be76:4eff:fe11:b587/64 scope global valid_lft forever preferred_lft forever inet6 fe80::be76:4eff:fe11:b587/64 scope link valid_lft forever preferred_lft forever 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether bc:76:4e:11:b7:85 brd ff:ff:ff:ff:ff:ff inet 10.210.102.116/19 brd 10.210.127.255 scope global eth1 valid_lft forever preferred_lft forever inet6 fe80::be76:4eff:fe11:b785/64 scope link valid_lft forever preferred_lft forever root@ovs-tests:~# ip r default via 104.130.212.1 dev eth0 10.176.0.0/12 via 10.210.96.1 dev eth1 10.208.0.0/12 via 10.210.96.1 dev eth1 10.210.96.0/19 dev eth1 proto kernel scope link src 10.210.102.116 104.130.212.0/24 dev eth0 proto kernel scope link src 104.130.212.227
Now lets create 2 network namespaces called ns1 and ns2 and list them:
root@ovs-tests:~# ip netns add ns1 root@ovs-tests:~# ip netns add ns2 root@ovs-tests:~# ip netns ns2 ns1 root@ovs-tests:~# ls -la /var/run/netns/ total 0 drwxr-xr-x 2 root root 80 Jul 20 14:54 . drwxr-xr-x 19 root root 600 Jul 20 14:54 .. -r--r--r-- 1 root root 0 Jul 20 14:54 ns1 -r--r--r-- 1 root root 0 Jul 20 14:54 ns2 root@ovs-tests:~#
To execute a command inside the namespace:
root@ovs-tests:~# ip netns exec ns1 ip link 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 root@ovs-tests:~# ip netns exec ns1 bash root@ovs-tests:~# ip link 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 root@ovs-tests:~# exit exit root@ovs-tests:~#
We can use "ip netns exec ns1 command" where command is either the actual command we want to execute or bash, which puts us in the namespace's shell, where we can run commands as usual without the need of prefixing them with "ip netns exec ns1".
As you can see the ns1 namespace only contains the loopback interface in a DOWN state. The same is true for the ns2 network namespace.
To connect the two lets first create a software switch using Open vSwitch:
root@ovs-tests:~# apt-get update && apt-get install openvswitch-switch root@ovs-tests:~# ovs-vsctl add-br OVS-1 root@ovs-tests:~# ovs-vsctl show cad47b00-2d1d-4149-9031-d369592d6d88 Bridge "OVS-1" Port "OVS-1" Interface "OVS-1" type: internal ovs_version: "2.3.0" root@ovs-tests:~# ip a s OVS-1 5: OVS-1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default link/ether c6:e3:a0:8b:47:49 brd ff:ff:ff:ff:ff:ff
To create the two pairs run:
root@ovs-tests:~# ip link add eth1-ns1 type veth peer name veth-ns1 root@ovs-tests:~# ip link add eth1-ns2 type veth peer name veth-ns2 root@ovs-tests:~# ip link 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether bc:76:4e:11:b5:87 brd ff:ff:ff:ff:ff:ff 3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000 link/ether bc:76:4e:11:b7:85 brd ff:ff:ff:ff:ff:ff 4: ovs-system: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default link/ether 36:ff:6e:ca:01:ae brd ff:ff:ff:ff:ff:ff 5: OVS-1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default link/ether c6:e3:a0:8b:47:49 brd ff:ff:ff:ff:ff:ff 6: veth-ns1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 2e:eb:33:7b:62:86 brd ff:ff:ff:ff:ff:ff 7: eth1-ns1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether de:0c:5f:c2:1c:0d brd ff:ff:ff:ff:ff:ff 8: veth-ns2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether 56:6e:02:21:15:1f brd ff:ff:ff:ff:ff:ff 9: eth1-ns2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether b6:e3:94:fe:be:23 brd ff:ff:ff:ff:ff:ff
First lets connect one end of the virtual connections to each name space:
root@ovs-tests:~# ip link set eth1-ns1 netns ns1 root@ovs-tests:~# ip netns exec ns1 ip link 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 7: eth1-ns1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether de:0c:5f:c2:1c:0d brd ff:ff:ff:ff:ff:ff root@ovs-tests:~# root@ovs-tests:~# ip link set eth1-ns2 netns ns2 root@ovs-tests:~# ip netns exec ns2 ip link 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 9: eth1-ns2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000 link/ether b6:e3:94:fe:be:23 brd ff:ff:ff:ff:ff:ff root@ovs-tests:~#
Then lets connect the other end to a port on the OVS:
root@ovs-tests:~# ovs-vsctl add-port OVS-1 veth-ns1 root@ovs-tests:~# ovs-vsctl add-port OVS-1 veth-ns2 root@ovs-tests:~# ovs-vsctl show cad47b00-2d1d-4149-9031-d369592d6d88 Bridge "OVS-1" Port "veth-ns2" Interface "veth-ns2" Port "OVS-1" Interface "OVS-1" type: internal Port "veth-ns1" Interface "veth-ns1" ovs_version: "2.3.0" root@ovs-tests:~#
In the root namespace lets bring the veth-ns1/2 interfaces up:
root@ovs-tests:~# ip link set veth-ns1 up root@ovs-tests:~# ip link set veth-ns2 up
root@ovs-tests:~# ip netns exec ns1 ip link set dev lo up root@ovs-tests:~# ip netns exec ns1 ip link set dev eth1-ns1 up root@ovs-tests:~# ip netns exec ns1 ip address add 192.168.0.1/24 dev eth1-ns1 root@ovs-tests:~# ip netns exec ns1 ip a s 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 7: eth1-ns1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether de:0c:5f:c2:1c:0d brd ff:ff:ff:ff:ff:ff inet 192.168.0.1/24 scope global eth1-ns1 valid_lft forever preferred_lft forever inet6 fe80::dc0c:5fff:fec2:1c0d/64 scope link valid_lft forever preferred_lft forever root@ovs-tests:~# root@ovs-tests:~# ip netns exec ns2 ip link set dev lo up root@ovs-tests:~# ip netns exec ns2 ip link set dev eth1-ns2 up root@ovs-tests:~# ip netns exec ns2 ip address add 192.168.0.2/24 dev eth1-ns2 root@ovs-tests:~# ip netns exec ns2 ip a s 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 9: eth1-ns2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether b6:e3:94:fe:be:23 brd ff:ff:ff:ff:ff:ff inet 192.168.0.2/24 scope global eth1-ns2 valid_lft forever preferred_lft forever inet6 fe80::b4e3:94ff:fefe:be23/64 scope link valid_lft forever preferred_lft forever root@ovs-tests:~#
root@ovs-tests:~# ip netns exec ns1 ping -c 3 192.168.0.2 PING 192.168.0.2 (192.168.0.2) 56(84) bytes of data. 64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.237 ms 64 bytes from 192.168.0.2: icmp_seq=2 ttl=64 time=0.066 ms 64 bytes from 192.168.0.2: icmp_seq=3 ttl=64 time=0.059 ms
--- 192.168.0.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1999ms rtt min/avg/max/mdev = 0.059/0.120/0.237/0.083 ms root@ovs-tests:~# ip netns exec ns2 ping -c 3 192.168.0.1 PING 192.168.0.1 (192.168.0.1) 56(84) bytes of data. 64 bytes from 192.168.0.1: icmp_seq=1 ttl=64 time=0.215 ms 64 bytes from 192.168.0.1: icmp_seq=2 ttl=64 time=0.051 ms 64 bytes from 192.168.0.1: icmp_seq=3 ttl=64 time=0.061 ms
--- 192.168.0.1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2000ms rtt min/avg/max/mdev = 0.051/0.109/0.215/0.075 ms root@ovs-tests:~#
root@ovs-tests:~# ip netns exec ns1 bash root@ovs-tests:~# ip a s 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 7: eth1-ns1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether de:0c:5f:c2:1c:0d brd ff:ff:ff:ff:ff:ff inet 192.168.0.1/24 scope global eth1-ns1 valid_lft forever preferred_lft forever inet6 fe80::dc0c:5fff:fec2:1c0d/64 scope link valid_lft forever preferred_lft forever root@ovs-tests:~# dnsmasq --interface=eth1-ns1 --dhcp-range=192.168.0.100,192.168.0.200,255.255.255.0 root@ovs-tests:~# pgrep -lf dnsmasq 13219 dnsmasq root@ovs-tests:~# exit exit root@ovs-tests:~# ip netns exec ns2 bash root@ovs-tests:~# dhclient -r Killed old client process root@ovs-tests:~# ip a s 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 9: eth1-ns2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether b6:e3:94:fe:be:23 brd ff:ff:ff:ff:ff:ff inet6 fe80::b4e3:94ff:fefe:be23/64 scope link valid_lft forever preferred_lft forever root@ovs-tests:~# dhclient eth1-ns2 root@ovs-tests:~# ip a s 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 9: eth1-ns2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether b6:e3:94:fe:be:23 brd ff:ff:ff:ff:ff:ff inet 192.168.0.195/24 brd 192.168.0.255 scope global eth1-ns2 valid_lft forever preferred_lft forever inet6 fe80::b4e3:94ff:fefe:be23/64 scope link valid_lft forever preferred_lft forever root@ovs-tests:~# exit exit root@ovs-tests:~#
root@ovs-tests:~# tail -f /var/log/syslog Jul 20 16:25:31 localhost dnsmasq[13219]: started, version 2.72 cachesize 150 Jul 20 16:25:31 localhost dnsmasq[13219]: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect Jul 20 16:25:31 localhost dnsmasq-dhcp[13219]: DHCP, IP range 192.168.0.100 -- 192.168.0.200, lease time 1h Jul 20 16:25:31 localhost dnsmasq[13219]: reading /etc/resolv.conf Jul 20 16:25:31 localhost dnsmasq[13219]: using nameserver 173.203.4.9#53 Jul 20 16:25:31 localhost dnsmasq[13219]: using nameserver 173.203.4.8#53 Jul 20 16:25:31 localhost dnsmasq[13219]: ignoring nameserver 192.168.0.1 - local interface Jul 20 16:25:31 localhost dnsmasq[13219]: read /etc/hosts - 4 addresses Jul 20 16:26:03 localhost dhclient: Killed old client process Jul 20 16:26:04 localhost dhclient: DHCPRELEASE on eth1-ns2 to 192.168.0.1 port 67 Jul 20 16:26:04 localhost dnsmasq-dhcp[13219]: DHCPRELEASE(eth1-ns1) 192.168.0.195 b6:e3:94:fe:be:23 Jul 20 16:26:25 localhost dhclient: DHCPDISCOVER on eth1-ns2 to 255.255.255.255 port 67 interval 4 Jul 20 16:26:25 localhost dnsmasq[13219]: reading /etc/resolv.conf Jul 20 16:26:25 localhost dnsmasq[13219]: using nameserver 173.203.4.9#53 Jul 20 16:26:25 localhost dnsmasq[13219]: using nameserver 173.203.4.8#53 Jul 20 16:26:25 localhost dnsmasq-dhcp[13219]: DHCPDISCOVER(eth1-ns1) 192.168.0.195 b6:e3:94:fe:be:23 Jul 20 16:26:25 localhost dnsmasq-dhcp[13219]: DHCPOFFER(eth1-ns1) 192.168.0.195 b6:e3:94:fe:be:23 Jul 20 16:26:25 localhost dhclient: DHCPREQUEST on eth1-ns2 to 255.255.255.255 port 67 Jul 20 16:26:25 localhost dhclient: DHCPOFFER from 192.168.0.1 Jul 20 16:26:25 localhost dnsmasq-dhcp[13219]: DHCPREQUEST(eth1-ns1) 192.168.0.195 b6:e3:94:fe:be:23 Jul 20 16:26:25 localhost dnsmasq-dhcp[13219]: DHCPACK(eth1-ns1) 192.168.0.195 b6:e3:94:fe:be:23 ovs-tests Jul 20 16:26:28 localhost dhclient: DHCPREQUEST on eth1-ns2 to 255.255.255.255 port 67 Jul 20 16:26:28 localhost dnsmasq-dhcp[13219]: DHCPREQUEST(eth1-ns1) 192.168.0.195 b6:e3:94:fe:be:23 Jul 20 16:26:28 localhost dnsmasq-dhcp[13219]: DHCPACK(eth1-ns1) 192.168.0.195 b6:e3:94:fe:be:23 ovs-tests Jul 20 16:26:28 localhost dhclient: DHCPACK from 192.168.0.1 Jul 20 16:26:28 localhost dhclient: bound to 192.168.0.195 -- renewal in 1499 seconds.
root@ovs-tests:~# ovs-vsctl set port veth-ns1 tag=100 root@ovs-tests:~# ovs-vsctl set port veth-ns2 tag=200 root@ovs-tests:~# ovs-vsctl show cad47b00-2d1d-4149-9031-d369592d6d88 Bridge "OVS-1" Port "veth-ns2" tag: 200 Interface "veth-ns2" Port "OVS-1" Interface "OVS-1" type: internal Port "veth-ns1" tag: 100 Interface "veth-ns1" ovs_version: "2.3.0" root@ovs-tests:~#
Now connectivity between both ns1 and ns2 should be lost.
Resources:
[1]. http://man7.org/linux/man-pages/man7/namespaces.7.html
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK