diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0426a8a --- /dev/null +++ b/.dockerignore @@ -0,0 +1,25 @@ +**/.classpath +**/.dockerignore +**/.env +**/.git +**/.gitignore +**/.project +**/.settings +**/.toolstarget +**/.vs +**/.vscode +**/*.*proj.user +**/*.dbmdl +**/*.jfm +**/azds.yaml +**/bin +**/charts +**/docker-compose* +**/compose* +**/Dockerfile* +**/node_modules +**/npm-debug.log +**/obj +**/secrets.dev.yaml +**/values.dev.yaml +README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..23fbb42 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "files.eol": "\n", +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 96dc170..e691f62 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ RUN apt-get update \ && apt-get install -y software-properties-common \ && add-apt-repository ppa:qbittorrent-team/qbittorrent-stable \ && apt-get update \ - && apt-get install -y qbittorrent-nox openvpn curl moreutils net-tools dos2unix kmod iptables ipcalc unrar \ + && apt-get install -y jq traceroute qbittorrent-nox openvpn curl moreutils net-tools dos2unix kmod iptables ipcalc unrar \ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # Add configuration and scripts diff --git a/docker-compose.debug.yml b/docker-compose.debug.yml new file mode 100644 index 0000000..a9203a8 --- /dev/null +++ b/docker-compose.debug.yml @@ -0,0 +1,23 @@ +version: '3.4' + +services: + dockerqbittorrentvpn: + image: dockerqbittorrentvpn + environment: + - VPN_ENABLED=yes + - PIA_PORT_FORWARD=yes + - PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + - NAME_SERVERS=8.8.8.8,8.8.4.4 + - LAN_NETWORK=192.168.12.0/24 + - TZ=MST + - DEBIAN_FRONTEND=noninteractive + ports: + - "8080:8080" + privileged: true + cap_add: + - NET_ADMIN + volumes: + - ~/vpncreds:/config + build: + context: . + dockerfile: ./Dockerfile diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..28b7202 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +version: '3.4' + +services: + dockerqbittorrentvpn: + image: dockerqbittorrentvpn + build: + context: . + dockerfile: ./Dockerfile diff --git a/openvpn/pia_port_forwarding.sh b/openvpn/pia_port_forwarding.sh new file mode 100644 index 0000000..0f62d49 --- /dev/null +++ b/openvpn/pia_port_forwarding.sh @@ -0,0 +1,136 @@ +#!/bin/bash +echo "Starting script" +export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin + +# Vers: 0.1 beta +# Date: 9/14/2020 + +###### PIA Variables ###### +curl_max_time=15 +curl_retry=5 +curl_retry_delay=15 +user='p6131381' +pass='kSrMgK2r4Y' +CONFFILE=/config/qBittorrent/config/qBittorrent.conf + +###### Nextgen PIA port forwarding ################## + +get_auth_token () { + tok=$(curl --insecure --silent --show-error --request POST --max-time $curl_max_time \ + --header "Content-Type: application/json" \ + --data "{\"username\":\"$user\",\"password\":\"$pass\"}" \ + "https://www.privateinternetaccess.com/api/client/v2/token" | jq -r '.token') + [ $? -ne 0 ] && echo "Failed to acquire new auth token" && exit 1 + echo "$tok" +} + +echo "getting token" +get_auth_token #> /dev/null 2>&1 +echo "done getting token" + +bind_port () { + pf_bind=$(curl --insecure --get --silent --show-error \ + --retry $curl_retry --retry-delay $curl_retry_delay --max-time $curl_max_time \ + --data-urlencode "payload=$pf_payload" \ + --data-urlencode "signature=$pf_getsignature" \ + $verify \ + "https://$pf_host:19999/bindPort") + if [ "$(echo $pf_bind | jq -r .status)" != "OK" ]; then + echo "$(date): bindPort error" + echo $pf_bind + fatal_error + fi +} + +get_sig () { + pf_getsig=$(curl --insecure --get --silent --show-error \ + --retry $curl_retry --retry-delay $curl_retry_delay --max-time $curl_max_time \ + --data-urlencode "token=$tok" \ + $verify \ + "https://$pf_host:19999/getSignature") + if [ "$(echo $pf_getsig | jq -r .status)" != "OK" ]; then + echo "$(date): getSignature error" + echo $pf_getsig + fatal_error + fi + pf_payload=$(echo $pf_getsig | jq -r .payload) + pf_getsignature=$(echo $pf_getsig | jq -r .signature) + pf_port=$(echo $pf_payload | base64 -d | jq -r .port) + pf_token_expiry_raw=$(echo $pf_payload | base64 -d | jq -r .expires_at) + if date --help 2>&1 /dev/null | grep -i 'busybox' > /dev/null; then + pf_token_expiry=$(date -D %Y-%m-%dT%H:%M:%S --date="$pf_token_expiry_raw" +%s) + else + pf_token_expiry=$(date --date="$pf_token_expiry_raw" +%s) + fi +} + +pf_port () { + # Get current NAT port number using xmlstarlet to parse the config file. + CURPORT=`cat $CONFFILE | grep PortRangeMin | cut -d\= -f2` + echo "Current Port: $CURPORT" + echo "pia-port: Current port forward: $CURPORT" + # The port mapping doesn't always change. + # We don't want to force pfSense to re-read it's config if we don't need to. + if [ "$CURPORT" = "$pf_port" ]; then + echo "pia-port: Current Port: $CURPORT, PIA Port: $pf_port - Port not changed. Exiting." + # Create the pia_port file, as it's possible it could have been + # removed by external means. + echo $pf_port > /config/pia_port.txt + else + # Port forward has changed, so we update the rules in the config file. + #sed -i.bak 's/^\(download_start_port=\).*/\1'\"$pf_port\"'/' $CONFFILE + source /etc/qbittorrent/qbittorrent.init stop + sleep 5 + sed -i.bak 's/^\(Connection\\PortRangeMin=\).*/\1'$pf_port'/' $CONFFILE + echo "pia-port: New port number ($pf_port) inserted into config file $CONFFILE." + #cat $CONFFILE + # This can then be read by other hosts in order to update the open port in + # whatever torrent client is in use. + echo $pf_port > /config/pia_port.txt + # restart download station to use new port + #PUID=0 PGID=0 /etc/qbittorrent/qbittorrent.init restart + source /etc/qbittorrent/qbittorrent.init start + #/usr/syno/bin/synopkg stop DownloadStation + #/usr/syno/bin/synopkg start DownloadStation + #systemctl start qbittorrent + fi + +} + +# Rebind every 15 mins (same as desktop app) +pf_bindinterval=$(( 15 * 60)) +# Get a new token when the current one has less than this remaining +# Defaults to 7 days (same as desktop app) +pf_minreuse=$(( 60 * 60 * 24 * 7 )) + +pf_remaining=0 +pf_firstrun=1 + +while true; do + echo "starting port forwarding check" + vpn_ip=$(traceroute -m 1 privateinternetaccess.com | tail -n 1 | awk '{print $2}') + pf_host="$vpn_ip" + pf_remaining=$(( $pf_token_expiry - $(date +%s) )) + # Get a new pf token as the previous one will expire soon + if [ $pf_remaining -lt $pf_minreuse ]; then + if [ $pf_firstrun -ne 1 ]; then + echo "$(date): PF token will expire soon. Getting new one." + else + echo "$(date): Getting PF token" + pf_firstrun=0 + + fi + get_sig + echo "$(date): Obtained PF token. Expires at $pf_token_expiry_raw" + bind_port + echo "$(date): Server accepted PF bind" + echo "$(date): Forwarding on port $pf_port" + pf_port + echo "$(date): Rebind interval: $pf_bindinterval seconds" + fi + sleep $pf_bindinterval & + wait $! + + bind_port + +done diff --git a/openvpn/start.sh b/openvpn/start.sh index 3ef9456..345b157 100755 --- a/openvpn/start.sh +++ b/openvpn/start.sh @@ -10,7 +10,7 @@ if [[ ! -z "${check_network}" ]]; then echo "[crit] Network type detected as 'Host', this will cause major issues, please stop the container and switch back to 'Bridge' mode" | ts '%Y-%m-%d %H:%M:%.S' && exit 1 fi -export VPN_ENABLED=$(echo "${VPN_ENABLED}" | sed -e 's~^[ \t]*~~;s~[ \t]*$~~') +export VPN_ENABLED=$(echo "${VPN_ENABLED}" | sed 's/"//g' ) #| sed -e 's~^[ \t]*~~;s~[ \t]*$~~') if [[ ! -z "${VPN_ENABLED}" ]]; then echo "[info] VPN_ENABLED defined as '${VPN_ENABLED}'" | ts '%Y-%m-%d %H:%M:%.S' else @@ -19,6 +19,7 @@ else fi if [[ $VPN_ENABLED == "yes" ]]; then + echo "[info] Initializing OpenVpn" | ts '%Y-%m-%d %H:%M:%.S' # create directory to store openvpn config files mkdir -p /config/openvpn # set perms and owner for files in /config/openvpn directory @@ -131,7 +132,8 @@ if [[ $VPN_ENABLED == "yes" ]]; then echo "[info] VPN_OPTIONS not defined (via -e VPN_OPTIONS)" | ts '%Y-%m-%d %H:%M:%.S' export VPN_OPTIONS="" fi -elif [[ $VPN_ENABLED == "no" ]]; then +#elif [[ $VPN_ENABLED == "no" ]]; then +else echo "[warn] !!IMPORTANT!! You have set the VPN to disabled, you will NOT be secure!" | ts '%Y-%m-%d %H:%M:%.S' fi diff --git a/qbittorrent/start.sh b/qbittorrent/start.sh index a465d73..696733e 100644 --- a/qbittorrent/start.sh +++ b/qbittorrent/start.sh @@ -77,9 +77,17 @@ sleep 1 qbpid=$(pgrep -o -x qbittorrent-nox) echo "[info] qBittorrent PID: $qbpid" | ts '%Y-%m-%d %H:%M:%.S' +export PFWD=$(echo "${PIA_PORT_FORWARD}" | sed 's/"//g' ) + if [ -e /proc/$qbpid ]; then if [[ -e /config/qBittorrent/data/logs/qbittorrent.log ]]; then chmod 775 /config/qBittorrent/data/logs/qbittorrent.log + if [[ $PFWD == "yes" ]]; then + echo "[info] PIA Port forwarding configured, calling pia_port_forwarding.sh" + /bin/bash /etc/openvpn/pia_port_forwarding.sh + else + echo "[info] PIA Port forwarding not enabled" + fi fi sleep infinity else