VyOS Policy Based Routing with OpenVPN

Guides May 22, 2020

Sometimes you want some hosts on your network to use a vpn connection, but not all of them. Here is how i got it to work on VyOS 1.2.0 (LTS) with PIA vpn

OpenVPN Connection

This is a fairly standard OpenVPN conection for PIA (unofficial)

# show interfaces openvpn
 openvpn vtun101 {
     authentication {
         password xxxxxxx
         username xxxxxxx
     description DE
     encryption aes128
     hash sha1
     mode client
     openvpn-option "--cipher aes-128-cbc"
     openvpn-option --fast-io
     openvpn-option --route-nopull
     openvpn-option "--ping-restart 60"
     openvpn-option --persist-tun
     openvpn-option --persist-key
     openvpn-option "--ping 10"
     protocol udp
     remote-host xxxxx.privateinternetaccess.com
     remote-port 1198
     tls {
         ca-cert-file /config/auth/ca.rsa.2048.crt
         crl-file /config/auth/crl.rsa.2048.pem

Policy based route

First we create a Firewall group that contains the IP addresses of the hosts we want to apply the policy based routes on.

# set firewall group address-group VPN-PIA-DE address 10.0.x.x
Add any hosts you want the policy to apply to in a FW group

Set up our static route for vpn hosts, on a different table (101)

# show protocols static
 table 101 {
     route {
         next-hop {
From the "show protocols static" command

Replace with the gateway for your openvpn interface, which can be found by running ip route:

# ip route | grep vtun101 dev vtun101 proto kernel scope link src
Retrieving the openvpn gateway address

Create a policy for hosts in our firewall group VPN-PIA-DE to use table 101

# show policy
 route PIA {
     rule 101 {
         description PIA-DE
         destination {
         set {
             table 101
         source {
             group {
                 address-group VPN-PIA-DE
From the "show policy" command

Apply the policy to packets comming in on eth1 (LAN)

# set interfaces ethernet eth1 policy route PIA

Auto update gateway address

Since the PIA gateway addresses change all the time, i created a script to update the value once a minute if changes are detected:

echo table=$table interface=$openvpn_interface
openvpn_route=$(ip route | grep $openvpn_interface | awk {'print $1'})
source /opt/vyatta/etc/functions/script-template
current_route=$(show protocols static table $table route next-hop | grep next-hop | awk {'print $2'})
echo current=$current_route openvpn=$openvpn_route

if [ "$current_route" ] && [ "$current_route" != "$openvpn_route" ]; then
    delete protocols static table $table route next-hop
    set protocols static table $table route next-hop $openvpn_route
echo "No configuration changes"
exit discard
chmod +x /config/pbr.sh
set system task-scheduler task openvpn-pbr-101 executable path /config/pbr.sh
set system task-scheduler task openvpn-pbr-101 executable arguments '101 vtun101'
set system task-scheduler task openvpn-pbr-101 interval 5m