diff options
-rwxr-xr-x | src/netns-script | 39 | ||||
-rwxr-xr-x | src/vpn_wrapper.sh | 30 |
2 files changed, 61 insertions, 8 deletions
diff --git a/src/netns-script b/src/netns-script index 7c29811..f4380eb 100755 --- a/src/netns-script +++ b/src/netns-script @@ -3,9 +3,14 @@ # adapted from # https://unix.stackexchange.com/questions/149293/feed-all-traffic-through-openvpn-for-a-specific-network-namespace-only -# vpn_wrapper.sh creates another script of name helper_script<timestamp>.sh, -# which gets called by openvpn process, exports NAMESPACE_NAME and WRAPPER_PID -# variables and then runs this script +# vpn_wrapper.sh passes the following variables through openvpn's +# --setenv option: +# NAMESPACE_NAME +# WRAPPER_PID +# VETH_HOST0 +# VETH_HOST1 +# ROUTE_THROUGH_VETH +# PHYSICAL_IP case $script_type in up) @@ -19,19 +24,45 @@ case $script_type in ip netns exec $NAMESPACE_NAME ip addr add dev "$1" \ "$ifconfig_ipv6_local"/112 fi + + # the following is done to enable some connections to bypass vpn + VETH0=v0tdns${WRAPPER_PID}_0 + VETH1=v0tdns${WRAPPER_PID}_1 + ip link add $VETH0 type veth peer name $VETH1 + ip link set $VETH1 netns $NAMESPACE_NAME + ip addr add $VETH_HOST0/30 dev $VETH0 + ip netns exec $NAMESPACE_NAME ip addr add $VETH_HOST1/30 dev $VETH1 + ip link set $VETH0 up + ip netns exec $NAMESPACE_NAME ip link set $VETH1 up ;; route-up) - ip netns exec $NAMESPACE_NAME ip route add default via "$ifconfig_remote" + # TODO change to only forward from necessary interfaces + echo 1 > /proc/sys/net/ipv4/conf/all/forwarding + ip netns exec $NAMESPACE_NAME ip route add default via "$ifconfig_remote" + if [ -n "$ifconfig_ipv6_remote" ]; then ip netns exec $NAMESPACE_NAME ip route add default via \ "$ifconfig_ipv6_remote" fi + # here go routes for bypassing vpn + for ADDRESS in $ROUTE_THROUGH_VETH; do + ip netns exec $NAMESPACE_NAME ip route add $ADDRESS via $VETH_HOST0 + iptables -t nat -A POSTROUTING -s $VETH_HOST1/32 \ + -j SNAT --to-source $PHYSICAL_IP + done + + # notify our sh process, that openvpn finished initializing kill -usr1 $WRAPPER_PID ;; down) + for ADDRESS in $ROUTE_THROUGH_VETH; do + iptables -t nat -D POSTROUTING -s $VETH_HOST1/32 \ + -j SNAT --to-source $PHYSICAL_IP + done + ip netns delete $NAMESPACE_NAME ;; esac diff --git a/src/vpn_wrapper.sh b/src/vpn_wrapper.sh index 848f16e..c3dfaa8 100755 --- a/src/vpn_wrapper.sh +++ b/src/vpn_wrapper.sh @@ -1,14 +1,31 @@ #!/bin/sh OPENVPN_CONFIG="$1" +PHYSICAL_IP="$2" # rest of args is the command to run in network namespace shift +shift + +# for routing some traffic from within the namespace to physical +# network (e.g. database connection) we need to create a veth pair; +# as we want multiple instances of vpn_wrapper.sh to be able to +# run simultaneously, we need unique ip addresses for them; +# the solution is to derive an ip address from current shell's +# PID (which is unique within a system) +NUMBER=$((($$ - 1) * 4)) +WORD0HOST0=$(($NUMBER % 256 + 1)) +WORD0HOST1=$(($NUMBER % 256 + 2)) +NUMBER=$(($NUMBER / 256)) +WORD1=$(($NUMBER % 256)) +NUMBER=$(($NUMBER / 256)) +WORD2=$(($NUMBER % 256)) +VETH_HOST0=10.$WORD2.$WORD1.$WORD0HOST0 +VETH_HOST1=10.$WORD2.$WORD1.$WORD0HOST1 # to enable multiple instances of this script to run simultaneously, # we tag namespace name with this shell's PID - -NETNS_SCRIPT=/var/lib/0tdns/netns-script NAMESPACE_NAME=0tdns$$ +NETNS_SCRIPT=/var/lib/0tdns/netns-script # in case we want some process in the namespace to be able # to resolve domain names via libc we put some random public @@ -17,8 +34,9 @@ NAMESPACE_NAME=0tdns$$ # dns addresses provided by us, it is still possible to pass # a domain name as forwarder address to unbound, in which case # it will try to resolve it first using libc +DEFAULT_DNS=23.253.163.53 mkdir -p /etc/netns/$NAMESPACE_NAME/ -echo nameserver 23.253.163.53 > /etc/netns/$NAMESPACE_NAME/resolv.conf +echo nameserver $DEFAULT_DNS > /etc/netns/$NAMESPACE_NAME/resolv.conf # starts openvpn with our just-created helper script, which calls # the netns-script, which creates tun inside network namespace @@ -28,7 +46,11 @@ openvpn --ifconfig-noexec --route-noexec --up $NETNS_SCRIPT \ --route-up $NETNS_SCRIPT --down $NETNS_SCRIPT \ --config "$OPENVPN_CONFIG" --script-security 2 \ --setenv NAMESPACE_NAME $NAMESPACE_NAME \ - --setenv WRAPPER_PID $$ & + --setenv WRAPPER_PID $$ \ + --setenv VETH_HOST0 $VETH_HOST0 \ + --setenv VETH_HOST1 $VETH_HOST1 \ + --setenv ROUTE_THROUGH_VETH $DEFAULT_DNS/32 \ + --setenv PHYSICAL_IP $PHYSICAL_IP & OPENVPN_PID=$! |