Yes, pfSense supports WireGuard on both CE and Plus through an add-on package. To set it up, install the package, create a tunnel on UDP 51820, add one peer per device, assign the tunnel as an interface with an address such as 10.50.60.1/24, then pass UDP 51820 on WAN and the tunnel subnet on the WireGuard interface.
WireGuard on pfSense uses a tunnel-and-peer model rather than the connection-oriented model OpenVPN admins are used to, and most setup failures trace back to one of two things: a missing interface assignment, or a firewall rule that never got written because the interface was never assigned. Work through the steps below in order and you avoid both. The same package can also make pfSense a Mullvad client, covered near the end.
Which pfSense versions support WireGuard
| pfSense release | WireGuard status |
|---|---|
| CE 2.5.0 / Plus 21.02 | In the base system |
| CE 2.5.1 / Plus 21.02.2 | Removed when FreeBSD dropped it |
| CE 2.5.2 / Plus 21.05 and later | Add-on package |
| CE 2.9.0 / Plus 26.07 | Add-on package, with the kernel fix for CVE-2026-58085 |
Upgrade before exposing the port. FreeBSD-SA-26:52.if_wg reports that the kernel wg(4) driver accepted packets with an invalid Poly1305 tag, so anyone able to send UDP to your endpoint could inject forged packets; NVD rates it 7.5 (High). Netgate shipped the fix in Plus 26.07 and CE 2.9.0 in August 2026. It lives in the base system, not the package, so upgrade under System > Update.
Prerequisites
Before touching the WireGuard menu, confirm three things:
- A reachable WAN. WireGuard listens on a UDP port (51820 by default) that has to be reachable from wherever your clients connect. If pfSense sits behind your own ISP router and its WAN address is private (RFC 1918), forward UDP 51820 to pfSense on that router. If the WAN address is in 100.64.0.0/10, you are behind carrier-grade NAT (common on cellular and some fiber ISPs; here is how to check for CGNAT), and no port forward is possible: ask the ISP for a public IPv4 address, or use an outbound overlay or relay as described under “When a road-warrior tunnel is the wrong approach” below.
- A stable endpoint. Clients need an IP address or hostname to connect to. If your WAN IP isn’t static, set up Dynamic DNS under System > Dynamic DNS before you configure client files, so you’re not editing every config later.
- A free, non-overlapping subnet. Pick an address range for the tunnel interface that doesn’t collide with your LAN, any other VLAN, or a site you connect to remotely.
Step 1: Install the WireGuard package
WireGuard ships as an installable package rather than a base-system feature. Go to System > Package Manager > Available Packages, search for WireGuard, and click Install. Once it finishes, a new VPN > WireGuard menu appears, according to the official pfSense WireGuard documentation.
Netgate’s docs describe WireGuard as operating “completely in the kernel,” which is a meaningful architectural difference from OpenVPN: there’s no persistent session state, no built-in user authentication, and configuration lives directly on the interface rather than in a separate daemon config. That simplicity is also why WireGuard performs close to hardware-accelerated IPsec despite running entirely in software.
Step 2: Create the WireGuard tunnel
Navigate to VPN > WireGuard > Tunnels and click Add Tunnel:
- Enable: checked
- Description: something identifiable, e.g.
WG_Remote - Listen Port:
51820(the WireGuard default; change it only if you have a specific reason to) - Interface Keys: click Generate to create the tunnel’s public/private keypair
- Interface Addresses: leave unset here; Step 4 configures
10.50.60.1/24on the assigned interface
Save, then enable WireGuard under VPN > WireGuard > Settings. The address assigned in Step 4 will identify pfSense inside the VPN network.
Step 3: Add a peer
A “peer” is any device that will connect to this tunnel: a laptop, a phone, or another firewall in a site-to-site setup. Under VPN > WireGuard > Peers, click Add Peer:
- Tunnel: the tunnel created in Step 2
- Description: e.g.
Laptop-Remote - Dynamic Endpoint: checked, if the client’s IP changes (typical for road-warrior clients); unchecked with a fixed Endpoint field for a peer with a known static address
- Public Key: the client’s public key (generate on Linux/macOS with
wg genkey | tee privatekey | wg pubkey > publickeyafterumask 077, or let the mobile app generate one) - Allowed IPs:
10.50.60.2/32— a single address inside the tunnel subnet, unique per peer
The remote-access configuration example in Netgate’s documentation is worth reading in full here, since Allowed IPs is the field most people get wrong: on the server-side peer entry it defines what source address that specific peer is allowed to use, not what networks it can reach. Putting a LAN subnet here instead of the peer’s single tunnel address breaks WireGuard’s cryptokey routing.
Step 4: Assign the interface
Under System > Routing, explicitly select the intended WAN default gateway before assigning the tunnel. Netgate’s assignment instructions warn that Automatic gateway selection can choose WireGuard.
Go to Interfaces > Assignments, add the tunnel, enable it, and set Static IPv4 to 10.50.60.1/24. Leave IPv6 unconfigured for this IPv4 example and do not select an upstream gateway on this internal VPN interface. Assigned tunnels keep their addresses here rather than in the tunnel editor.
What is 10.50.60.1 in this setup?
10.50.60.1 is a private IPv4 address from the 10.0.0.0/8 block that RFC 1918 reserves for internal networks, so it is not routed on the public internet. Here it is pfSense’s own address on the WireGuard interface, the firewall end of the 10.50.60.0/24 tunnel, with peers at .2, .3 and up.
Ping it first from a connected client: a reply proves the tunnel and interface rule work before LAN routing is involved. The number is arbitrary, and Netgate’s own example uses 10.6.210.1/24; any unused private subnet works if it avoids your LAN, VLANs and the networks clients join. Seen elsewhere as a gateway, it belongs to a device on that network, not to pfSense.
Step 5: Write the firewall rules
Two separate rule sets are required.
On Firewall > Rules > WAN, allow the tunnel’s listen port in from the internet:
Action: Pass
Protocol: UDP
Destination: WAN address
Destination port: 51820
On Firewall > Rules > [WireGuard interface], allow traffic from the tunnel subnet to wherever it needs to go:
Action: Pass
Protocol: Any
Source: WireGuard tunnel subnet
Destination: LAN subnet (or specific hosts/ports if you want it tighter)
Without the WAN rule the handshake cannot arrive; without an internal permission rule a handshake may succeed while application traffic is blocked.
Step 6: Build the client configuration
On the client, create a .conf file (or scan a QR code from it, for mobile apps):
[Interface]
PrivateKey = <client private key>
Address = 10.50.60.2/32
DNS = 192.168.1.1
[Peer]
PublicKey = <pfSense tunnel public key from Step 2>
Endpoint = your-wan-ip-or-ddns-hostname:51820
AllowedIPs = 192.168.1.0/24, 10.50.60.0/24
PersistentKeepalive = 25
AllowedIPs here is the client-side field, and it means something different than the server-side field in Step 3: it defines which destination networks the client routes into the tunnel. List your LAN subnet for split-tunnel access. Use 0.0.0.0/0 only with the IPv4 full-tunnel routing and NAT checks below. Do not add ::/0 without configuring IPv6 end to end.
In this tunnel config, Address and DNS are wg-quick extensions rather than core wg keys, and PersistentKeepalive = 25 follows the WireGuard quick start, which calls 25 seconds “a sensible interval that works with a wide variety of firewalls” for peers behind NAT.
Limit peer access and check rule precedence
For a peer that only needs a NAS, replace the broad LAN pass with explicit permissions to that host and its required ports. Allow DNS to the selected resolver on TCP/UDP 53, then block other access to firewall management and internal networks. Any optional internet pass belongs below those restrictions.
Review the common WireGuard rule tab as well as the assigned interface. Netgate’s WireGuard rules guidance notes that group rules are evaluated first. A broad pass there can defeat narrower rules on the assigned interface.
IPv4 full tunnel, NAT and DNS
For full-tunnel IPv4, permit the peer’s intended internet egress and set client AllowedIPs to 0.0.0.0/0. Keep the pfSense peer entry at that device’s unique tunnel address. Inspect outbound NAT for source 10.50.60.0/24 leaving WAN. If missing, add the required WAN translation to the interface address in Hybrid or Manual mode, following Netgate’s outbound NAT guidance.
Permit VPN clients in the DNS Resolver ACLs and ensure the resolver listens on the address used by the client profile. Routed WireGuard does not automatically carry local discovery broadcasts; use internal DNS names for services.
This example covers IPv4. Configure routed IPv6 and matching policy before claiming complete tunnel coverage, or use client controls to prevent IPv6 traffic outside the VPN. Verify client behavior when the tunnel disconnects.
Step 7: Verify the connection
From the pfSense console or over SSH, run:
wg show
A peer entry with a recent handshake timestamp and non-zero transfer counters means the tunnel itself is working. From there, ping the pfSense LAN IP from the client, then a real LAN host, to confirm routing and firewall rules are both correct. If the handshake never appears, the problem is almost always upstream — the WAN rule, a port forward on a device in front of pfSense, or a stale endpoint address in the client config. This same tunnel is the recommended way to reach the web GUI remotely without ever exposing it to the internet, as the pfSense initial setup hardening checklist spells out.
Troubleshooting, in diagnostic order
Work from the outside in, because each step isolates a layer:
- No handshake at all. Almost always the inbound path: the WAN firewall rule isn’t passing UDP to the listen port, the upstream router or CGNAT is dropping it, or the client’s
Endpointis wrong or stale. UDP does not port-scan usefully, so rely on the handshake timestamp and check the pfSense firewall log for the inbound packets. - Handshake succeeds but no traffic passes. This is a routing and rules problem, not a crypto one. Check three things: the WireGuard-interface firewall rule allows the client subnet to the destinations you want; the client’s
AllowedIPsincludes the LAN subnet you are trying to reach; and Outbound NAT covers the WireGuard subnet if LAN hosts have no route back. The simplest fix for “I can ping the firewall but not LAN devices” is hybrid Outbound NAT translating the WireGuard subnet on the LAN interface, or static routes and host firewalls that accept the WireGuard range. - Works on Wi-Fi but not cellular, or the reverse. Usually a missing
PersistentKeepaliveon a NAT’d client, or an MTU issue. Try lowering the client interface MTU to around 1380–1420 if large packets stall while the handshake works. - DNS doesn’t resolve over the tunnel. The client
DNS =must be a resolver reachable through the tunnel (normally the pfSense LAN IP), and the pfSense DNS Resolver must accept queries from the WireGuard subnet under Services > DNS Resolver > network ACLs.
wg show is the single best diagnostic: a recent handshake plus incrementing rx/tx confirms the tunnel itself, and the absence of either points you at the layer above.
Using pfSense as a Mullvad WireGuard client
The same package lets pfSense dial out to a provider on a second tunnel. Mullvad costs €5 per month for up to 5 devices (checked September 2026), and its pfSense guide, written for 2.7.0 and updated January 20, 2026, comes down to six steps:
- Over SSH in
/usr/local/etc/wireguard/, runwg genkey | tee privkey | wg pubkey > pubkey, then register the key withcurl https://api.mullvad.net/wg/ -d account=YOURMULLVADACCOUNTNUMBER --data-urlencode pubkey=YOURPUBLICKEY; the reply is your tunnel address. - Add a tunnel with that private key and a peer using a server’s IP and public key from Mullvad’s server list, port
51820, Allowed IPs0.0.0.0/0. - Assign the interface as Static IPv4 with that address, and add a gateway at
10.64.0.1with Use non-local gateway checked. - Translate the LAN subnet on the WireGuard interface in Outbound NAT (Mullvad’s guide uses Manual mode).
- Set Gateway on the LAN pass rule to the Mullvad gateway, narrowing the source to route only chosen hosts.
- Point DNS at
10.64.0.1, or100.64.0.31for filtered DNS, via that gateway with the DNS Resolver in Forwarding mode.
Two leaks to close. When a rule’s gateway is down, pfSense by default drops the gateway and sends the traffic via the default gateway, per Netgate’s Miscellaneous settings; enable Do not create rules when gateway is down and add a matching block rule beneath the policy route. Mullvad also provides no IPv6 /64, so block IPv6 egress from VPN-routed hosts. If you would rather fail over to WAN, Netgate’s client example builds a VPN-first gateway group, covered in the multi-WAN guide.
When a road-warrior tunnel is the wrong approach
If your ISP uses CGNAT and you cannot get an inbound port or a forwarded endpoint, a self-hosted listening VPN simply will not work. A managed mesh or overlay network, which uses an outbound-initiated relay, or a small public relay host, is the right tool instead, and forcing WireGuard here wastes hours. If you only need occasional access to a single web service, an authenticated reverse proxy may be simpler than a full VPN.
Full-tunnel mode (AllowedIPs = 0.0.0.0/0) routes all client traffic through home, which is excellent on a hostile network but adds latency and depends on your home uplink. Use split-tunnel with LAN subnets only unless you specifically want every packet to egress via home.
WireGuard uses ChaCha20-Poly1305 rather than AES, so AES-NI does not establish its throughput; so if a saturated gigabit tunnel matters, pick a box with the headroom described in the best hardware for pfSense guide. If you are still weighing protocols, the OpenVPN vs WireGuard comparison covers throughput, the Plus-only DCO offload, and the auth features that still favour OpenVPN.
Related across the network
- VPN vs Tor vs Proxy: What Actually Protects Your Privacy — anonguide.com
- Zero Trust Access and Tunnels Instead of VPN Ingress — cloudflarezerotrust.org
- OPNsense WireGuard Road Warrior: Remote Access Setup — opnsenselab.com
- Cloudflare Tunnel Setup: Your First Tunnel Step by Step — cloudflarezerotrust.org
- How to Set Up OPNsense as a VPN Server: WireGuard, OpenVPN — opnsenselab.com
Related on this site
FAQ
Is WireGuard built into pfSense CE 2.9.0?
No. On CE 2.9.0, as on every release since CE 2.5.2 and Plus 21.05, WireGuard is an add-on you install from System > Package Manager. What 2.9.0 does bring is the base-system fix for CVE-2026-58085 in the kernel wg(4) driver, so upgrade before exposing a WireGuard port.
What port does WireGuard use on pfSense?
WireGuard on pfSense listens on UDP 51820 by default, the port set in the tunnel’s Listen Port field. Pass that UDP port to the WAN address in Firewall > Rules > WAN. WireGuard does not tunnel over TCP, so a network that blocks outbound UDP will stop clients from completing a handshake.
Can pfSense use Mullvad WireGuard for the whole network?
Yes. Register a pfSense-generated key with Mullvad’s API, add a tunnel and peer, create a gateway at 10.64.0.1, translate the LAN on the tunnel interface, and policy-route LAN traffic through it. Enable “Do not create rules when gateway is down” and add a block rule beneath, so traffic stops rather than leaking.