VPN as exit point
Selecting a VPN provider
Very few VPN providers allow to use WireGuard with a manual configuration, they usually force you to use their own binary utilities. One exception (I haven’t looked for others) is Mullvad, which allows you to download raw configuration file.
Further more it give you a web API to check the state of your connection:
curl https://am.i.mullvad.net/connected # Plain text connection status curl https://am.i.mullvad.net/ip # IP used for connection curl https://am.i.mullvad.net/json # Full connection description
Configuration
Create VPN interface vpn0:
- it’s a renamed cloned WireGuard interface
- created on a dedicated empty routing table (fib 1)
- associated to group
vpnfor easy management from the firewall
cloned_interfaces="wg0" # Clone wireguard interface create_args_wg0="group vpn fib 1" # Associate wg0 to fib 1 and group vpn ifconfig_wg0_name="vpn0" # Rename wg0 to vpn0
Now we need to generate a key pair that will be used for requesting a configuration for our device.
wg genkey | tee device.key | wg pubkey > device.pubkey
Once the configuration information has been retrieved, it will be used to configure FreeBSD startup scripts.
In the case of Mullvad, the configuration can be generated here:
And you will get something like:
[Interface] PrivateKey = ...........censored.private.key............. Address = 198.51.100.7/32,fd00:2001:db8::2/128 DNS = 198.51.100.53 [Peer] PublicKey = ............censored.public.key............. AllowedIPs = 0.0.0.0/0,::0/0 Endpoint = 198.51.100.1:51820
Note that the configuration is generated such that:
- IPv4 and IPv6 assigned addresses are tight to the interface key
- Each endpoint address have a different key
The Address and DNS fields are not used/understood by wg setconf,
and will need to be stripped down from the configuration for later use with it,
using for example:
grep -Ev '^(DNS|Address)' > /etc/wireguard/vpn0.conf
These removed fields will need to be used in other configuration parts:
Address- will be used directly by
ifconfigin/etc/rc.conf DNS- can be used in
resolv.confto rely on the VPN provided DNS server to avoid DNS leak to your ISP… but if you are already using your own DNS that can be unnecessary
Interface vpn0 is initialized with the IP addresses that have
been allocated for it on the VPN server side:
ifconfig_vpn0_descr="WireGuard VPN interface" ifconfig_vpn0="inet 198.51.100.7/32" ifconfig_vpn0_ipv6="inet6 fd00:2001:db8::2/128"
The directive defaultif is not supported
by the interface, it will not be possible to use it to
indicate that we want to be the route by default if none
are present. So we need to add a default route ourselves:
# Define the route by default on the fib 1 routing table as being our vpn route_vpn0_default="-iface vpn0 -fib 1" # Adding vpn0_default to the list of static routes static_routes="... vpn0_default ..."
As FreeBSD integration with WireGuard has been delayed to 13.1
release, we will need to rely on /etc/rc.local and
/etc/rc.shutdown.local to perform additional configuration
steps that can’t be performed yet in /etc/rc.conf:
When using wg setconf, only the following fields are allowed in the
configuration file:
| Section | Fields |
|---|---|
Interface |
PrivateKey, ListenPort, FwMark |
Peer |
PublicKey, PresharedKey, AllowedIPs, Endpoint, PersistentKeepalive |
# Set initiale interface configuration /usr/local/bin/wg setconf vpn0 /etc/wireguard/vpn0.conf
# Synchronize interface configuration on shutdown /usr/local/bin/wg syncconf vpn0 /etc/wireguard/vpn0.conf
Incoming VPN
Server configuration
wg genkey | tee server.key | wg pubkey > server.pubkey
$ cat server.key AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0= $ cat server.pubkey BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB1=
# Incoming VPN
wg set vpn0 \
listen-port 51820 \
private-key /etc/wireguard/server.key
If you have firewall, you will need to tailor the following configuration fragment to your need:
scrub in on vpn0 all # Reassemble fragments to avoid ambiguities antispoof quick for vpn0 # Basic antispoofing rules pass in on vpn0 # Allows incoming traffic # If being a NAT and you want to give access to other network ressources nat pass on interface to gateway inet from (vpn0:network) to any -> interface to gateway
Generating device configuration
This will need to be done for each device that is allowed to connect to the VPN
-
Create a key pair
Generate private/public key pair wg genkey | tee device.key | wg pubkey > device.pubkey
$ cat device.key CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC2= $ cat device.pubkey DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD3=
-
Create the configuration file. Here the peer is the server to which we will connect to establish the VPN connection, and we will allow routing all the traffic to the VPN (look for:
0.0.0.0/0,::0/0)[Interface] PrivateKey = Interface private key Address = Device allocated IP DNS = DNS considered to be privacy safe [Peer] PublicKey = Peer public key AllowedIPs = 0.0.0.0/0,::0/0 Endpoint = 1.2.3.4:51820
-
Generate a QR-code (optional).
QR-code allows easy integration with android WireGuard application, which can be found on:
- F-Droid: https://f-droid.org/en/packages/com.wireguard.android/
- Play Store: https://play.google.com/store/apps/details?id=com.wireguard.android
Generate QR-code from config file qrencode -t ansiutf8 < device.conf -
Add device peer to the server.
You usually want to restrict the
allowed-ipsto the same set of addresses defined inAddressin the client configuration file.Adding peer to the server side wg set vpn0 peer Peer public key \ allowed-ips Device allocated IP
FAQ
wg genkey | tee device.key | wg pubkey > device.pubkey