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.