X-Git-Url: https://iankelling.org/git/?a=blobdiff_plain;f=newns;h=894ac310b2963866328fe545b20ced78e1d2ceab;hb=f57d11a6635aa26b32085db9aa53d8baedb47944;hp=a2d896d0b13ea33dd9121122f84e7331066ac197;hpb=6b15ac48b3f675a208d18bb267b82305eb8c8457;p=newns diff --git a/newns b/newns index a2d896d..894ac31 100755 --- a/newns +++ b/newns @@ -38,7 +38,7 @@ Nat a network namespace. systemd friendly 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. @@ -48,7 +48,7 @@ Also creates a mount namespace with a cloned /run/resolvconf. 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. @@ -60,9 +60,9 @@ From within a systemd network namespace, we nat it to the outside. This 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 @@ -143,7 +143,6 @@ if $install_error; then fi #### end sanity checking #### - v0=veth0-$nn v1=veth1-$nn ip_base=10.173 @@ -153,22 +152,24 @@ if ! $create && [[ $(readlink /proc/self/ns/net) == "$(readlink /proc/1/ns/net)" 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 @@ -191,7 +192,7 @@ fi nat() { for if in ${gateway_ifs[@]}; do - dexec iptables -t nat $1 POSTROUTING -o $if -j MASQUERADE \ + dexec iptables -t nat $1 POSTROUTING -s $network.0/24 -o $if -j MASQUERADE \ -m comment --comment "systemd network namespace nat" done } @@ -274,7 +275,7 @@ start() { 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 @@ -285,35 +286,38 @@ start() { 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 @@ -328,8 +332,8 @@ stop() { 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