OPNsenseXXI · WireGuardWireGuard
WireGuard firewall rules and NAT — the rules that let VPN traffic through
What you'll learn
- Write OPNsense firewall rules for the WireGuard interface deliberately
- Apply outbound NAT to WireGuard traffic when full-tunnel is in use
- Recognise the rule patterns that permit remote-access users, site-to-site peers, and deny by default
- Plan rule sets that scale with the number of peers and subnets
- Diagnose common rule-related WireGuard failures
Prerequisites
Verified against OPNsense 25.x · FreeBSD 14.x · PF (FreeBSD packet filter) FreeBSD 14.x · Unbound 1.20+ · Kea DHCP OPNsense 25.x plugin · WireGuard in-kernel + OPNsense plugin · strongSwan (IPsec plugin) OPNsense 25.x plugin · OpenVPN 2.6.x · Suricata 7.x · 2026-08-14
The tunnel is up. AllowedIPs are configured. Authentication works. The packet arrives at the WireGuard interface, decrypted and validated against the peer’s authorisation. From here, the firewall rules decide what the packet can reach. A WireGuard deployment without deliberate firewall rules is a deployment where every VPN user can reach every internal subnet — usually not what the operator intended.
This lesson covers how OPNsense firewall rules interact with WireGuard traffic, how to write rules that permit and deny tunnel traffic deliberately, how NAT applies to VPN flows, and the production patterns for split-tunnel and full-tunnel rule sets.
The WireGuard interface as a rule source
OPNsense assigns each WireGuard instance to an interface (wg0, wg1, …). The interface appears in the firewall rule list alongside LAN, WAN, VLANs, and other OPT interfaces. Rules on the WireGuard interface apply to traffic after decapsulation — the firewall sees the inner packet (with its original source and destination IPs), not the outer encrypted header.
The dual nature of WireGuard rules:
- Rules on the WireGuard interface apply to inbound tunnel traffic (peer → firewall → inside). The source is the peer’s inner IP; the destination is an internal subnet.
- Rules on the LAN interface apply to outbound traffic from the LAN to the tunnel subnet. The source is a LAN host; the destination is a peer’s inner IP.
- Rules on the WAN interface apply to traffic from the firewall to the peer’s outer IP (the public endpoint) — but this traffic is the encrypted outer packet, which matches the WireGuard transport rules (typically allow UDP 51820 from any to the firewall).
$ pfctl -s rules | grep -E 'wg0|WireGuard' | head -10scrub in on wg0 all fragment reassemble
block return in on wg0 all
pass in quick on wg0 inet proto udp from any to any port = 51820 keep state
pass in on wg0 inet proto tcp from 10.99.0.0/24 to 10.0.0.0/24 keep state
pass in on wg0 inet proto tcp from 10.99.0.0/24 to 10.1.0.0/24 keep state
pass out on wg0 all keep stateIllustrative output
The discipline: the WireGuard interface has its own default-deny rule. The operator writes explicit allow rules for every subnet the peers should reach. Anything not explicitly allowed is denied.
Writing rules for site-to-site
A site-to-site deployment typically has:
- A WireGuard interface (e.g.
wg0) for the tunnel. - A remote subnet (e.g.
10.1.0.0/24at Site B). - A local subnet (e.g.
10.0.0.0/24at Site A) that needs to reach Site B.
The rules:
- On the LAN interface: allow LAN hosts to reach the remote subnet via the tunnel.
- On the WireGuard interface: allow traffic from the remote subnet to reach the LAN.
- On the WireGuard interface: allow the WireGuard transport (UDP 51820 from the remote peer’s public IP).
In OPNsense, the first two rules are on the LAN and the WireGuard interface; the third is on the WAN interface (where the transport arrives).
For multi-peer deployments, the rules grow with the number of subnets:
pass in on wg0 inet from 10.1.0.0/24 to 10.0.0.0/24 keep state # Site A -> Site B
pass in on wg0 inet from 10.2.0.0/24 to 10.0.0.0/24 keep state # Site A -> Site C
pass in on wg0 inet from 10.3.0.0/24 to 10.0.0.0/24 keep state # Site A -> Site D
The pattern scales by adding one rule per remote subnet. Aliases (RemoteSites containing 10.1.0.0/24, 10.2.0.0/24, 10.3.0.0/24) compress the rules to a single line per direction.
Writing rules for remote access
A remote-access deployment has different requirements. Each user (peer) typically reaches:
- The corporate subnet (
10.0.0.0/16). - Internal services (file shares, intranet, internal DNS).
- Sometimes the Internet via full-tunnel.
The rules for split-tunnel remote access:
# On the WireGuard interface: allow VPN users to reach corporate subnets
pass in on wg0 inet from 10.99.0.0/24 to 10.0.0.0/16 keep state
# On the WireGuard interface: allow VPN users to reach specific services
pass in on wg0 inet from 10.99.0.0/24 to 10.0.10.0/24 port 443 keep state # HTTPS
pass in on wg0 inet from 10.99.0.0/24 to 10.0.20.0/24 port 445 keep state # SMB
# On the LAN interface: allow LAN hosts to reach VPN users
pass in on lan inet from 10.0.0.0/16 to 10.99.0.0/24 keep state
The pattern: the VPN pool (10.99.0.0/24) is the source for inbound rules on the WireGuard interface; the corporate subnets are the destinations. Per-service rules (HTTPS, SMB) tighten the authorisation further.
For full-tunnel remote access, the rules are typically more permissive — the VPN user should reach the Internet through the firewall:
# On the WireGuard interface: allow VPN users to reach any internal subnet
pass in on wg0 inet from 10.99.0.0/24 to 10.0.0.0/8 keep state
# Outbound NAT for VPN traffic (full-tunnel users going to the Internet)
nat on igb1 inet from 10.99.0.0/24 to any -> (igb1)
The outbound NAT rule translates the VPN user’s source IP to the firewall’s WAN IP when the user reaches the Internet. Without the NAT rule, the user can reach internal subnets but not the Internet — the upstream sees a source IP from the VPN pool and cannot route the return traffic.
Aliases for rule scaling
A deployment with 50 remote-access users and 10 corporate subnets produces 50 × 10 = 500 rule combinations if written explicitly. Aliases collapse the rule set to a handful of lines.
Three alias types are useful:
- VPN pool alias —
VPNUsers = 10.99.0.0/24(the entire pool) orVPNAdmins = 10.99.0.0/26(the admin slice of the pool). - Corporate subnets alias —
CorporateSubnets = 10.0.0.0/16, 172.16.0.0/12. - Service aliases —
InternalServices = {IP address list of file servers, intranet, internal DNS}.
With aliases, the rule set becomes:
pass in on wg0 inet from VPNUsers to CorporateSubnets keep state
pass in on wg0 inet from VPNAdmins to InternalServices keep state
Two rules instead of dozens. Adding a new corporate subnet is an alias update, not a rule update.
Common rule failures
Four rule failures appear repeatedly:
-
No rule on the WireGuard interface. The peer authenticates, AllowedIPs is configured, but no firewall rule permits traffic from the peer’s subnet. The default deny blocks the traffic. The fix: add an explicit allow rule.
-
Rule on the wrong interface. The operator writes a rule on the LAN interface to allow VPN traffic, but the packet arrives on the WireGuard interface, not the LAN. The rule never matches. The fix: rules for VPN traffic go on the WireGuard interface (for inbound) and on the LAN interface (for outbound).
-
NAT missing for full-tunnel. Full-tunnel VPN users can reach internal subnets but not the Internet. The fix: add an outbound NAT rule for the VPN pool on the WAN interface.
-
Alias not updated. A new corporate subnet is added; the alias for
CorporateSubnetsis not updated; the rule does not include the new subnet. The fix: update the alias.
Summary
- The WireGuard interface has its own firewall rule list. Rules apply to traffic after decapsulation, with the inner source and destination IPs.
- Default deny on the WireGuard interface is the baseline. The operator writes explicit allow rules for every subnet the peers should reach.
- Full-tunnel remote access requires an outbound NAT rule for the VPN pool on the WAN interface; without it, clients cannot reach the Internet.
- Aliases collapse the rule set for many peers and subnets to a handful of rules.
- Rule failures typically produce “connected but cannot reach anything” — the diagnostic is
pfctl -s rulesandtcpdumpon the WireGuard interface.
Knowledge check · 4 questions
Q1. A WireGuard site-to-site peer authenticates successfully, AllowedIPs is configured correctly, the tunnel comes up, but no traffic flows. The pfctl rules show a default-deny on the WireGuard interface and no allow rules. What is the fix?
Q2. A full-tunnel WireGuard remote-access VPN (peers with AllowedIPs = 0.0.0.0/0) requires an outbound NAT rule on the WAN interface for the VPN pool, otherwise clients cannot reach the Internet.
Q3. Which of the following are valid firewall rule patterns for WireGuard deployments? Select all that apply.
Q4. A remote-access user reports they can reach internal subnets but cannot reach the Internet. The peer's AllowedIPs is 0.0.0.0/0 (full-tunnel). The firewall rules on the WireGuard interface allow VPNUsers to any. What is the most likely cause?
Passing score: 75%. Answers are checked in this browser.