I feel like this question must have been asked before but I cannot find it for the life of me in the forum (maybe I’m just bad at searching, if that’s the case I apologize). I’m trying to understand the general packet flow of a wireguard packet to determine the best way to assign firewall filter rules. I was reading through the overall Packet Flow in RouterOS but that doesn’t seem to include WireGuard packets, which appear to be different.
For context, I wanted to setup 3 different types of wireguard tunnels:
- The first tunnel type only has access to my home media servers static IP and will be shared with friends and family. It has subnet 172.16.50.0/24
- The second tunnel type is only for me, and allows access to my entire LAN but not the broader public IP space. It has subnet 172.17.50.0/24
- The third tunnel is also only for me, but it forwards all traffic through the router (AllowedIps=0.0.0.0/0,::/0)
For the purposes of this post, I am mostly just considering the first tunnel type which should be locked down to only accessing a single IP address on my LAN. I was looking at the docs some WireGuard filter rules on the forum, the default ones that get applied when creating a back-to-home VPN, and playing around in wireshark with a wireguard connection I have setup so I can get an idea of how I should be making my filter rules. It seems like the primary recommendation is just accepting packets based on the udp port specified when setting up the wireguard interface. eg.
/ip firewall filter add action=accept chain=input dst-port=13231 protocol=udp in-interface-list=WAN
and any inter-subnet rules are done on the default forward chain:
/ip firewall filter add action=accept chain=forward dst-address=10.1.202.0/24 src-address=10.1.101.0/24
After playing around with packet inspection via WireShark, it seems like the flow is the following:
- A packet comes in on the WAN port (ether1 in my case) using the UDP port specified when I setup the WG1 interface
- A firewall rule is setup to accept the WAN WG traffic
- /ip firewall filter add action=accept chain=input dst-port=13231 protocol=udp in-interface-list=WAN
- The packet is accepted, and then routed to the WG1 interface
- A standard routing decision is applied to the packet to determine if it should be on the input chain (like for a DNS request to the mikrotik itself) or on the forward chain (like communicating with the media server)
- The packet goes through the filter rules again, only this time with an interface of WG1
My questions are the following:
- Did I correctly deduce the flow of a wireguard packet or is there anything Im missing / got wrong?
- When I setup a interface=WG1 chain=input passthrough rule and a interface=WG1 chain=forward passthrough rule, the sum of the input and forward chains is always less than the WAN:wg-port accept rule shown above, as listed by the rule counters. Is this a sign some packets are getting dropped? Or do keep-alive packets, for example, not get placed on the forward or input chains?
- At what point does decryption occur?
- At what point does WireGuard drop packets that are unauthenticated or disallowed by the servers AllowedIps config? I assume this is the same place as decryption?
My ideal scenario is a where I can make an interface list with all wireguard interfaces, have a rule at the top of my default chains with action=jump, which takes it to a custom wg chain where I have very specific rules. Would there be anything wrong with the following? (Assuming a default filter rule config, and noting the place-before’s on some rules)
/interface list add name=WG_IN_INTFLST
/interface list member add interface=WG1 list=WG_IN_INTFLST
/interface list member add interface=WG2 list=WG_IN_INTFLST
/ip firewall filter add action=accept chain=input dst-port=13231 protocol=udp in-interface-list=WAN place-before=1 comment=”accept the WAN WG traffic”
/ip firewall filter add chain=forward action=jump jump-target=wg_forward in-interface-list=WG_IN_INTFLST place-before=1 comment=”send WG forward traffic to a custom chain”
/ip firewall filter add chain=wg_forward src-address=172.16.50.0/24 dst-address=10.42.50.51/32 (media server on LAN) dst-port=5056,8096 action=accept comment=”accept media wg tunnel to server:port”
/ip firewall filter add chain=wg_forward src-address=172.17.50.0/24 dst-address=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16 action=accept comment=”accept lan wg tunnel to private IP space”
/ip firewall filter add chain=wg_forward action=drop comment=”drop all other WG traffic”
(keeping it simple and only looking at the forward chain for this example)
Essentially, I just want to make sure I have a solid foundational understanding of how routing wireguard packets work so that I can reason over the filter rules better. Thank you all in advance!