How To: VPN and Plex Tutorial

Well, I've spent the better half of two weeks trying to get my VPN service to run the way I want to, so I thought I'd put together a little how to to help others.  

Please note:  I will be putting a more detailed version on my website once I get it updated (I'll let you know here when I do).

 

A Little background and common problems people have with running a VPN.  I've done a lot of research and found a lot of people having the same questions as I did. I will focus this tutorial specifically on getting Plex up and running with the VPN.

 

 

Question 1: "Once I turn on my VPN, I can't access my server outside my home network (remote access) / This goes for Plex too.

 

Answer 1: When you run a VPN you are creating a "new" encrypted connection to the web.  Since you are bypassing your ISP, unless your VPN provider has open ports (most of them do not for security reasons), then you will no longer have access to your services that you port forwarded at home.  There are two options to solve this problem.  

                  Option A: see if your VPN provider has the option to open ports, if they do, then follow their support, open a port, then port forward the service you want to use remotely through that port.  There are a couple of problems with this option.  First, if you are opening a port through the VPN, you are lowing the level of security that you signed up for in the first place.  Another issue is that even if your VPN provider can open a port for you, it will most likely only be one, so if you have multiple services you are trying to access remotely, you are out of luck.  Finally, accessing Plex remotely with a VPN on requires more than just having a port open through the VPN tunnel (I'll explain more in a minute).

                  Option B: This is the option I recommend, and have working on my setup at home.  Use a "Split Tunnel"/Create a "Routing Policy".  What this means is that you would use iptables to selectively route your traffic either through the VPN or directly through your ISP.  This includes allowing traffic to flow to ports you have open on your router.

 

Question 2: "I setup a Split Tunnel, and can successfully access my server outside my home network, but I still can't access Plex".  

 

Answer 2: Well, for some reason (that others could probably better explain than I can), because Plex is a "connected service" where it requires to talk to PMS behind your firewall, you not only need to get port 32400 to bypass the VPN, but you also need to allow any traffic from the IP addresses associated with plex.tv to also bypass the VPN.

 

 

Okay, let's move on...one more thing before I dig in:

Things you need for this to work:

1. You must have a router that is running an open source firmware (like DD-wrt or Tomato etc.) that supports iptables.

2. I would recommend that you have your modem set to "Bridged" mode and let your router handle your ISP traffic.  To see

if your modem is in "Bridged" mode, go to google.com and type: "what is my ip address" in the search bar.  Google will return your public IP addresss.  

See if this matches your WAN IP address on your router.  If it does, then you are good to go.  If not, then that potentially means that your modem is also routing traffic to your router, which means you are running a "double NAT".  

You probably won't have much issue if you are just surfing the web and don't need remote access, but if you do, this could cause you some headaches...

3.  This is a BIG one for those of you who have a NAS like Synology or QNAP that can run a VPN client.

 I would recommend that you run your VPN client on your router NOT the NAS!  

Unfortunately, these servers don't usually support any kind of routing policy (iptables), and if you setup

to route your traffic ahead of your vpn client in your network chain, this can also cause lots of problems.

 I had started this "journey" by running the VPN client on my Synology server, then discovered the routing issues.  An addition problem with running the VPN client on Synology boxes

(This appears to be a bug in the current DSM), when your router reboots (I have mine shut down at night) the VPN client doesn't automatically reconnect on startup.  

So if you are unaware of this, you could be potentially running services in the open without knowing it.

4. If you are accessing your network remotely, then chances are you are using a DDNS service to update your domain.  I would recommend that you also run the DDNS client on your router and not on your NAS.  Again, if you have your DDNS behind your VPN client in your chain, you could also have trouble.

 

To make plex work remotely you have two basic things that need to be done:

1. Create a routing policy to open necessary ports

2. Create a way to dynamically route plex.tv ip addresses around the vpn

(note: both of these steps are available in multiple places on the web.  #2 is available in the following post on this forum: https://forums.plex.tv/topic/64600-using-plex-server-with-a-vpn/page-4

I want to give credit to zanechua.  The solution I put to use to update the plex.tv ip addresses came from that post.

 

1. ROUTING POLICY

place the following code into your firewall script of DD-wrt or WAN-UP (I believe) of Tomato etc.

The Variable PlexServer should be the server that has your Plex on it. 

The logger statements were simply added to put notes in the log (if you run syslog these will show up).

This policy was designed to make sure traffic that is going to ports that are bittorrents on my Synology server get dropped should the VPN go down.

If you don't care about that, you can comment out the line that has the $BitTorrentPortList variable

Modify the $ByPassPortList variable to have the ports that you'd like bypass the VPN.  Notice 32400 is on the list (Plex).  All the other ports are services that I use on my Synology NAS.

 

Important NOTE:  On some versions of DD-wrt, if you make changes to your router and click "apply changes" but don't reboot, your vpn connection will stop.  (this happens to me with build 18777).  In this case you can either add a script with cron that checks the status of the vpn and restarts it automatically if it sees it's down or simply make sure that you reboot the router when making changes...

#!/bin/sh

Script to route traffic from home network through VPN selectively.

Based off the discussion at http://www.smallnetbuilder.com/forums/showthread.php?t=9311

The setup is a Roku box, a Home PC running Plex, and a Synology NAS with a torrent client running a web interface.

The aim is to have all traffic from Roku go through the VPN, all traffic from the Home PC (and all other devices) bypassing the VPN,

and the Synology NAS using the VPN. There are however some exceptions. Since Plex uses port 32400, Roku has to bypass the VPN when

using that port. In addition, port 9091 has to bypass the VPN as well in order to access the Synology torrent client. Lastly, ports 5000

and 5001 has to bypass the VPN for the Synology Management UI.

Requirements: Asuswrt-Merlin with OpenVPN already set up

logger -t “($(basename $0))” $$ ExpressVPN Selective Customization Starting… " 0{:+ $}."

PlexServer=“192.168.1.XXX”
ByPassPortList=“32400,5000,5001,5100,5101,5005,5006,5010,6690,8001,8801,7101,7001”
BitTorrentPortList=“16881,6881,6882,6883,6884,6885,6886,6887,6888,6889,6890”

SHELL COMMANDS FOR MAINTENANCE.

DO NOT UNCOMMENT, THESE ARE INTENDED TO BE USED IN A SHELL COMMAND LINE

List Contents by line number

iptables -L PREROUTING -t mangle -n --line-numbers

Delete rules from mangle by line number

iptables -D PREROUTING type-line-number-here -t mangle

To list the current rules on the router, issue the command:

iptables -t mangle -L PREROUTING

Flush/reset all the rules to default by issuing the command:

iptables -t mangle -F PREROUTING

Disable Reverse Path Filtering on all current and future network interfaces:

for i in /proc/sys/net/ipv4/conf/*/rp_filter ; do
echo 0 > $i
done

Delete table 100 and flush any existing rules if they exist.

ip route flush table 100
ip route del default table 100
ip rule del fwmark 1 table 100
ip route flush cache
iptables -t mangle -F PREROUTING

Copy all non-default and non-VPN related routes from the main table into table 100.

Then configure table 100 to route all traffic out the WAN gateway and assign it mark “1”

tun_if=“tun0”

ip route show table main | grep -Ev ^default | grep -Ev $tun_if
| while read ROUTE ; do
ip route add table 100 ROUTE logger -t "((basename $0))" $$ ExpressVPN Table 100 added entry: $ROUTE
done

ip route add default table 100 via $(nvram get wan_gateway)
ip rule add fwmark 1 table 100
ip route flush cache

By default all traffic bypasses the VPN

iptables -t mangle -A PREROUTING -i br0 -j MARK --set-mark 1

logger -t “($(basename $0))” $$ Selective customisation for: "$"PlexServer PlexServer

By default Synology uses the VPN, and FORCES the use of the VPN tunnel except ports needing access from outside LAN

MediaVault Server

iptables -t mangle -A PREROUTING -i br0 -m iprange --src-range $PlexServer -j MARK --set-mark 0
#Just drop packets to Bit Torrents should the VPN go down
iptables -I FORWARD -i br0 -s $PlexServer -o eth0 -m multiport --port $BitTorrentPortList -j DROP
iptables -I FORWARD -i br0 -s $PlexServer -o eth0 -p tcp -m multiport --port $ByPassPortList -j ACCEPT

logger -t “($(basename $0))” $$ Routing ports to bypass VPN on all Devices:
#ports to bypass the VPN for all available devices
iptables -t mangle -A PREROUTING -i br0 -p tcp -m multiport --port $ByPassPortList -j MARK --set-mark 1
#All WOL signal to bypass VPN
iptables -t mangle -A PREROUTING -i br0 -p udp -m multiport --port 9 -j MARK --set-mark 1

#Note: Plex.tv static routing is done in startup and cronjob. Updates every 60 minutes

logger -t “($(basename $0))” $$ ExpressVPN Selective Customization completed.

Now this is half the battle for Plex.(and actually the easy part).  The other part requires grabbing the ip addresses that plex.tv uses and have them bypass the VPN  tunnel.  Originally I tried just to add a static list of addresses, but this was cumbersome, and not very reliable.  What happens if Plex changes their addresses?  You'll have to figure it out all over again.  Unfortunately, there really isn't any way to automatically grap ip addresses from a domain.  The simplest solution relies on the script that zanechua created.  Since DD-wrt and other open source firmware use a different flavor of linux that what he wrote it for, I had to modify it to work for this purpose.  

There were a few other issues I discovered trying to implement this script for use on the router.

1. Most of the directories on my DD-wrt router get re-created everytime it reboots.  So, if I need to boot the router, I have to copy the script over to the location again.

2. You must make sure the script has executable permissions

3. You will need to have the script run using a cron so that it will run on a regular interval (every hour).  That way it will pickup the latest ip and create a static route for it.

4. Depending on your version of DD-wrt you may need to fix the permissions of cron before you can start using it.

 

To keep things as simple as possible, I decided to have this script get created everytime the router boots up.  That way I didn't have to worry about it being wiped everytime.

The permissions are also automatically set properly, and I will include the code to fix cron.

 

Here's the code for the Plex.tv address updater

##################################################
#Create Plex Static Route Script on Startup
cat < /tmp/Plex_StaticRoute.sh
#!/bin/sh

#Fetch Current Server Address for plex.tv
#DNS="(dig plex.tv +short) (dig @8.8.8.8 plex.tv +short) (dig @209.244.0.3 plex.tv +short)" #DD-wrt Friendly logger "Starting Plex static route script..." DNS1=(nslookup plex.tv | tail -1 | awk -F " " '{print 3}') #Google DNS lookup DNS2=(nslookup plex.tv 8.8.8.8 | tail -2 | awk -F " " '{print 3}' | tail -1) DNS3=(nslookup plex.tv 8.8.4.4 | tail -2 | awk -F " " '{print 3}' | tail -1) #Level3.net DNS lookup DNS4=(nslookup plex.tv 209.244.0.3 | tail -2 | awk -F " " ‘{print $3}’ | tail -1)
logger “Grabbing current ipaddresses from plex.tv
DNS="$DNS1 $DNS2 $DNS3 DNS4" UNIQ_IP=(echo “$DNS” | tr ’ ’ ’
’ | sort -u | tr ’
’ ’ ')
logger “Current registered ip addresses: $DNS”

for IP in $UNIQ_IP
do
#Create localroute variable to see if route exists
localroute=route | grep $IP
#Check if route exists
if [[ -z “$localroute” ]]; then
#route doesn’t exist, add route
logger “Route doesn’t exist, creating…”
route add -net “$IP” netmask 255.255.255.255 gw nvram get wan_gateway
logger “New routes using $IP created”
echo $IP
else
#route exists, hurray
logger “Plex static routes exist. Cool!”
echo “yay”
fi
done
logger “Plex static route script complete.”
EOL
chmod +x /tmp/Plex_StaticRoute.sh
/tmp/Plex_StaticRoute.sh
exit 0

Note: you will see at the very bottom of this script that it runs itself when it's done being created.  That way, when your router reboots, the plex script runs right away, then cron

takes over...

 

Again logger comments have been added so you can check the status in syslog or other logs in your router.

if cron is not enabled in the router turn it on now.

put the following in the cron section:

#*/1 * * * * root /usr/bin/logger TESTING THE WEBUI....
#Runs a script every hour to check the ip address of plex.tv and then creates a static route so that it bypasses the VPN 
*/60 * * * * root /bin/sh /tmp/Plex_StaticRoute.sh

Formatting the cron is EXTREMELY IMPORTANT!  I accidentally forgot a space and it prevented from cron to work.

A simple way to see if cron is functioning properly, remove the # from the first statement above and save the changes.  If cron is working properly you should see "TESTING THE WEBUI..." in your log file or syslog.

If it is, then your permissions are probably set correctly.  This is a "dumbed down" test.  If you are more adventurous, then you can log into the router and do an ls -al on the cron directories and files and sees what they are currently at.  Below is the cron permission fix script.  This also goes in the startup section of the router (Administration>Commands) DD-wrt.  In the code below you will see the directories and permissions that are necessary.

#!/bin/sh
##################################################
#Fix Crontab permission problem
#CronFix startup script 
#Place in WebUI or {opt/jffs}/etc/config/____.startup 

sleep 60
#Might not be necessary…
stopservice cron

#This one keep password same as root, duplicates Shell of root
[ -z cat /tmp/etc/passwd | grep -o crontabs ] && cat /tmp/etc/passwd | grep -m 1 root | sed ‘s/root/crontabs/’>> /tmp/etc/passwd

#This one leaves it blank, and is limited to OptWare. Change /opt/bin/bash to /bin/sh otherwise.
#grep -q “^crontabs:” /tmp/etc/passwd || echo 'crontabs::0:0:Contab User,:/tmp/root:/opt/bin/bash’ >> /tmp/etc/passwd
chmod 600 /tmp/crontab
chmod 750 /tmp/cron.d/
chmod 644 /tmp/cron.d/

sleep 1

#Might not be necessary…
startservice cron
##################################################

After you have confimed that cron is working you can put the # back in front of the first statement so you aren't stuck with that message appearing every minute.

The Plex_StaticRoute.sh script will run every 60 minutes.  That has worked fine for me.  Feel free to adjust if you are noticing that plex isn't always connecting to the service, but I think 60 should be plenty.

 

And that's pretty much it. 

 

I discovered a few caveats which required that I add a couple of more iptable rules.

1.  If you are finding that ever so often your internet has stopped working while your VPN is running (I'm running OpenVPN), in my case, it turned out that with the VPN up, notices about DHCP lease renewal weren't getting to my ISP to update my WAN IP Address.  Regardless of whether your ISP WAN IP address gets updated, if this doesn't get to them, then your connect could drop.  If this is happening to you, do some research on your ISP as to how long their DHCP lease is.  Mine is 24 hours with Time Warner.  Then divide that in 1/2.  That's the amount of time till your next lease update.  So, it turned out my internet (this was just internal internet by the way) was dropping at about 12 hours every day...thus the connection.

 

Put the following iptable statement below your other iptables in the firewall section:

#Fixes Firewall blocking DHCP Renew Responses
iptables -I INPUT -p udp --dport 68 -j ACCEPT 

2. Another issue I discovered when running my VPN was that if I was inside my LAN (on my home network), but was trying to access my server through my Dynamic DNS domain I couldn't connect.  However if I was outside my home network, I could connect just fine.  It turns out I had what's called a "NAT loopback".  Apparently some builds of DD-wrt have a bug that causes this problem.  When my VPN wasn't on, I didn't have this problem.  However, when the VPN was on, this was happening to me.  The following statement fixed it for me.  Also put this in your firewall script:

#correcting NAT loopback problem.  Fixes accessing public IP address from within LAN network.  This is needed when running OpenVPN (for some reason)
insmod ipt_mark 
insmod xt_mark 
iptables -t mangle -A PREROUTING -i ! `get_wanface` -d `nvram get wan_ipaddr` -j MARK --set-mark 0xd001
iptables -t mangle -A PREROUTING -i ! `get_wanface` -d 192.168.1.0/24 -j MARK --set-mark 0xd001  
iptables -t mangle -A PREROUTING -j CONNMARK --save-mark 
iptables -t nat -A POSTROUTING -m mark --mark 0xd001 -j MASQUERADE

The line that has "192.168.1.0/24" make sure it matches your LAN IP address.  This statement was key to getting this to work for my setup.

 

I appologize if this tutorial is short on details.  If you are struggling with something please feel free to post, and I'll see if I can help.  At some point, I'll be putting this on my website in more detail, so hopefully that will answer any questions.

If you see any errors, or bad explanations, please feel free to post corrections (please be constructive) I'm open and happy for any feedback.

 

I hope this helps someone.  It took a lot of time, patience and research to get through this.

Question: Are you using dd-wrt or merlin's firmware? I see in the script that there is a line about using asuswrt-merlin. I'm using the stock firmware on the Asus RT-AC68W along with OpenVPN to PIA, but I'm willing to switch to get Plex to work nicely with the VPN.

P.S. Thanks in advance for this how-to. I haven't set up the bypass of the VPN yet, but I can tell this post will be immensely helpful.

I don't mean to revive an old thread, but this seems to be the closest thing i can find in a google search for what i want to do with my VPN. My issue with it is this:

I read all the scripts you posted, and tried to apply them to my DD-WRT VPN router. but when i reboot and run all the scripts setup how i copied what you have i lose the use of my wireless radios. my 2.4 and 5 GHz wireless clients can not connect to internet, just LAN.

I do get the VPN / ISP split. i belive i had CRON setup right, but i'm not very sure.

Note: My VPN uses Startup Script in DD-WRT to run the VPN (OpenVPN Script) and my router gateway is 192.168.11.1 and i know there will be changes for that.

Question 1: Where do i put the first script that starts with "# Script to route traffic from home network through VPN selectively. " in DD-WRT? Startup? Firewall? Custom Script? /tmp/script_name.sh? I think Firewall, but i would like to be certain.

Question 2: in the first script, i set PlexServer="192.168.1.XXX" to 192.168.11.101 for my Plex Media Server, But i also have a Synology NAS on 192.168.11.126, do i need to add that IP in the script due to bittorrent running on the synology? Also, I run a VPN on the synology, should that be disabled?

I Run my DDNS on the Router, as suggested already.

Question 3: The second script for Plex.tv address updater i saved as Plex_StaticRoute.sh and put in my DD-WRT Directory as /tmp/Plex_StaticRoute.sh as shown in the script. Is this correct? Also, i set the script as executable.

Question 4: The Cron script, i placed in the Cron script box under management in DD-WT, with Cron Enabled. that is correct?

Question 5: For the script "#Fix Crontab permission problem" i am not clear on the script's name, it say's ____.startup, Is this correct? Do i need to set permissions as executable? The correct location @ {opt/jffs}/etc/config/?

Question 6: The last 2 scripts, say they go in your IP_Tables script section (in Firewall right?) at the bottom of the first script?

I do know i will need to correct the IP address on the net loopback script to 192.168.11.0/24 for my network, i do have the net loopback problem, i see that show up in my Plex Media Server Logs.

Question 7: If everything is setup correctly, with my router having VPN (tun0), LAN (eth0), LAN (vlan1), WAN (vlan2), wireless 2.4GHz (wl0), wireless 5GHz (wl1) all listed as points of connection, is there anywhere in the scripts i should change anything to ensure it works for my configuration?

If begunfx or anyone else who has used this can clear up any of my questions, that would be so much help. Thanks for any one who can help.

Additional Edit:

I have tested this set of scripts with DD-WRT, and Tomato Shibby. I tested with asus-merlin, but could not find any way to add "firewall" scripts. I am unable to get this working as described in the original post. assistance would be very helpful.

Thanks for this post, it was exactly what I was looking for.

In my configuration, I have pFsense where I am doing my NAT and I have OpenVPN installed on my linux box where I am using Plex Version 1.7.1.3856 and noticed there are some additional IP addresses that are in play. I’ve updated the script and tested it on Ubuntu 14.04.5 LTS. I also run the bash script in my hourly cron to be sure I always have the latest IP’s.

#!/bin/sh

GW_ADDR=192.168.1.1

#Fetch Current Server Address for plex.tv
logger "Starting Plex static route script..."
DNS1=$(nslookup plex.tv | awk '/Address/&&!/#/{print $2}')
DNS2=$(nslookup plexapp.com | awk '/Address/&&!/#/{print $2}')
DNS3=$(nslookup app.plex.tv | awk '/Address/&&!/#/{print $2}')
logger "Grabbing current ipaddresses from plex.tv, plexapp.com and app.plex.tv"
DNS="$DNS1 $DNS2 $DNS3 "
UNIQ_IP=$(echo "$DNS" | tr ' ' '
' | sort -u | tr '
' ' ')
logger "Current registered ip addresses: $DNS"

for IP in $UNIQ_IP
do
        #Create localroute variable to see if route exists
        localroute=`route -n | grep "$IP" | awk -F'[: ]+' '{ print $1 }'`
        #Check if route exists
        if [ -z $localroute ]; then
                #route doesn't exist, add route
                logger "Route doesn't exist, creating..."
                route add -host "$IP" gw $GW_ADDR
                logger "New routes using $IP created"
                echo $IP
        else
                #route exists, hurray
                logger "Plex static routes exist.  Cool!"
                echo "Route Exists not doing anything."
        fi
done
logger "Plex static route script complete."

I have been googling various aspects of how to accomplish this mission, so first a thank you for laying this out.

I have followed these steps and it has accomplished (so far) the mission of selectively routing Plex traffic while maintaining the VPN for all other traffic.

Austin

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.