Skip to content

Commit

Permalink
Initial project setup
Browse files Browse the repository at this point in the history
  • Loading branch information
Sudip Bhattarai committed Jan 12, 2023
0 parents commit ec23bae
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 0 deletions.
36 changes: 36 additions & 0 deletions Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# usernetns
Helpers for Setting private network namespace per-user basis. It provides cli helper and example systemd-service file.

## Install
```
sudo ./install.sh
```

## Quick Start
1) Run a command inside network namespace ( create if not present )
```
sudo usenetnsexe "$(whoami)" ifconfig
```

2) Run [test-systemd-service](./lib/systemd/system/usernetnstest%40.service)
```
sudo systemctl start "usernetnstest@$(whoami)".service
journalctl -a --no-pager -u "usernetnstest@$(whoami)".service
```


## Commands provided
- `makebridge name ipAddress ` : Helper for creating bridge interface and setting it up
- `makeusernetns userName` : Setup namespace for a user
- `usernetnsexe userName command` : Setup namespace if not set up and run a command on namespace of that user. The command is run as root.

## Services

1) `usernetns-bridge.service` : Sets up bridge for working with user network namespaces

2) `usernetns@.service` : Sets up network namespace for per-user
Usage: let's say that your username is `username`, to setup network namespace for `username`

`systemctl start usernetns@myusername.service`

3) `usernetnstest@.service` : An example service that can be started per-user basis, on that user's network namespace.
4 changes: 4 additions & 0 deletions etc/usernetns.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
USERNETNS_BRIDGE=userswitch
USERNETNS_BRIDGE_IP=172.31.6.0/24
USERNETNS_DNS=172.21.0.6
USERNETNS_NAMESPACE_DEV=eth0
36 changes: 36 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/bin/bash
INSTALL_PATH=${INSTALL_PATH:-""}

function doInstall(){
local arg1="$1"
shift
echo + install ".$arg1" " $INSTALL_PATH$arg1" "$@"
install "./$arg1" "$INSTALL_PATH$arg1" "$@"
}
function doUninstall(){
echo + rm -f "$1"
rm -f "$1"

}
function perform(){
$1 /lib/systemd/system/usernetns-bridge.service
$1 /lib/systemd/system/usernetnstest@.service
$1 /lib/systemd/system/usernetns@.service
$1 /usr/local/bin/makebridge
$1 /usr/local/bin/makeusernetns
$1 /usr/local/bin/usernetnsexec
$1 /etc/usernetns.conf

}

if [ "$1" == "uninstall" ]
then
perform doUninstall
elif [ "$#" == "0" ] || [ "$1" == "install"]
then
set -e
perform doInstall
else
echo "Unknown options: " "$@" 1>&2
exit 1
fi
25 changes: 25 additions & 0 deletions lib/systemd/system/usernetns-bridge.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[Unit]
Description=Bridge for per-user network namespace

After=network-online.target nss-lookup.target
Wants=network-online.target nss-lookup.target

[Service]
Type=oneshot
RemainAfterExit=yes
EnvironmentFile=/etc/usernetns.conf

ExecStartPost=iptables -A FORWARD -i ${USERNETNS_BRIDGE} -j ACCEPT
ExecStartPost=iptables -A FORWARD -o ${USERNETNS_BRIDGE} -j ACCEPT
ExecStartPost=iptables -t nat -A POSTROUTING -o enp2s0 -j MASQUERADE

ExecStart=makebridge ${USERNETNS_BRIDGE} USERNETNS_BRIDGE_IP

ExecStopPost=iptables -D FORWARD -i ${USERNETNS_BRIDGE} -j ACCEPT
ExecStopPost=iptables -D FORWARD -o ${USERNETNS_BRIDGE} -j ACCEPT
ExecStopPost=iptables -t nat -D POSTROUTING -o enp2s0 -j MASQUERADE


[Install]
WantedBy=multi-user.target

14 changes: 14 additions & 0 deletions lib/systemd/system/usernetns@.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[Unit]
Description=Setup private network namespace for user (%i)
After=usernetns-bridge.service
Wants=usernetns-bridge.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=makeusernetns %i
ExecStop=ip netns delete %i

[Install]
WantedBy=multi-user.target

19 changes: 19 additions & 0 deletions lib/systemd/system/usernetnstest@.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[Unit]
Description=Demo usernetns instance (%i)
After=usernetns@%i.service
Wants=usernetns@%i.service

[Service]
NetworkNamespacePath=/var/run/netns/%i
WorkingDirectory=/home/%i
PrivateMounts=true
User= %i
Group= %i
BindPaths=/etc/netns/%i/resolv.conf:/etc/resolv.conf
Type=oneshot
#ExecStartPre=!mount --bind /etc/netns/%i/resolv.conf /etc/resolv.conf
#ExecStartPre=!mount -t sysfs none /sys
ExecStart=/bin/bash -c "set -x ;whoami; ip addr show; ip route; cat /etc/resolv.conf ;ls /sys/class/net | head; "
[Install]
WantedBy=multi-user.target

31 changes: 31 additions & 0 deletions usr/local/bin/makebridge
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash


set -e
if (( $# != 2 )); then

>&2 echo "Usage: makebridge name ipAddress"
>&2 echo "eg :"
>&2 echo " : makebridge br0 10.0.1.0/24"

exit 1
fi


BRIDGE_DEV=$1
BRIDGE_IP=$2
NAMESPACE_DEV=eth0


set -x
# setup bridge
function makebridge() {
ip link add ${BRIDGE_DEV} type bridge
ip link set ${BRIDGE_DEV} up

# setup bridge ip
ip addr add ${BRIDGE_IP} dev ${BRIDGE_DEV}
}
(ip link show ${BRIDGE_DEV} && ip link delete $BRIDGE_DEV && false ) || makebridge


57 changes: 57 additions & 0 deletions usr/local/bin/makeusernetns
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/bash
source /etc/usernetns.conf
set -e
if (( $# != 1 && $# != 2 )); then

>&2 echo "Usage: makeusernetns UserName [bridge=userswitch]"
exit 1
fi

function failreturn(){
>&2 echo "makeusernetns: $1" && false
}

USERNETNS_BRIDGE_IP=172.31.31.0/24

USERNAME=$1
USERID="$(id -u $USERNAME )"

test $USERID -ge 1000 || failreturn "Expected uid to be > 1000";
test $USERID -lt 1252 || failreturn "Expected uid to be < 1252"


NAMESPACE=$USERNAME
USERNETNS_BRIDGE=${2:-"${USERNETNS_BRIDGE:-userswitch}"}
USERNETNS_NAMESPACE_DEV="${USERNETNS_NAMESPACE_DEV:-eth0}"
USERNETNS_DNS=${USERNETNS_DNS:-"8.8.8.8"}


ip link show ${USERNETNS_BRIDGE} 2>&1 >/dev/null || failreturn "Bridge \"$USERNETNS_BRIDGE\" doesn't exist"

BRIDGE_IP="$(ip -4 addr show $USERNETNS_BRIDGE | grep inet | grep -oe '[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*' | tail -n 1)"
IP_PREFIX="$(echo $BRIDGE_IP | grep -oe '^[0-9]*\.[0-9]*\.[0-9]*' | tail -n 1)"
NAMESPACE_IP="$IP_PREFIX.$(( $USERID - 999 ))/24"


test ! -z "$BRIDGE_IP" || failreturn "Bridge \"$USERNETNS_BRIDGE\" doesn't have ip set"
mkdir -p /etc/netns/$NAMESPACE
set -x
test -f "/etc/netns/$NAMESPACE/resolve.conf" || echo "nameserver $USERNETNS_DNS" > "/etc/netns/$NAMESPACE/resolv.conf"
# delete namespace if exists
(ip netns list | grep -e '^\w*' -o | grep -e '^'$NAMESPACE'$' 2>&1 >/dev/null ) && ip netns delete $NAMESPACE


# create namespace
ip netns add $NAMESPACE

# create veth link
ip link delete "veth_$NAMESPACE" || true
ip link add "veth_$NAMESPACE" type veth peer name $USERNETNS_NAMESPACE_DEV netns $NAMESPACE
ip link set "veth_$NAMESPACE" up
ip link set "veth_$NAMESPACE" master ${USERNETNS_BRIDGE}

ip netns exec $NAMESPACE sh -c "\
ip link set dev $USERNETNS_NAMESPACE_DEV up && \
ip link set dev lo up &&\
ip addr add $NAMESPACE_IP dev $USERNETNS_NAMESPACE_DEV &&\
ip route add default via ${BRIDGE_IP} dev $USERNETNS_NAMESPACE_DEV"
28 changes: 28 additions & 0 deletions usr/local/bin/usernetnsexec
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/bin/bash

source /etc/usernetns.conf
set -e
if (( $# < 2 )); then
>&2 echo "usernetnsexec"
>&2 echo " Automatically makes bridge and namespace if required and runs the program on that namespace "
>&2 echo " runonusernetns UserName command [commandargs]"
exit 1
fi

function failreturn(){
>&2 echo $1 && false
}

NAMESPACE=$1
USERNETNS_BRIDGE=${USERNETNS_BRIDGE:-"userswitch"}
USERNETNS_BRIDGE_IP=${USERNETNS_BRIDGE_IP:-"172.31.31.0/24"}

# make bridge if not exists
ip link show ${BRIDGE_DEV} > /dev/null|| makebridge ${BRIDGE_DEV} ${BRIDGE_IP}/24

# make namespace if not exists
(ip netns list | grep -e '^\w*' -o | grep -e '^'$NAMESPACE'$' 2>&1 >/dev/null ) || makeusernetns

shift
exec ip netns exec $NAMESPACE su - $USERNAME -c "$*"

0 comments on commit ec23bae

Please sign in to comment.