Saturday 12 March 2022

systemd service inside a namespace

 Network namespaces are a very versatile feature in Linux. Here we implement a service (dhclient) in an isolated namespace.

 This implementation was tested  on a NanoPi R4S - 1GB . 


 

This kit has two gigabit ethernet interfaces. eth0 is the wan interface and at startup systemd service moves this interface to red  namespace and linked by a veth pair to the main namespace.

There are three files involved in this systemd approach. Two template files and one service file.

netns@.service

This service called as netns@red.service where red is %i in the script
 
[Unit]
Description=Named network namespace %i
StopWhenUnneeded=true
[Service]
Type=oneshot
RemainAfterExit=yes
PrivateNetwork=yes

ExecStart=/sbin/ip netns add %i
ExecStart=/bin/umount /var/run/netns/%i
ExecStart=/bin/mount --bind /proc/self/ns/net /var/run/netns/%i

ExecStop=/sbin/ip netns delete %i
ExecStop=iptables -F -t nat
 

attach-eth0@.service

invoked as attach-eth0@red.service, (%i = red)
 
[Unit]
Description=Attach eth0 to Named network namespace %i and link with a veth pair
Requires=netns@%i.service
After=netns@%i.service
PartOf=red.service

[Service]
Type=oneshot
RemainAfterExit=yes


ExecStart=/sbin/ip link set eth0 netns %i
ExecStart=/sbin/ip netns exec %i ip l set up dev eth0
ExecStart=/sbin/ip link add veth-%i0 type veth peer name  veth-%i1
ExecStart=/sbin/ip link set veth-%i1 netns %i
ExecStart=/sbin/ip netns exec %i ip a a 192.168.99.1/24  dev veth-%i1
ExecStart=/sbin/ip a a 192.168.99.2/24  dev veth-%i0
ExecStart=/sbin/ip l s up dev veth-%i0
ExecStart=/sbin/ip r a default via 192.168.99.1  dev veth-%i0
ExecStart=/sbin/ip netns exec %i ip l set up dev veth-%i1
ExecStart=/sbin/ip netns exec %i ip l set up dev lo 
ExecStart=/sbin/ip netns exec %i iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE 
ExecStart=/sbin/ip netns exec %i sysctl -w net.ipv4.ip_forward=1 
ExecStart=iptables -t nat -A POSTROUTING -o veth-%i0 -j MASQUERADE 
ExecStart=sysctl -w net.ipv4.ip_forward=1 


ExecStop=/sbin/ip netns exec red iptables -F 
ExecStop=/sbin/ip netns exec red iptables -F -t nat
ExecStop=/sbin/ip netns exec %i ip a f  dev veth-%i1 
ExecStop=/sbin/ip a f 192.168.99.2/24  dev veth-%i0
ExecStop=/sbin/ip link delete veth-%i0
ExecStop=/sbin/ip netns exec %i ip l set down dev eth0
 
the parameter PartOf ensures this service is shut off when the calling service is stopped.
 
 

red.service

[Unit]
Description=Systemd service for red namespace

# Require the network namespace is set up
Requires=netns@red.service
After=netns@red.service
JoinsNamespaceOf=netns@red.service

# Require the interface is set up
Requires=attach-eth0@red.service
After=attach-eth0@red.service

[Service]
Type=simple

PrivateNetwork=true
ExecStart=/sbin/ip netns exec red /sbin/dhclient -4 eth0



[Install]
WantedBy=multi-user.target
 

 when systemctl start red.service is invoked, the "Requires" stanza starts attach-eth0@red.service & netns@red.service. 

 

footnote : This method may not be very processor efficient.