Help with policy based routing using wireguard with zone based firewall

Hi Forum

I am new to vyos and trying to setup zone based firewall (LAN, DMZ and WAN). In addition I want to run wireguard on vyos router and force all traffic from one specific host in the DMZ (172.16.20.4) via wireguard interface, which I suspect I need to use policy based routing.

WAN - 192.168.0.251 (Default gateway)
LAN - 172.16.10.0/24
DMZ - 172.16.20.0/29
WG0

Ive created all the firewall polices I think I need for WAN/LAN/DMZ/Local. I created 4 specific ones for WG0 - DMZ-WG0, WG0-DMZ, WG-LOCAL and LOCAL-WG0.

Once configured WG0 interface I CAN ping 8.8.8.8 via WG0 from the router.

vyos@vyos:~$ping 8.8.8.8 interface wg0
vyos@vyos:~$traceroute 8.8.8.8 interface wg0

How do I setup policy based routing so I can force all traffic from 172.16.20.4 via wg0?

Secondly if wg0 is DOWN how do drop all traffic from 172.16.20.4 to the internet (eg via eth0)?

Ive tried to follow VyOS Policy Based Routing with WireGuard + Mullvad, but it was too complicated to figure out.

Could I get some pointers as to what I need to do next? Are my zone-policies correct?

Here is the configuration I have created thus far template

Densha

set firewall name DMZ-LAN default-action 'drop'
set firewall name DMZ-LAN enable-default-log
set firewall name DMZ-LAN rule 1 action 'accept'
set firewall name DMZ-LAN rule 1 description 'Allow Established/Related Traffic'
set firewall name DMZ-LAN rule 1 state established 'enable'
set firewall name DMZ-LAN rule 1 state related 'enable'
set firewall name DMZ-LAN rule 2 action 'drop'
set firewall name DMZ-LAN rule 2 log 'enable'
set firewall name DMZ-LAN rule 2 state invalid 'enable'
set firewall name DMZ-LAN rule 100 action 'accept'
set firewall name DMZ-LAN rule 100 log 'enable'
set firewall name DMZ-LAN rule 100 protocol 'icmp'
set firewall name DMZ-LOCAL default-action 'drop'
set firewall name DMZ-LOCAL enable-default-log
set firewall name DMZ-LOCAL rule 1 action 'accept'
set firewall name DMZ-LOCAL rule 1 description 'Allow Established/Related Traffic'
set firewall name DMZ-LOCAL rule 1 state established 'enable'
set firewall name DMZ-LOCAL rule 1 state related 'enable'
set firewall name DMZ-LOCAL rule 2 action 'drop'
set firewall name DMZ-LOCAL rule 2 log 'enable'
set firewall name DMZ-LOCAL rule 2 state invalid 'enable'
set firewall name DMZ-LOCAL rule 100 action 'accept'
set firewall name DMZ-LOCAL rule 100 log 'enable'
set firewall name DMZ-LOCAL rule 100 protocol 'icmp'
set firewall name DMZ-LOCAL rule 600 action 'accept'
set firewall name DMZ-LOCAL rule 600 destination port '53'
set firewall name DMZ-LOCAL rule 600 log 'enable'
set firewall name DMZ-LOCAL rule 600 protocol 'tcp_udp'
set firewall name DMZ-LOCAL rule 700 action 'accept'
set firewall name DMZ-LOCAL rule 700 destination port '67-68'
set firewall name DMZ-LOCAL rule 700 log 'enable'
set firewall name DMZ-LOCAL rule 700 protocol 'udp'
set firewall name DMZ-LOCAL rule 800 action 'accept'
set firewall name DMZ-LOCAL rule 800 destination port '22'
set firewall name DMZ-LOCAL rule 800 log 'enable'
set firewall name DMZ-LOCAL rule 800 protocol 'tcp'
set firewall name DMZ-WAN default-action 'accept'
set firewall name DMZ-WG0 default-action 'accept'
set firewall name LAN-DMZ default-action 'accept'
set firewall name LAN-LOCAL default-action 'accept'
set firewall name LAN-WAN default-action 'accept'
set firewall name LOCAL-DMZ default-action 'accept'
set firewall name LOCAL-LAN default-action 'accept'
set firewall name LOCAL-WAN default-action 'accept'
set firewall name LOCAL-WG0 default-action 'accept'
set firewall name WAN-DMZ default-action 'drop'
set firewall name WAN-DMZ enable-default-log
set firewall name WAN-DMZ rule 1 action 'accept'
set firewall name WAN-DMZ rule 1 description 'Allow Established/Related Traffic'
set firewall name WAN-DMZ rule 1 state established 'enable'
set firewall name WAN-DMZ rule 1 state related 'enable'
set firewall name WAN-DMZ rule 2 action 'drop'
set firewall name WAN-DMZ rule 2 log 'enable'
set firewall name WAN-DMZ rule 2 state invalid 'enable'
set firewall name WAN-LAN default-action 'drop'
set firewall name WAN-LAN enable-default-log
set firewall name WAN-LAN rule 1 action 'accept'
set firewall name WAN-LAN rule 1 description 'Allow Established/Related Traffic'
set firewall name WAN-LAN rule 1 state established 'enable'
set firewall name WAN-LAN rule 1 state related 'enable'
set firewall name WAN-LAN rule 2 action 'drop'
set firewall name WAN-LAN rule 2 log 'enable'
set firewall name WAN-LAN rule 2 state invalid 'enable'
set firewall name WAN-LOCAL default-action 'drop'
set firewall name WAN-LOCAL enable-default-log
set firewall name WAN-LOCAL rule 1 action 'accept'
set firewall name WAN-LOCAL rule 1 description 'Allow Established/Related Traffic'
set firewall name WAN-LOCAL rule 1 state established 'enable'
set firewall name WAN-LOCAL rule 1 state related 'enable'
set firewall name WAN-LOCAL rule 2 action 'drop'
set firewall name WAN-LOCAL rule 2 log 'enable'
set firewall name WAN-LOCAL rule 2 state invalid 'enable'
set firewall name WG0-DMZ default-action 'drop'
set firewall name WG0-DMZ enable-default-log
set firewall name WG0-DMZ rule 1 action 'accept'
set firewall name WG0-DMZ rule 1 description 'Allow Established/Related Traffic'
set firewall name WG0-DMZ rule 1 state established 'enable'
set firewall name WG0-DMZ rule 1 state related 'enable'
set firewall name WG0-DMZ rule 2 action 'drop'
set firewall name WG0-DMZ rule 2 log 'enable'
set firewall name WG0-DMZ rule 2 state invalid 'enable'
set firewall name WG0-LOCAL default-action 'drop'
set firewall name WG0-LOCAL enable-default-log
set firewall name WG0-LOCAL rule 1 action 'accept'
set firewall name WG0-LOCAL rule 1 description 'Allow Established/Related Traffic'
set firewall name WG0-LOCAL rule 1 state established 'enable'
set firewall name WG0-LOCAL rule 1 state related 'enable'
set firewall name WG0-LOCAL rule 2 action 'drop'
set firewall name WG0-LOCAL rule 2 log 'enable'
set firewall name WG0-LOCAL rule 2 state invalid 'enable'
set interfaces ethernet eth0 address 'xxx.xxx.0.251/24'
set interfaces ethernet eth0 description 'WAN'
set interfaces ethernet eth1 address 'xxx.xxx.10.1/24'
set interfaces ethernet eth1 description 'LAN'
set interfaces ethernet eth2 address 'xxx.xxx.20.1/29'
set interfaces ethernet eth2 description 'DMZ'
set interfaces loopback lo
set interfaces wireguard wg0 address 'xxx.xxx.47.252/32'
set interfaces wireguard wg0 peer mullvad address 'xxx.xxx.162.234'
set interfaces wireguard wg0 peer mullvad allowed-ips 'xxx.xxx.0.0/0'
set interfaces wireguard wg0 peer mullvad port '51820'
set interfaces wireguard wg0 peer mullvad public-key 'kOpdNLq/ePrlc2WXGinRvbQWRhy755cZ4G4S7xwsKIw='
set interfaces wireguard wg0 private-key xxxxxx
set nat source rule 100 outbound-interface 'eth0'
set nat source rule 100 source address 'xxx.xxx.10.0/24'
set nat source rule 100 translation address 'masquerade'
set nat source rule 200 outbound-interface 'eth0'
set nat source rule 200 source address 'xxx.xxx.20.0/29'
set nat source rule 200 translation address 'masquerade'
set protocols static route xxx.xxx.0.0/0 next-hop xxx.xxx.0.1 interface 'eth0'
set protocols static route xxx.xxx.20.4/32
set service dhcp-server shared-network-name DMZ subnet 172.16.20.0/29 default-router 'xxx.xxx.20.1'
set service dhcp-server shared-network-name DMZ subnet 172.16.20.0/29 domain-name xxxxxx
set service dhcp-server shared-network-name DMZ subnet 172.16.20.0/29 name-server 'xxx.xxx.20.1'
set service dhcp-server shared-network-name DMZ subnet 172.16.20.0/29 range 0 start 'xxx.xxx.20.2'
set service dhcp-server shared-network-name DMZ subnet 172.16.20.0/29 range 0 stop 'xxx.xxx.20.3'
set service dhcp-server shared-network-name DMZ subnet 172.16.20.0/29 static-mapping xxxxxx ip-address 'xxx.xxx.20.4'
set service dhcp-server shared-network-name DMZ subnet 172.16.20.0/29 static-mapping xxxxxx mac-address 'xx:xx:xx:xx:xx:04'


set service dns forwarding allow-from 'xxx.xxx.10.0/24'
set service dns forwarding allow-from 'xxx.xxx.20.0/29'
set service dns forwarding listen-address 'xxx.xxx.20.1'
set service dns forwarding name-server 'xxx.xxx.8.8'
set service ssh port '22'
set system config-management commit-revisions '100'
set system conntrack modules ftp
set system conntrack modules h323
set system conntrack modules nfs
set system conntrack modules pptp
set system conntrack modules sip
set system conntrack modules sqlnet
set system conntrack modules tftp
set system console device ttyS0 speed '115200'
set system host-name xxxxxx
set system login user xxxxxx authentication encrypted-password xxxxxx
set system login user xxxxxx authentication plaintext-password xxxxxx
set system name-server 'xxx.xxx.8.8'
set system syslog global facility all level 'info'
set system syslog global facility protocols level 'debug'
set zone-policy zone DMZ default-action 'drop'
set zone-policy zone DMZ from LAN firewall name 'LAN-DMZ'
set zone-policy zone DMZ from LOCAL firewall name 'LOCAL-DMZ'
set zone-policy zone DMZ from WAN firewall name 'WAN-DMZ'
set zone-policy zone DMZ from WG0 firewall name 'WG0-DMZ'
set zone-policy zone DMZ interface 'eth2'
set zone-policy zone LAN default-action 'drop'
set zone-policy zone LAN from DMZ firewall name 'DMZ-LAN'
set zone-policy zone LAN from LOCAL firewall name 'LOCAL-LAN'
set zone-policy zone LAN from WAN firewall name 'WAN-LAN'
set zone-policy zone LAN interface 'eth1'
set zone-policy zone LOCAL default-action 'drop'
set zone-policy zone LOCAL from DMZ firewall name 'DMZ-LOCAL'
set zone-policy zone LOCAL from LAN firewall name 'LAN-LOCAL'
set zone-policy zone LOCAL from WAN firewall name 'WAN-LOCAL'
set zone-policy zone LOCAL from WG0 firewall name 'WG0-LOCAL'
set zone-policy zone LOCAL local-zone
set zone-policy zone WAN default-action 'drop'
set zone-policy zone WAN from DMZ firewall name 'DMZ-WAN'
set zone-policy zone WAN from LAN firewall name 'LAN-WAN'
set zone-policy zone WAN from LOCAL firewall name 'LOCAL-WAN'
set zone-policy zone WAN interface 'eth0'
set zone-policy zone WG0 default-action 'drop'
set zone-policy zone WG0 from DMZ firewall name 'DMZ-WG0'
set zone-policy zone WG0 from LOCAL firewall name 'LOCAL-WG0'
set zone-policy zone WG0 interface 'wg0'

You can use “policy local-route”
policy local-route rule 10 set table 10
policy local-route rule 10 source 172.16.20.4

https://docs.vyos.io/en/latest/configuration/policy/local-route.html

Thanks. I will check it out. PBR is very new to me.

show interfaces wireguard wg0
wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none 
    inet 10.67.47.252/32 scope global wg0
       valid_lft forever preferred_lft forever
    inet6 fe80::f5d2:ffff:fe3d:dbc8/64 scope link 
       valid_lft forever preferred_lft forever

Do you mean to add just this?

set policy local-route rule 10 set table 10
set policy local-route rule 10 source 172.16.20.4
set policy local-route rule 10 destination 10.67.47.252

Or is there more to it? Do need to add rule to routing table? Should I see anything in show route

vyos@firewall:~$ show ip route
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

S>* 0.0.0.0/0 [1/0] via 192.168.0.1, eth0, weight 1, 00:11:39
C>* 10.67.47.252/32 is directly connected, wg0, 03:14:05
C>* 172.16.10.0/24 is directly connected, eth1, 03:22:10
C>* 172.16.20.0/29 is directly connected, eth2, 03:22:11
C>* 192.168.0.0/24 is directly connected, eth0, 03:22:10
vyos@firewall:~$ show ip route table 10

You don’t need a destination, all traffic match source 172.16.20.4 will be via table 10:

set policy local-route rule 10 set table 10
set policy local-route rule 10 source 172.16.20.4
set protocols static table 10 route 0.0.0.0/0 next-hop 203.0.113.1 interface wgX

For my case, zone-policy zone VPN w/ wireguard i configured the ethernet interface AND wiregaurd interface on the same policy.

Traffic for the wireguard traffic is dedicated to an interface.

to make sure, you don’t leak packets from 172.16.20.4 to WAN when wg0 is down, make sure to add a black-hole route for 0.0.0.0/0 in table 10. Of course this needs worse administrative distance than wg route

1 Like

Thanks all. I have added the following configuration lines and committed and saved

set policy local-route rule 10 set table 10
set policy local-route rule 10 source 172.16.20.4
set protocols static table 10 route 0.0.0.0/0 next-hop 10.67.47.252 interface wg0
set protocols static table 10 route 0.0.0.0/0 blackhole distance 254
vyos@firewall:~$ show ip route table 10
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

VRF default table 10:
S>r 0.0.0.0/0 [1/0] via 10.67.47.252, wg0 onlink, weight 1, 00:42:49
S   0.0.0.0/0 [254/0] unreachable (blackhole), weight 1, 00:42:49

What does r=rejected here mean?

main routing table

vyos@firewall:~$ show ip route 
Codes: K - kernel route, C - connected, S - static, R - RIP,
       O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
       T - Table, v - VNC, V - VNC-Direct, A - Babel, F - PBR,
       f - OpenFabric,
       > - selected route, * - FIB route, q - queued, r - rejected, b - backup
       t - trapped, o - offload failure

S>* 0.0.0.0/0 [1/0] via 192.168.0.1, eth0, weight 1, 00:46:22
C>* 10.67.47.252/32 is directly connected, wg0, 00:46:23
C>* 172.16.10.0/24 is directly connected, eth1, 00:46:24
C>* 172.16.20.0/29 is directly connected, eth2, 00:46:24
C>* 192.168.0.0/24 is directly connected, eth0, 00:46:24

However, on my node - 172.16.20.4 when I traceroute to the 8.8.8.8 I see if go via my ISP and not via the wg0.

Is it related to NAT rule 200? I assume not, as that should only apply to traffic leaving eth0.

On the router I can confirm that I can capture the packets and the address is 172.16.20.4

vyos@firewall:~$ sudo tcpdump -i eth2 "host 172.16.20.4"
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth2, link-type EN10MB (Ethernet), snapshot length 262144 bytes
22:44:38.966205 IP 172.16.20.4.55784 > dns.google.33434: UDP, length 32
22:44:38.966205 IP 172.16.20.4.51515 > dns.google.33435: UDP, length 32

What are the next steps that I can do to debug?

The tcpdump just shows packets as they arrive on Vyos eth2 , what do you see on eth0?

I see the traffic leaving eth0 using NAT rule 200 (172.16.20.4/29 via eth0)

vyos@vyos:~$ tcpdump -i eth0 "icmp"
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
09:45:37.640393 IP 192.168.0.251 > dns.google: ICMP echo request, id 53395, seq 1, length 64
09:45:37.643080 IP dns.google > 192.168.0.251: ICMP echo reply, id 53395, seq 1, length 64

I changed the NAT 200 to use wg0 instead of eth0 (as this makes more sense)

 source {


     rule 200 {
         outbound-interface wg0
         source {
             address 172.16.20.0/29
         }
         translation {
             address masquerade
         }
     }
 }

I repeated the ping test - it failed as expected.
The traffic is still following the main routing table default.

vyos@firewall# tcpdump -i eth0 "icmp"
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
09:51:45.553084 IP 172.16.20.4 > dns.google: ICMP echo request, id 10376, seq 1, length 64

Why is the status of my route - r-> rejected?

vyos@firewall# run show ip route table 10 

VRF default table 10:
S>r 0.0.0.0/0 [1/0] via 10.67.47.252, wg0 onlink, weight 1, 00:03:17
S   0.0.0.0/0 [254/0] unreachable (blackhole), weight 1, 00:10:55

It is seems you are trying to set next-hop the router itself and not remote wireguard address

1 Like

Perfect . Thanks for that. I added correct next and it worked.

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