Sharing: Setting up VyOS 1.4rc* + VPN Provider on Single or Multiple Systems

Hi All,

Previously I posted a community question asking for assistance setting up a VPN to service provider using VyOS. When I reinstalled latest 1.4RCx, I wrote out some notes which I thought I’d share with whomever is interested. Maybe I’ll also get some feedback on doing configuration a better way.

Note: I’m still using traditional stateful firewall zones though looking at common chains at some point.

I chose OpenVPN over Wireguard because Wireguard configuration did not support fully qualified domain names for the connection address. Basically same principles apply.

Background / Layout:

I have three networks LAN, IoT and Guest Wireless.

Guest Wireless: is connected to VyOS but segregated to have full outbound access with no dependencies on the internal LAN or IoT. It uses external DNS Servers.

IoT: Contains any device I don’t want on my LAN, although it still uses internal DNS. Within the IoT network, I wanted to test sending a couple devices via a VPN Provider (Surfshark, PIA, Nord etc).

“VPN PCs” within IoT network will ignore the internal DNS and use the providers DNS servers.

VyOS is the authoritative DHCP server for each of the networks.

Design:

Assumptions:
Firewall is already configured with basic connectivity.

Configuring Groups

I wanted to setup some better logic so went and created some groups. Found out that you cannot mix network groups with address groups, so you needed to select one or the other. I went with address groups.
set firewall group address-group AG_GuestWLAN_DEVICES address '172.16.120.2-172.16.120.250'
# System address I want to use for VPN connectivity.
set firewall group address-group AG_SURFSHARK_SYSTEMS address '192.168.200.12'
set firewall group address-group AG_LAN_DNS address '192.168.100.100'
set firewall group address-group AG_IGNORE_DNS_DNAT include 'AG_LAN_DNS'
set firewall group address-group AG_IGNORE_DNS_DNAT include 'AG_GuestWLAN_DEVICES'
set firewall group address-group AG_IGNORE_DNS_DNAT include 'AG_SURFSHARK_SYSTEMS'

Configuring VPN Tunnel:

Most VPN providers, provide an OpenVPN configuration file from their portal. They also provide a username and password for the connectivity (usually different to your login account).

I’ll reference Surfshark as that is what I was testing this on.

Configure the CA and Shared Key Information.

Key information is provided in downloaded .opvn file.
set pki ca Surfshark-CA certificate '<Text Between BEGIN/End CERTIFICATE>'
set pki openvpn shared-secret Surfshark-Auth key '<Text Between BEGIN/End static key>'

Configure the OpenVPN tunnel information.

Most, if not all, the information will come from the OpenVPN configuration file. Some providers use different tls authentication methods so change if required.
set interfaces openvpn vtun99 authentication password '<Available via account info>'
set interfaces openvpn vtun99 authentication username '<Available via account info >'
set interfaces openvpn vtun99 description 'OpenVPN to Surfshark'
set interfaces openvpn vtun99 encryption cipher 'from OpenVPN file'
set interfaces openvpn vtun99 hash 'from OpenVPN file'
set interfaces openvpn vtun99 mode 'client'
set interfaces openvpn vtun99 openvpn-option 'pull-filter ignore redirect-gateway'
set interfaces openvpn vtun99 persistent-tunnel
set interfaces openvpn vtun99 protocol 'udp'
set interfaces openvpn vtun99 remote-host 'FQDN of Provider IP'
set interfaces openvpn vtun99 remote-port '1194'
set interfaces openvpn vtun99 tls auth-key 'Surfshark-Auth'
set interfaces openvpn vtun99 tls ca-certificate 'Surfshark-CA'

Note: set interfaces OpenVPN vtun99 openvpn-option 'pull-filter ignore redirect-gateway' prevents the tunnel from becoming the VyOS default gateway.

I found this command, but it’s currently not documented. Not sure if it makes a difference?

set interface openvpn vtun99 replace-default-route <value>

Configuring Firewall information

Allow OpenVPN connections from the firewall itself
Create a rule that allows OpenVPN connection out from the firewall.

set firewall ipv4 name LOCAL-WAN rule 1000 action 'accept'
set firewall ipv4 name LOCAL-WAN rule 1000 description 'Allow Surfshark VPN LOCAL-WAN'
set firewall ipv4 name LOCAL-WAN rule 1000 destination port '1194'
set firewall ipv4 name LOCAL-WAN rule 1000 log
set firewall ipv4 name LOCAL-WAN rule 1000 protocol 'udp'
set firewall ipv4 name LOCAL-WAN rule 1000 state new

Check to see if the tunnel interface is configured and if it is connecting.

run show interfaces
journalctl -r | grep openvpn

At this point the VPN tunnel should be established.

Allow VPN PC to communicate over tunnel.

set firewall ipv4 name IoT-VPN default-action 'drop'
set firewall ipv4 name IoT-VPN enable-default-log
set firewall ipv4 name IoT-VPN rule 50 action 'accept'
set firewall ipv4 name IoT-VPN rule 50 log
set firewall ipv4 name IoT-VPN rule 50 state established
set firewall ipv4 name IoT-VPN rule 50 state related
set firewall ipv4 name IoT-VPN rule 51 action 'drop'
set firewall ipv4 name IoT-VPN rule 51 state invalid
set firewall ipv4 name IoT-VPN rule 1000 action 'accept'
set firewall ipv4 name IoT-VPN rule 1000 description 'Allow All IoT-VPN'
set firewall ipv4 name IoT-VPN rule 1000 log
set firewall ipv4 name IoT-VPN rule 1000 state 'new'

set firewall ipv4 name VPN-IoT default-action 'accept'
set firewall ipv4 name VPN-IoT enable-default-log
set firewall ipv4 name VPN-IoT rule 50 action 'accept'
set firewall ipv4 name VPN-IoT rule 50 log
set firewall ipv4 name VPN-IoT rule 50 state established
set firewall ipv4 name VPN-IoT rule 50 state related
set firewall ipv4 name VPN-IoT rule 51 action 'drop'
set firewall ipv4 name VPN-IoT rule 51 state invalid

Configure the additional zones
I am assuming that the IoT zone is already configured, so we are just adding an additional zone for VPN.

set firewall zone IoT from VPN firewall name 'VPN-IoT'

#Add new VPN zone.
set firewall zone VPN default-action 'drop'
set firewall zone VPN from IoT firewall name 'IoT-VPN'
set firewall zone VPN interface 'vtun99'

Set VPN PC specific DHCP entries.

As mentioned, the DHCP server pushes the internal DNS address. We want to use the VPN providers DNS. These can be found in the log during connection running following command.

journalctl -f | grep "openvpn.*dhcp-option"

We then set the DHCP option values for our system to set external DNS and set domain name to nothing.

set service dhcp-server shared-network-name IoT_POOL subnet 192.168.200.0/24 static-mapping PCviaVPN static-mapping-parameters 'option domain-name-servers <DNS1 IP>, <DNS2 IP>;'
set service dhcp-server shared-network-name IoT_POOL subnet 192.168.200.0/24 static-mapping PCviaVPN static-mapping-parameters 'option domain-name &quot;&quot;;'

Configuring VPN NAT:

One thing I find strange is that source address can’t be a group whereas destination can. Unless there is another way to do this? So for each system you want to push you will need a separate NAT rule. ``` set nat source rule 99 description 'NAT VPN' set nat source rule 99 outbound-interface name 'vtun99' set nat source rule 99 source address '192.168.200.12' set nat source rule 99 translation address 'masquerade ```

I use a separate DNAT rule to redirect all DNS traffic from LAN and IoT to the internal DNS. This causes an issue for the VPN systems. I need to ignore both GuestWLAN, and VPN PC. Hence the access group AG_IGNORE_DNS_DNAT.

set nat destination rule 100 description 'DNAT - Redirect to Internal DNS'
set nat destination rule 100 destination group address-group '!AG_LAN_DNS'
set nat destination rule 100 destination port '53'
set nat destination rule 100 protocol 'tcp_udp'
set nat destination rule 100 source group address-group '!AG_IGNORE_DNS_DNAT'
set nat destination rule 100 translation address '192.168.100.100'

Configuring Policy Based Routing:

I still want to be able to communicate with this host from my LAN network. So I create two Policy Based Routes. First policy uses the default route table. The second allows the VPN PC out via the VPN interface.

set policy route SurfsharkPBR enable-default-log
set policy route SurfsharkPBR interface 'eth2.20'
set policy route SurfsharkPBR rule 98 description 'Allouw Surfshark Client Internal'
set policy route SurfsharkPBR rule 98 destination group network-group 'NG_LAN_NETWORK'
set policy route SurfsharkPBR rule 98 set table 'main'
set policy route SurfsharkPBR rule 98 source group address-group 'AG_SURFSHARK_SYSTEMS'
set policy route SurfsharkPBR rule 99 description 'Route Via Surfshark PBR'
set policy route SurfsharkPBR rule 99 set table '99'
set policy route SurfsharkPBR rule 99 source group address-group 'AG_SURFSHARK_SYSTEMS'
# create a static route for table 99 to go out via vtun99 
set protocols static table 99 route 0.0.0.0/0 interface vtun99

That’s it… hopefully it all works :grinning:

5 Likes