pfSense WireGuard VPN Setup - Complete Configuration Guide

WireGuard is a modern VPN protocol implemented as a kernel module that delivers performance comparable to hardware-accelerated IPsec while requiring significantly less configuration complexity. The protocol uses a fixed set of cryptographic primitives (Curve25519, ChaCha20, Poly1305, BLAKE2s), eliminating the need for cipher negotiation and removing an entire class of vulnerabilities related to weak algorithm selection.

Starting with pfSense 2.7, WireGuard is available as a built-in package. This guide covers the complete setup process: from tunnel creation to client connections across multiple platforms and site-to-site deployment between two locations.

WireGuard Advantages

WireGuard was designed with a focus on simplicity and performance. Its primary advantages include:

  • Minimal codebase - approximately 4,000 lines of kernel code, making security audits substantially easier compared to IPsec (~400,000 lines) or OpenVPN (~100,000 lines).
  • High performance - kernel-level operation eliminates context switching between user space and kernel space, achieving throughput of 1 Gbps and above on modern hardware.
  • Fast connection establishment - key exchange completes in a single round-trip (1-RTT), whereas IKEv2 requires at least two exchanges.
  • Modern cryptography - the fixed algorithm set prevents downgrade attacks and configuration errors.
  • Built-in roaming - the protocol automatically updates the endpoint when a client’s IP address changes, which is essential for mobile devices.
  • Minimal attack surface - WireGuard does not respond to packets from unauthorized sources (stealth mode), making the server invisible to port scanners.

Limitations

Before selecting WireGuard as a VPN protocol, the following limitations must be considered.

No Username/Password Authentication

WireGuard does not support username/password authentication. Peer identification relies exclusively on cryptographic keys. For organizations requiring centralized account management through LDAP or RADIUS, this may be a significant constraint. In such cases, consider OpenVPN with RADIUS authentication .

Static Address Assignment

WireGuard has no built-in mechanism for dynamic IP address assignment (no DHCP equivalent). Each peer must be manually assigned an address from the designated tunnel subnet. With a large number of clients, this requires maintaining an address allocation registry.

No Session Management

The protocol has no concept of sessions or connections. There is no way to determine whether a client is currently connected, except by checking the latest handshake timestamp on the Status > WireGuard page. Forcibly disconnecting a client is only possible by removing its public key from the peer configuration.

Limited Logging

WireGuard performs minimal logging at the kernel level. Information about connection attempts, authentication failures, and traffic details is limited. For environments with strict audit requirements (PCI DSS, HIPAA), this may require additional monitoring measures.

Port Binding Behavior

WireGuard accepts traffic on its designated UDP port across all firewall interfaces, not just a selected one. This must be taken into account when planning filtering rules.

Prerequisites

Before proceeding with the setup, ensure the following conditions are met:

  1. pfSense version 2.7.0 or later - WireGuard is available as a built-in package. To verify the version: System > General Setup.
  2. WireGuard package installed - install via System > Package Manager > Available Packages. Search for WireGuard and click Install.
  3. Static public IP address or configured Dynamic DNS on the pfSense WAN interface (for remote access scenarios).
  4. Dedicated tunnel subnet - use an RFC 1918 address range that does not overlap with existing networks. Example: 10.10.10.0/24.
  5. Open UDP port on upstream equipment (if pfSense is behind NAT).

Tunnel Creation

WireGuard tunnels are created under VPN > WireGuard > Tunnels.

  1. Click Add Tunnel.
  2. Configure the tunnel parameters:
FieldValueDescription
EnableCheckedActivate the tunnel
DescriptionWG-RemoteAccessDescriptive name for the tunnel
Listen Port51820Standard WireGuard port (can be changed)
Interface KeysGenerateGenerate key pair (private + public)
Interface Addresses10.10.10.1/24pfSense address within the tunnel
  1. Click Save Tunnel.

WireGuard tunnel configuration

Fig. 1. Creating a WireGuard tunnel in the pfSense web interface

After saving, the system automatically generates a key pair. The public key is displayed on the tunnel page - copy it for subsequent distribution to clients.

Warning:

The private key must never be shared with third parties. Compromise of the private key requires immediate key pair regeneration and reconfiguration of all peers.

Port Selection

The standard WireGuard port is 51820/UDP. When using multiple tunnels, each must be assigned a unique port. If WireGuard needs to operate from networks with strict outbound traffic restrictions, port 443/UDP may be used, although this can conflict with HTTPS traffic when HAProxy or similar services are present.

Tunnel Addressing

A dedicated subnet should be allocated for tunnel addressing, with no overlap with other networks:

ScenarioRecommended SubnetMask
Remote access (up to 254 clients)10.10.10.0/24
Site-to-site (two nodes)10.10.10.0/30
Multiple tunnels10.10.10.0, 10.10.20.0, …/24

Adding Peers

Peers are added under VPN > WireGuard > Peers. Each client or remote node is a separate peer.

  1. Click Add Peer.
  2. Configure the parameters:
FieldValueDescription
EnableCheckedActivate the peer
TunnelWG-RemoteAccessSelect the previously created tunnel
DescriptionLaptop-AdminClient description
Dynamic EndpointCheckedFor clients with dynamic IP (remote access)
Public Key(client key)Public key generated on the client side
Pre-Shared Key(optional)Additional layer of protection (post-quantum security)
Allowed IPs10.10.10.2/32Client address within the tunnel
Keep Alive25Keepalive interval in seconds (for clients behind NAT)
  1. Click Save Peer.

WireGuard peer configuration

Fig. 2. Adding a WireGuard peer in pfSense

Key Exchange

Public key exchange between server and client is performed manually over a secure channel:

  1. The server (pfSense) generates a key pair during tunnel creation. The server’s public key is provided to the client.
  2. The client generates its own key pair (using the WireGuard client application). The client’s public key is entered in the Public Key field when adding a peer on pfSense.

Warning:

Public keys should be transmitted over a secure channel: in person, via an encrypted messenger, or through a corporate secrets management system. Public keys are not secrets themselves, but their substitution (MITM) would allow an attacker to impersonate a legitimate node.

The Allowed IPs Field

The Allowed IPs field determines which IP addresses are accepted from a given peer and which addresses are routed through the tunnel. Correct configuration of this field is critical:

ScenarioAllowed IPs ValueDescription
Remote access (single client)10.10.10.2/32Client tunnel address only
Site-to-site10.10.10.2/32, 192.168.2.0/24Peer address + remote subnet
Full tunnel (all traffic via VPN)0.0.0.0/0All IPv4 client traffic
Full tunnel (IPv4 + IPv6)0.0.0.0/0, ::/0All client traffic

Pre-Shared Key (PSK)

Using a PSK adds a symmetric encryption layer on top of Curve25519. This provides additional protection in case the asymmetric algorithm is compromised (post-quantum resilience). A PSK is generated with:

wg genpsk

The generated key is entered in the Pre-Shared Key field both on the pfSense side (in peer settings) and in the client configuration.

Interface Assignment

After creating the tunnel, an interface must be assigned to it in pfSense. Without interface assignment, it is not possible to create specific firewall rules for traffic within the tunnel.

  1. Navigate to Interfaces > Assignments.
  2. From the Available network ports dropdown, select the tun_wgN interface (where N is the tunnel number).
  3. Click Add.
  4. Click on the assigned interface name (e.g., OPT1) to access its settings.
  5. Configure the parameters:
FieldValueDescription
EnableCheckedActivate the interface
DescriptionWIREGUARDInterface name (displayed in firewall rules)
IPv4 Configuration TypeNoneAddressing is already configured at the tunnel level
IPv6 Configuration TypeNoneIf IPv6 is not in use
  1. Click Save, then Apply Changes.

Warning:

The IPv4 Configuration Type should remain set to None, as the IP address is already assigned at the WireGuard tunnel level. Assigning an address at both the interface and tunnel levels simultaneously can cause routing conflicts.

Firewall Rules

Two sets of rules are required for WireGuard to function correctly: on the WAN interface (to accept incoming connections) and on the WireGuard interface (to control traffic within the tunnel).

WAN Rule

Permits incoming UDP connections to the WireGuard port.

Navigate to Firewall > Rules > WAN and click Add.

FieldValue
ActionPass
InterfaceWAN
Address FamilyIPv4
ProtocolUDP
SourceAny
DestinationWAN Address
Destination Port Range51820 (or configured tunnel port)
DescriptionAllow WireGuard VPN

WireGuard Interface Rules

Control which traffic is permitted for VPN clients within the tunnel.

Navigate to Firewall > Rules > WIREGUARD (the assigned interface name) and click Add.

Option 1 - allow all traffic (for testing):

FieldValue
ActionPass
InterfaceWIREGUARD
Address FamilyIPv4
ProtocolAny
SourceWIREGUARD net
DestinationAny
DescriptionAllow all WireGuard traffic

Option 2 - allow LAN access only (recommended for production):

FieldValue
ActionPass
InterfaceWIREGUARD
Address FamilyIPv4
ProtocolAny
SourceWIREGUARD net
DestinationLAN net
DescriptionAllow WireGuard to LAN

An additional rule may be added to permit DNS access to the pfSense resolver:

FieldValue
ActionPass
InterfaceWIREGUARD
ProtocolTCP/UDP
SourceWIREGUARD net
DestinationWIREGUARD Address
Destination Port Range53
DescriptionAllow DNS from WireGuard

For more details on firewall rule configuration: pfSense Firewall Rules .

Routing

Standard Routing (Split Tunnel)

By default, WireGuard in split tunnel mode routes only traffic destined for subnets specified in AllowedIPs on the client side through the VPN. All other client traffic uses the regular internet connection.

For routing between tunnel subnets and local pfSense networks, additional routes are typically not required, as pfSense automatically adds routes based on interface addressing.

Full Tunnel (All Traffic via VPN)

To route all client traffic through the VPN:

  1. On the client side: set AllowedIPs = 0.0.0.0/0, ::/0 in the WireGuard configuration.
  2. On pfSense: ensure that firewall rules on the WireGuard interface allow internet-bound traffic (Destination: Any).
  3. NAT: configure Outbound NAT for the WireGuard subnet. Navigate to Firewall > NAT > Outbound, switch to Hybrid or Manual mode, and add a rule:
FieldValue
InterfaceWAN
Address FamilyIPv4
ProtocolAny
Source10.10.10.0/24 (tunnel subnet)
DestinationAny
Translation AddressWAN Address

Static Routes

When configuring a site-to-site tunnel, static routes may be required if pfSense is not the default gateway for the subnet behind WireGuard.

Navigate to System > Routing > Static Routes and add a route:

FieldValue
Destination network192.168.2.0/24 (remote subnet)
GatewayWireGuard interface gateway

Warning:

When configuring routing through WireGuard, ensure that the Default gateway in System > Routing is not set to Automatic. Otherwise, pfSense may designate the WireGuard interface as the default gateway, resulting in loss of internet connectivity.

Client Connections

To connect to the WireGuard server on pfSense, a client requires:

  • The server’s (pfSense) public key
  • The server’s public IP address or domain name
  • The WireGuard port on the server
  • The assigned client IP address within the tunnel
  • The Pre-Shared Key (if configured)

Client Configuration Template

WireGuard client configuration uses a unified format across all platforms:

[Interface]
PrivateKey = <private_key_client>
Address = 10.10.10.2/32
DNS = 10.10.10.1

[Peer]
PublicKey = <public_key_pfsense>
PresharedKey = <psk_if_used>
AllowedIPs = 10.10.10.0/24, 192.168.1.0/24
Endpoint = vpn.example.com:51820
PersistentKeepalive = 25

Configuration parameters:

ParameterDescription
PrivateKeyClient private key (generated on the client)
AddressClient IP address in the tunnel (must match Allowed IPs on the server)
DNSDNS server to use while the tunnel is active
PublicKeyServer (pfSense) public key
PresharedKeyPre-Shared Key (optional)
AllowedIPsSubnets routed through the tunnel
EndpointWireGuard server address and port
PersistentKeepaliveKeepalive interval in seconds (required behind NAT)

Windows

  1. Download the WireGuard client from the official website: wireguard.com/install .
  2. Install the application.
  3. Click Add Tunnel > Add empty tunnel or Import tunnel(s) from file.
  4. For manual creation, paste the configuration into the text field. The private key is generated automatically when creating an empty tunnel.
  5. Click Save, then Activate.

When creating an empty tunnel, the application automatically generates a key pair and displays the public key - copy it and add it to the peer settings on pfSense.

macOS

  1. Install WireGuard from the Mac App Store or via Homebrew:
brew install wireguard-tools
  1. GUI client (App Store): import a .conf configuration file or create a tunnel manually through the application interface.

  2. Command line: create a configuration file and activate the tunnel:

# Generate key pair
wg genkey | tee privatekey | wg pubkey > publickey

# Create configuration
sudo mkdir -p /etc/wireguard
sudo nano /etc/wireguard/wg0.conf

# Activate tunnel
sudo wg-quick up wg0

# Check status
sudo wg show

Linux

  1. Install WireGuard:
# Debian / Ubuntu
sudo apt install wireguard

# CentOS / RHEL 8+
sudo dnf install wireguard-tools

# Fedora
sudo dnf install wireguard-tools
  1. Generate a key pair:
wg genkey | tee /etc/wireguard/privatekey | wg pubkey > /etc/wireguard/publickey
chmod 600 /etc/wireguard/privatekey
  1. Create the configuration file /etc/wireguard/wg0.conf:
[Interface]
PrivateKey = <content_of_privatekey>
Address = 10.10.10.2/32
DNS = 10.10.10.1

[Peer]
PublicKey = <public_key_pfsense>
PresharedKey = <psk_if_used>
AllowedIPs = 10.10.10.0/24, 192.168.1.0/24
Endpoint = vpn.example.com:51820
PersistentKeepalive = 25
  1. Tunnel management:
# Activate
sudo wg-quick up wg0

# Deactivate
sudo wg-quick down wg0

# Enable autostart
sudo systemctl enable wg-quick@wg0

# Check status
sudo wg show

iOS

  1. Install the WireGuard application from the App Store.
  2. Tap + and select one of the following options:
    • Create from QR code - scan a QR code containing the configuration (preferred method).
    • Create from file or archive - import a .conf file.
    • Create from scratch - enter parameters manually.
  3. Activate the tunnel using the toggle switch.

Android

  1. Install the WireGuard application from Google Play.
  2. Tap + and select:
    • Scan from QR code - scan a QR code.
    • Import from file or archive - import a .conf file.
    • Create from scratch - enter parameters manually.
  3. Activate the tunnel.

QR Code Generation

For mobile clients, QR codes provide the most convenient setup method. Generate them on Linux or macOS:

# Install qrencode
sudo apt install qrencode    # Debian/Ubuntu
brew install qrencode         # macOS

# Generate QR code from configuration file
qrencode -t ansiutf8 < /path/to/client.conf

# Save QR code as PNG
qrencode -t png -o client-qr.png < /path/to/client.conf

Warning:

The QR code contains the client’s private key. After the client has scanned the code, the PNG file should be deleted. Do not transmit QR codes through unsecured channels (email, messengers without end-to-end encryption).

Site-to-Site Configuration

WireGuard can establish a tunnel between two pfSense locations to interconnect remote networks. Compared to IPsec, site-to-site configuration with WireGuard is considerably simpler and does not require negotiating numerous cryptographic parameters.

Network Diagram

Site A                              Site B
┌─────────────────┐                ┌─────────────────┐
│ LAN: 10.1.0.0/24│                │ LAN: 10.2.0.0/24│
│ WG:  10.10.10.1 │────WireGuard───│ WG:  10.10.10.2 │
│ WAN: 203.0.113.1│                │ WAN: 198.51.100.1│
└─────────────────┘                └─────────────────┘

Site A Configuration

  1. Create a tunnel (VPN > WireGuard > Tunnels):

    • Listen Port: 51820
    • Interface Address: 10.10.10.1/30
    • Generate key pair.
  2. Add a peer (VPN > WireGuard > Peers):

FieldValue
TunnelSite A tunnel
Public KeySite B public key
Endpoint198.51.100.1
Endpoint Port51820
Allowed IPs10.10.10.2/32, 10.2.0.0/24
Keep Alive25
  1. Assign the interface and create firewall rules (as described above).

Site B Configuration

Site B configuration mirrors Site A:

  1. Tunnel: Listen Port 51820, Interface Address 10.10.10.2/30.
  2. Peer: Site A Public Key, Endpoint 203.0.113.1:51820, Allowed IPs 10.10.10.1/32, 10.1.0.0/24.
  3. Interface and firewall: identical to Site A.

Inter-Site Routing

A static route to the remote subnet must be added on each site:

Site A (System > Routing > Static Routes):

FieldValue
Destination10.2.0.0/24
GatewayWireGuard gateway

Site B:

FieldValue
Destination10.1.0.0/24
GatewayWireGuard gateway

If pfSense is the default gateway for all LAN devices, no routes need to be added on client devices. Otherwise, devices on the LAN must have a route to the remote subnet via pfSense.

Connectivity Verification

# From Site A, verify connectivity to Site B LAN
ping 10.2.0.1

# Check WireGuard tunnel status
# On pfSense: Status > WireGuard
# Verify latest handshake timestamp and transferred data

Comparison with IPsec and OpenVPN

When selecting a VPN protocol for pfSense, the characteristics of each should be evaluated.

CharacteristicWireGuardIPsec (IKEv2)OpenVPN
Operating levelKernelKernelUser space
PerformanceHigh (1+ Gbps)High (with AES-NI)Medium (300-500 Mbps)
Connection setup time1-RTT (~100 ms)4 IKEv2 messagesTLS handshake (~500 ms)
Codebase size~4,000 lines~400,000 lines~100,000 lines
AuthenticationKeysPSK / Certificates / EAPCertificates / LDAP / RADIUS
Dynamic client IPsNoYes (Mode Config)Yes (built-in DHCP)
NAT traversalBuilt-inNAT-T (UDP 4500)TCP 443 (bypasses restrictions)
LoggingMinimalDetailedDetailed
CompatibilityLinux, Windows, macOS, iOS, AndroidAll platforms, network equipmentAll platforms
Session managementNoYesYes
pfSense supportPackage (since 2.7)Built-inBuilt-in

When to Choose WireGuard

  • Maximum performance with minimal overhead is required.
  • Small number of clients (up to 50) where manual key management is feasible.
  • Username/password authentication or LDAP/RADIUS integration is not needed.
  • Simplicity and configuration auditability are priorities.

When to Choose IPsec

  • Integration with third-party equipment (Cisco, FortiGate, MikroTik).
  • Compatibility with cloud VPN gateways (AWS VPN, Azure VPN Gateway) is required.
  • Multiple Phase 2 entries for different subnets are needed.
  • More details: IPsec Site-to-Site VPN .

When to Choose OpenVPN

  • LDAP/RADIUS authentication is required.
  • Clients connect from networks with strict restrictions (only TCP 443 is available).
  • Detailed logging and session management are necessary.
  • More details: OpenVPN Remote Access Server .

Troubleshooting

Handshake Not Completing

The most common issue is a failed handshake. Check the status on the Status > WireGuard page.

WireGuard status

Fig. 3. Status > WireGuard page in pfSense

Possible causes:

SymptomCauseResolution
Latest handshake missingPackets not reaching pfSenseVerify the WAN firewall rule and confirm the correct port
Latest handshake missingKey mismatchVerify that the server’s public key is correctly specified in the client configuration and vice versa
Latest handshake missingPSK mismatchVerify that the Pre-Shared Key is identical on both sides
Handshake present, no trafficIncorrect Allowed IPsVerify that Allowed IPs on the server contains the client address, and on the client contains the target subnets
Handshake present, no trafficMissing WireGuard interface rulesAdd rules on the WIREGUARD tab

MTU Issues

WireGuard uses a default MTU of 1420 bytes (with a standard 1500 MTU on the physical interface). WireGuard overhead is 80 bytes for IPv4 (60 bytes WireGuard + 20 bytes outer IPv4 header) and 80 bytes for IPv6.

Symptoms of MTU problems:

  • Ping works but HTTP connections hang.
  • Large file transfers fail.
  • SSH works but SCP/SFTP hangs on large files.

Resolution:

  1. Explicitly set the MTU in the client’s [Interface] section:
[Interface]
PrivateKey = ...
Address = 10.10.10.2/32
MTU = 1420
  1. With additional encapsulation (PPPoE, VLAN, double NAT), reduce the MTU:
ScenarioRecommended MTU
Standard (Ethernet 1500)1420
PPPoE (MTU 1492)1412
Double NAT / CGNAT1400
Behind another VPN tunnel1380

NAT Traversal

WireGuard natively supports operation through NAT. For clients behind NAT to function correctly:

  1. Set PersistentKeepalive = 25 in the client configuration. This forces the client to send keepalive packets every 25 seconds, maintaining an active NAT translation.
  2. On the pfSense side, set Keep Alive to 25 in the peer settings.

Without keepalive, the NAT translation expires (typically after 30-120 seconds), and the server loses the ability to send packets to the client.

Allowed IPs Misconfiguration

Incorrect Allowed IPs settings are the second most common cause of issues:

  • On the server (pfSense): Allowed IPs for each peer must be unique. Two peers cannot have overlapping Allowed IPs. If two peers claim 10.10.10.2/32, traffic will be routed to the most recently added peer.
  • On the client: Allowed IPs determines which traffic is directed into the tunnel. A value of 0.0.0.0/0 routes all traffic, while 10.10.10.0/24, 192.168.1.0/24 routes only traffic to the specified subnets (split tunnel).

Diagnostic Commands

With command-line access to pfSense (SSH or console):

# Check WireGuard interface status
wg show

# Check WireGuard interface details
wg show wg0

# Check routing table
netstat -rn | grep wg

# Check firewall logs for blocked packets
clog /var/log/filter.log | grep 51820

# Check WireGuard kernel module
kldstat | grep if_wg

External Port Accessibility Check

To verify WireGuard port accessibility from an external network, use nmap from another host:

nmap -sU -p 51820 vpn.example.com

A status of open|filtered is normal for WireGuard, as the protocol does not respond to unauthorized packets.

Related Sections

Last updated on