Also creates a mount namespace with a cloned /run/resolvconf.
--c, --create Create a named network namespace. When running from
+-c, --create Create or destroy a named network namespace. When running from
the same network namespace as pid 1, this is set automatically.
A systemd created private network is in a network namespace
different than pid 1.
From a normal shell:
-If we do create the netns, to join it with a shell, we can do
+If we do create the netns, to join it with a shell, we can do (as root)
/usr/bin/nsenter --mount=/root/mount_namespaces/NAME --net=/var/run/netns/NAME bash
If you dont care about the mount namespace, you can leave that option off.
would be called from ExecStartPre, and or subsequent units called with
JoinsNamespaceOf= and PrivateNetwork=true.
-We also create a named mount namespace under /root/mount_namespaces, so we
-can alter some system config for this namespace. systemd
-command lines would be prefixed with:
+If resolvconf is installed, we create a named mount namespace under
+/root/mount_namespaces, so we can alter some system config for this
+namespace. systemd command lines would be prefixed with:
/usr/bin/nsenter --mount=/root/mount_namespaces/NS_NAME
fi
#### end sanity checking ####
-
v0=veth0-$nn
v1=veth1-$nn
ip_base=10.173
fi
# make the default network namespace be named
+
+mkdir -p /run/netns
target=/run/netns/default
if [[ ! -e $target && ! -L $target ]]; then
- mkdir -p /run/netns
- ln -s /proc/1/ns/net $target
+ # -f to avoid a race condition with running twice
+ ln -sf /proc/1/ns/net $target
fi
-
ipd() { ip -n default "$@"; }
+
+
+# otherwise we are already in the network namespace and it's unnamed.
if $create; then
- # run ip in the network namespace
- ipnn() { ip -n $nn "$@"; }
-else
- # we are already in the network namespace and it's unnamed.
- # run ip in the network namespace
- ipnn() { ip "$@"; }
+ ipnnargs="-n $nn"
fi
+# run ip in the network namespace
+ipnn() { ip $ipnnargs "$@"; }
+
# default network namespace exec
dexec() { ip netns exec default "$@"; }
# mount namespace exec
diptables-add FORWARD -o $v0 -j ACCEPT
- _errcatch_cleanup=stop
+ err-cleanup() { stop; }
ipnn link add $v0 type veth peer name $v1
ipnn link set $v0 netns default
ipd addr add $network.1/24 dev $v0
ipnn route add default via $network.1
###### begin setup resolvconf
- resolv_copy=/root/resolvconf-$nn
+ if [[ -e /run/resolvconf ]]; then # resolvconf probably installed
+ resolv_copy=/root/resolvconf-$nn
- # this condition should never happen, just coding defensively
- if mexec mountpoint /run/resolvconf &>/dev/null; then
- mexec umount /run/resolvconf
- fi
- cp -aT /run/resolvconf $resolv_copy
- if ! mexec mount -o bind $resolv_copy /run/resolvconf; then
- echo "error: resolv-conf bindmount failed"
- exit 1
- fi
- # if running dnsmasq, we have 127.0.0.1 for dns, but it can't listen on the loopback
- # in the network namespace, so adjust the address.
- if mexec [ -s /run/resolvconf/interface/lo.dnsmasq ]; then
- mexec sed --follow-symlinks -i "s/nameserver 127\..*/nameserver $network.1/" /run/resolvconf/interface/lo.dnsmasq
- mexec resolvconf -u
- fi
- # and in debian based distros at least, it runs with --local-service, and needs a restart
- # to know about the new local network
- if [[ $(systemctl --no-pager show -p ActiveState dnsmasq ) == ActiveState=active ]]; then
- systemctl restart dnsmasq
- fi
+ # this condition should never happen, just coding defensively
+ if mexec mountpoint /run/resolvconf &>/dev/null; then
+ mexec umount /run/resolvconf
+ fi
+ cp -aT /run/resolvconf $resolv_copy
+ if ! mexec mount -o bind $resolv_copy /run/resolvconf; then
+ echo "error: resolv-conf bindmount failed"
+ exit 1
+ fi
+ # if running dnsmasq, we have 127.0.0.1 for dns, but it can't listen on the loopback
+ # in the network namespace, so adjust the address.
+ if mexec [ -s /run/resolvconf/interface/lo.dnsmasq ]; then
+ mexec sed --follow-symlinks -i "s/nameserver 127\..*/nameserver $network.1/" /run/resolvconf/interface/lo.dnsmasq
+ mexec resolvconf -u
+ fi
+ # and in debian based distros at least, it runs with --local-service, and needs a restart
+ # to know about the new local network
+ if [[ $(systemctl --no-pager show -p ActiveState dnsmasq ) == ActiveState=active ]]; then
+ systemctl restart dnsmasq
+ fi
+
+ # background: if we did this in openvpn's resolv-conf script, we could guard it in
+ # if capsh --print|grep '\bcap_sys_admin\b' &>/dev/null
+ # and we could get $nn by
+ # config_basename=${config%%.*}
+ # config_basename=${config_basename##*/}
+ # but dnsmasq forces us to do it earlier.
- # background: if we did this in openvpn's resolv-conf script, we could guard it in
- # if capsh --print|grep '\bcap_sys_admin\b' &>/dev/null
- # and we could get $nn by
- # config_basename=${config%%.*}
- # config_basename=${config_basename##*/}
- # but dnsmasq forces us to do it earlier.
+ fi # end if [[ -e /run/resolvconf ]]
###### end setup resolvconf
if ! $existing; then
if nat -C &>/dev/null; then nat -D; fi
fi
- dexec iptables -D FORWARD -i $v0 -j ACCEPT ||:
- if $create && [[ -e /var/run/netns/client ]]; then
+ dexec iptables -D FORWARD -i $v0 -j ACCEPT &>/dev/null ||:
+ if $create && [[ -e /var/run/netns/$nn ]]; then
ip netns del $nn
fi