Kevin Gyorick

My Computer Science Blog

Unifi Dream Machine Pro Network Wide OpenVPN Client

**The UDM Pro has native support for OpenVPN Client since Unifi OS V3: See an updated guide here**

One of the main disappointments of Unifi’s controller software is that it doesn’t support network-wide virtual private network (VPN) clients. But there is a way to add this feature yourself using an SSH terminal. Out of the box, Unifi’s controller only offers site-to-site VPNs and L2TP VPN Server. Today I will walk you through the steps of connecting your UDM Pro as an OpenVPN Client and share this connection with a whole bridge interface.

SSH Login

In order to log in to your UDM Pro using SSH, you will need to enable SSH and set a password. The setting can be found on the Unifi dashboard. Click your controller so that you are on the screen that shows the different services network, protect, access, and talk. On that screen, you will see a system settings button, click that. Next, go to advance and click on the SSH toggle. It will ask you to set a password and confirm it. After SSH is enabled you can use it. To use SSH open a terminal on your computer and type the following command.

ssh [email protected]

The gateway IP of my UDM Pro is 10.0.0.1 if yours is different you will need to change it. After entering this command it will prompt you for the password you just set enter it now. The screen will appear as you are not typing anything, this is a security measure to not show your password on the screen.

Boot Scripts

The first GitHub repository we are going to look at will give us the ability to create shell scripts that run on bootup of the controller. We will need this in order to start the VPN after a reboot if on Unifi OS v1. Unifi OS v2 and up has native support for boot scripts via systemd and will not be covered in this guide. The boot script repository can be found here, there are a few projects within that repository that you may also want to take a look at after setting up the VPN.

To install the on boot utility open your ssh terminal with the command from earlier and enter the following commands. If you are on Unifi OS v2 or higher this command will not work since a container is no longer used. This command can be skipped if that is the case.

unifi-os shell

This command enters the Unifi OS docker container that is running and managing the Unifi controller software.

curl -L https://udm-boot.boostchicken.dev -o udm-boot_1.0.5_all.deb
dpkg -i udm-boot_1.0.5_all.deb
exit

These commands will download the on boot utility package and install it. The exit command will exit the docker container. Now any shell script that you want to run on boot can be placed in the “/mnt/data/on_boot.d” directory. Make sure the script it marked as executable using chmod and starts with the correct shebang of “#!/bin/sh”.

Split-VPN

We will use the Split-VPN utility to run our OpenVPN Client. It is worth noting that this utility supports other VPN Clients. The repository can be found here. To get started, start by opening an ssh connection to the UDM Pro and enter these commands.

cd /mnt/data
mkdir -p /mnt/data/split-vpn && cd /mnt/data/split-vpn
curl -L https://github.com/peacey/split-vpn/archive/main.zip | unzip - -o
cp -rf split-vpn-main/vpn ./ && rm -rf split-vpn-main
chmod +x vpn/*.sh vpn/hooks/*/*.sh vpn/vpnc-script

These commands will make the directories needed for the new utility and install it. Now we need to setup our VPN provider, I am currently using Private Internet Access (PIA). Let’s start off by creating a directory for our configuration and copying the sample.

mkdir -p /mnt/data/split-vpn/openvpn/pia
cd /mnt/data/split-vpn/openvpn/pia
cp /mnt/data/split-vpn/vpn/vpn.conf.sample /mnt/data/split-vpn/openvpn/pia/vpn.conf

Next we need our OVPN file, PIA’s OVPNs can be found here. Download the set for the amount of encryption you want onto your computer. Extract the OVPN for the region that you want into your downloads folder. If your VPN provider uses a username and password you will need to add a line to the OVPN file. Add “auth-user-pass username_password.txt”. Next, open a terminal in your downloads directory and use SCP to copy the OVPN file onto the UDM Pro. Here is an example command. Replace “10.0.0.1” with the gateway IP of your UDM Pro.

scp filename.ovpn [email protected]:/mnt/data/split-vpn/openvpn/pia/

If your VPN provider uses a username and password create a “username_password.txt” file in your downloads directory. The file needs your username on the first line and your password on the second line of the text file. Copy it over to the UDM Pro using the same SCP command with “username_password.txt” instead of “filename.ovpn”. Some VPN providers will provide you with a separate username and password for OpenVPN but PIA does not. Next we will need to edit the sample conf that we copied. Move it to your computer for editing using SCP like so.

scp [email protected]:/mnt/data/split-vpn/openvpn/pia/vpn.conf .

This command will copy the file to your current working directory. Open it with a text editor. There are alot of settings described in this config file. The setting we need to worry about for our purposes is called “FORCED_SOURCE_INTERFACE”. Within the quotes on the right side we need to specify the VLANs that we want to connect over our VPN. Each additional VLAN needs to be separated by a space. My VLAN is 90 so I will put “br90” within those quotes. If you are not sure what bridge interface to put try running the command “ifconfig” within your SSH terminal and look for the subnet you want to send through the VPN. After you are done configuring the file you will need to update the file on the UDM Pro using the SCP command like so.

scp vpn.conf [email protected]:/mnt/data/split-vpn/openvpn/pia/vpn.conf

Test your VPN connection by running the following command on the SSH terminal. Make sure to change the “filename.ovpn” to the correct filename.

openvpn --config filename.ovpn \
        --route-noexec \
        --up /mnt/data/split-vpn/vpn/updown.sh \
        --down /mnt/data/split-vpn/vpn/updown.sh \
        --auth-user-pass username_password.txt \
        --script-security 2

Remove the “auth-user-pass” line if you are not using a username and password with your provider. Now lookup your IP address on a client that is connected over this VLAN and make sure it is your VPN providers IP instead. If you are satisfied with the results shutdown the client by going to your SSH terminal and pressing “ctrl + c”. Now lets run the client in the background so we can close our SSH terminal. Run the following command and remove the same line if you are not using a username and password. Also use the correct filename for the OVPN.

nohup openvpn --config filename.ovpn \
              --route-noexec \
              --up /mnt/data/split-vpn/vpn/updown.sh \
              --down /mnt/data/split-vpn/vpn/updown.sh \
              --auth-user-pass username_password.txt \
              --script-security 2 \
              --ping-restart 15 \
              --mute-replay-warnings &> openvpn.log &

You now have a working network-wide VPN client connection. If you would like to run the VPN on boot move on to the next section. If you would like to block out internet access until after the VPN is connected on your VPN VLAN there is a section on that as well.

VPN On Boot

Create a file on your computer called “99-run-vpn.sh” with the following contents. Make sure to update the provider folder and filename of the OVPN. Here I am using the provider PIA. If you do not need a username and password for your provider remove the line “auth-user-pass”.

#!/bin/sh
# Load configuration and run openvpn
cd /mnt/data/split-vpn/openvpn/pia
source ./vpn.conf
/mnt/data/split-vpn/vpn/updown.sh ${DEV} pre-up &> pre-up.log
nohup openvpn --config filename.ovpn \
              --route-noexec \
              --up /mnt/data/split-vpn/vpn/updown.sh \
              --down /mnt/data/split-vpn/vpn/updown.sh \
              --auth-user-pass username_password.txt \
              --dev-type tun --dev ${DEV} \
              --script-security 2 \
              --ping-restart 15 \
              --mute-replay-warnings &> openvpn.log &

Next we need to copy the boot script into the UDM Pro on boot directory using SCP like so. Replace “10.0.0.1” with the gateway IP of your UDM Pro.

scp 99-run-vpn.sh [email protected]:/mnt/data/on_boot.d/

Now we need to open our SSH terminal and change directory to the on boot folder like so.

ssh [email protected] 
cd /mnt/data/on_boot.d

Make the boot script executable with the following command.

chmod +x 99-run-vpn.sh

Next we need to reboot the UDM Pro so that the boot script can run. On the Unifi dashboard within the same settings panel as SSH there is a restart button for the UDM Pro click that to reboot.

Block Internet Access Until VPN Connection

In your vpn.conf file on the UDM Pro make sure the following option is set “REMOVE_STARTUP_BLACKHOLES=1”, it should be by default. Once you do the following you will lose internet access for all clients until the VPN connects. In order to block internet access until the VPN connection is establish go to the Unifi dashboard and select network settings. Under advanced features > advanced gateway settings > static routes. Set the following routes.

Name: VPN Blackhole. Destination: 0.0.0.0/1. Static Route Type: Black Hole. Enabled: True
Name: VPN Blackhole. Destination: 128.0.0.0/1. Static Route Type: Black Hole. Enabled: True
Name: VPN Blackhole. Destination: ::/1. Static Route Type: Black Hole. Enabled: True
Name: VPN Blackhole. Destination: 8000::/1. Static Route Type: Black Hole. Enabled: True

After setting up the blackhole routes you may need to restart the UDM Pro in order to regain internet connection.

Allow LAN to LAN Communication

In order for our VPN clients to communicate with other LAN or VLAN clients we will need to go back to our “vpn.conf”. Find the property “EXEMPT_DESTINATIONS_IPV4” and add the subnet that you use for your LAN and VLANs. For me all my subnets fall under the bigger subnet 10.0.0.0/8 so I’ll use that value here. Now send the changes to the UDM Pro by using the SCP command.

scp vpn.conf [email protected]:/mnt/data/split-vpn/openvpn/pia/vpn.conf

In order for the changes to take affect you may need to restart the UDM Pro. If you are running the VPN Client in the foreground simply stop it by pressing “ctrl+c” and then rerun it with the same start command.

33 thoughts on “Unifi Dream Machine Pro Network Wide OpenVPN Client

  • AirportDrunk
    October 26, 2021 at 11:09 pm

    Thanks for the write-up. It was very helpful to me. I am having trouble getting the script to execute on boot. When I check the file permissions they are chmod 751. However, when I manually run the script everything works flawless and provides a VPN connection on my guest network. Thanks again.

  • Nick
    November 14, 2021 at 5:51 pm

    Really great walkthrough! Very easy to follow. I am having an issue with the VPN on boot portion, however. The only way I can get the VPN to start is by staritng it manually. I have the boot file in the boot directory, I am also using PIA and edited the file to look at the right file names ect. No matter how many times i reboot, though, i cannot get the VPN to automatically start. Any ideas?

    • Kevin Gyorick
      November 14, 2021 at 7:12 pm

      Make sure to download and install the on-boot script package and make the script executable. Another tutorial for UDM boot scripts can be found here
      https://github.com/boostchicken/udm-utilities/blob/master/on-boot-script/README.md

      • Nick
        November 15, 2021 at 1:16 am

        Thanks for the added info, but I have indeed done this already. I have my boot script in the location it is supposed to be and I ran the command to make it executable. I looked at the other tutorial but it was the exact same steps i had already completed. I have retried all of these steps several times now and i am not able to get the VPN to start automatically. Is there any other insight you could provide?

        • Kevin Gyorick
          November 16, 2021 at 4:44 pm

          Sorry I am not sure what else I can suggest. These are the steps that I followed when I first got my UDM Pro. I have the original UDM Pro, not the new one with built-in PoE. When executing the commands be careful to make sure you are in the correct shell. The UDM Pro runs a docker container that is accessed with the command “unifi-os shell” as well as the default shell. So you are dealing with two different file systems on your UDM Pro. The deb package should be installed within the docker container while the boot scripts should be placed outside the container within the on boot directory.

  • Oleg Gerts
    December 9, 2021 at 3:00 pm

    Just a question: Can I connect udm to expressvpn. response is appreciated

    • Kevin Gyorick
      December 9, 2021 at 6:55 pm

      Yes, express VPN is supported. Any VPN that works on OpenVPN will work using this method. You will need to make the necessary changes to the vpn.conf config file. You will also need an OVPN from express VPN.

  • Dustin
    December 11, 2021 at 9:16 am

    Forgive me for my ignorance, but the unzip command doesn’t exist within my unifi-OS shell… How do I add this capability? Thank you.

    • Kevin Gyorick
      December 11, 2021 at 10:30 am

      You should not be in the unifi-os shell when running the commands that involve unzip. You should only be sshed into the udm pro but not within the unifi-os docker container. Unzip should be an included command within that environment.

    • Dustin
      December 11, 2021 at 12:37 pm

      Thanks! You are correct. After I took a nap and realized my stupidity, I resolved the problem outside of the unifi-os shell.

  • George
    February 8, 2022 at 11:30 am

    Hi, great tutorial! I assume that the whole setup will be overriden after UDM-PRO software upgrade. Is that right?

    • Kevin Gyorick
      February 8, 2022 at 11:36 am

      Updating the software of the UDM Pro does not override the VPN configuration.

  • Garry
    March 9, 2022 at 3:24 pm

    Are there any differences between implementation on the UDM Pro and the UDM SE? I’m assuming this should work the same on both machines. Thanks!

    • Kevin Gyorick
      March 9, 2022 at 8:01 pm

      This process should work on the UDM SE as well. The UDM SE has native boot script support via systemd as stated on the readme of the Split VPN repository. I personally have not configurated a UDM SE since I do not own one.

  • otw
    April 12, 2022 at 10:45 pm

    Is it possible to only connect using Open VPN for a particular VLAN? I’m trying to have a separate “VPN” Wifi in addition to my existing wifi network. Thanks!

    • Kevin Gyorick
      April 17, 2022 at 8:29 pm

      Yes it is possible. That is already covered in the guide, “There are alot of settings described in this config file. The setting we need to worry about for our purposes is called “FORCED_SOURCE_INTERFACE”. Within the quotes on the right side we need to specify the VLANs that we want to connect over our VPN. Each additional VLAN needs to be separated by a space. My VLAN is 90 so I will put “br90” within those quotes”.

  • Ryan
    April 16, 2022 at 2:53 pm

    This is overall a great tutorial! Like others have mentioned, I’m still having the issue where I am not able to get open vpn to run on boot. As suggested in the other comments, I made sure it is a .sh file with #!/bin/sh at the beginning. I also made sure to follow the directions to install the udm boot github in the container and lead the path with the file outside of it.

    In the meantime, I will just have to remember to run this any time this boots up. Is there anything else I should look for to resolve this issue? Thanks in advance.

    • Kevin Gyorick
      April 17, 2022 at 8:36 pm

      Sorry, I do not know why everyone is having this issue now. My VPN still starts on boot and I do not want to risk factory resetting it to discover I cannot overcome the issue either.

  • Ryan
    April 17, 2022 at 10:05 am

    Hi there, great guide! Do you know how to set up port forwarding? PIA for example assigns you to a port, so I was wondering if there was a way to figure out what that is to have in the vpn.conf file.

  • MP
    April 24, 2022 at 9:35 pm

    So i am trying to get this setup on a pair of new DMP.

    On the 1st unit every works out as planned but the launch on boot script doesnt seem to be working. If a ssh in and launch the commands it works correctly. Where can i look for a log or error to indicate what’s not working.

    One the 2nd unit, it starts to connect but exits with:
    2022-04-24 23:32:39 TUN/TAP device tun0 opened
    2022-04-24 23:32:39 net_iface_mtu_set: mtu 1500 for tun0
    2022-04-24 23:32:39 net_iface_up: set tun0 up
    2022-04-24 23:32:39 net_addr_v4_add: 172.21.20.159/23 dev tun0
    2022-04-24 23:32:39 /mnt/data/split-vpn/vpn/updown.sh tun0 1500 1553 172.21.20.159 255.255.254.0 init
    : not foundplit-vpn/vpn/updown.sh: ./vpn.conf: line 4:
    2022-04-24 23:32:39 WARNING: Failed running command (–up/–down): could not execute external program
    2022-04-24 23:32:39 Exiting due to fatal error

    The issue with the 1st unit, I can probably resolve but I am not sure where to go next with this 2nd unit. Any assistance would be appreciated

    • Kevin Gyorick
      May 9, 2022 at 3:20 pm

      On your second unit, it looks like you have an error on line 4 of your vpn.conf

  • Michael Tran
    December 2, 2022 at 12:07 am

    Hey Kevin,

    This is a fantastic writeup and we have got the VPN running however we cant seem to default traffic first to the internet and then via the tunnel. We can only do 1 or the other. I am not sure on the vpn file on how to configure the default route to internet first and if any traffic destined for 10.0.0.0/8 will use the VPN. We tried the following configuration but doesn’t work as it forces all traffic via VPN.

    # Force these sources through the VPN.
    # Format: [brX] for interface. [IP/nn] for IP. [xx:xx:xx:xx:xx:xx] for mac.
    FORCED_SOURCE_INTERFACE=”br0″
    FORCED_SOURCE_IPV4=””
    FORCED_SOURCE_IPV6=””
    FORCED_SOURCE_MAC=””

    # Format: [tcp/udp/both]-[IP/MAC Source]-[port1,port2:port3,port4,…]
    # Maximum 15 ports per entry.
    FORCED_SOURCE_IPV4_PORT=””
    FORCED_SOURCE_IPV6_PORT=””
    FORCED_SOURCE_MAC_PORT=””

    # Force these destinations through the VPN.
    # These destinations will be forced regardless of source.
    # Format: [IP/nn]
    FORCED_DESTINATIONS_IPV4=”10.0.0.0/8″
    FORCED_DESTINATIONS_IPV6=””

    The only way I can get internet is if I use the subnet exemption but then I can no longer access the VPN.

    # Exempt these destinations from the VPN.
    # Format: [IP/nn]
    EXEMPT_DESTINATIONS_IPV4=”192.168.20.0/24″
    EXEMPT_DESTINATIONS_IPV6=””

    Any help on this would be greatly appreciated.

    • Kevin Gyorick
      December 2, 2022 at 7:03 am

      You have FORCED_SOURCE_INTERFACE set, so anything on br0 will always go through the VPN. FORCED_DESTINATIONS_IPV4 ignores interfaces anything going to the specified ip addresses on any interface is redirected through the VPN. Hope that helps.

      • Michael Tran
        December 3, 2022 at 2:24 am

        Thank you Kevin. Your amazing and really appreciate the response. This is now working. One last question, how can I run 2x VPN scripts. I can’t seem to get 2 tunnels up.

        I thought i can run 100-run-vpn.sh but that doesn’t work. Any ideas how I can get 2x VPN’s up and running. It comes from the same certificate and i can manually use it using the commands openvpn – with your test script. I just can’t automate it from boot.

        • Kevin Gyorick
          December 3, 2022 at 11:12 am

          I only have a single tunnel for my setup. But the approach you are describing sounds like it should work. This setup will be easier to configure soon. As Unifi has announced OpenVPN Client support through the GUI. For the UDM Pro this feature will be available with Unifi OS V2. There is already a release candidate for Unifi OS V3 on the UDM SE with this new feature. If you are interested in seeing a video on how the feature will work see the note I left at the top of the post yesterday.

          • Michael Tran
            December 3, 2022 at 5:11 pm

            Thanks Kevin. The issue at hand with the GUI is that is needs username and password for the connector and I don’t use a username and password hence it wont accept it on the GUI. Appreciate the help.

  • Michael Tran
    December 6, 2022 at 6:34 pm

    Hey Kevin,
    Thanks as always for your help. Was just wondering if there is a way to set a schedule to restart the VPN or run these commands as we finding our VPN links are dropping every so often.
    we are running 2x VPN connections so wanted to know if you had a script that can restart the vpn for say every 4 hours to run the below:

    cd /mnt/data/split-vpn/openvpn/pia
    —————–
    nohup openvpn –config filename1.ovpn \
    –route-noexec \
    –up /mnt/data/split-vpn/vpn/updown.sh \
    –down /mnt/data/split-vpn/vpn/updown.sh \
    –script-security 2 \
    –ping-restart 15 \
    –mute-replay-warnings &> openvpn.log &

    nohup openvpn –config filename2.ovpn \
    –route-noexec \
    –up /mnt/data/split-vpn/vpn/updown.sh \
    –down /mnt/data/split-vpn/vpn/updown.sh \
    –script-security 2 \
    –ping-restart 15 \
    –mute-replay-warnings &> openvpn.log &

    • Kevin Gyorick
      December 6, 2022 at 8:43 pm

      The OpenVPN Client command is supposed to restart on its own when pings to the OpenVPN Server are failing. That’s what the ping-restart argument is for. The OpenVPN Server you are connecting to may be misconfigured if the ping-restart argument is not automatically restarting your client.

      • Michael Tran
        December 7, 2022 at 4:04 am

        Thanks Kevin. Yeah, i believe the issue is because I am running 2x VPN’s and they have the same destination traffic which may be causing issues. Will troubleshoot further. Thanks again.

Leave a Reply

Your email address will not be published. Required fields are marked *.

*
*
You may use these <abbr title="HyperText Markup Language">HTML</abbr> tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

This site uses Akismet to reduce spam. Learn how your comment data is processed.