specify full path to openvpn
[0tDNS.git] / src / vpn_wrapper.sh
blob38eeabafba5512c631c132110a2ffbdd85b711b2
1 #!/bin/sh
3 # We give the full path, because PATH environment variable
4 # might be unset if run by cron
5 OVPN_COMMAND="/usr/sbin/openvpn"
7 OPENVPN_CONFIG="$1"
8 PHYSICAL_IP="$2"
9 ROUTE_THROUGH_VETH="$3"
10 # rest of args is the command to run in network namespace
11 shift
12 shift
13 shift
15 # for routing some traffic from within the namespace to physical
16 # network (e.g. database connection) we need to create a veth pair;
17 # as we want multiple instances of vpn_wrapper.sh to be able to
18 # run simultaneously, we need unique ip addresses for them;
19 # the solution is to derive an ip address from current shell's
20 # PID (which is unique within a system)
21 NUMBER=$((($$ - 1) * 4))
22 WORD0HOST0=$(($NUMBER % 256 + 1))
23 WORD0HOST1=$(($NUMBER % 256 + 2))
24 NUMBER=$(($NUMBER / 256))
25 WORD1=$(($NUMBER % 256))
26 NUMBER=$(($NUMBER / 256))
27 WORD2=$(($NUMBER % 256))
28 VETH_HOST0=10.$WORD2.$WORD1.$WORD0HOST0
29 VETH_HOST1=10.$WORD2.$WORD1.$WORD0HOST1
31 # to enable multiple instances of this script to run simultaneously,
32 # we tag namespace name with this shell's PID
33 NAMESPACE_NAME=0tdns$$
34 NETNS_SCRIPT=/var/lib/0tdns/netns-script
36 # in case we want some process in the namespace to be able
37 # to resolve domain names via libc we put some random public
38 # dns in namespace sepcific's resolv.conf;
39 # note, that while libunbound we're using will probably have
40 # dns addresses provided by us, it is still possible to pass
41 # a domain name as forwarder address to unbound, in which case
42 # it will try to resolve it first using libc
43 DEFAULT_DNS=23.253.163.53
44 mkdir -p /etc/netns/$NAMESPACE_NAME/
45 echo nameserver $DEFAULT_DNS > /etc/netns/$NAMESPACE_NAME/resolv.conf
47 # starts openvpn with our just-created helper script, which calls
48 # the netns-script, which creates tun inside network namespace
49 # of name $NAMESPACE_NAME
50 # we could consider using --daemon option instead of &
51 $OVPN_COMMAND --ifconfig-noexec --route-noexec --up $NETNS_SCRIPT \
52 --route-up $NETNS_SCRIPT --down $NETNS_SCRIPT \
53 --config "$OPENVPN_CONFIG" --script-security 2 \
54 --connect-timeout 20 \
55 --setenv NAMESPACE_NAME $NAMESPACE_NAME \
56 --setenv WRAPPER_PID $$ \
57 --setenv VETH_HOST0 $VETH_HOST0 \
58 --setenv VETH_HOST1 $VETH_HOST1 \
59 --setenv ROUTE_THROUGH_VETH $ROUTE_THROUGH_VETH\ $DEFAULT_DNS/32 \
60 --setenv PHYSICAL_IP $PHYSICAL_IP &
62 OPENVPN_PID=$!
64 # waiting for signal from our netns script
65 # https://stackoverflow.com/questions/9052847/implementing-infinite-wait-in-shell-scripting
66 trap true usr1
68 # wait on openvpn process;
69 # if we get a signal - wait will terminate;
70 # if openvpn process dies - wait will also terminate
71 wait $OPENVPN_PID
73 # TODO check which of 2 above mention situations occured and
74 # return from script with error code if openvpn process died
76 # run the provided command inside newly created namespace
77 # under '0tdns' user;
78 sudo ip netns exec $NAMESPACE_NAME sudo -u 0tdns "$@"
80 # close the connection
81 kill $OPENVPN_PID
82 wait $OPENVPN_PID
84 # we no longer need those
85 rm -r /etc/netns/$NAMESPACE_NAME/