Kaynağa Gözat

Added vpn fuctions

neal 4 yıl önce
ebeveyn
işleme
9cf5f0d82b

+ 4 - 0
Dockerfile

@@ -236,9 +236,11 @@ RUN \
 	bsd-compat-headers \
 	bzip2 \
 	curl \
+	dos2unix \
 	ffmpeg \
 	ffmpeg-libs \
 	gnu-libiconv \
+	grep \
 	gzip \
 	libcrypto1.1 \
 	libcurl \
@@ -249,10 +251,12 @@ RUN \
 	libva-intel-driver \
 	intel-media-driver \
 	mesa-dri-ati \
+	moreutils \
 	libvpx \
 	libxml2 \
 	libxslt \
 	linux-headers \
+	openvpn \
 	openssl \
 	opus \
 	pcre2 \

+ 1 - 1
root/etc/cont-init.d/30-config

@@ -2,7 +2,7 @@
 
 # make folders
 mkdir -p \
-	/config/comskip
+	/config/{comskip,openvpn}
 
 # copy config
 [[ ! -e /config/dvr/config ]] && \

+ 1 - 0
root/etc/modules-load.d/tun.conf

@@ -0,0 +1 @@
+tun

+ 31 - 0
root/etc/scripts/dos2unix.sh

@@ -0,0 +1,31 @@
+#!/bin/bash
+
+if [[ -z "${1}" ]]; then
+    echo "No parameter supplied for file to convert" | ts '%Y-%m-%d %H:%M:%S'
+    exit 1
+fi
+
+if [[ ! -f "${1}" ]]; then
+    echo "File '${1}' does not exist" | ts '%Y-%m-%d %H:%M:%S'
+    exit 1
+fi
+
+# create temp files used during the conversion
+TEMP_FILE=$(mktemp /tmp/dos2unixtemp.XXXXXXXXX)
+STDOUT_FILE=$(mktemp /tmp/dos2unixstdout.XXXXXXXXX)
+
+# file to convert
+SOURCE_FILE="${1}"
+
+# run conversion, creating new temp file
+/usr/bin/dos2unix -v -n "${SOURCE_FILE}" "${TEMP_FILE}" > "${STDOUT_FILE}" 2>&1
+
+# if the file required conversion then overwrite (move with force) source file with converted temp file
+if ! cat "${STDOUT_FILE}" | grep -q 'Converted 0'; then
+    echo "Line ending conversion required, moving '${TEMP_FILE}' to '${SOURCE_FILE}'"
+    mv -f "${TEMP_FILE}" "${SOURCE_FILE}"
+fi
+
+# remove temporary files
+rm -f "${TEMP_FILE}"
+rm -f "${STDOUT_FILE}"

+ 35 - 0
root/etc/scripts/health-check.sh

@@ -0,0 +1,35 @@
+#!/bin/bash
+
+#Network check
+# Ping uses both exit codes 1 and 2. Exit code 2 cannot be used for docker health checks,
+# therefore we use this script to catch error code 2
+HOST=${HEALTH_CHECK_HOST}
+
+if [[ -z "$HOST" ]]
+then
+    echo "Host not set! Set env 'HEALTH_CHECK_HOST'. For now, using default google.com" | ts '%Y-%m-%d %H:%M:%S'
+    HOST="google.com"
+fi
+
+ping -c 1 $HOST
+STATUS=$?
+if [[ ${STATUS} -ne 0 ]]
+then
+    echo "Network is down" | ts '%Y-%m-%d %H:%M:%S'
+    exit 1
+fi
+
+echo "Network is up" | ts '%Y-%m-%d %H:%M:%S'
+
+#Service check
+#Expected output is 2 for both checks, 1 for process and 1 for grep
+OPENVPN=$(pgrep openvpn | wc -l )
+
+if [[ ${OPENVPN} -ne 1 ]]
+then
+    echo "OpenVPN process not running" | ts '%Y-%m-%d %H:%M:%S'
+    exit 1
+fi
+
+echo "OpenVPN process is running" | ts '%Y-%m-%d %H:%M:%S'
+exit 0

+ 32 - 0
root/etc/scripts/openvpn-config-clean.sh

@@ -0,0 +1,32 @@
+#!/bin/bash
+
+# convert dos to unix
+/etc/scripts/dos2unix.sh "${1}";
+
+# Remove up/down resolv-conf script calls (Mullvad)
+sed -i "/update-resolv-conf/d" "${1}"
+
+# if 'proto' is old format 'tcp' then replace with newer 'tcp-client' format
+sed -i "s/^proto\stcp$/proto tcp-client/g" "${1}"
+
+# remove persist-tun from ovpn file if present, this allows reconnection to tunnel on disconnect
+#sed -i '/^persist-tun/d' "${1}"
+
+# remove reneg-sec from ovpn file if present, this is removed to prevent re-checks and dropouts
+sed -i '/^reneg-sec.*/d' "${1}"
+
+# remove windows specific openvpn options
+sed -i '/^route-method exe/d' "${1}"
+sed -i '/^service\s.*/d' "${1}"
+sed -i '/^block-outside-dns/d' "${1}"
+
+VPN_DEVICE_TYPE=$(cat "${1}" | grep -P -o -m 1 '(?<=^dev\s)[^\r\n\d]+' | sed -e 's~^[ \t]*~~;s~[ \t]*$~~')
+if [[ ! -z "${VPN_DEVICE_TYPE}" ]]; then
+    # forcibly set virtual network device to 'tun0/tap0'
+    sed -i "s/^dev\s${VPN_DEVICE_TYPE}.*/dev ${VPN_DEVICE_TYPE}/g" "${1}"
+else
+    echo "VPN_DEVICE_TYPE not found in ${1}, deleting file"
+    rm "${1}" && exit 1
+fi
+
+

+ 81 - 0
root/etc/scripts/openvpn-config-validation.sh

@@ -0,0 +1,81 @@
+#!/bin/bash
+
+# if network interface docker0 is present then we are running in host mode and thus must exit
+if [[ ! -z "$(ifconfig | grep docker0 || true)" ]]; then
+    echo "[OpenVPN] docker network type detected as 'Host', this will cause major issues, please stop the container and switch back to 'Bridge'. Exiting..."
+    rm -rf /etc/services.d/openvpn && exit 1
+fi
+
+VPN_PROVIDER="${OPENVPN_PROVIDER,,}"
+echo VPN_PROVIDER is $VPN_PROVIDER
+# Remove the extension so we allow the user to specify or not specify the .ovpn extension
+VPN_CONFIG="$(echo ${OPENVPN_CONFIG} | sed 's/\b.ovpn\b//g')"
+
+# Get the directory where the providers config files sit
+if [[ "${VPN_PROVIDER}" == "custom" ]]; then
+    VPN_PROVIDER_CONFIGS="/config/openvpn"
+
+    # If no file has been specified or the file specified does not exist in the custom directory then find the first file in that directory
+    if [[ ! -f "${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}.ovpn" ]]; then
+        # Remove mac os files before we try find the first
+        rm -rf /config/openvpn/._*.ovpn
+
+        VPN_CONFIG=$(basename -- $(find ${VPN_PROVIDER_CONFIGS} -maxdepth 1 -name "*.ovpn" -print -quit) | sed 's/\b.ovpn\b//g')
+    fi
+
+    # If the file exists then lets clean it and link our credentials files
+    if [[ -f "${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}.ovpn" ]]; then
+        /etc/scripts/openvpn-config-clean.sh "${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}.ovpn"
+        sed -i "s/auth-user-pass.*/auth-user-pass \/config\/openvpn\/custom-openvpn-credentials.txt/g" "${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}.ovpn"
+    fi
+else
+    # Set the pia config file to tcp directory if the protocol is tcp
+    if [[ "${VPN_PROVIDER}" == "pia" && "${OPENVPN_PROTOCOL,,}" == "tcp" ]]; then
+        VPN_PROVIDER_CONFIGS="/etc/openvpn/${VPN_PROVIDER}/tcp"
+    else
+        VPN_PROVIDER_CONFIGS="/etc/openvpn/${VPN_PROVIDER}"
+        # allow for a config file without the _udp (protocol) to be used
+        if [[ ! -f "${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}.ovpn" ]] && [[ -f "${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}_${OPENVPN_PROTOCOL,,}.ovpn" ]]; then
+            VPN_CONFIG="${VPN_CONFIG}_${OPENVPN_PROTOCOL,,}"
+        fi
+    fi
+fi
+
+# Exit out if the provider config directory does not exist
+if [[ ! -d "${VPN_PROVIDER_CONFIGS}" ]]; then
+    echo "[OpenVPN] Could not find provider: ${OPENVPN_PROVIDER}. Exiting..." | ts '%Y-%m-%d %H:%M:%S'
+    rm -rf /etc/services.d/openvpn && exit 1
+fi
+
+if [[ "${VPN_PROVIDER}" == "surfshark" ]] && [[ ! -f "${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}.ovpn" ]]; then
+    # This allows us to use a list similar to PIA list file and try and match it to surfsharks config file. Allows for a somewhat quick transition from PIA to Surfshark
+    SURFSHARK_CLUSTERS_URL='https://my.surfshark.com/vpn/api/v1/server/clusters'
+    LOCATIONS=$(curl -s "${SURFSHARK_CLUSTERS_URL}" | jq -r '.[] | [.countryCode,.location,":",.location,":",.country,":",.connectionName] | @sh' | tr -d "'")
+    readarray -t LOCATIONS_ARRAY <<< "${LOCATIONS//,/$'\n'}"
+
+    ## Try match the config file to SURSHARKS config files
+    for i in "${!LOCATIONS_ARRAY[@]}"; do
+        IFS=: read -r -a VALUES <<< "${LOCATIONS_ARRAY[${i}]}"
+        CODE_AND_LOCATION=$(echo ${VALUES[0]} | sed 's/ *$//g')
+        LOCATION=$(echo ${VALUES[1]} | sed 's/ *$//g')
+        COUNTRY=$(echo ${VALUES[2]} | sed 's/ *$//g')
+        FILE=$(echo ${VALUES[3]} | sed 's/ *$//g')
+
+        if [[ "${CODE_AND_LOCATION}" == "${VPN_CONFIG}" ]] || [[ "${COUNTRY} ${LOCATION}" == "${VPN_CONFIG}" ]] || [[ "${COUNTRY}" == "${VPN_CONFIG}" ]]; then
+            VPN_CONFIG="$(echo "${FILE}" | sed -e 's/\<.ovpn\>//g')_${OPENVPN_PROTOCOL,,}"
+
+            if [[ "${DEBUG}" == "true" ]]; then
+                echo "[OpenVPN] ${VPN_CONFIG} found using the surfshark API" | ts '%Y-%m-%d %H:%M:%S'
+            fi
+        fi
+    done
+fi
+
+if [[ -f "${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}.ovpn" ]]; then
+    echo "[OpenVPN] config file ${VPN_CONFIG}.ovpn found" | ts '%Y-%m-%d %H:%M:%S'
+    VPN_CONFIG="${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}.ovpn"
+else
+    echo "[OpenVPN] supplied config ${VPN_PROVIDER_CONFIGS}/${VPN_CONFIG}.ovpn could not be found. Exiting..." | ts '%Y-%m-%d %H:%M:%S'
+    rm -rf /etc/services.d/openvpn && exit 1
+fi
+

+ 38 - 0
root/etc/services.d/openvp/run

@@ -0,0 +1,38 @@
+#!/usr/bin/with-contenv bash
+
+# Needed for the variables defined
+source /etc/scripts/openvpn-config-validation.sh
+
+echo "[OpenVPN] using provider: ${OPENVPN_PROVIDER}" | ts '%Y-%m-%d %H:%M:%S'
+
+echo "[OpenVPN] Start Script: /usr/sbin/openvpn --reneg-sec 0 --disable-occ --auth-nocache --mute-replay-warnings --pull-filter ignore 'ping' --pull-filter ignore 'ping-restart' --pull-filter ignore 'route-ipv6' --pull-filter ignore 'ifconfig-ipv6 --pull-filter ignore 'tun-ipv6' --pull-filter ignore 'dhcp-option DNS6' --pull-filter ignore 'reneg-sec' --pull-filter ignore 'persist-tun' --pull-filter ignore 'block-outside-dns' ${OPENVPN_OPTIONS} --config ${VPN_CONFIG}" | ts '%Y-%m-%d %H:%M:%S'
+
+if [[ "${DEBUG}" == "true" ]]; then
+    echo "[OpenVPN] Contents of ovpn file ${VPN_CONFIG} as follows..." | ts '%Y-%m-%d %H:%M:%S'; cat "${VPN_CONFIG}"
+
+    echo "[OpenVPN] Adding ${NAME_SERVER_ITEM} to /etc/resolv.conf" | ts '%Y-%m-%d %H:%M:%S'
+
+    if [[ "${VPN_PROVIDER}" == "pia" ]]; then
+        echo "[OpenVPN] PIA config files available as follows..." | ts '%Y-%m-%d %H:%M:%S'; cat "${VPN_PROVIDER_CONFIGS}/list.txt" | grep ".ovpn" | tr '\n' '|' | sed 's/\b.ovpn\b//g'
+    fi
+
+    if [[ "${VPN_PROVIDER}" == "surfshark" ]]; then
+        echo "[OpenVPN] Surfshark config files available as follows..." | ts '%Y-%m-%d %H:%M:%S'; cat "${VPN_PROVIDER_CONFIGS}/list.txt" | grep "_${OPENVPN_PROTOCOL,,}.ovpn" | tr '\n' '|' | sed 's/\b.ovpn\b//g'
+    fi
+fi
+
+/usr/sbin/openvpn \
+    --reneg-sec 0 \
+    --disable-occ \
+    --auth-nocache \
+    --mute-replay-warnings \
+    --pull-filter ignore 'route-ipv6' \
+    --pull-filter ignore 'ifconfig-ipv6' \
+    --pull-filter ignore 'tun-ipv6' \
+    --pull-filter ignore 'dhcp-option DNS6' \
+    --pull-filter ignore 'reneg-sec' \
+    --pull-filter ignore 'persist-tun' \
+    --pull-filter ignore 'block-outside-dns' \
+    ${OPENVPN_OPTIONS} --config "${VPN_CONFIG}"
+
+echo "[tvheadend] Public IP: $(curl -s ifconfig.me)" | ts '%Y-%m-%d %H:%M:%S'