IPv4 & IPv6 Leasing - Any RIR, Any LocationOrder Now
Hostperl

FreeBSD WireGuard Routing for VPS Connectivity Troubleshooting

By Raman Kumar

Share:

Updated on Sep 10, 2026

FreeBSD WireGuard Routing for VPS Connectivity Troubleshooting

What this FreeBSD WireGuard routing tutorial solves

If your FreeBSD VPS can reach the internet but remote services are still unreachable, the problem is usually routing, firewall rules, or a tunnel that never came up cleanly. This tutorial shows you how to build a production-safe WireGuard tunnel on FreeBSD, route traffic through it, and verify each layer before you rely on it for customer access or support work.

The result is practical. You will install the right packages, create a non-root admin, bring up a WireGuard interface, add routes, allow the tunnel through pf, and test both the tunnel and the public path. If you are sizing a new platform for this kind of work, a Hostperl VPS gives you a clean base for network troubleshooting, migrations, and secure remote administration.

Primary search intent: configure and troubleshoot FreeBSD WireGuard routing on a VPS.
Focus keyword: FreeBSD WireGuard routing
Semantic variants: FreeBSD VPN routing, WireGuard on FreeBSD, tunnel diagnostics, pf firewall rules, VPS connectivity troubleshooting.

Prerequisites and support limits

  • FreeBSD 14.1-RELEASE or newer.
  • Root SSH access to the VPS.
  • Two public IPs or one public IP plus one private tunnel subnet for testing.
  • WireGuard support from your provider or kernel module package availability on the release you are using.

This guide is for FreeBSD only. The commands below do not apply to Linux, Windows Server, or appliances with their own network stack. If you need a broader VPS preparation baseline after this tunnel is working, Hostperl customers often pair it with the Linux maintenance checklist for VPS in 2026 for the Linux side of mixed environments, and with regional hosting guidance for agencies when routing matters to clients in APAC or nearby markets.

Connect to the VPS and confirm FreeBSD

On your local computer: connect with the reserved example address first, then replace it with your real server IP.

ssh root@203.0.113.10

Here, 203.0.113.10 is a documentation example. Replace it with the public IP assigned to your FreeBSD VPS. If your provider uses a different SSH port, use that port in the same pattern.

On the VPS as root: confirm the platform before you touch packages or firewall rules.

freebsd-version

You should see a FreeBSD release string such as 14.1-RELEASE. That confirms you are on the intended system.

Create a non-root admin for FreeBSD WireGuard routing work

Keep the original root session open until the new login works. That gives you a safe fallback if the SSH key step fails.

On the VPS as root:

adduser

Create the account named deploy, choose a strong password if you need local console fallback, and add it to the wheel group when prompted. On FreeBSD, wheel membership is the normal path for sudo-like administration.

Install sudo if it is not already present, then grant access explicitly.

pkg update -f
pkg install -y sudo

Now add deploy to sudoers safely.

visudo

Add this line at the end of the file:

deploy ALL=(ALL) ALL

Save and exit. Next, create SSH keys for the new account.

mkdir -p /home/deploy/.ssh
chmod 700 /home/deploy/.ssh
cp /root/.ssh/authorized_keys /home/deploy/.ssh/authorized_keys
chown -R deploy:deploy /home/deploy/.ssh
chmod 600 /home/deploy/.ssh/authorized_keys

This reuses the working key so you can test the account without changing your workstation setup.

On your local computer: open a second terminal and test the new login.

ssh deploy@203.0.113.10

After you log in, confirm sudo works.

sudo -i
whoami
exit

You should see root after sudo -i. Only after this works should you consider disabling root SSH login in your final hardening step.

Install WireGuard and the tools you need

On the VPS as root: install the tunnel package, packet tools, and pf utilities you will use for testing.

pkg update -f
pkg install -y wireguard-tools tcpdump pf

Verify the binaries are present before you continue.

wg --version
sysctl net.inet.ip.forwarding

The version output confirms WireGuard tools are installed. The forwarding check matters because route tests fail if forwarding is off.

Enable IPv4 forwarding now, and keep it persistent.

sysctl net.inet.ip.forwarding=1
sysrc gateway_enable="YES"
echo 'net.inet.ip.forwarding=1' >> /etc/sysctl.conf

The immediate sysctl takes effect now, and the sysrc line keeps routing active after reboot.

Create the WireGuard interface and keys

Use a dedicated directory for tunnel files. FreeBSD does not need a sprawling layout for one interface, and keeping everything together makes support work easier later.

On the VPS as root:

install -d -m 700 /usr/local/etc/wireguard
wg genkey | tee /usr/local/etc/wireguard/server.key | wg pubkey > /usr/local/etc/wireguard/server.pub
chmod 600 /usr/local/etc/wireguard/server.key /usr/local/etc/wireguard/server.pub
cat /usr/local/etc/wireguard/server.pub

Copy the public key output now. You will need it for the peer configuration. A successful run prints one WireGuard public key line.

If your remote peer is another VPS or a workstation, generate its key pair on that device now and note its public key. For this tutorial, the tunnel network will use 10.44.0.0/24, with the FreeBSD server at 10.44.0.1.

Write the WireGuard configuration

On the VPS as root: create the interface file.

vi /usr/local/etc/wireguard/wg0.conf

Insert this complete example, replacing the peer public key and allowed IPs with your real values:

[Interface]
PrivateKey = REPLACE_WITH_CONTENTS_OF_/usr/local/etc/wireguard/server.key
Address = 10.44.0.1/24
ListenPort = 51820
SaveConfig = false

[Peer]
PublicKey = REPLACE_WITH_PEER_PUBLIC_KEY
AllowedIPs = 10.44.0.2/32

Save and exit. The server listens on UDP port 51820, and the peer is allowed only the tunnel IP shown above.

Load the private key into the file without leaving it exposed in shell history.

sed -i '' "s|REPLACE_WITH_CONTENTS_OF_/usr/local/etc/wireguard/server.key|$(cat /usr/local/etc/wireguard/server.key)|" /usr/local/etc/wireguard/wg0.conf

If you prefer, you can paste the key manually with vi instead of using sed. The final file must contain the actual key text, not the filename.

Open pf for the tunnel before bringing it up

Do not start the tunnel and then discover the firewall blocks it. Add the pf rule first, then enable or reload pf.

On the VPS as root: back up the current pf file before editing it.

cp /etc/pf.conf /etc/pf.conf.bak

Edit /etc/pf.conf and add rules similar to these near the top, above any blocking policy:

ext_if = "vtnet0"
wg_if = "wg0"
set skip on lo
pass in on $ext_if proto udp to ($ext_if) port 51820 keep state
pass on $wg_if all keep state

If your NIC is not vtnet0, replace it with the name from ifconfig. That is the most common mismatch on VPS platforms.

Validate the pf syntax before loading it.

pfctl -nf /etc/pf.conf

No output means the file parses cleanly. Then load the rules and enable pf at boot.

service pf restart
sysrc pf_enable="YES"

Bring the tunnel up and make it persistent

On the VPS as root: create the FreeBSD rc.conf entries for WireGuard.

sysrc wireguard_enable="YES"
sysrc wireguard_interfaces="wg0"
service wireguard start

Check the interface state immediately.

ifconfig wg0
wg show

You should see the wg0 interface with 10.44.0.1/24 and a peer entry once the remote side connects. If the peer never appears, the tunnel path is incomplete or the key is wrong.

Configure the remote peer and test routing

On your workstation or the second VPS, create a peer config that points to the FreeBSD server public IP and the UDP port you opened. Example only:

[Interface]
PrivateKey = REPLACE_WITH_PEER_PRIVATE_KEY
Address = 10.44.0.2/32

[Peer]
PublicKey = REPLACE_WITH_SERVER_PUBLIC_KEY
Endpoint = 203.0.113.10:51820
AllowedIPs = 10.44.0.0/24
PersistentKeepalive = 25

Once both ends are configured, bring the peer up and test the path.

ping -c 3 10.44.0.1

If you need to route a private subnet through the FreeBSD box, add the subnet to AllowedIPs on the peer and the matching routes on the FreeBSD side. Keep the route scope tight. Do not advertise your entire LAN unless that is truly required.

If you are building a business-critical service path, this is the point where Hostperl customers usually document the route and failover plan. That is also where remote hands and cross-connect planning become relevant for hardware you own in a rack, while FreeBSD colocation migrations help when the tunnel is part of a move between facilities.

Confirm packet flow, ports, and latency

On the VPS as root: verify that UDP 51820 is listening.

sockstat -4 -l | grep 51820

You should see wireguard or the relevant process bound to the UDP port. Then watch the wire while you ping from the peer.

tcpdump -ni vtnet0 udp port 51820

If you see inbound packets but no handshake in wg show, the usual causes are wrong keys, wrong endpoint IP, or a firewall rule on the peer side. If you see no packets at all, the provider security group or remote firewall is blocking the UDP port.

Run a latency test across the tunnel from the peer.

ping -c 5 10.44.0.1

For a routed subnet, test the first host in the target network as well. Consistent loss means your route path needs correction before you move any customer traffic.

Rollback and recovery if you lose access

If the tunnel breaks your access path, reverse the changes in the same order you added them.

On the VPS as root:

service wireguard stop
sysrc -x wireguard_enable
sysrc -x wireguard_interfaces
pfctl -f /etc/pf.conf.bak
cp /etc/pf.conf.bak /etc/pf.conf
service pf restart

If you also changed SSH policy, restore that from your original session before closing anything. Keeping the root shell open until the new login is proven is the simplest rollback safety net.

Final verification from server and client

On the VPS as root: confirm services and persistence.

service wireguard status
service pf status
ifconfig wg0
wg show
sysrc wireguard_enable
sysrc pf_enable

On your local computer or remote peer:

ping -c 3 10.44.0.1

If you are forwarding a route through the tunnel, test an application port on the next hop, not just ICMP. A working ping with a dead application port still means the job is unfinished.

Troubleshooting the most common failures

1. No handshake appears in wg show.
Diagnostic:

wg show
sockstat -4 -l | grep 51820
tail -n 50 /var/log/messages

Expected clue: either no listener on UDP 51820, or no packets arrive. Corrective action: check the peer public key, endpoint address, firewall rules, and provider network filter.

2. The interface starts, but pings fail.
Diagnostic:

ifconfig wg0
route -n get 10.44.0.2
pfctl -sr | grep 51820

Expected clue: the route may point the wrong way, or pf may block the subnet. Corrective action: fix the AllowedIPs value and confirm pf passes traffic on wg0.

3. The service does not start after reboot.
Diagnostic:

sysrc -a | grep wireguard
service wireguard onestatus
cat /usr/local/etc/wireguard/wg0.conf

Expected clue: a missing rc.conf entry or a malformed config file. Corrective action: restore the exact sysrc values and re-check the file syntax by comparing against a known good copy.

Hostperl VPS plans are a practical fit for tunnel work like this because you need stable networking, predictable latency, and responsive support when routes misbehave. If you are planning a VPS build around VPN access, remote administration, or customer migrations, start with Hostperl VPS hosting and keep your rollback path documented from day one.

For teams that want extra capacity or stricter infrastructure control, Hostperl also provides dedicated options that fit heavier routing and multi-site access patterns.

FAQ

Can I use this on a FreeBSD jail?
Usually not for the host-side tunnel setup. Run WireGuard on the FreeBSD host unless your jail architecture explicitly supports the networking features you need.

Should I expose WireGuard on the default port?
Port 51820 is common, but any UDP port works. Use the one your security policy and provider firewall allow.

Why does the tunnel connect but not route traffic?
That usually means the interface is fine, but forwarding, pf rules, or AllowedIPs are wrong.

What should I check first during an incident?
Check wg show, then pfctl -sr, then tcpdump on the external NIC. That order usually finds the fault fastest.