Created
April 27, 2020 10:29
-
-
Save gustavohenrique/a169a286660efe5abf3bef210ead34de to your computer and use it in GitHub Desktop.
Create a namespace for running applications which are only allowed to use certain network connections
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| set -Eeuo pipefail | |
| if [ "$#" != 2 ] | |
| then | |
| ( | |
| echo "Usage: $0 <vpn-interface> <nameserver>" | |
| echo "" | |
| echo "For example: $0 tun0 8.8.8.8" | |
| echo "" | |
| echo "Warning: This script will flush and create iptables rules!" | |
| exit 1 | |
| ) >&2 | |
| fi | |
| VPN_INTERFACE="${1}" | |
| NNS_NAME="${VPN_INTERFACE}ns" | |
| NNS_VETH_PREFIX="${VPN_INTERFACE}nsi" | |
| NNS_VETH0="${NNS_VETH_PREFIX}0" | |
| NNS_VETH1="${NNS_VETH_PREFIX}1" | |
| IP_ADDRESS_BASE="10.157.0" | |
| NAMESERVER="${2}" | |
| # Clean up old configuration entries | |
| ip link delete "${NNS_VETH0}" || true | |
| ip netns delete "${NNS_NAME}" || true | |
| # Create new network namespace | |
| ip netns add "${NNS_NAME}" | |
| # Create veth pair and move ${NNS_VETH1} into network namespace | |
| ip link add "${NNS_VETH0}" type veth peer name "${NNS_VETH1}" | |
| ip link set "${NNS_VETH1}" netns "${NNS_NAME}" | |
| # Configure non-namespaced interface | |
| ip a a "${IP_ADDRESS_BASE}.1/24" dev "${NNS_VETH0}" | |
| ip link set "${NNS_VETH0}" up | |
| sysctl -q -w "net/ipv6/conf/${NNS_VETH0}/disable_ipv6=1" | |
| # Configure namespaced interface | |
| ip netns exec "${NNS_NAME}" ip a a "${IP_ADDRESS_BASE}.2/24" dev "${NNS_VETH1}" | |
| ip netns exec "${NNS_NAME}" ip link set "${NNS_VETH1}" up | |
| ip netns exec "${NNS_NAME}" ip link set lo up | |
| ip netns exec "${NNS_NAME}" ip route add default via "${IP_ADDRESS_BASE}.1" | |
| ip netns exec "${NNS_NAME}" sysctl -q -w "net/ipv6/conf/${NNS_VETH1}/disable_ipv6=1" | |
| # Enable masquerading for connections from network namespace | |
| iptables -t nat -F | |
| iptables -t nat -A POSTROUTING \ | |
| -s "${IP_ADDRESS_BASE}".0/24 -d 0/0 \ | |
| -j MASQUERADE | |
| # Ensure that data from/to the network namespace must traverse the VPN | |
| # interface | |
| iptables -t filter -F | |
| iptables -t filter -P FORWARD DROP | |
| iptables -t filter -A FORWARD \ | |
| -i "${NNS_VETH0}" -o "${VPN_INTERFACE}" -s "${IP_ADDRESS_BASE}".0/24 -d 0/0 \ | |
| -j ACCEPT | |
| iptables -t filter -A FORWARD \ | |
| -i "${VPN_INTERFACE}" -o "${NNS_VETH0}" -d "${IP_ADDRESS_BASE}".0/24 -s 0/0 \ | |
| -j ACCEPT | |
| # Configure a nameserver for the network namespace | |
| mkdir -p /etc/netns/"${NNS_NAME}" | |
| sh -c 'echo "nameserver '"${NAMESERVER}"'" > /etc/netns/'"${NNS_NAME}"'/resolv.conf' | |
| # Finally, enable forwarding | |
| sysctl -q net.ipv4.ip_forward=1 | |
| if [ "${NAMESERVER}" == "8.8.8.8" ] | |
| then | |
| echo -n "Warning: Your nameserver is set to 8.8.8.8, which will " | |
| echo "expose your DNS queries." | |
| fi | |
| echo | |
| echo -n "VPN-only network namespace ${NNS_NAME} has been set up. To run " | |
| echo "applications in this namespace, use:" | |
| echo " sudo ip netns exec \"${NNS_NAME}\" sudo -u \"${SUDO_USER:-<user>}\" <command>" | |
| echo | |
| echo "For example: " | |
| echo " sudo ip netns exec \"${NNS_NAME}\" sudo -u \"${SUDO_USER:-<user>}\" ping heise.de" | |
| echo | |
| echo -n "Warning: Ensure that all programs you start are actually performing " | |
| echo -n "network operations inside the network namespace. For example, if you " | |
| echo -n "use Firefox and a Firefox instance is already running outside the " | |
| echo -n "network namespace, the new instance will also be running outside it. " | |
| echo -n "You can easily check if traffic is limited to the VPN interface by " | |
| echo "disabling the VPN and trying to use the application." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment