aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWojciech Kosior <kwojtus@protonmail.com>2020-05-29 12:58:12 +0200
committerWojciech Kosior <kwojtus@protonmail.com>2020-05-29 12:58:12 +0200
commitc03e009d01ebe2e55a4383e934385dabd9ea0749 (patch)
tree95228b48146ae05e19005246831b450171f901ac /src
parent459fd487fcbdc33fcccddbf4c82eae048275ba51 (diff)
download0tdns-c03e009d01ebe2e55a4383e934385dabd9ea0749.tar.gz
0tdns-c03e009d01ebe2e55a4383e934385dabd9ea0749.zip
move sources to src/
Diffstat (limited to 'src')
-rwxr-xr-xsrc/hourly.py20
-rwxr-xr-xsrc/hourly.sh3
-rwxr-xr-xsrc/netns-script38
-rwxr-xr-xsrc/perform_queries.py39
-rwxr-xr-xsrc/vpn_wrapper.sh68
5 files changed, 168 insertions, 0 deletions
diff --git a/src/hourly.py b/src/hourly.py
new file mode 100755
index 0000000..543ed20
--- /dev/null
+++ b/src/hourly.py
@@ -0,0 +1,20 @@
+#!/bin/python3
+
+from sys import argv
+import subprocess
+
+wrapper = '/var/lib/0tdns/vpn_wrapper.sh'
+perform_queries = '/var/lib/0tdns/perform_queries.py'
+
+def get_vpn_connections(hour):
+ # TODO query database for the necessary information,
+ # for now, return some sample though-up data
+ return (
+ # vpn_id | config_path
+ (14, "./vpngate_178.254.251.12_udp_1195.ovpn"),
+ (13, "./vpngate_public-vpn-229.opengw.net_tcp_443.ovpn")
+ )
+
+hour = argv[1]
+for vpn_id, config_path in get_vpn_connections(hour):
+ subprocess.run([wrapper, config_path, perform_queries, hour])
diff --git a/src/hourly.sh b/src/hourly.sh
new file mode 100755
index 0000000..be1c52a
--- /dev/null
+++ b/src/hourly.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+hourly.py "`date '+%Y-%m-%d %H:00'`"
diff --git a/src/netns-script b/src/netns-script
new file mode 100755
index 0000000..ba2d226
--- /dev/null
+++ b/src/netns-script
@@ -0,0 +1,38 @@
+#!/bin/sh
+
+# 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
+
+case $script_type in
+ up)
+ env
+ ip netns add $NAMESPACE_NAME
+ ip netns exec $NAMESPACE_NAME ip link set dev lo up
+ ip link set dev "$1" up netns $NAMESPACE_NAME mtu "$2"
+ ip netns exec $NAMESPACE_NAME ip addr add dev "$1" \
+ "$4/${ifconfig_netmask:-30}" \
+ ${ifconfig_broadcast:+broadcast "$ifconfig_broadcast"}
+ if [ -n "$ifconfig_ipv6_local" ]; then
+ ip netns exec $NAMESPACE_NAME ip addr add dev "$1" \
+ "$ifconfig_ipv6_local"/112
+ fi
+ ;;
+ route-up)
+ 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
+
+ # notify our sh process, that openvpn finished initializing
+ kill -usr1 $WRAPPER_PID
+ ;;
+ down)
+ ip netns delete $NAMESPACE_NAME
+ ;;
+esac
diff --git a/src/perform_queries.py b/src/perform_queries.py
new file mode 100755
index 0000000..4762e14
--- /dev/null
+++ b/src/perform_queries.py
@@ -0,0 +1,39 @@
+#!/bin/python3
+
+import unbound
+
+def query_planned_queries(hour, vpn_id):
+ # TODO query database
+ # for now, return some sample thought-up data
+ return (
+ # dns server IP | dns server id | service_id | service_name
+ ("195.98.79.117", 23, ((89, "devuan.org"),
+ (44, "gry.pl"),
+ (112, "invidio.us"))),
+ ("192.71.245.208", 33, ((77, "debian.org"),
+ (22, "nie.ma.takiej.domeny"),
+ (100, "onet.pl")))
+ )
+
+def resolve_call_back(mydata, status, result):
+ dns_id, service_id = mydata
+ # TODO write to database
+ print("callback called for {}".format(result.qname))
+ if status==0 and result.havedata:
+ print("Result:",result.data.address_list)
+
+# hour from argv | vpn_id in database
+contexts = []
+for dns_addr, dns_id, services in query_planned_queries("1999-01-08 04:00", 11):
+ ctx = unbound.ub_ctx()
+ ctx.set_fwd(dns_addr)
+ for service_id, service_name in services:
+ print(service_name)
+ print("starting resolution: {} through {}".format(service_name, dns_addr))
+ ctx.resolve_async(service_name, (dns_id, service_id),
+ resolve_call_back,
+ unbound.RR_TYPE_A, unbound.RR_CLASS_IN)
+ contexts.append(ctx)
+
+for ctx in contexts:
+ ctx.wait()
diff --git a/src/vpn_wrapper.sh b/src/vpn_wrapper.sh
new file mode 100755
index 0000000..b4b9350
--- /dev/null
+++ b/src/vpn_wrapper.sh
@@ -0,0 +1,68 @@
+#!/bin/sh
+
+OPENVPN_CONFIG="$1"
+# rest of args is the command to run in network namespace
+shift
+
+# just in case something causes more instances of this script
+# to run simultaneously, we timestamp some names
+SECONDS=`date '+%s'`
+
+HELPER_SCRIPT=/var/lib/0tdns/helper_script$SECONDS.sh
+NAMESPACE_NAME=0tdns$SECONDS
+
+# we create another script as a way of passing variables
+# to netns-script
+cat > $HELPER_SCRIPT <<EOF
+#!/bin/sh
+
+export NAMESPACE_NAME=$NAMESPACE_NAME
+export WRAPPER_PID=$$
+
+/var/lib/0tdns/netns-script "\$@"
+EOF
+
+chmod u+x $HELPER_SCRIPT
+
+# in case we want some process in the namespace to be able
+# to resolve domain names via libc we put some random public
+# dns in namespace sepcific's resolv.conf;
+# note, that while libunbound we're using will probably have
+# 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
+mkdir -p /etc/netns/$NAMESPACE_NAME/
+echo nameserver 23.253.163.53 > /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
+# of name $NAMESPACE_NAME
+# we could consider using --daemon option instead of &
+openvpn --ifconfig-noexec --route-noexec --up $HELPER_SCRIPT \
+ --route-up $HELPER_SCRIPT --down $HELPER_SCRIPT \
+ --config "$OPENVPN_CONFIG" --script-security 2 &
+
+OPENVPN_PID=$!
+
+# waiting for signal from our netns script
+# https://stackoverflow.com/questions/9052847/implementing-infinite-wait-in-shell-scripting
+trap true usr1
+
+# wait on openvpn process;
+# if we get a signal - wait will terminate;
+# if openvpn process dies - wait will also terminate
+wait $OPENVPN_PID
+
+# TODO check which of 2 above mention situations occured and
+# return from script with error code if openvpn process died
+
+# run the provided command inside newly created namespace
+# under '0tdns' user;
+sudo ip netns exec $NAMESPACE_NAME sudo -u 0tdns "$@"
+
+# close the connection
+kill $OPENVPN_PID
+wait $OPENVPN_PID
+
+# we no longer need those
+rm -r $HELPER_SCRIPT /etc/netns/$NAMESPACE_NAME/