This is the continuation of what I wrote here previously. One thing that should be immediately obvious to you is that I’m not the best at coming up with interesting article titles :P. In the previous part, we got the script provided by Private Internet Access (PIA) to work directly on our Asus routers running RMerlin. However, all the script does is to return a port number, after which we still probably have to do the following:

  • Updating our port forwarding rules
  • Updating our applications to use the updated port number

And this has to happen each time we have a new port number, which will likely happen when our router restarts, our internet goes down and comes back up, power trip, etc. Depending on where you’re from, any or all of the cases may happen a lot, or it may rarely happen. Whatever it is, I don’t enjoy repetitive work, so let’s see how we can automate parts of it.

Pre-reqruisites: Before we can continue, please make sure that you have the JFFS partition enabled on RMerlin. While we are on it, you may also want to check out user scripts you can have in the JFFS partition to automate some parts of your router setup. Secondly, we do not need the script that was in the previous post. That’s all for the pre-requisites :).

Next, we are going to make use of openvpn-event. I already have this file as I use it for selective routing; my configuration can be found here if you are interested (I’d love to cover it but then it’ll be out of the scope of this article, perhaps another time). If you already have this file, you don’t have to do anything at this step as all we are going to do later on is to add a line to it. If you do not have this file, please ssh into your router, and do the following:

cd /jffs/scripts
touch openvpn-event
chmod +x openvpn-event

Next, we are going to create a separate shell script within /jffs/scripts to handle the actual port forwarding. For the purposes of this article, we’ll name the file pia_port_forward.sh. For the first part, we are going to just attempt to get port forwarding number, and output it into a file. The reason for outputting it into a file is so that we can refer to it later, and you will see the use case for it later. As always, you can create it as follows:

cd /jffs/scripts
touch pia_port_forward.sh
chmod +x pia_port_forward.sh

You can now edit it in the text editor of your choice. The initial script will be as follows (based off the original script from PIA and also this post here):

#!/bin/sh

logger -t "($(basename $0))" $$ Get PIA Port Forward Response

local_ip=`ifconfig tun11|grep -oE "inet addr: *10\.[0-9]+\.[0-9]+\.[0-9]+"|tr -d "a-z :"|tee /tmp/vpn_ip`
client_id=`head -n 100 /dev/urandom | md5sum | tr -d " -"`
FPort=`wget -q --post-data="user=<PIA_USERNAME>&pass=<PIA_PASSWORD>!&client_id=$client_id&local_ip=$local_ip" -O - 'https://www.privateinternetaccess.com/vpninfo/port_forward_assignment' --no-check-certificate | head -1 | grep -o "[0-9]*"`
echo $FPort > /tmp/PIA_PORT

logger -t "($(basename $0))" $$ Port Number: $FPort

Replace <PIA_USERNAME> and <PIA_PASSWORD> with your PIA username and password respectively. Now, if you run ./pia_port_forward.sh, you should see just the port number as the output. Additionally, a file should be created at /tmp/PIA_PORT and if you type cat /tmp/PIA_PORT you should see that the port number has been saved into it. Now, we are going to add this script into openvpn-event and see if it is working. Edit openvpn-event in the text editor of your choice. If you already have your own openvpn-event previously, you just need to add the following to the end of your file (including the & symbol):

/jffs/scripts/pia_port_forward.sh &

If your openvpn-event is a new and blank file, you’d need the following:

#!/bin/sh

/jffs/scripts/pia_port_forward.sh &

We are now going to test if openvpn-event and pia_port_forward.sh are working. You can either restart your router, or turn off and on the OpenVPN client. Once done, check the System Log, and you should see something like the following:

PIA Port Forward Response

Technically, you are now done. Since the port number is being stored in /tmp/PIA_PORT, you can copy the file somewhere, and then have your applications access it in one way or another to update their port forward setup. For the purposes of this article, I will be using my Synology NAS as an example. The two main things we need to do are:

  • Set up port forwarding
  • Get the port number from PIA to Synology

Updating the original pia_port_forward.sh script, we now have the following (new lines are highlighted):

#!/bin/sh

Synology_NAS="192.168.1.51"

logger -t "($(basename $0))" $$ Get PIA Port Forward Response

local_ip=`ifconfig tun11|grep -oE "inet addr: *10\.[0-9]+\.[0-9]+\.[0-9]+"|tr -d "a-z :"|tee /tmp/vpn_ip`
client_id=`head -n 100 /dev/urandom | md5sum | tr -d " -"`
FPort=`wget -q --post-data="user=<PIA_USERNAME>&pass=<PIA_PASSWORD>!&client_id=$client_id&local_ip=$local_ip" -O - 'https://www.privateinternetaccess.com/vpninfo/port_forward_assignment' --no-check-certificate | head -1 | grep -o "[0-9]*"`
echo $FPort > /tmp/PIA_PORT

logger -t "($(basename $0))" $$ Port Number: $FPort
logger -t "($(basename $0))" $$ Configure iptables

iptables -I FORWARD -i tun11 -p udp -d $Synology_NAS --dport $FPort -j ACCEPT
iptables -I FORWARD -i tun11 -p tcp -d $Synology_NAS --dport $FPort -j ACCEPT
iptables -t nat -I PREROUTING -i tun11 -p tcp --dport $FPort -j DNAT --to-destination $Synology_NAS
iptables -t nat -I PREROUTING -i tun11 -p udp --dport $FPort -j DNAT --to-destination $Synology_NAS

ssh -i /jffs/dropbear_private -y -y root@192.168.1.51 "echo `cat /tmp/PIA_PORT` > /root/PIA_PORT"

The various iptables commands are to handle port forwarding. In my case, I was forwarding to my Synology NAS. It could be anything else :). Another thing I want to touch on quickly is the use of ssh to “copy” the port number across instead of scp. The main reason is that the ssh and scp that comes with RMerlin does not have the -o flag available, so I can’t use StrictHostKeyChecking=no. In addition, even if you have stored the hosts into known_hosts before, I believe only the contents of /jffs are kept while everything else is lost upon reboot. I was not able to find a way to skip the checks on scp, but ssh conveniently came with the -y -y flag which achieves the same thing. I also have a couple of additional ssh commands running other scripts on the Synology NAS after the port number is copied across, but I did not include them here.

Also, I did not touch on the ssh setup between my router and Synology NAS. In short, I used dropbearkey on the router to generate the keys. I kept the private key on /jffs while I copied the public key and set it up on the Synology NAS. I found this guide to be useful on configuring the Synology NAS. Perhaps I will write a quick guide next time on this :)!

comments powered by Disqus