Network namespaces
One feature of Linux that isn't widely known is the ability to have separate network namespaces in a single Linux instance. This enables segregation of network stacks, which can be very useful for testing and running programs without impacting your main network stack.
Here is a very simple example to show it in action.
# ip netns add NEWNS # ip netns exec NEWNS bash # ifconfig -a lo: flags=8<LOOPBACK> mtu 65536 loop txqueuelen 1000 (Local Loopback) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 # route -n Kernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface # ping 127.0.0.1 ping: connect: Network is unreachable
As you can see from this output above, we create a new namespace (NEWNS), and then run a bash shell inside it. The bash shell is started inside the NEWNS namespace, which has no networking configured at all - there are no IP addresses assigned, no devices (other than a loopback device that's not up), and no routes added at all. We're unable to ping 127.0.0.1 (which exists in the main namespace). Any network applications we start (webserver, etc) will be bound to the namespace's network stack and won't be accessible from outside the network namespace. This provides a nice way to test network applications without affecting your main network stack.
VPNs
A more useful example could be the following. You have a VPN (OpenVPN, Wireguard, etc) and you want to use it without affecting the networking on your main machine. The following script will create a new network namespace and start a Wireguard VPN inside it. It assumes you have a working Wireguard setup already.
Run it as your standard user.
NSNAME=wireguard CONF=/etc/wireguard/wg0.conf # Grab the IPs from the config file for later IPV4=$(sudo grep Address ${CONF} | cut -d "=" -f 2 | cut -d "," -f 1) IPV6=$(sudo grep Address ${CONF} | cut -d "=" -f 2 | cut -d "," -f 2) # Set up DNS resolution for the namespace sudo mkdir -p /etc/netns/${NSNAME} sudo bash -c "echo nameserver 8.8.8.8 > /etc/netns/${NSNAME}/resolv.conf" # Create the namespace sudo ip netns add ${NSNAME} # Bind Wireguard to the new namespace sudo ip link add wg0 type wireguard sudo wg setconf wg0 /etc/wireguard/wg0.conf sudo ip link set wg0 netns ${NSNAME} # Add the IPs and routes sudo ip -n ${NSNAME} addr add ${IPV4} dev wg0 sudo ip -n ${NSNAME} addr add ${IPV6} dev wg0 sudo ip -n ${NSNAME} link set wg0 up sudo ip -n ${NSNAME} route add default dev wg0 # Drop the user into a bash shell in the new namespace echo Starting bash in the ${NSNAME} namespace sudo -E ip netns exec ${NSNAME} sudo -E -u \#$(id -u) -g \#$(id -g) bash
After this script has run (assuming no errors), you should be left in a bash shell that only has network access via the VPN.