#!/bin/sh export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin # Private Internet Access Advanced Port Forward Script for pfSense # v1.06 (28th April 2018) # Written by Andy Fox # Pre-requisites for this script: # pfSense v2.1 (Port forward NAT return destination broken in earlier versions) # curl - pkg_add -r curl # xmlstarlet - pkg_add -r xmlstarlet # For pfSense v2.2, pkg_add has been replaced by pkg # Please run 'pkg', and follow prompts for installation. # Once pkg is installed, please run 'pkg update', followed by # pkg install curl # pkg install xmlstarlet # Fixed in this revision (v1.03) # If VPN is down, we get a NULL return for the port number, but still # attempt to modify the port mapping in the config file. This results in # a blank config.xml being generated. # Fixed in this revision (v1.04) # Added -k to curl to bypass certificate checks # Fixed in this revision (v1.05) # PIA have radically changed their port forwarding configuration. # This version of the script uses the new method, as the older API # is being removed shortly. # Fixed in this revision (v1.06) # Add support for Deluge as the torrent client CONFFILE=/cf/conf/config.xml # Get the port number for the forwarded port PIA_CLIENT_ID=`head -n 100 /dev/urandom | shasum -a 256 | tr -d " -"` logger "pia-port: port forward client-id=$PIA_CLIENT_ID" FORWARDED_PORT=$(curl --interface ovpnc1 "http://209.222.18.222:2000/\?client_id=$PIA_CLIENT_ID" 2>/dev/null | awk -F ':' '{ print $2 }'| awk -F '}' '{ print $1 }') # Capture return code from curl, for use in diagnosis later. RETURN=$? if [ "$FORWARDED_PORT" == "" ]; then FORWARDED_PORT='Port forwarding is already activated on this connection, has expired, or you are not connected to a PIA region that supports port forwarding.' logger "pia-port: $FORWARDED_PORT" exit 0 fi logger "pia-port: Port forward acquired: $FORWARDED_PORT" # Get current NAT port number using xmlstarlet to parse the config file. CURPORT=`xml sel -t -v '//rule[descr="NAT Torrent"]/destination/port' $CONFFILE` #logger "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" = "$FORWARDED_PORT" ]; then logger "pia-port: Current Port: $FORWARDED_PORT, PIA Port: $FORWARDED_PORT - Port not changed. Exiting." # Create the pia_port file, as it's possible it could have been # removed by external means. echo $FORWARDED_PORT > /usr/local/www/pia_port.txt exit 0 fi # Port forward has changed, so we update the rules in the config file. xml ed -u '//rule[descr="Torrent"]/destination/port' -v $FORWARDED_PORT -u '//rule[descr="Torrent"]/local-port' -v $FORWARDED_PORT -u '//rule[descr="NAT Torrent"]/destination/port' -v $FORWARDED_PORT $CONFFILE > /tmp/config.pia # Put the config file in the correct location. cp /tmp/config.pia $CONFFILE # Create a file in the pfSense web server root that contains the current port. # This can then be read by other hosts in order to update the open port in # whatever torrent client is in use. echo $FORWARDED_PORT > /usr/local/www/pia_port.txt # Force pfSense to re-read it's config rm /tmp/config.cache logger "pia-port: New port number ($FORWARDED_PORT) inserted into config file." RESULTTRANS=`ssh root@192.168.0.100 "/usr/local/deluge/env/bin/deluge-console -c /usr/local/deluge/var 'config --set listen_ports ($(cat /usr/local/www/pia_port.txt), $(cat /usr/local/www/pia_port.txt))'" 2>&1 ` len=${#RESULTTRANS} case "$RESULTTRANS" in *success*) logger "pia-port: $RESULTTRANS" logger "pia-port: Updated deluge port." exit 0 ;; esac # If we get here, there must be an error communicating with main deluge process. logger "pia-port: Port update failed. Cannot communicate with deluge." logger "pia-port: Error: $RESULTTRANS"