Synopsis #
WireGuard associates peers with public keys and AllowedIPs. On transmit, AllowedIPs selects the peer for a destination; on receive, it also limits which source addresses that peer may use. A broad value such as 0.0.0.0/0 can replace the default route when wg-quick brings up the interface.
This procedure builds only a private routed subnet between two peers. It does not turn either peer into a default-route VPN gateway. Forwarding, NAT, DNS replacement, and public service exposure are separate policy decisions.
Define the two peers #
The examples use:
| Peer | Tunnel address | Endpoint |
|---|---|---|
| Server | 10.77.0.1/24 | Public UDP port 51820 |
| Client | 10.77.0.2/24 | Dynamic or private address |
Confirm that 10.77.0.0/24 does not overlap LAN, jail, cloud, or other VPN routes. Record the server’s receiving interface and public address before changing PF.
Install tools and create keys #
Install the WireGuard management tools on both peers:
# pkg install wireguard-tools
# install -d -m 700 /usr/local/etc/wireguard
# sh -c 'umask 077; wg genkey > /usr/local/etc/wireguard/private.key'
# sh -c 'wg pubkey < /usr/local/etc/wireguard/private.key > /usr/local/etc/wireguard/public.key'
$ cat /usr/local/etc/wireguard/public.key
Exchange only public keys. Never paste private keys into a ticket, command history, or diagnostic output. Restrict each final configuration file to root.
Create the server configuration #
Create /usr/local/etc/wireguard/wg0.conf with the server private key and client public key substituted locally:
[Interface]
Address = 10.77.0.1/24
PrivateKey = SERVER_PRIVATE_KEY
ListenPort = 51820
[Peer]
PublicKey = CLIENT_PUBLIC_KEY
AllowedIPs = 10.77.0.2/32
Protect the file:
# chmod 600 /usr/local/etc/wireguard/wg0.conf
PF must admit UDP 51820 only on the intended server address and interface. Add that narrow rule through the method in Change PF safely on a remote host . No forwarding or NAT is required for traffic whose endpoint is the server itself.
Create the client configuration #
Create the same path on the client:
[Interface]
Address = 10.77.0.2/24
PrivateKey = CLIENT_PRIVATE_KEY
[Peer]
PublicKey = SERVER_PUBLIC_KEY
AllowedIPs = 10.77.0.0/24
Endpoint = vpn.example.net:51820
PersistentKeepalive = 25
The keepalive is useful when the client is behind stateful NAT. It is not normally necessary for a peer with a stable directly reachable address.
Start and verify manually #
Bring up the server and then the client:
# wg-quick up wg0
$ ifconfig wg0
# wg show wg0
$ netstat -rn
Verify that no default route was replaced and that the only new route covers the intended tunnel prefix. From the client:
$ ping -c 3 10.77.0.1
# wg show wg0
The latest handshake and transfer counters establish WireGuard state. A configured interface without a recent handshake does not prove endpoint reachability.
When the tested configuration should start at boot:
# sysrc wireguard_enable=YES
# sysrc wireguard_interfaces=wg0
# service wireguard restart
Use the rc script installed by the selected wireguard-tools package. Do not combine that script, hand-created cloned interfaces, and another network manager unless their ownership has been designed explicitly.
Extend routing separately #
Access to another LAN or jail network requires all of the following: a matching AllowedIPs entry, a route on the opposite peer, IP forwarding on the routing host, a PF policy that permits the flow, and a valid return route or deliberate NAT. Add these controls as a separate change and diagnose them with Diagnose DNS, routing, and firewall paths
.