FreeBSD: How to Set Up a Simple and Actually Working Wireguard Server
In my quest to get a Wireguard setup working, I have come across many guides and tutorials. All of them were missing crucial information or operating off outdated information. Often just subtle instructions are broken. In a cascade with other points of potential failure, this quickly becomes a frustrating game of whack-a-mole with lots of dead ends.
That being said, here’s a minimal setup that works, as of today, on a Raspberry Pi 3 with a single Ethernet connection, running FreeBSD 13.2.
First off, install the required software:
pkg install wireguard wireguard-tools libqrencode
Enable Wireguard service:
service wireguard enable sysrc wireguard_interfaces="wg0"
Enable IP forwarding and activate it immediately:
sysrc gateway_enable=YES sysctl -w net.inet.ip.forwarding=1
Set up firewall and logging:
service pf enable service pflog enable
# /etc/pf.conf ext_if="ue0" wg_net="10.10.10.0/24" scrub in all nat on $ext_if from $wg_net to any -> ($ext_if) pass log all
service pf start service pflog start
Then generate the server keys:
cd /usr/local/etc/wireguard/ umask 077 wg genkey | tee /usr/local/etc/wireguard/server_private.key | wg pubkey | tee /usr/local/etc/wireguard/server_public.key
You’re going to need client keys as well. This example assumes an iPhone for naming but the process is the same for any client:
cd /usr/local/etc/wireguard/ umask 077 wg genkey | tee /usr/local/etc/wireguard/iphone_private.key | wg pubkey | tee /usr/local/etc/wireguard/iphone_public.key wg genpsk > iphone_preshared.key
Create the server configuration:
# /usr/local/etc/wireguard/wg0.conf [Interface] Address = 10.10.10.1/32 # address the server will bind to ListenPort = 51820 PrivateKey = your-private-server-key-here [Peer] AllowedIPs = 10.10.10.2/32 PreSharedKey = your-preshared-client-key PublicKey = your-public-client-key
Create the client configuration:
# /usr/local/etc/wireguard/wg_iphone.conf [Interface] PrivateKey = your-private-client-key Address = 10.10.10.2/32 DNS = 126.96.36.199 # optional, useful to avoid DNS leaks [Peer] PublicKey = your-public-server-key PreSharedKey = your-preshared-client-key AllowedIPs = 0.0.0.0/0 # entire Internet Endpoint = your-external-ip-or-host:51820 PersistentKeepalive = 30
For additional clients, repeat the key generation with different filenames.
Then add another
[Peer] section with a unique IP and the clients’ key
contents to the server configuration. Also create a respective client
configuration. Restart Wireguard after you have changed the server
To ease transfer to iPhone, generate a QR code and import via camera in the Wireguard app:
qrencode -t ansi < wg_iphone.conf
Start the Wireguard service:
service wireguard start
You should now be able to connect successfully with the iPhone and reach both your internal network as well as the internet.
A couple of notes:
- Remember to set up port forwarding in your router if you do this at home. Wireguard exclusively uses UDP.
- DNS could be a local server like Adguard Home. This is what I do. This way you get comprehensive ad blocking everywhere.
- If you run into issues, first reboot the machine. If things still won’t work,
inspect the connection logs with
tcpdump -n -e -i pflog0.
- In almost all cases when connections do not work, you either forgot to set up IP forwarding, have other firewall rules in place that interfere or the NAT rule is wrong.
- I have found handshake reliability to be flaky. You may need to stop and start the client connection multiple times for it to work.