Navigation

    Netgate Discussion Forum
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Search

    Automated scripts for Private Internet Access port forwarding

    NAT
    37
    69
    249011
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • B
      Bagpuss last edited by

      Please read the second post in this thread before going ahead with any of the steps below.
      Some things have changed since I first posted, and updated scripts are now attached.

      Hi All,

      As those of you who use PIA might know, their port forwarding mechanism isn't very friendly for those people who don't use their bespoke client software.
      It is possible to setup a port forward outside their client, but they don't really support it. See here.

      I've seen several requests on the forum here for an automated mechanism to update the port forward and firewall rules to adapt to changing ports at the PIA end.
      Given that I wanted to do the same thing myself, I've spent the last few days working out how to do it….......

      NOTE: This will only work on pfSense 2.1 or above, as the outbound NAT for VPNs is broken in earlier releases.

      The only way that I could find to modify the firewall was to edit the /cf/conf/config.xml file, and then delete the /tmp/config.cache file. This forces pfSense to re-read it's configuration. This appears to be the only safe way to modify the configuration.

      In order for my script to work, you do need two extra packages on your pfSense box. These are curl and xmlstarlet.
      Curl is used to retrieve the current port forward from PIA, and xmlstarlet is used to safely edit the config.xml.

      Get them by running the following as admin:
      pkg_add -r curl
      pkg_add -r xmlstarlet

      NOTE: From 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

      There is one other requirement, which is that you must have already configured a port forward that points at your internal target system.
      You do this under Firewall -> NAT -> Port forward.

      When you create the port forward for the first time, ensure that you change the description to be 'Torrent'.
      It's also important that 'Filter rule association' is set to 'Create new associated filter rule'.

      Once you've saved this port forward, go into the Firewall -> Rules section, and select the tab for your VPN gateway (used when you created the port forward).
      You should see the 'associated rule'. You need to edit this, and change it's description to be "NAT Torrent".

      I've attached screenshots to show what both sections should look like when you're done.

      The description names are important, as I use these to match the rules when editing the config.xml file.

      Now that you've done this, you need to download the attached pia-port script. The file has a .txt extension in order to allow me to attach it here. Please remove this once you've downloaded the file.

      The script is as follows:

      
      #!/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.0 (21st January 2014)
      
      # 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
      
      # Add your PIA username and password
      USERNAME="username"
      PASSWORD="password"
      PIACLIENTID=/cf/conf/pia_client_id
      CONFFILE=/cf/conf/config.xml
      
      # Check to see if we have a valid PIA Client ID file.
      # If not, create one. Linux is included for illustration only.
      if [ ! -e $PIACLIENTID ]; then
      
      	# OSX/FreeBSD (pfSense)
      	head -n 100 /dev/urandom | md5 > $PIACLIENTID
      
      	# Linux
      	#head -n 100 /dev/urandom | md5sum | tr -d " -" > $PIACLIENTID
      
      	logger "pia-port: Created new PIA Client ID."
      fi
      
      # Find out the tunnelling device for your VPN and get your IP address.
      # There are several options presented here. Personally, I prefer to use
      # the interface which I know relates to my VPN tunnel for forwarding.
      
      #DEVICE=`ifconfig | grep -o "tun[0-9]"`
      #LOCAL_IP=`ifconfig $DEVICE | grep -Po "(?<=addr.)[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*"`
      LOCAL_IP=`ifconfig ovpnc1 | grep "inet " | cut -d\  -f2`
      
      # Get the port number for the forwarded port
      PORT=`curl -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" https://www.privateinternetaccess.com/vpninfo/port_forward_assignment`
      
      PORTNUM=`echo $PORT | grep -oE "[0-9]+"` 
      
      # Some error detection. If PORTNUM is longer than 5 characters, we know that
      # an error has been returned. We log it to syslog, and exit.
      len=`expr $PORTNUM : '.*'`
      echo $len
      
      if [ $len -gt 5 ]; then
      	logger "pia-port: $PORTNUM"
      	exit 0
      fi
      
      logger "pia-port: Port number acquired: $PORTNUM"
      
      # 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" = "$PORTNUM" ]; then
      	logger "pia-port: Port not changed. Exiting."
      	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 $PORTNUM -u '//rule[descr="Torrent"]/local-port' -v $PORTNUM -u '//rule[descr="NAT Torrent"]/destination/port' -v $PORTNUM $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 $PORTNUM > /usr/local/www/pia_port.txt
      
      # Force pfSense to re-read it's config
      rm /tmp/config.cache
      
      logger "pia-port: New port number ($PORTNUM) inserted into config file."
      
      

      The next thing to do is insert your PIA username and password into the USERNAME and PASSWORD variables at the top of the script.
      A second change could be to the method for discovering your local IP address.
      This is done in the lines starting with LOCAL_IP. I've put several methods in there. Please choose the one which works best for you.

      If you've never used the PIA advanced port forwarding, then it takes care of creating your pia_client_id file as well.

      Once you've edited the script, then copy it into the /usr/local/bin directory on your pfSense box.
      You also need to ensure it has execute permissions by running 'chmod 755 /usr/local/bin/pia-port'

      PIA recommend checking the port at least once an hour to see if the mapping has changed.
      With that in mind, we now need to add a crontab entry. The easiest way to do this is by running 'crontab -e'.
      An editor will open (usually vi), and you simply insert the following into the file:

      
      0 * * * * /usr/local/bin/pia-port
      
      

      Once you've pasted this in, exit vi with shift-ZZ, and cron will re-read it's configuration.

      To know if it's working, check the Status -> System Logs tab.
      On first run, you should see entries like:

      
      an 22 00:21:53 	        admin: pia-port: Created new PIA Client ID.
      Jan 22 00:21:54 	admin: pia-port: Port number acquired: 50650
      Jan 22 00:21:54 	admin: pia-port: Current port forward: 29615
      Jan 22 00:21:54 	admin: pia-port: New port number (50650) inserted into config file.
      
      

      and subsequently:

      
      Jan 22 00:25:14 	admin: pia-port: Port number acquired: 50650
      Jan 22 00:25:14 	admin: pia-port: Current port forward: 50650
      Jan 22 00:25:14 	admin: pia-port: Port not changed. Exiting.
      
      

      or:

      
      Jan 22 00:25:14 	admin: pia-port: Port number acquired: 51444
      Jan 22 00:25:14 	admin: pia-port: Current port forward: 50650
      Jan 22 00:25:14 	admin: pia-port: New port number (51444) inserted into config file.
      
      

      If you then check the Firewall -> NAT -> Port forward tab, you should see the 'Dest. ports' entry changing.
      Likewise, the 'Port' entry in the associated rule should also be changing to match.

      This covers things at the pfSense side, but what about your torrent client?
      Well, my script creates a file called pia_port.txt (not to be confused with the attachment on this post) in the web root of the pfSense UI.
      This file contains the current port being forwarded, which can then be retrieved from another system using curl (or similar).

      As an illustration of this, I also attach a script for updating the port in Transmission running on a Synology DSM box.
      I'm sure this can be adapted to fit any number of different Torrent client situations.

      The script is as follows:

      
      #!/bin/sh
      export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/syno/sbin:/usr/syno/bin:/usr/local/sbin:/usr/local/bin
      
      # Script to update port used by Transmission torrent client
      # Developed for use on Synology DSM. Should work on other platforms.
      # v1.0 (22nd January 2014)
      
      # This script is configured to work with Transmission that has password
      # protection on the web GUI. You can remove this stuff if you don't use it.
      USERNAME="username"
      PASSWORD="password"
      
      if [ ! -e /tmp/pia_port.txt ]; then
      
      	logger -p user.crit "transmission-port: Setting up port forward for first time."
      	cd /tmp && curl -O -k https://192.168.0.1/pia_port.txt
      	/usr/local/transmission/bin/transmission-remote --auth $USERNAME:$PASSWORD -p $(cat /tmp/pia_port.txt)
      
      else
      
      	CURPORT=`cat /tmp/pia_port.txt`
      	cd /tmp && curl -o pia_new.txt -k https://192.168.0.1/pia_port.txt
      	NEWPORT=`cat /tmp/pia_new.txt`
      
      	logger -p user.crit "transmission-port: Current port: $CURPORT"
      	logger -p user.crit "transmission-port: New Port: $NEWPORT" 
      
      	if [ "$CURPORT" = "$NEWPORT" ]; then
      		logger -p user.crit "transmission-port: Port not changed. Exiting."
      		exit 0
      	fi
      
      	logger -p user.crit "transmission-port: Updating port."
      	mv /tmp/pia_new.txt /tmp/pia_port.txt
      	/usr/local/transmission/bin/transmission-remote --auth $USERNAME:$PASSWORD -p $(cat /tmp/pia_port.txt)
      
      fi
      
      

      This script is written with a password protected Transmission web interface in mind.
      You therefore need to put the correct username and password at the top of the script.

      On my system, I then copy this script into the /usr/local/transmission/bin directory on the Synology box.
      Set permissions with 'chmod 755 transmission-port' and you should be good to go.

      Again, you really need to run this on an automated basis, so we have to put an entry in /etc/crontab.
      Synology boxes lack a crontab command, so we have to edit the file by hand.
      You need to be very careful with this, as the crontab format is very sensitive on a Synology NAS.
      Each field has to be separated with a TAB, and there can be no extra characters at the end of the file.

      A suitable entry would be:

      
      2       *       *       *       *       root    /usr/local/transmission/bin/transmission-port
      
      

      That entry will run at two minutes past the hour, every hour. This is to allow the pfSense configuration a couple of minutes to update, as it's running on the hour.

      Be careful not to remove any other entries that already exist in this file.

      Once you've edited the file, you need to run (as root), the following:
      /usr/syno/sbin/synoservice –restart crond

      This will force crond to re-read it's configuration file.

      NOTE: In DSM 5.x and above, synoservice no longer appears to support the –restart option.
      In this case, you need to run 'ps w | grep crond' to get the process ID.
      Then run kill -HUP <cronpid>to force it to re-read the config file.

      Assuming you've got this correct, your /var/log/messages file will start to contain entries like:

      
      Jan 22 10:58:03 MicroServer root: transmission-port: Current port: 50650
      Jan 22 10:58:03 MicroServer root: transmission-port: New Port: 50650
      Jan 22 10:58:03 MicroServer root: transmission-port: Port not changed. Exiting.
      
      

      I think that's about it. It's all working flawlessly on my configuration, but there could be bugs.
      With that in mind, please backup your pfSense configuration before trying any of this.

      Any bug reports, feedback etc. are warmly welcomed.

      Andy.





      pia-port.txt
      transmission-port.txt</cronpid>

      1 Reply Last reply Reply Quote 0
      • B
        Bagpuss last edited by Bagpuss

        **** UPDATE - 30th April 2018 ****

        For those who use Deluge on Synology NAS, I've now provided some updated scripts to handle this.
        The pia-port script (v1.06) has been updated to ssh into the NAS and update the deluge port on the fly.
        There is a new script, deluge-port, which runs via cron on the NAS to poll for port changes. This might seem a little redundant, given that pia-port now updates the port on the fly, but it does handle the case where the port changes and the SSH might have failed.

        NOTE: Do not use v1.06 is you want to continue using Transmission. This is for Deluge only.

        In order for pia-port to work correctly with deluge, you will need to ensure that your create a valid key to allow login without password. 
        To achieve this, do the following as root on pfsense:

        $ ssh-keygen -t ecdsa -b 521 (do not provide a passphrase when prompted)
        $ ssh-copy-id -i ~/.ssh/id_ecdsa.pub root@synology (where synology is the hostname or IP address of your Synology NAS)

        To test that you can now login without password, run
        $ ssh root@synology

        If this works, then the pia-port script will now work to update the deluge port on the fly.

        There is another issue with Deluge on Synology, which is related to the umask. By default, all files are created as the deluge user with a umask of 022.
        This results in files which users in the same group cannot delete or change (perms are -rw-r–r--).

        Changing the umask for deluge is not straightforward on Synology, as the start-stop-daemon command doesn't support the -k or --umask parameters which are present on other OS's.

        To fix this, I've provided another script, run-with-umask.sh, which can be used as a wrapper to set the umask to whatever you like.
        Copy this script to /usr/local/bin on the Synology, and ensure that it has execute permissions.

        Now backup the standard deluge start-stop script, by doing the following:
        $ cp /var/packages/deluge/scripts/start-stop-status /var/packages/deluge/scripts/start-stop-status.orig

        Replace the original script with the version attached to this post.
        You can then set the umask to whatever you want by editing run-with-umask.sh.

        **** UPDATE - 24th April 2018 ****

        Realised that I'd not visited this thread for quite some time, so wanted to provide some updates to my original post.
        PIA are about to radically change the API for acquiring port forwards (see here and here).
        As a result of this, my scripts will soon stop working. You might already be seeing issues if you were using the Netherlands endpoint, as port forwarding was recently disabled.
        If you're in Europe, the most performant endpoint now appears to be Germany.

        I've attached a new version of the main script (v1.05), which has to be used slightly differently.
        It's no longer necessary to have a cron job which runs every hour, as the port is only assigned once for the existence of a connection. In addition, you must request the port forward within two minutes of bringing up the connection. Attempts after that will fail.

        In order to run the script on interface bring up, you can use devd (as I've seen mentioned by others later in the thread).
        To do this, you need to ensure that the directory /usr/local/etc/devd exists. If not, create it.
        In this, put the following script. It's name can be anything which ends in .conf. I call mine portforward.conf.

        notify 0 {
                match "system"          "IFNET";
                match "subsystem"       "(ovpnc1)";
                match "type"            "LINK_UP";
                action "logger $subsystem is UP";
                action "/usr/local/bin/pia-port";
        };
        
        notify 0 {
                match "system"          "IFNET";
                match "subsystem"       "(ovpnc1)";
                match "type"            "LINK_DOWN";
                action "logger $subsystem is DOWN";
        };
        
        

        You need to change ovpnc1 to whatever the interface is that you are using for your port forwarding endpoint.
        Once you've created the file, run /etc/rc.d/devd restart.
        In the main script, you will also see a –interface ovpnc1 directive to the curl command. You need to change this also.

        I've also attached v1.04 of the original script, which contains some fixes that have come up since I originally made this post.

        Hope this helps.

        Andy.

        start-stop-status.txt
        run-with-umask.sh.txt
        pia-port.106.txt
        pia-port.105.txt
        pia-port.104.txt
        deluge-port.txt

        P 1 Reply Last reply Reply Quote 0
        • P
          phil.davis last edited by

          PIA recommend checking the port at least once an hour to see if the mapping has changed.
          With that in mind, we now need to add a crontab entry. The easiest way to do this is by running 'crontab -e'.
          An editor will open (usually vi), and you simply insert the following into the file

          On pfSense, crontab will get rebuilt from config.xml - so manual edit changes will get overwritten.
          Install the Cron package, and use that to add the crontab entry.

          As the Greek philosopher Isosceles used to say, "There are 3 sides to every triangle."
          If I helped you, then help someone else - buy someone a gift from the INF catalog http://secure.inf.org/gifts/usd/

          1 Reply Last reply Reply Quote 0
          • B
            Bagpuss last edited by

            @phil.davis:

            On pfSense, crontab will get rebuilt from config.xml - so manual edit changes will get overwritten.
            Install the Cron package, and use that to add the crontab entry.

            Hi Phil,

            Thanks for the feedback. I wasn't aware of this.

            Can you tell me in what circumstances pfSense will do this? I've had a manually entered crontab entry running for a number of days, and it's still okay.
            I'm not totally sure that my manual entry will be overwritten, as it's in a completely different crontab file.

            The crontab which is built from the config.xml appears to be /etc/crontab.
            The crontab which is changed by crontab -e is /var/cron/tabs/root.

            I'm thinking that the two can co-exist without interfering with each other.

            Having said that, it does make a lot of sense to use the Cron package, and manage things from the GUI.

            Andy.

            1 Reply Last reply Reply Quote 0
            • V
              VTOLfreak last edited by

              Thank you for this. :) Any chance of packing this up into a handy plugin for pfsense with a GUI page?

              I don't really like the idea of adding too much scripts and files to my pfsense setup outside of plugins. Rightnow I'm putting off trying the 2.1.1 snapshots because I dont know if upgrading will wipe out all the changes I made to my 2.1 setup. If this script was in a plugin, pfsense takes care of setting it all up for you.

              1 Reply Last reply Reply Quote 0
              • P
                phil.davis last edited by

                Can you tell me in what circumstances pfSense will do this?

                Definitely at boot time - crontab, passwd databases, all that sort of "system management" setting gets rebuilt from the settings specified in config.xml
                For crontab and passwd I don't think there are run-time events that cause them to rebuild from scratch, so manual edits probably survive a long time.
                I definitely recommend NOT manually editing any files. Do it all through the GUI and available packages. If the available GUI+packages does not have a button for what you need, then put a feature request in RedMine and (if you have some coding skills) make the GUI enhancements and submit a pull request on GitHub.
                It is an Open Source project, and if everyone contributes features that they need then we all get the benefit - or the software bloat  ;)

                As the Greek philosopher Isosceles used to say, "There are 3 sides to every triangle."
                If I helped you, then help someone else - buy someone a gift from the INF catalog http://secure.inf.org/gifts/usd/

                1 Reply Last reply Reply Quote 0
                • S
                  sacredgaming last edited by

                  Do think this would work with plex server for viewing outside my network?

                  1 Reply Last reply Reply Quote 0
                  • D
                    dalesd last edited by

                    Hi Andy,
                    I'm also a PIA customer and I'm trying your script for port forwarding.

                    So far, it's not working.  Where do I find the log file so I can troubleshoot this?  Your post says to check the /var/log/messages file, but there isn't one.

                    1 Reply Last reply Reply Quote 0
                    • D
                      dalesd last edited by

                      Turns out I had my cron entry set up wrong. I fixed that and now the log is showing what's going on.

                      
                      Mar 1 09:12:19	php: /index.php: New alert found: pfSense is restoring the configuration /conf/backup/config-1393680553.xml
                      Mar 1 09:12:19	php: /index.php: pfSense is restoring the configuration /conf/backup/config-1393680553.xml
                      Mar 1 09:12:19	php: /index.php: New alert found: No config.xml found, attempting last known config restore.
                      Mar 1 09:12:19	php: /index.php: No config.xml found, attempting last known config restore.
                      Mar 1 09:02:00	root: pia-port: New port number () inserted into config file.
                      Mar 1 09:02:00	root: pia-port: Created new PIA Client ID.
                      
                      

                      When I run the script in a terminal, here's what I get:

                      [2.1-RELEASE][admin@pfsense.localdomain]/usr/local/bin(51): ./pia-port 
                        % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                                       Dload  Upload   Total   Spent    Left  Speed
                      100   149    0    57  100    92    245    395 --:--:-- --:--:-- --:--:--   519
                      expr: syntax error
                      
                      [: -gt: unexpected operator
                      I/O warning : failed to load external entity "/rule[descr="Torrent"]/local-port"
                      [2.1-RELEASE][admin@pfsense.localdomain]/usr/local/bin(52): 
                      
                      

                      I think curl isn't working or installed correctly, because this happens:

                      
                      [2.1-RELEASE][admin@pfsense.localdomain]/var/log(46): pkg_add -r curl           
                      Fetching ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/curl.tbz... Done.
                      pkg_add: package 'curl-7.24.0' or its older version already installed
                      [2.1-RELEASE][admin@pfsense.localdomain]/var/log(47): curl                      
                      curl: Command not found.
                      
                      

                      I don't know how to fix that.

                      1 Reply Last reply Reply Quote 0
                      • J
                        jgorman last edited by

                        Hello,

                        Thanks a lot for this script.

                        I'm getting the following:

                        cron: login_getclass: unknown class 'pia-port # #'

                        I should not, I created the pia-port using the Diagnostics-Edit File from within pfsense and not by ssh-ing it ont the machine…

                        Don't know if that makes a difference.

                        Any help would be greatly appreciated.

                        THANKS!

                        1 Reply Last reply Reply Quote 0
                        • P
                          ppierre last edited by

                          Nice script.

                          Juste an edge case that I've encounter. I've got this reply :

                          {"error":"port forwarding not available for this region"} 
                          

                          Ewrything was fine, but in my setup I haven't setup the VPN as default route (only one IP go through it).

                          So I had to add this to your script :

                          curl [b]--interface [/b]"$LOCAL_IP" ...
                          

                          And everything went smooth. It seem IPA need to get the port request from his own network.
                          Maybe you should add it to your post. In case someone would try a similar setup.

                          1 Reply Last reply Reply Quote 0
                          • Z
                            zounder1 last edited by

                            To clarify this.  Change the "PORT" line in the the script with this:

                            PORT=curl –interface $LOCAL_IP -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" https://www.privateinternetaccess.com/vpninfo/port_forward_assignment

                            This should be put into V1.02 of this script.  For setups with multiple gateways you need this to ensure the request goes out via the proper PIA VPN connection.  With this change the script will try and use the default gateway which may not be the correct gateway.

                            Hats off to Bagpuss the creator of this script!  This is awesome.

                            Hats off to  ppierre for adding that important last catch with the script.

                            @ppierre:

                            Nice script.

                            Juste an edge case that I've encounter. I've got this reply :

                            {"error":"port forwarding not available for this region"} 
                            

                            Ewrything was fine, but in my setup I haven't setup the VPN as default route (only one IP go through it).

                            So I had to add this to your script :

                            curl [b]--interface [/b]"$LOCAL_IP" ...
                            

                            And everything went smooth. It seem IPA need to get the port request from his own network.
                            Maybe you should add it to your post. In case someone would try a similar setup.

                            1 Reply Last reply Reply Quote 0
                            • B
                              Bagpuss last edited by

                              @zounder1:

                              To clarify this.  Change the "PORT" line in the the script with this:

                              PORT=curl –interface $LOCAL_IP -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" https://www.privateinternetaccess.com/vpninfo/port_forward_assignment

                              This should be put into V1.02 of this script.  For setups with multiple gateways you need this to ensure the request goes out via the proper PIA VPN connection.  With this change the script will try and use the default gateway which may not be the correct gateway.

                              Hats off to Bagpuss the creator of this script!  This is awesome.

                              Hats off to  ppierre for adding that important last catch with the script.

                              Not checked this thread for a while, and I've just realised that I hadn't posted v1.02 where I did indeed catch this bug. My apologies.
                              My fix is slightly different, but it achieves the same thing.

                              Attached to this post is v1.03, where I've caught another issue.
                              I kept seeing entries in my syslog which said 'pfSense is restoring the configuration /conf/backup/config-1393680553.xml' or similar.
                              Further debugging revealed that the PIA address wasn't resolving for curl, and hence the script returned a NULL for the port number.
                              I wasn't catching this error, and so the script was copying an empty /tmp/config.pia over the config.xml.

                              The new script fixes this, and also provides the return code from curl, so you can try and work out what went wrong.

                              pia-port.v103.txt

                              1 Reply Last reply Reply Quote 0
                              • B
                                Bagpuss last edited by

                                @dalesd:

                                Hi Andy,
                                I'm also a PIA customer and I'm trying your script for port forwarding.

                                So far, it's not working.  Where do I find the log file so I can troubleshoot this?  Your post says to check the /var/log/messages file, but there isn't one.

                                Sorry. That should have been /var/log/system.log

                                1 Reply Last reply Reply Quote 0
                                • B
                                  Bagpuss last edited by

                                  As an aside, my original instructions contain details for managing cron from the command line.
                                  Whilst this works, there is a cron GUI package available, and this works just as well.

                                  I'm pretty sure that anyone who is okay with installing this stuff in the first place can use cron,
                                  but the pfSense preferred way is to use the GUI package. I'm told that changes to the underlying
                                  pfSense OS going forward might mean that command line cron entries are lost across reboots.
                                  The GUI package stores the cron entries in your config.xml, thereby ensuring their survival.

                                  1 Reply Last reply Reply Quote 0
                                  • B
                                    binaryjay last edited by

                                    Amazing post.  I was in the middle of reinventing this wheel (moving away from openvpn client on specific hosts) but this saved me a bunch of time.  Had to make some minor changes to account for nanoBSD which I have PM'd you about.  May be worth checking if the filesystem is ro and remounting before continuing to make your script pfsense distribution agnostic.

                                    Also, instead of force deleting config.cache (doesn't that seem a little messy?), would it not be better to just run:
                                    /etc/rc.reload_all

                                    ?  Scratch that, running that manually seems to kill everything and requires a reboot.

                                    After I started running this script I've been seeing inetd complaining in the logs about connection aborts and I wonder if it has something to do with the unexpected blowing away of config.cache.

                                    1 Reply Last reply Reply Quote 0
                                    • I
                                      Imaginos last edited by

                                      So these two commands are causing an interesting problem:

                                      pkg_add -r curl
                                      pkg_add -r xmlstarlet
                                      

                                      They both reach out to ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/… and both generate the following error.

                                      Error: Unable to get ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/xmlstarlet.tbz: File unavailable (e.g., file not found, no access)
                                      pkg_add: unable to fetch 'ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/xmlstarlet.tbz' by URL
                                      

                                      A brief investigation reveals that the error is correct and that file path does not exist. There is a packages-8-stable, 8.4-release, 9-stable and others, but not an 8.3 flavor.

                                      You can see the directory here http://ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/.

                                      I'm at a loss of how to proceed and my kung fu with this is 30 years old and not potent enough to figure it out.

                                      1 Reply Last reply Reply Quote 0
                                      • C
                                        Cino last edited by

                                        @Imaginos:

                                        So these two commands are causing an interesting problem:

                                        pkg_add -r curl
                                        pkg_add -r xmlstarlet
                                        

                                        They both reach out to ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/… and both generate the following error.

                                        Error: Unable to get ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/xmlstarlet.tbz: File unavailable (e.g., file not found, no access)
                                        pkg_add: unable to fetch 'ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/xmlstarlet.tbz' by URL
                                        

                                        A brief investigation reveals that the error is correct and that file path does not exist. There is a packages-8-stable, 8.4-release, 9-stable and others, but not an 8.3 flavor.

                                        You can see the directory here http://ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/.

                                        I'm at a loss of how to proceed and my kung fu with this is 30 years old and not potent enough to figure it out.

                                        searching with help your kung fu

                                        https://forum.pfsense.org/index.php?topic=78935.0

                                        AMD64
                                        setenv PACKAGESITE http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-8.3-release/

                                        I386
                                        setenv PACKAGESITE http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/i386/packages-8.3-release/

                                        1 Reply Last reply Reply Quote 0
                                        • Z
                                          zounder1 last edited by

                                          @Cino:

                                          @Imaginos:

                                          So these two commands are causing an interesting problem:

                                          pkg_add -r curl
                                          pkg_add -r xmlstarlet
                                          

                                          They both reach out to ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/… and both generate the following error.

                                          Error: Unable to get ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/xmlstarlet.tbz: File unavailable (e.g., file not found, no access)
                                          pkg_add: unable to fetch 'ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/packages-8.3-release/Latest/xmlstarlet.tbz' by URL
                                          

                                          A brief investigation reveals that the error is correct and that file path does not exist. There is a packages-8-stable, 8.4-release, 9-stable and others, but not an 8.3 flavor.

                                          You can see the directory here http://ftp://ftp.freebsd.org/pub/FreeBSD/ports/amd64/.

                                          I'm at a loss of how to proceed and my kung fu with this is 30 years old and not potent enough to figure it out.

                                          searching with help your kung fu

                                          https://forum.pfsense.org/index.php?topic=78935.0

                                          AMD64
                                          setenv PACKAGESITE http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-8.3-release/

                                          I386
                                          setenv PACKAGESITE http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/i386/packages-8.3-release/

                                          I used:
                                          setenv PACKAGESITE http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-8.3-release/Latest/

                                          Then I could install curl.

                                          But quite the output for xmlstarlet
                                          pkg_add -r xmlstarlet
                                          Fetching http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-8.3-release/Latest/xmlstarlet.tbz… Done.
                                          Fetching http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-8.3-release/All/pkg-config-0.25_1.tbz... Done.
                                          Fetching http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-8.3-release/All/libxml2-2.7.8_2.tbz... Done.
                                          pkg_add: warning: package 'libxml2-2.7.8_2' requires 'libiconv-1.13.1_2', but 'libiconv-1.14_1' is installed
                                          Fetching http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-8.3-release/All/libgpg-error-1.10.tbz... Done.
                                          pkg_add: warning: package 'libgpg-error-1.10' requires 'libiconv-1.13.1_2', but 'libiconv-1.14_1' is installed
                                          pkg_add: warning: package 'libgpg-error-1.10' requires 'gettext-0.18.1.1', but 'gettext-0.18.3.1' is installed
                                          Fetching http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-8.3-release/All/libgcrypt-1.5.0.tbz... Done.
                                          pkg_add: warning: package 'libgcrypt-1.5.0' requires 'libiconv-1.13.1_2', but 'libiconv-1.14_1' is installed
                                          pkg_add: warning: package 'libgcrypt-1.5.0' requires 'gettext-0.18.1.1', but 'gettext-0.18.3.1' is installed
                                          Fetching http://ftp-archive.freebsd.org/pub/FreeBSD-Archive/ports/amd64/packages-8.3-release/All/libxslt-1.1.26_3.tbz... Done.
                                          pkg_add: warning: package 'libxslt-1.1.26_3' requires 'libiconv-1.13.1_2', but 'libiconv-1.14_1' is installed
                                          pkg_add: warning: package 'libxslt-1.1.26_3' requires 'gettext-0.18.1.1', but 'gettext-0.18.3.1' is installed
                                          pkg_add: warning: package 'xmlstarlet-1.0.5' requires 'libiconv-1.13.1_2', but 'libiconv-1.14_1' is installed
                                          pkg_add: warning: package 'xmlstarlet-1.0.5' requires 'gettext-0.18.1.1', but 'gettext-0.18.3.1' is installed

                                          It seems to have installed xmlstarlet despite the warnings.  But I'm new to this package manager so I'm not sure if this is asking for trouble or if it just installs and hopes that everything runs with different versions of the dependencies.

                                          1 Reply Last reply Reply Quote 0
                                          • Soloam
                                            Soloam last edited by

                                            @ppierre:

                                            Nice script.

                                            Juste an edge case that I've encounter. I've got this reply :

                                            {"error":"port forwarding not available for this region"} 
                                            

                                            Ewrything was fine, but in my setup I haven't setup the VPN as default route (only one IP go through it).

                                            So I had to add this to your script :

                                            curl [b]--interface [/b]"$LOCAL_IP" ...
                                            

                                            And everything went smooth. It seem IPA need to get the port request from his own network.
                                            Maybe you should add it to your post. In case someone would try a similar setup.

                                            Hello, I'm having the same error

                                            {"error":"port forwarding not available for this region"} 
                                            

                                            All runs well, the pia_port.txt is created but in the log I get that error.

                                            Can any one help me? Using last version of the script.

                                            Best Regards
                                            Soloam

                                            1 Reply Last reply Reply Quote 0
                                            • S
                                              saytar last edited by

                                              Not sure I can help as I don't have My VPN back up yet since my box crashed and I had to reflash and set it backup,,,But before the crash I did have PIA up and working on Pfsense 2.1.3.

                                              I didn't have any trouble with it changing IP's when they switched around…my logs showed Pfsense detecting the change and just remaking the tunnel.....and I never noticed it............until I happened to check the logs.....

                                              Their is a how to on line somewhere I went by to set it up. The setup was for ONLY the Client setup. I think maybe everyone is Making the Issue More complex than needed.

                                              Check this link.  http://www.bodenzord.com/archives/324
                                              Maybe it will help

                                              Chow

                                              “An armed society is a polite society. Manners are good when one may have to back up his acts with his life.”

                                              “Ignorance is curable, stupid is forever.”
                                              ― Robert A. Heinlein, Beyond This Horizon

                                              1 Reply Last reply Reply Quote 0
                                              • K
                                                khyr0n last edited by

                                                OMG This post is the Holy Grail I had to revive it! (And because I have a question)

                                                Thanks a lot! I only changed
                                                PORT=curl -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" https://www.privateinternetaccess.com/vpninfo/port_forward_assignment

                                                to

                                                PORT=curl -k -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" https://www.privateinternetaccess.com/vpninfo/port_forward_assignment

                                                Because I was getting an error… Now it's fine!

                                                BUT...

                                                Would anyone have an idea on how to go about reading the pia_port.txt file from a remote windows machine running utorrent client???

                                                Thanks again!

                                                1 Reply Last reply Reply Quote 0
                                                • Soloam
                                                  Soloam last edited by

                                                  Hello, yes I had to make that change to, something regarding certificates on the SSH.

                                                  Also I made a small change to Bagpuss pfsense script, to make it use a Alias with a port, instead of changing the rules. That way I can use the torrent port in other rules.

                                                  It assumes a port alias with the name "TorrentBoxPortPIA".

                                                  
                                                  #!/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.0 (21st January 2014)
                                                  
                                                  # 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
                                                  
                                                  # Add your PIA username and password
                                                  USERNAME=USER
                                                  PASSWORD=PASSWORD
                                                  PIACLIENTID=/cf/conf/pia_client_id
                                                  CONFFILE=/cf/conf/config.xml
                                                  
                                                  # Check to see if we have a valid PIA Client ID file.
                                                  # If not, create one. Linux is included for illustration only.
                                                  if [ ! -e $PIACLIENTID ]; then
                                                  
                                                  	# OSX/FreeBSD (pfSense)
                                                  	head -n 100 /dev/urandom | md5 > $PIACLIENTID
                                                  
                                                  	# Linux
                                                  	#head -n 100 /dev/urandom | md5sum | tr -d " -" > $PIACLIENTID
                                                  
                                                  	logger "pia-port: Created new PIA Client ID."
                                                  fi
                                                  
                                                  # Find out the tunnelling device for your VPN and get your IP address.
                                                  # There are several options presented here. Personally, I prefer to use
                                                  # the interface which I know relates to my VPN tunnel for forwarding.
                                                  
                                                  #DEVICE=`ifconfig | grep -o "tun[0-9]"`
                                                  #LOCAL_IP=`ifconfig $DEVICE | grep -Po "(?<=addr.)[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*"`
                                                  LOCAL_IP=`ifconfig ovpnc1 | grep "inet " | cut -d\  -f2`
                                                  
                                                  # Get the port number for the forwarded port
                                                  PORT=`curl -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" -k https://www.privateinternetaccess.com/vpninfo/port_forward_assignment`
                                                  
                                                  PORTNUM=`echo $PORT | grep -oE "[0-9]+"` 
                                                  
                                                  # Some error detection. If PORTNUM is longer than 5 characters, we know that
                                                  # an error has been returned. We log it to syslog, and exit.
                                                  len=`expr $PORTNUM : '.*'`
                                                  echo $len
                                                  
                                                  if [ $len -gt 5 ]; then
                                                  	logger "pia-port: $PORTNUM"
                                                  	exit 0
                                                  fi
                                                  
                                                  logger "pia-port: Port number acquired: $PORTNUM"
                                                  
                                                  # Get current NAT port number using xmlstarlet to parse the config file.
                                                  CURPORT=`xml sel -t -v '//alias[name="TorrentBoxPortPIA"]/address' $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" = "$PORTNUM" ]; then
                                                  	logger "pia-port: Port not changed. Exiting."
                                                  	exit 0
                                                  fi
                                                  
                                                  # Port forward has changed, so we update the rules in the config file.
                                                  xml ed -u '//alias[name="TorrentBoxPortPIA"]/address' -v $PORTNUM $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 $PORTNUM > /usr/local/www/pia_port.txt
                                                  
                                                  # Force pfSense to re-read it's config
                                                  rm /tmp/config.cache
                                                  
                                                  logger "pia-port: New port number ($PORTNUM) inserted into config file."
                                                  
                                                  

                                                  Best Regards

                                                  1 Reply Last reply Reply Quote 0
                                                  • P
                                                    plainzwalker last edited by

                                                    Sorry for resurrecting an old post but I just found it and I have it 90% working. The problem I am having is with the transmission script, I am using an Ubuntu server instead of a Synology system for transmission, and apparently I wasn't lucky enough for this script to work out of the box for me. Can someone please point me in the right direction so I can convert this to a linux script so I can get it to work?

                                                    Error I am getting is:

                                                    jeff@behemuth:/usr/local/bin$ sh transmission-port
                                                    transmission-port: 40: transmission-port: Syntax error: end of file unexpected (                  expecting "then")
                                                    jeff@behemuth:/usr/local/bin$
                                                    
                                                    

                                                    Thank you

                                                    1 Reply Last reply Reply Quote 0
                                                    • D
                                                      DocLove last edited by

                                                      First,
                                                          Thank everyone for their hard work on this thread, it was exactly what i needed to get my tunnel working. Since it took me some work to get this operational I thought I would share the final files I am running with.

                                                      1 Reply Last reply Reply Quote 0
                                                      • A
                                                        Attackduck last edited by

                                                        Thank you for the information!  And the script/instructions.
                                                        I managed to make the PFSense side work by adding "-k" to this line in pia-port script Line 46 as someone suggested here:

                                                        PORT=curl –interface $INTERFACE -k -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" https://www.privateinternetaccess.com/vpninfo/port_forward_assignment

                                                        PIA was not allowing port forwarding on the original server I was connected to, and did not see that error message till after I changed this line.  After I changed servers to one that allowed port forwarding, it was working.

                                                        Instead of a second script running to change the port on the application side, can we hard code the port on the destination side to match the application?  PIA assigned me 27494, and I thought I would try it, but failed.  Tried changing the destination port to 29493 and hard coding the application to this, but the connection would not work unless all the port numbers were the same right to the application.  Would an outbound rule need to be created then added to the script as well?  Figured if this was possible, it would keep the config in one spot, cleaner for me.
                                                        Line 90:
                                                        xml ed -u '//rule[descr="Torrent"]/destination/port' -v $PORTNUM -u '//rule[descr="Torrent"]/local-port' -v 29493 -u '//rule[descr="NAT Torrent"]/destination/port' -v $PORTNUM $CONFFILE > /tmp/config.pia

                                                        1 Reply Last reply Reply Quote 0
                                                        • T
                                                          thumbsp0t last edited by

                                                          @Attackduck:

                                                          Thank you for the information!  And the script/instructions.
                                                          I managed to make the PFSense side work by adding "-k" to this line in pia-port script Line 46 as someone suggested here:

                                                          PORT=curl –interface $INTERFACE -k -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" https://www.privateinternetaccess.com/vpninfo/port_forward_assignment

                                                          PIA was not allowing port forwarding on the original server I was connected to, and did not see that error message till after I changed this line.  After I changed servers to one that allowed port forwarding, it was working.

                                                          Instead of a second script running to change the port on the application side, can we hard code the port on the destination side to match the application?  PIA assigned me 27494, and I thought I would try it, but failed.  Tried changing the destination port to 29493 and hard coding the application to this, but the connection would not work unless all the port numbers were the same right to the application.  Would an outbound rule need to be created then added to the script as well?  Figured if this was possible, it would keep the config in one spot, cleaner for me.
                                                          Line 90:
                                                          xml ed -u '//rule[descr="Torrent"]/destination/port' -v $PORTNUM -u '//rule[descr="Torrent"]/local-port' -v 29493 -u '//rule[descr="NAT Torrent"]/destination/port' -v $PORTNUM $CONFFILE > /tmp/config.pia

                                                          You want to keep the NAT Torrent destination port as the static port as well.

                                                          What I did is a little different;

                                                          I do the port verification against the Torrent rule's destination port;

                                                          CURPORT=xml sel -t -v '//rule[descr="Torrent"]/destination/port' $CONFFILE

                                                          and only write it again if it changed

                                                          xml ed -u '//rule[descr="Torrent"]/destination/port' -v $PORTNUM $CONFFILE > /tmp/config.pia

                                                          I also added /etc/rc.filter_configure at the end of the script pfsense didn't really seem to reload the config properly.

                                                          1 Reply Last reply Reply Quote 0
                                                          • D
                                                            Defyant last edited by

                                                            I know this is an old thread, but it is the first one to come up in google when searching "pfSense PIA Portforward". So I just wanted to add a few things on how I got port-forwarding using PIA setup with pfSense and a separate torrent download box running Deluge. I've attached two txt files to this post (pia-port.txt and deluge-port.txt), both of these are edited versions of soloam's and Bagpuss' scripts.

                                                            soloam's script I only edited slightly in order to get working (added a -k to the curl command and tweaked a few names). In pfSense 2.3.1 you also only need to run the below command to install xmlstarlet and don't need to worry about installing curl.

                                                            pkg install xmlstarlet

                                                            Once that's done you just need to edit the pia-port script, put it somewhere on the pfSense box (/usr/local/bin is the path recommended by Bagpuss) and use chmod 755 so you can run it. You will also need to configure the Cron plugin to run it every hour. Lastly make sure you have an port alias setup called PIAPort in pfSense and port forwards as necessary setup.

                                                            
                                                            #!/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.0 (21st January 2014)
                                                            # v1.1 (24th June 2016)
                                                            
                                                            # 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
                                                            
                                                            # Add your PIA username and password
                                                            USERNAME=USERNAME
                                                            PASSWORD=PASSWORD
                                                            PIACLIENTID=/cf/conf/pia_client_id
                                                            CONFFILE=/cf/conf/config.xml
                                                            
                                                            # Check to see if we have a valid PIA Client ID file.
                                                            # If not, create one. Linux is included for illustration only.
                                                            if [ ! -e $PIACLIENTID ]; then
                                                            
                                                                    # OSX/FreeBSD (pfSense)
                                                                    head -n 100 /dev/urandom | md5 > $PIACLIENTID
                                                            
                                                                    # Linux
                                                                    #head -n 100 /dev/urandom | md5sum | tr -d " -" > $PIACLIENTID
                                                            
                                                                    logger "pia-port: Created new PIA Client ID."
                                                            fi
                                                            
                                                            # Find out the tunnelling device for your VPN and get your IP address.
                                                            # There are several options presented here. Personally, I prefer to use
                                                            # the interface which I know relates to my VPN tunnel for forwarding.
                                                            
                                                            #DEVICE=`ifconfig | grep -o "tun[0-9]"`
                                                            #LOCAL_IP=`ifconfig $DEVICE | grep -Po "(?<=addr.)[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*"`
                                                            LOCAL_IP=`ifconfig ovpnc1 | grep "inet " | cut -d\  -f2`
                                                            
                                                            # Get the port number for the forwarded port
                                                            PORT=`curl -k -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" -k https://www.privateinternetaccess.com/vpninfo/port_forward_assignment`
                                                            
                                                            PORTNUM=`echo $PORT | grep -oE "[0-9]+"`
                                                            
                                                            # Some error detection. If PORTNUM is longer than 5 characters, we know that
                                                            # an error has been returned. We log it to syslog, and exit.
                                                            len=`expr $PORTNUM : '.*'`
                                                            echo $len
                                                            
                                                            if [ $len -gt 5 ]; then
                                                                    logger "pia-port: $PORTNUM"
                                                                    exit 0
                                                            fi
                                                            
                                                            logger "pia-port - Port number acquired: $PORTNUM"
                                                            
                                                            # Get current NAT port number using xmlstarlet to parse the config file.
                                                            CURPORT=`xml sel -t -v '//alias[name="PIAPort"]/address' $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" = "$PORTNUM" ]; then
                                                                   logger "pia-port - Port Not Changed. Exiting."
                                                                   exit 0
                                                            fi
                                                            
                                                            # Port forward has changed, so we update the rules in the config file.
                                                            xml ed -u '//alias[name="PIAPort"]/address' -v $PORTNUM $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 $PORTNUM > /usr/local/www/pia-port.txt
                                                            
                                                            # Force pfSense to re-read it's config
                                                            rm /tmp/config.cache
                                                            
                                                            logger "pia-port - New port number ($PORTNUM) inserted into config file."
                                                            
                                                            

                                                            Once the pia-port script is running on pfSense then on whatever box is running Deluge you simply need to copy the below script, edit it with credentials as necessary, run chmod 755 on it and then configure Cron to run it shortly after the pia-port script runs.

                                                            
                                                            #!/bin/sh
                                                            export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/syno/sbin:/usr/syno/bin:/usr/local/sbin:/usr/local/bin
                                                            
                                                            # Script to update port used by Deluge torrent client
                                                            # Developed for use on FreeNAS 9.10\. Should work on other platforms.
                                                            # v1.0 (24th June 2016)
                                                            
                                                            # This script is configured to work with Deluge that has password
                                                            # protection on the daemon. You can remove this stuff if you don't use it.
                                                            
                                                            USERNAME="USERNAME"
                                                            PASSWORD="PASSWORD"
                                                            
                                                            if [ ! -e /tmp/pia-port.txt ]; then
                                                            
                                                                    logger -p user.crit "deluge-port: Setting up port forward for first time."
                                                                    cd /tmp && curl -O -k https://192.168.200.254/pia-port.txt
                                                                    read -r NEWPORT < /tmp/pia-port.txt
                                                                    deluge-console "connect 127.0.0.1:58846 $USERNAME $PASSWORD; config --set listen_ports ($NEWPORT,$NEWPORT)"
                                                            
                                                            else
                                                            
                                                                    read -r CURPORT < /tmp/pia-port.txt
                                                                    cd /tmp && curl -o pia-new.txt -k https://192.168.200.254/pia-port.txt
                                                                    read -r NEWPORT < /tmp/pia-new.txt
                                                            
                                                                    logger -p user.crit "deluge-port: Current port: $CURPORT"
                                                                    logger -p user.crit "deluge-port: New Port: $NEWPORT"
                                                            
                                                                    if [ "$CURPORT" = "$NEWPORT" ]; then
                                                                            logger -p user.crit "deluge-port: Port not changed. Exiting."
                                                                            exit 0
                                                                    fi
                                                            
                                                                    logger -p user.crit "deluge-port: Updating port. Port: $NEWPORT"
                                                                    mv /tmp/pia_new.txt /tmp/pia-port.txt
                                                                    deluge-console "connect 127.0.0.1:58846 $USERNAME $PASSWORD; config --set listen_ports ($NEWPORT,$NEWPORT)"
                                                            
                                                            fi
                                                            
                                                            exit 0
                                                            
                                                            

                                                            The credentials that need to be used are the Deluge daemon login credentials. If you haven't configured any should be able to remove the bits of code for connections and the rest of the script should run fine.

                                                            connect 127.0.0.1:58846 $USERNAME $PASSWORD;
                                                            

                                                            Hopefully this information/these scripts prove useful to someone else that stumbles onto this page.

                                                            pia-port.txt
                                                            deluge-port.txt

                                                            1 Reply Last reply Reply Quote 0
                                                            • M
                                                              madhartigan last edited by

                                                              Thank you for following up on this!!

                                                              The timing could not have been more perfect.  I just got done configuring my pfSense box, got PIA running and figured out how to route certain interfaces around PIA directly to the WAN.

                                                              I am not script savvy, but I do have the know-how to properly edit your script with my appropriate information.  (I think)  I have set up deluged, deluge-web and deluge-webui on my Ubuntu 16.04 box following this guide and it seems to be running just fine.

                                                              If you have the time, I'd appreciate a bit of assistance configuring this properly to work with my setup.

                                                              1. The step in which I'm supposed to configure the port Alias "PIAPort" . . . I'm not sure what port forwards I should assign to that Alias.  Would that be for outgoing ports I assign in Deluge (ie: not set to random)?

                                                              2. pia-port gets to the length check for the port number and then spits a syntax error.

                                                              [2.3.1-RELEASE][admin@pfsense.mydomain.net]/usr/local/bin: ./pia-port
                                                              VENDOR
                                                              SSH_CLIENT
                                                              LSCOLORS
                                                              LOGNAME
                                                              OSTYPE
                                                              MACHTYPE
                                                              FTP_PASSIVE_MODE
                                                              CLICOLOR
                                                              MAIL
                                                              PATH
                                                              HOST
                                                              REMOTEHOST
                                                              SSH_AUTH_SOCK
                                                              PWD
                                                              GROUP
                                                              TERM
                                                              SSH_TTY
                                                              USER
                                                              HOME
                                                              SSH_CONNECTION
                                                              HOSTTYPE
                                                              SHELL
                                                              BLOCKSIZE
                                                              SHLVL
                                                                % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                                                                               Dload  Upload   Total   Spent    Left  Speed
                                                              100   149  100    57  100    92     26     42  0:00:02  0:00:02 --:--:--    42
                                                              expr: syntax error
                                                              
                                                              [: -gt: unexpected operator
                                                              [2.3.1-RELEASE][admin@pfsense.mydomain.net]/usr/local/bin:
                                                              
                                                              

                                                              (edited to change host and domain)

                                                              Output from System.log:

                                                              Jun 28 20:47:41 pfsense admin: pia-port - Port number acquired:
                                                              Jun 28 20:47:41 pfsense admin: pia-port - Current Port Forward: 62420:62430
                                                              
                                                              

                                                              Doesn't seem to be acquiring a port?

                                                              2a: Just curious why all those Uppercase field appear at the beginning of the runtime of the script . . . (VENDOR, SSH_CLIENT, LSCOLORS, LOGNAME, etc. etc.)

                                                              For now, that's all I have until I can get pia-port properly executing and providing the pia-port.txt file in /usr/local/www/ , I can't verify the functionality of deluge-port.txt.  ;-)

                                                              THANK YOU for putting the time into creating this.  I have every confidence it will be a huge help for me once I fix these simple issues.  I just definitely need some help to iron out these kinks.

                                                              Any and all help is greatly appreciated.

                                                              ADD: silly detail, but might be worth mentioning . . . in deluge-port, second line has "exporrt" not "export"

                                                              1 Reply Last reply Reply Quote 0
                                                              • E
                                                                Elegant last edited by

                                                                I've noticed that in 2.3_5 that removing config.cache does NOT reload the port settings. I have found a workaround but I'm hoping some other people can test this so that I can be sure that I'm not just crazy…

                                                                http://www.ipfingerprints.com/portscan.php

                                                                Example: If my port was previously 25623 and it changed to 42344 I can easily see that 42344 is NOT open. However if I re-save the NAT Port Forward Rule 42344 opens. Hopefully someone else can see this on 2.3_5.

                                                                1 Reply Last reply Reply Quote 0
                                                                • D
                                                                  Defyant last edited by

                                                                  madhartigan,

                                                                  The PIAPort alias can be set as anything to start with. As long as the PIAPort alias exists it will update to the correct value the first time you run the script.

                                                                  Regarding the syntax error,  I've checked over the scripts I posted for something that could be causing it and I can't see anything. One thing I did notice however, was that when I copied out of the code field from the forums that the formatting changed compared to the attached txt file. So if you copied it from there you might want to try downloading the text file version and using that. Failing that can you please post an exact copy of the script you're using (attach it as txt file)? Just remember to edit out the USERNAME and PASSWORD fields first.

                                                                  To answer your last question those uppercase fields shouldn't appear at all. I suspect these are related to the syntax/formatting error. When you run the script the only output should be the last 3 lines of text before the syntax error.

                                                                  Lastly what version of pfSense are you using? Because if Elegant is right and 2.3_5 doesn't update the port when clearing the config.cache then the script I posted won't work. I'm still running 2.3.1 at the moment.

                                                                  Elegant, what was the workaround you are using to reload the port settings?

                                                                  PS. madhartigan thanks for picking up that typo in the deluge-port script. I've now fixed it and edited my post to use the correct information.

                                                                  1 Reply Last reply Reply Quote 0
                                                                  • Q
                                                                    qwertytheking last edited by

                                                                    First let me say this script and post was extremely helpful and works great (mostly)!

                                                                    I am running 2.3.1-RELEASE-p5 and have the same issue as Elegant in that the rules don't seem to get updated unless I use the web GUI to save and then apply changes.  I see the port number getting updated in the web GUI but the port is not actually open on the firewall until I manually save and use the button to apply changes.

                                                                    What is the workaround you spoke of?  Is it something that can be easily automated?

                                                                    Thanks!

                                                                    1 Reply Last reply Reply Quote 0
                                                                    • S
                                                                      SpaceAvenger last edited by

                                                                      I know this is an old post. I've already created a new topic post but have yet to receive any replies to it. Thought I would just throw this in here and hope someone will reply back with helpful into.

                                                                      I am attempting to add a script to my pfSense box that pulls or receives a port assignment from PIA. I'm basing my script on one created and modified from https://forum.pfsense.org/index.php?topic=71725.15  I'm not sure if something has changed with either pfSense or PIA since last July but I'm not able to get a port number with this script. It keeps coming back with "Port forward not available for this region." I've tried both Netherlands and Switzerland which are both servers that have port forwarding available. My first hunch is maybe I have a setting incorrectly set in pfSense. Or maybe PIA has changed something in their URL. Not sure. Anyway, I've verified that the variables going into the command below to receive a port assignment from PIA are correct (ie - username, password, client_id, local_ip).

                                                                      PORT=curl -k -d "user=$USERNAME&pass=$PASSWORD&client_id=$(cat $PIACLIENTID)&local_ip=$LOCAL_IP" -k https://www.privateinternetaccess.com/vpninfo/port_forward_assignment

                                                                      I've got a working OpenVPN tunnel created to the Netherlands currently. Just can't seem to get this script to get a port number.

                                                                      Any ideas would be greatly appreciated. If you need more info let me know.

                                                                      Thank you.

                                                                      1 Reply Last reply Reply Quote 0
                                                                      • U
                                                                        urby last edited by

                                                                        I am interested in this as well.  Does anyone know if this is working completely with the most recent release?

                                                                        1 Reply Last reply Reply Quote 0
                                                                        • S
                                                                          SpaceAvenger last edited by

                                                                          OK… I got my script working. Turns out it wasn't the command that pulls the port from PIA that was causing my issue. It was the line where the CLIENTID is generated. It seems just adding the pipe the removes " -" made the difference. Not sure why but it doesn't matter. It's all happy now.

                                                                          CLIENTID=head -n 100 /dev/urandom | md5 -r | tr -d " -"

                                                                          However, I am having the same issue now that Elegant and qwertytheking are having with regards to a port change not applying at least right away. Like qwertytheking mentioned, if you access the port alias and save/apply it, it opens that port but until then, it's still closed.

                                                                          Is there a command or something that saves/applies these changes through CLI that I can add to my script?

                                                                          1 Reply Last reply Reply Quote 0
                                                                          • J
                                                                            jhboricua last edited by

                                                                            Looks like PIA introduced a new API in February. The announcement is here:

                                                                            New PIA Port Forwarding API

                                                                            The old API will be going away, they say. And the new one works a little different. For example:

                                                                            • The query for the port must be done withing the first 2 minutes after the connection is made.

                                                                            • You no longer need to poll the API periodically, the initial request is sufficient

                                                                            Does anyone have a working solution using the new API that they're willing to share?

                                                                            1 Reply Last reply Reply Quote 0
                                                                            • A
                                                                              AccountIsTaken last edited by

                                                                              I appear to have worked out a script with the new API that works if anyone wants to test it. Preconditions are:

                                                                              1. That you have deluge set up on a server that you can ssh into without a password.
                                                                              2. That the user you are SSHing into is able to edit deluge-console.
                                                                              3. That you have xmlstarlet installed (curl appears to be preinstalled on my version, otherwise install it as well).
                                                                              4. That you have a port forward setup using an alias name of PIAPort.

                                                                              You'll need to append –route-up /location/script.sh to the custom options of your VPN setup.

                                                                              #!/bin/sh
                                                                              CONFFILE=/cf/conf/config.xml
                                                                              TMP_CONFFILE=/tmp/config.pia
                                                                              
                                                                              #Interface name of vpn connection
                                                                              INTERFACE='ovpnc7'
                                                                              
                                                                              #IP of server deluge is running on
                                                                              SERVER_IP=''
                                                                              
                                                                              #Username that has ssh setup that is able to edit deluge-console
                                                                              USER=''
                                                                              
                                                                              #Delay for 5 seconds to ensure vpn is up
                                                                              sleep 5
                                                                              
                                                                              #Generate a client ID.
                                                                              CLIENT_ID=`head -n 100 /dev/urandom | sha256 | tr -d " -"`
                                                                              
                                                                              #Get a forwarded port from PIA
                                                                              PORT=`curl --interface $INTERFACE "http://209.222.18.222:2000/?client_id=$CLIENT_ID"`
                                                                              
                                                                              #Cleanup port output
                                                                              PORTNUM=`echo $PORT | grep -oE "[0-9]+"`
                                                                              
                                                                              # Some error detection. If PORTNUM is not 5 characters, we know that
                                                                              # an error has been returned. We log it to syslog, and exit.
                                                                              if [ ${#PORTNUM} -ne 5 ]; then
                                                                              	logger "pia-port - Error setting port"
                                                                              	exit 0
                                                                              fi
                                                                              
                                                                              logger "pia-port - Port number acquired: $PORTNUM"
                                                                              
                                                                              #Change Deluge port
                                                                              ssh $USER@$SERVER_IP "deluge-console 'config --set listen_ports ($PORTNUM, $PORTNUM)'"
                                                                              
                                                                              # Update the port forward rules in the config file.
                                                                              xml ed -u '//alias[name="PIAPort"]/address' -v $PORTNUM $CONFFILE > $TMP_CONFFILE
                                                                              
                                                                              # Put the config file in the correct location.
                                                                              cp $TMP_CONFFILE $CONFFILE
                                                                              
                                                                              # Force pfSense to re-read it's config
                                                                              rm /tmp/config.cache
                                                                              
                                                                              #Reload the filter
                                                                              /etc/rc.filter_configure
                                                                              
                                                                              logger "pia-port - New port number ($PORTNUM) inserted into config file."
                                                                              

                                                                              Edit: Upon further testing the script works but executing it that way would only work some of the time. I added the below code to the end of /etc/devd.conf which is responsible for executing tasks depending on kernel events. It seems to work consistently this way. Edit ovpnc to the interface number of your vpn connection and change /location/script.sh to the location that you saved the script.

                                                                              notify 0 {
                                                                                      match "system"          "IFNET";
                                                                                      match "subsystem"       "(ovpnc7)";
                                                                                      match "type"            "LINK_UP";
                                                                                      action " /location/script.sh";
                                                                              };
                                                                              
                                                                              1 Reply Last reply Reply Quote 0
                                                                              • J
                                                                                jhboricua last edited by

                                                                                Thanks AccountIsTaken.

                                                                                ~~Correct me if I'm wrong but isn't the portion of the script dealing with the torrent client optional? As long as my pfsense NAT rule forwards the port I'm opening on the WAN side (set to the PIAPort Alias) to the port of my torrent client in my LAN subnet I should be ok, right? In other words:

                                                                                WAN:PIAPort –> LAN:TorrentClient:port

                                                                                I only care about updating the alias and will leave the port on the client side unchanged, letting pfSense port forwarding do it's thing.~~

                                                                                I figured it would be easier to just test it out. I used your script minus the lines dealing with Deluge, meaning the script will only update the port alias and reload the filter in pfSense once the VPN connection is established. It works like a charm.  My NAT rule has the port forwarding in the WAN interface using the PIAport alias but the destination port for the forwarded traffic on the LAN IP is a static value that never changes. That way I don't have to update my torrent client every time I reconnect the VPN.

                                                                                1 Reply Last reply Reply Quote 0
                                                                                • A
                                                                                  AccountIsTaken last edited by

                                                                                  Glad it's working for you jhboricua.

                                                                                  Yes the part dealing with the torrent client is completely optional. You could strip out that part without any problems as you've found. You could also program multiple port forwards as long as each port forward runs through a separate vpn client connection if you wanted to run various services. You just have to create multiple connections and update for each connection.

                                                                                  1 Reply Last reply Reply Quote 0
                                                                                  • H
                                                                                    Hakon74 last edited by

                                                                                    Thank you AccountIsTaken  :D
                                                                                    Great script! Deluge is working perfectly

                                                                                    Can this be modified to work with Plex? I do get a port from PIA but I have to change the port manually in PMS every time it changes.

                                                                                    1 Reply Last reply Reply Quote 0
                                                                                    • First post
                                                                                      Last post