Re: Filtering incoming WireGuard traffic with pf?

From: Lexi Winter <lexi_at_le-fay.org>
Date: Sun, 17 Mar 2024 11:05:02 UTC
Wesley Aptekar-Cassels:
> The relevant section of my /etc/pf.conf is:
> 
> ```
> ext_if = "vtnet0"
> wg_lan = "10.10.0.0/24"
> 
> set skip on lo
> scrub in
> 
> nat on $ext_if from $wg_lan to any -> ($ext_if)
> 
> block in on $ext_if
> pass out
> ```
[...]
> My expectation was that `block in on $ext_if` would block WireGuard traffic and
> that I'd need a `pass in on $ext_if proto udp to ($ext_if) port 51820` line in
> order to enable it, but my WireGuard tunnel works even without that, which
> makes it seem to me that the decapsulation of the WireGuard traffic happens
> before it hits pf.

that shouldn't be the case; it's not like IPsec where decryption happens
in a way which is a bit magical.  

what's likely going on here is that your local machine (the one running
pf) is creating an outgoing connection to the Wireguard peer, which pf
allows because of the 'pass out' rule.  then because pf keeps state by
default, the return traffic is also allowed, and there's no need for an
incoming rule.

you could test this by blocking traffic on the Wireguard port on both
ends of the tunnel; that should prevent the Wireguard connection from
coming up at all.  however, you'll need to disable both ends of the
peers for a few minutes before testing, to make sure any existing pf
state has expired.

in practice, although Wireguard will work this way (with incoming
traffic blocked on one end), it's still better to allow incoming traffic
on both ends of the tunnel so that either machine can initiate the
connection.