ProtonVPN is a popular VPN service known for its strong security and privacy features. While it supports port forwarding, the process on Linux currently requires manual intervention. This tutorial will guide you through automating port forwarding for qBittorrent using a Bash script. The script will dynamically update the port in qBittorrent whenever ProtonVPN assigns a new one.

Introduction

When using ProtonVPN with qBittorrent on Linux, setting up port forwarding can enhance your torrenting experience by allowing incoming connections, which improves download and upload speeds. However, ProtonVPN’s port forwarding assignments can change, and updating qBittorrent manually each time is inconvenient.

This tutorial provides a solution: a Bash script that automates the port forwarding process. It retrieves the new port assigned by ProtonVPN and updates qBittorrent’s listening port accordingly, ensuring seamless connectivity. This guide focuses on qBittorrent and not qbittorrent-nox.

Prerequisites

  • A Linux system with administrative privileges.
  • An active ProtonVPN subscription that includes port forwarding.
  • qBittorrent installed on your system.
  • Basic knowledge of using the terminal and editing scripts.

Step-by-Step Guide

1. Install Necessary Programs

Open your terminal and install the required packages:

sudo apt-get update
sudo apt-get install -y natpmpc jq curl
  • natpmpc: A tool to interact with NAT-PMP gateways.
  • jq: A lightweight and flexible command-line JSON processor.
  • curl: A tool to transfer data from or to a server.

2. Prepare the Script

Create a new Bash script file:

nano port_forwarding.sh

Copy and paste the following script into the file:

#!/bin/bash

# Set the gateway IP address (ProtonVPN's NAT-PMP gateway)
GATEWAY_IP="10.96.0.1"

# qBittorrent Web UI settings
QBITTORRENT_WEBUI_URL="http://<YOUR_QBITTORRENT_IP>:<PORT>"
QBITTORRENT_USERNAME="admin"
QBITTORRENT_PASSWORD='<YOUR_QBITTORRENT_PASSWORD>'

# Initialize variable for the previous port
previous_port=""

# Function to update the qBittorrent port via the Web API
update_qbittorrent_port() {
    local new_port=$1

    # URL-encode username and password
    username_encoded=$(printf '%s' "$QBITTORRENT_USERNAME" | jq -s -R -r @uri)
    password_encoded=$(printf '%s' "$QBITTORRENT_PASSWORD" | jq -s -R -r @uri)

    # Log in and obtain session cookie
    login_response=$(curl -s -i -X POST \
        -d "username=${username_encoded}&password=${password_encoded}" \
        "${QBITTORRENT_WEBUI_URL}/api/v2/auth/login" \
        -c cookies.txt)

    # Check if login was successful (ignore case sensitivity)
    if ! echo "$login_response" | grep -iq "Set-Cookie: SID="; then
        echo "Error logging into the qBittorrent Web UI"
        echo "Response from qBittorrent:"
        echo "$login_response"
        rm -f cookies.txt
        return 1
    fi

    # Set new port and capture HTTP status code
    response=$(curl -s -i -X POST \
        "${QBITTORRENT_WEBUI_URL}/api/v2/app/setPreferences" \
        -b cookies.txt \
        --data-urlencode "json={\"listen_port\":${new_port}}")

    # Extract HTTP status code
    http_status=$(echo "$response" | grep HTTP | awk '{print $2}')

    if [ "$http_status" == "200" ]; then
        echo "Successfully updated qBittorrent port to $new_port."
    else
        echo "Error updating the qBittorrent port."
        echo "HTTP status code: $http_status"
        echo "Response from qBittorrent:"
        echo "$response"
    fi

    # Log out and delete cookies
    curl -s -X POST "${QBITTORRENT_WEBUI_URL}/api/v2/auth/logout" -b cookies.txt -o /dev/null
    rm -f cookies.txt
}

# Infinite loop to continuously set up port forwarding
while true; do
    # Output current date and time
    date

    # Attempt to assign TCP port with the gateway IP and save output
    output=$(natpmpc -g "$GATEWAY_IP" -a 1 0 tcp 60)
    if echo "$output" | grep -q "Mapped public port"; then
        # Extract port number from output
        new_port=$(echo "$output" | grep "Mapped public port" | grep -oP 'Mapped public port \K[0-9]+')
        echo "Newly assigned port: $new_port"

        # Check if the port has changed
        if [ "$new_port" != "$previous_port" ]; then
            echo "Port has changed. Updating qBittorrent port."
            # Update qBittorrent port
            update_qbittorrent_port "$new_port"

            # Save the new port as previous port
            previous_port="$new_port"
        else
            echo "Port has not changed. No action required."
        fi

    else
        echo -e "ERROR with natpmpc command \a"
        echo "Retrying in 15 seconds..."
        sleep 15
        continue
    fi

    # Wait 45 seconds before repeating the loop
    sleep 45
done

3. Configure the Script

  • Set the Gateway IP:
    Ensure that GATEWAY_IP is set to ProtonVPN’s NAT-PMP gateway IP. The default 10.96.0.1 should work for ProtonVPN.
    Configure qBittorrent Web UI Settings:
  • Replace <YOUR_QBITTORRENT_IP> with the IP address where qBittorrent’s Web UI is accessible (e.g., localhost or 192.168.1.100).
  • Replace <PORT> with the port number of the qBittorrent Web UI (default is 8080).
  • Replace <YOUR_QBITTORRENT_PASSWORD> with your qBittorrent Web UI password.

Note: If your password contains special characters, ensure it is enclosed in single quotes ‘…’ to prevent shell interpretation.

4. Secure the Script

Since the script contains sensitive information:
Set File Permissions:

chmod 700 port_forwarding.sh

This ensures that only your user can read, write, or execute the script.
Avoid Sharing: Do not share the script publicly or store it in a shared directory.

5. Run the Script

Make the script executable:

chmod +x port_forwarding.sh

Run the script:

./port_forwarding.sh

Important: Run the script under your user account (do not use sudo) to ensure that it has the correct permissions and environment.

Conclusion

By following this tutorial, you’ve automated the process of port forwarding with ProtonVPN and qBittorrent on Linux. The script continuously checks for new port assignments from ProtonVPN and updates qBittorrent’s listening port via its Web API whenever a change occurs.

This automation ensures that you maintain optimal torrenting speeds without manual intervention each time ProtonVPN assigns a new port.