Skip to content
Open
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b1b9b47
Update update-port.sh
BigRedBrent May 23, 2025
216f154
Update update-port.sh
BigRedBrent May 23, 2025
988de09
Update update-port.sh
BigRedBrent May 25, 2025
bbe15a9
Update update-port.sh
BigRedBrent May 26, 2025
cf6d29e
Update update-port.sh
BigRedBrent May 26, 2025
b73bf6e
Update update-port.sh
BigRedBrent May 26, 2025
660f3b8
Update update-port.sh
BigRedBrent May 26, 2025
455fd69
Update update-port.sh
BigRedBrent May 26, 2025
a88a328
Update update-port.sh
BigRedBrent May 27, 2025
f300e67
Update update-port.sh
BigRedBrent May 27, 2025
199b51c
Update update-port.sh
BigRedBrent May 27, 2025
c99a42f
Update update-port.sh
BigRedBrent May 27, 2025
a6cab99
Update update-port.sh
BigRedBrent May 27, 2025
e025937
Update update-port.sh
BigRedBrent May 28, 2025
fc40422
Update update-port.sh
BigRedBrent May 28, 2025
fd76084
Update update-port.sh
BigRedBrent May 28, 2025
7d6f736
Update update-port.sh
BigRedBrent May 28, 2025
8c0c75e
Update update-port.sh
BigRedBrent May 28, 2025
fcfcc9c
Update update-port.sh
BigRedBrent May 28, 2025
a6a85f9
Update update-port.sh
BigRedBrent May 28, 2025
1759e54
Update update-port.sh
BigRedBrent May 28, 2025
360d6c1
Update update-port.sh
BigRedBrent May 28, 2025
8eeaa3a
Update update-port.sh
BigRedBrent May 28, 2025
8b0df4b
Update update-port.sh
BigRedBrent May 28, 2025
509fb3d
Update update-port.sh
BigRedBrent May 30, 2025
d2f2c2e
Update update-port.sh
BigRedBrent May 30, 2025
dc43502
Update update-port.sh
BigRedBrent Jun 2, 2025
d3a9a62
Merge branch 'main' into patch-3
BigRedBrent Dec 12, 2025
3ffefea
Update update-port.sh
BigRedBrent Feb 13, 2026
25e43c3
Update update-port.sh
BigRedBrent Mar 13, 2026
440cfd1
Update update-port.sh
BigRedBrent Mar 13, 2026
eb9fb6e
Update update-port.sh
BigRedBrent Mar 13, 2026
ca1c2cb
Update update-port.sh
BigRedBrent Mar 13, 2026
c0bf288
Update update-port.sh
BigRedBrent Mar 19, 2026
e5f2638
Update update-port.sh
BigRedBrent Mar 19, 2026
97d16e5
Update update-port.sh
BigRedBrent Mar 19, 2026
c99d525
Update update-port.sh
BigRedBrent Mar 19, 2026
0090e96
Update update-port.sh
BigRedBrent Mar 19, 2026
e01495c
Update update-port.sh
BigRedBrent Mar 19, 2026
8094161
Update update-port.sh
BigRedBrent Mar 19, 2026
093f69f
Update update-port.sh
BigRedBrent Mar 19, 2026
5bcbd1d
Update update-port.sh
BigRedBrent Mar 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 125 additions & 60 deletions openvpn/protonvpn/update-port.sh
Original file line number Diff line number Diff line change
@@ -1,106 +1,171 @@
#!/usr/bin/env bash

sleep 60

set -euo pipefail

# shellcheck source=/dev/null
. /etc/transmission/environment-variables.sh

TRANSMISSION_PASSWD_FILE=/config/transmission-credentials.txt

transmission_username=$(head -1 ${TRANSMISSION_PASSWD_FILE})
transmission_passwd=$(tail -1 ${TRANSMISSION_PASSWD_FILE})
transmission_username=$(head -1 "${TRANSMISSION_PASSWD_FILE}")
transmission_passwd=$(tail -1 "${TRANSMISSION_PASSWD_FILE}")
transmission_settings_file=${TRANSMISSION_HOME}/settings.json
transmission_auth=""
new_port="unset"
last_port="unset"
current_port="unset"
double_check="false"

function box_out() {
log() { echo -e "update-port:\t$1"; }

box_out() {
local s="$*"
printf "\033[36m╭─%s─╮\n\033[36m│ \033[34m%s\033[36m │\n\033[36m╰─%s─╯\033[0;39m\n" "${s//?/─}" "$s" "${s//?/─}"
}

install_package() {
if command -v "$1" > /dev/null 2>&1; then
#log "Updating $1..."
#apt-get update -qq >/dev/null 2>&1 && apt-get install -y -qq "$1" >/dev/null 2>&1
return 0
fi
log "$1 not found – installing now..."
apt-get update -qq >/dev/null 2>&1 && apt-get install -y -qq "$1" >/dev/null 2>&1
if ! command -v "$1" > /dev/null 2>&1; then
log "Failed to install $1! $1 is required to configure ProtonVPN port forwarding."
log "Port forwarding for ProtonVPN has not been configured."
return 1
fi
log "$1 has been successfully installed."
return 0
}

open_port() {
timeout 5 natpmpc -a 1 0 udp 60 > /dev/null 2>&1 && timeout 5 natpmpc -a 1 0 tcp 60
}

remote() {
if test -n "$myauth"; then
timeout 5 "$tr_cmd" "$TRANSMISSION_RPC_PORT" --auth "$myauth" --json "$@"
if [[ -n "$transmission_auth" ]]; then
timeout 5 "$tr_cmd" "$TRANSMISSION_RPC_PORT" --auth "$transmission_auth" --json "$@"
else
timeout 5 "$tr_cmd" "$TRANSMISSION_RPC_PORT" --json "$@"
fi
}

bind_trans() {
# Ensure transmission is responsive
for attempt in {1..3}; do
if test "$(remote --list | jq -r .result)" == "success"; then
break
fi
sleep 5
if [ "$attempt" -eq 3 ]; then
return 1
# Ensure Transmission is responsive
if [[ "$(remote --list | jq -r .result)" != "success" ]]; then
return 1
fi

# Set last_port if unset
if [[ "$last_port" == "unset" ]]; then
last_port="$(remote --session-info | jq -r '.arguments["peer-port"]' || echo 0)"
if ! [[ "$last_port" =~ ^[0-9]+$ && "$last_port" -gt 1024 ]]; then
last_port="unset"
fi
done
fi

# Check if port is already bound to Transmission
if [[ "$new_port" -eq "$(remote --session-info | jq -r '.arguments["peer-port"]' || echo 0)" ]]; then
return 0
fi

# Bind port to Transmission
if test "$pf_port" -ne "$(remote --session-info | jq -r '.arguments["peer-port"]' || echo 0)"; then
for attempt in {1..3}; do
if test "$(remote --port "$pf_port" | jq -r .result)" == "success"; then
sleep 1
if test "$pf_port" -eq "$(remote --session-info | jq -r '.arguments["peer-port"]' || echo 0)"; then
return 0
if [[ "$(remote --port "$new_port" | jq -r .result)" != "success" ]]; then
return 1
fi

# Verify that port was bound to Transmission
sleep 1
if [[ "$new_port" -eq "$(remote --session-info | jq -r '.arguments["peer-port"]' || echo 0)" ]]; then
return 0
fi
box_out "Command to change port to $new_port returned success but actually failed!"
return 1
}

set_firewall() {
if [[ "${ENABLE_UFW,,}" != "true" ]]; then
return 0
fi

# Deny old port
if [[ "$last_port" =~ ^[0-9]+$ && "$last_port" -gt 1024 && "$current_port" != "$last_port" ]]; then
if timeout 5 ufw status | grep -qw "$last_port"; then
log "Denying $last_port through the firewall"
if ! timeout 5 ufw deny "$last_port"; then
log "Failed while denying port $last_port"
fi
fi
fi

# Allow new port
if [[ "$current_port" =~ ^[0-9]+$ && "$current_port" -gt 1024 ]]; then
if ! (timeout 5 ufw status | grep -qw "$current_port"); then
log "Allowing $current_port through the firewall"
if ! timeout 5 ufw allow "$current_port"; then
log "Failed while allowing port $current_port"
fi
fi
fi
}

update_port() {
new_port="$(open_port | sed -nr '1,//s/Mapped public port ([0-9]{4,5}) protocol.*/\1/p')"
if [[ "$new_port" =~ ^[0-9]+$ && "$new_port" -gt 1024 ]]; then
if [[ "$new_port" != "$current_port" ]]; then
if [[ "$double_check" != "true" ]]; then
if bind_trans; then
if [[ "$current_port" != "unset" ]]; then
last_port="$current_port"
fi
current_port="$new_port"
double_check="true"
box_out "The forwarded port is: $current_port"
else
box_out "Command to change port from $last_port to $pf_port returned success but actually failed!"
box_out "Attempt to change port to $new_port failed!"
fi
else
double_check="false"
fi
sleep 5
done
return 1
else
double_check="true"
fi
else
box_out "No valid port returned from natpmpc"
fi

return 0
}

if ! which jq; then
echo "jq is not installed! jq is required to configure ProtonVPN port forwarding."
echo "port forwarding for ProtonVPN has not been configured."
exit 1
log "Waiting for healthcheck to pass before updating ports..."
while ! /etc/scripts/healthcheck.sh; do
log "Not healthy yet. Retrying in 5 seconds..."
sleep 5
log "Retrying healthcheck..."
done
log "Healthcheck passed! Starting port update..."

# Install packages if they are not already installed
install_package natpmpc || exit 1
install_package jq || exit 1
if [[ "${ENABLE_UFW,,}" == "true" ]]; then
install_package ufw || exit 1
fi

if ! which natpmpc; then
echo "natpmpc is not installed! natpmpc is required to configure ProtonVPN port forwarding."
echo "port forwarding for ProtonVPN has not been configured."
exit 1
if [[ "$(jq -r '.["rpc-authentication-required"]' "$transmission_settings_file")" == "true" ]]; then
transmission_auth="$transmission_username:$transmission_passwd"
fi

tr_cmd=$(command -v transmission-remote)
if [[ -z "$tr_cmd" ]]; then
echo "Error: transmission-remote not found in PATH"
log "Error: transmission-remote not found in PATH"
exit 1
fi

if test "$(jq -r '.["rpc-authentication-required"]' "$transmission_settings_file")" == "true"; then
myauth="$transmission_username:$transmission_passwd"
else
myauth=""
fi

box_out "ProtonVPN Port Forwarding"
last_port="unset"

# Disable exiting on errors to allow the script to keep running even if commands fail
set +e

while true; do
pf_port="$(open_port | sed -nr '1,//s/Mapped public port ([0-9]{4,5}) protocol.*/\1/p')"
if [[ "$pf_port" =~ ^[0-9]+$ ]] && test "$pf_port" -gt 1024; then
if [[ "$pf_port" != "$last_port" ]]; then
if bind_trans; then
last_port="$pf_port"
box_out "The forwarded port is: $pf_port"
else
box_out "Attempt to change port from $last_port to $pf_port failed!"
fi
fi
else
box_out "No valid port returned from natpmpc"
fi
update_port
set_firewall
sleep 45
done