From 37313145a7812b1f57bf6f61a82cbcdb28dbd70b Mon Sep 17 00:00:00 2001 From: Jay Shridharani Date: Mon, 9 Mar 2015 10:40:23 -0400 Subject: [PATCH] Initial commit --- .gitignore | 1 + Dockerfile | 68 +++++++++++++++++++ apps/checkip.sh | 25 +++++++ apps/openvpn.sh | 6 ++ config/ca.crt | 23 +++++++ config/crl.pem | 11 +++ config/openvpn.ovpn | 20 ++++++ delugevpn.conf | 5 ++ nzbget.conf | 5 ++ startnzbget.sh | 19 ++++++ startvpn.sh | 162 ++++++++++++++++++++++++++++++++++++++++++++ 11 files changed, 345 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 apps/checkip.sh create mode 100644 apps/openvpn.sh create mode 100644 config/ca.crt create mode 100644 config/crl.pem create mode 100644 config/openvpn.ovpn create mode 100644 delugevpn.conf create mode 100644 nzbget.conf create mode 100644 startnzbget.sh create mode 100644 startvpn.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9c4ec36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +nzbgetvpn_dockerrun.txt diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f85a695 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,68 @@ +FROM binhex/arch-base:2015022600 +MAINTAINER binhex + +# additional files +################## +## NZBGET +# copy prerun bash shell script (checks for existence of nzbget config) +ADD startnzbget.sh /home/nobody/start.sh + +# add supervisor conf file for app +ADD nzbget.conf /etc/supervisor/conf.d/nzbget.conf + +## openVPN +# add supervisor conf file for app +ADD delugevpn.conf /etc/supervisor/conf.d/delugevpn.conf + +# add bash script to create tun adapter, setup ip route and create vpn tunnel +ADD startvpn.sh /root/start.sh + +# add bash script to run openvpn +ADD apps/openvpn.sh /root/openvpn.sh + +# add bash script to check tunnel ip is valid +ADD apps/checkip.sh /home/nobody/checkip.sh + +# add pia certificates +ADD config/ca.crt /home/nobody/ca.crt +ADD config/crl.pem /home/nobody/crl.pem + +# add sample openvpn.ovpn file (based on pia netherlands) +ADD config/openvpn.ovpn /home/nobody/openvpn.ovpn + +# install app +############# + +# install install app using pacman, set perms, cleanup +RUN pacman -Sy --noconfirm && \ + pacman -S nzbget --noconfirm && \ + pacman -S net-tools openvpn unrar unzip p7zip --noconfirm && \ + chmod +x /root/start.sh /root/openvpn.sh /home/nobody/checkip.sh && \ + chown -R nobody:users /usr/bin/nzbget /usr/share/nzbget/nzbget.conf /home/nobody/start.sh && \ + chmod -R 775 /usr/bin/nzbget /usr/share/nzbget/nzbget.conf /home/nobody/start.sh && \ + yes|pacman -Scc && \ + rm -rf /usr/share/locale/* && \ + rm -rf /usr/share/man/* && \ +# rm -rf /root/* && \ + rm -rf /tmp/* + +# docker settings +################# + +# map /config to host defined config path (used to store configuration from app) +VOLUME /config + +# map /data to host defined data path (used to store downloads or use blackhole) +VOLUME /data + +# map /media to host defined media path (used to read/write to media library) +VOLUME /media + +# expose port for http +EXPOSE 6789 + +# run supervisor +################ + +# run supervisor +CMD ["supervisord", "-c", "/etc/supervisor.conf", "-n"] \ No newline at end of file diff --git a/apps/checkip.sh b/apps/checkip.sh new file mode 100644 index 0000000..df7dbdb --- /dev/null +++ b/apps/checkip.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +# create function to check tunnel local ip is valid +check_valid_ip() { + + IP_ADDRESS="$1" + + # check if the format looks right + echo "$IP_ADDRESS" | egrep -qE '[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}' || return 1 + + # check that each octect is less than or equal to 255 + echo $IP_ADDRESS | awk -F'.' '$1 <=255 && $2 <= 255 && $3 <=255 && $4 <= 255 {print "Y" } ' | grep -q Y || return 1 + + return 0 +} + +# loop and wait until adapter tun0 local ip is valid +LOCAL_IP="" +while ! check_valid_ip "$LOCAL_IP" +do + sleep 0.1 + LOCAL_IP=`ifconfig tun0 2>/dev/null | grep 'inet' | grep -P -o -m 1 '(?<=inet\s)[^\s]+'` +done + +echo "[info] OpenVPN local ip is $LOCAL_IP" \ No newline at end of file diff --git a/apps/openvpn.sh b/apps/openvpn.sh new file mode 100644 index 0000000..f681016 --- /dev/null +++ b/apps/openvpn.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +echo "[info] Starting OpenVPN..." + +# run openvpn to create tunnel +/usr/bin/openvpn --cd /config/openvpn --config "$VPN_CONFIG" \ No newline at end of file diff --git a/config/ca.crt b/config/ca.crt new file mode 100644 index 0000000..6cbfe8b --- /dev/null +++ b/config/ca.crt @@ -0,0 +1,23 @@ +-----BEGIN CERTIFICATE----- +MIID2jCCA0OgAwIBAgIJAOtqMkR2JSXrMA0GCSqGSIb3DQEBBQUAMIGlMQswCQYD +VQQGEwJVUzELMAkGA1UECBMCT0gxETAPBgNVBAcTCENvbHVtYnVzMSAwHgYDVQQK +ExdQcml2YXRlIEludGVybmV0IEFjY2VzczEjMCEGA1UEAxMaUHJpdmF0ZSBJbnRl +cm5ldCBBY2Nlc3MgQ0ExLzAtBgkqhkiG9w0BCQEWIHNlY3VyZUBwcml2YXRlaW50 +ZXJuZXRhY2Nlc3MuY29tMB4XDTEwMDgyMTE4MjU1NFoXDTIwMDgxODE4MjU1NFow +gaUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJPSDERMA8GA1UEBxMIQ29sdW1idXMx +IDAeBgNVBAoTF1ByaXZhdGUgSW50ZXJuZXQgQWNjZXNzMSMwIQYDVQQDExpQcml2 +YXRlIEludGVybmV0IEFjY2VzcyBDQTEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHBy +aXZhdGVpbnRlcm5ldGFjY2Vzcy5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ +AoGBAOlVlkHcxfN5HAswpryG7AN9CvcvVzcXvSEo91qAl/IE8H0knKZkIAhe/z3m +hz0t91dBHh5yfqwrXlGiyilplVB9tfZohvcikGF3G6FFC9j40GKP0/d22JfR2vJt +4/5JKRBlQc9wllswHZGmPVidQbU0YgoZl00bAySvkX/u1005AgMBAAGjggEOMIIB +CjAdBgNVHQ4EFgQUl8qwY2t+GN0pa/wfq+YODsxgVQkwgdoGA1UdIwSB0jCBz4AU +l8qwY2t+GN0pa/wfq+YODsxgVQmhgaukgagwgaUxCzAJBgNVBAYTAlVTMQswCQYD +VQQIEwJPSDERMA8GA1UEBxMIQ29sdW1idXMxIDAeBgNVBAoTF1ByaXZhdGUgSW50 +ZXJuZXQgQWNjZXNzMSMwIQYDVQQDExpQcml2YXRlIEludGVybmV0IEFjY2VzcyBD +QTEvMC0GCSqGSIb3DQEJARYgc2VjdXJlQHByaXZhdGVpbnRlcm5ldGFjY2Vzcy5j +b22CCQDrajJEdiUl6zAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAByH +atXgZzjFO6qctQWwV31P4qLelZzYndoZ7olY8ANPxl7jlP3YmbE1RzSnWtID9Gge +fsKHi1jAS9tNP2E+DCZiWcM/5Y7/XKS/6KvrPQT90nM5klK9LfNvS+kFabMmMBe2 +llQlzAzFiIfabACTQn84QLeLOActKhK8hFJy2Gy6 +-----END CERTIFICATE----- diff --git a/config/crl.pem b/config/crl.pem new file mode 100644 index 0000000..278adac --- /dev/null +++ b/config/crl.pem @@ -0,0 +1,11 @@ +-----BEGIN X509 CRL----- +MIIBgTCB6zANBgkqhkiG9w0BAQ0FADCBpTELMAkGA1UEBhMCVVMxCzAJBgNVBAgT +Ak9IMREwDwYDVQQHEwhDb2x1bWJ1czEgMB4GA1UEChMXUHJpdmF0ZSBJbnRlcm5l +dCBBY2Nlc3MxIzAhBgNVBAMTGlByaXZhdGUgSW50ZXJuZXQgQWNjZXNzIENBMS8w +LQYJKoZIhvcNAQkBFiBzZWN1cmVAcHJpdmF0ZWludGVybmV0YWNjZXNzLmNvbRcN +MTQwNTA3MTgwOTE5WhcNMjQwNTA3MTgwOTE5WjAUMBICAQEXDTE0MDQyODIyMDMy +NVowDQYJKoZIhvcNAQENBQADgYEA4EA2wjio+BxYFui1mBj5gmypxUQyA7xQJ3Vo +cwWSllQKHpfmQ7fwyTL22uc21W9hM4geD1FwoXDUEraQjfyBJOxJwc6GOhTN2wHv +3vplKjdbXmxxAfjduBvlIB0a6qSz1L6hwZJrZUGimlWS9NQrmYaKLbtG07n2UyA+ +mqz5bEc= +-----END X509 CRL----- diff --git a/config/openvpn.ovpn b/config/openvpn.ovpn new file mode 100644 index 0000000..6539ceb --- /dev/null +++ b/config/openvpn.ovpn @@ -0,0 +1,20 @@ +client +dev tun +proto udp +remote nl.privateinternetaccess.com 1194 +ping 600 +ping-restart 1200 +resolv-retry infinite +nobind +persist-key +persist-tun +ca ca.crt +tls-client +remote-cert-tls server +auth-user-pass credentials.conf +comp-lzo +verb 1 +reneg-sec 0 +crl-verify crl.pem + + diff --git a/delugevpn.conf b/delugevpn.conf new file mode 100644 index 0000000..acc7b52 --- /dev/null +++ b/delugevpn.conf @@ -0,0 +1,5 @@ +[program:start] +autorestart = false +startsecs = 0 +user = root +command = /root/start.sh \ No newline at end of file diff --git a/nzbget.conf b/nzbget.conf new file mode 100644 index 0000000..5e7b813 --- /dev/null +++ b/nzbget.conf @@ -0,0 +1,5 @@ +[program:nzbget] +user = nobody +startsecs = 0 +autorestart = False +command = /home/nobody/start.sh \ No newline at end of file diff --git a/startnzbget.sh b/startnzbget.sh new file mode 100644 index 0000000..1bed935 --- /dev/null +++ b/startnzbget.sh @@ -0,0 +1,19 @@ +#!/bin/bash + +# check if nzbget.conf exists, if not copy sample config +if [[ -f /config/nzbget.conf ]]; then + + echo "nzbget.conf exists" + +else + + # copy to /config + cp /usr/share/nzbget/nzbget.conf /config/ + + # set maindir to /data folder for downloads + sed -i 's/MainDir=~\/downloads/MainDir=\/data/g' /config/nzbget.conf + +fi + +#run nzbget specifying config path and daemon flag +/usr/bin/nzbget -D -c /config/nzbget.conf \ No newline at end of file diff --git a/startvpn.sh b/startvpn.sh new file mode 100644 index 0000000..0882369 --- /dev/null +++ b/startvpn.sh @@ -0,0 +1,162 @@ +#!/bin/bash + +# create directory +mkdir -p /config/openvpn + +# wildcard search for openvpn config files +VPN_CONFIG=$(find /config/openvpn -maxdepth 1 -name "*.ovpn" -print) + +# if vpn provider not provided then exit +if [[ -z "${VPN_PROV}" ]]; then + echo "[crit] VPN provider not defined, please specify via env variable VPN_PROV" && exit 1 + +# if custom|airvpn vpn provider chosen then do not copy base config file +elif [[ $VPN_PROV == "custom" || $VPN_PROV == "airvpn" ]]; then + + echo "[info] VPN provider defined as $VPN_PROV" + if [[ -z "${VPN_CONFIG}" ]]; then + echo "[crit] VPN provider defined as $VPN_PROV, no files with an ovpn extension exist in /config/openvpn/ please create and restart delugevpn" && exit 1 + fi + +# if pia vpn provider chosen then copy base config file and pia certs +elif [[ $VPN_PROV == "pia" ]]; then + + # copy default certs + echo "[info] VPN provider defined as $VPN_PROV" + cp -f /home/nobody/ca.crt /config/openvpn/ca.crt + cp -f /home/nobody/crl.pem /config/openvpn/crl.pem + + # if no ovpn files exist then copy base file + if [[ -z "${VPN_CONFIG}" ]]; then + cp -f "/home/nobody/openvpn.ovpn" "/config/openvpn/openvpn.ovpn" + fi + + # if remote or port not specified then use netherlands + if [[ -z "${VPN_REMOTE}" || -z "${VPN_PORT}" ]]; then + echo "[warn] VPN provider remote and/or port not defined, defaulting to Netherlands" + sed -i -e "s/remote\s.*/remote nl.privateinternetaccess.com 1194/g" "/config/openvpn/openvpn.ovpn" + else + echo "[info] VPN provider remote and port defined as $VPN_REMOTE $VPN_PORT" + sed -i -e "s/remote\s.*/remote $VPN_REMOTE $VPN_PORT/g" "/config/openvpn/openvpn.ovpn" + fi + + # store credentials in separate file for authentication + if ! $(grep -Fxq "auth-user-pass credentials.conf" /config/openvpn/openvpn.ovpn); then + sed -i -e 's/auth-user-pass/auth-user-pass credentials.conf/g' /config/openvpn/openvpn.ovpn + fi + + # write vpn username to file + if [[ -z "${VPN_USER}" ]]; then + echo "[crit] VPN username not specified" && exit 1 + else + echo "${VPN_USER}" > /config/openvpn/credentials.conf + fi + + # append vpn password to file + if [[ -z "${VPN_PASS}" ]]; then + echo "[crit] VPN password not specified" && exit 1 + else + echo "${VPN_PASS}" >> /config/openvpn/credentials.conf + fi + +# if provider none of the above then exit +else + echo "[crit] VPN Provider unknown, please specify airvpn, pia, or custom" && exit 1 +fi + +# customise openvpn.ovpn to ping tunnel every 10 mins +if ! $(grep -Fxq "ping 600" "$VPN_CONFIG"); then + sed -i '/remote\s.*/a ping 600' "$VPN_CONFIG" +fi + +# customise openvpn.ovpn to restart tunnel after 20 mins if no reply from ping +if ! $(grep -Fxq "ping-restart 1200" "$VPN_CONFIG"); then + sed -i '/ping 600/a ping-restart 1200' "$VPN_CONFIG" +fi + +# read port number and protocol from openvpn.ovpn (used to define iptables rule) +VPN_PORT=$(cat "$VPN_CONFIG" | grep -P -o -m 1 '^remote\s[^\r\n]+' | grep -P -o -m 1 '[\d]+$') +VPN_PROTOCOL=$(cat "$VPN_CONFIG" | grep -P -o -m 1 '(?<=proto\s)[^\r\n]+') + +# set permissions to user nobody +chown -R nobody:users /config/openvpn +chmod -R 775 /config/openvpn + +# create the tunnel device +[ -d /dev/net ] || mkdir -p /dev/net +[ -c /dev/net/tun ] || mknod /dev/net/tun c 10 200 + +# get gateway ip for eth0 +DEFAULT_GATEWAY=$(ip route show default | awk '/default/ {print $3}') + +# setup route for nzbget webui using set-mark to route traffic for port 6789 to eth0 +echo "6789 webui" >> /etc/iproute2/rt_tables +ip rule add fwmark 1 table webui +ip route add default via $DEFAULT_GATEWAY table webui + +echo "[info] ip route" +ip route +echo "--------------------" + +# set policy to drop for input +iptables -P INPUT DROP + +# accept input to tunnel adapter +iptables -A INPUT -i tun0 -j ACCEPT + +# accept input to vpn gateway +iptables -A INPUT -p $VPN_PROTOCOL -i eth0 --sport $VPN_PORT -j ACCEPT + +# accept input to nzbget webui port 6789 +iptables -A INPUT -p tcp -i eth0 --dport 6789 -j ACCEPT +iptables -A INPUT -p tcp -i eth0 --sport 6789 -j ACCEPT + +# accept input dns lookup +iptables -A INPUT -p udp --sport 53 -j ACCEPT + +# accept input icmp (ping) +iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT + +# accept input to local loopback +iptables -A INPUT -i lo -j ACCEPT + +# set policy to drop for output +iptables -P OUTPUT DROP + +# accept output to tunnel adapter +iptables -A OUTPUT -o tun0 -j ACCEPT + +# accept output to vpn gateway +iptables -A OUTPUT -p $VPN_PROTOCOL -o eth0 --dport $VPN_PORT -j ACCEPT + +# accept output to nzbget webui port 6789 (used when tunnel down) +iptables -A OUTPUT -p tcp -o eth0 --dport 6789 -j ACCEPT +iptables -A OUTPUT -p tcp -o eth0 --sport 6789 -j ACCEPT + +# accept output to mzbget webui port 6789 (used when tunnel up) +iptables -t mangle -A OUTPUT -p tcp --dport 6789 -j MARK --set-mark 1 +iptables -t mangle -A OUTPUT -p tcp --sport 6789 -j MARK --set-mark 1 + +# accept output dns lookup +iptables -A OUTPUT -p udp --dport 53 -j ACCEPT + +# accept output icmp (ping) +iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT + +# accept output to local loopback +iptables -A OUTPUT -o lo -j ACCEPT + +echo "[info] iptables" +iptables -S +echo "--------------------" + +# add in google public nameservers (isp may block ns lookup when connected to vpn) +echo 'nameserver 8.8.8.8' > /etc/resolv.conf +echo 'nameserver 8.8.4.4' >> /etc/resolv.conf + +echo "[info] nameservers" +cat /etc/resolv.conf +echo "--------------------" + +# start openvpn tunnel +source /root/openvpn.sh \ No newline at end of file