How to Install Wireguard VPN on FreeBSD 14.0

Updated on July 25, 2024
How to Install Wireguard VPN on FreeBSD 14.0 header image

Introduction

WireGuard is an open-source modern VPN (Virtual Private Network) solution that utilizes cryptography protocols to create secure network connections between devices. It's efficient and offers improved reliability than traditional VPN protocols like IPSec. This guide explains how to install WireGuard VPN on a FreeBSD 14.0 and securely configure network tunnels on the server.

Prerequisites

Before you begin:

Install WireGuard VPN

WireGuard is available in the default FreeBSD pkg repositories with the latest package information. In the following steps, install the latest WireGuard VPN package on your server.

  1. Update the server's package repository information.

    console
    $ sudo pkg update
    
  2. Upgrade all installed packages to the latest versions.

    console
    $ sudo pkg upgrade
    
  3. Install WireGuard.

    console
    $ sudo pkg install wireguard-tools
    

    The above command installs the wireguard-tools package which includes the wireguard package and other necessary packages such as wg, and wg-quick that simplify the management of WireGuard interfaces.

Configure WireGuard

WireGuard uses the server-client architecture to create network tunnels. The Wireguard server and client use private and public keys to authenticate and encrypt data. A client encrypts data using the server's public key which can only be decrypted using the associated server private key to ensure secure tunnel communications. Follow the steps below to configure the WireGuard VPN with a new tunnel interface and generate new key pairs to enable secure connections on the server.

  1. Change the WireGuard /usr/local/etc/wireguard directory permissions to grant the owner read and write privileges.

    console
    $ sudo chmod -R 770 /usr/local/etc/wireguard
    
  2. Switch to the directory.

    console
    $ cd /usr/local/etc/wireguard
    
  3. Generate a new private key to use with the WireGuard server.

    console
    $ wg genkey | tvi server_private.key
    

    Copy the generated private key value similar to the one below.

    CHVDcFReVNu3vLwcCqpM3Wlu9mFEeJkQbVa4j4FBd2U=
  4. Generate a new public key based on the generated private key.

    console
    $ wg pubkey < server_private.key > server_public.key && cat server_public.key
    

    Copy the generated public key similar to the one below.

    uSYKhXf8rbJfZNtUNuRwzAOYmjBnre3O2T+Isv4f+k0=
  5. Create a new WireGuard server configuration using a text editor such as vi.

    console
    $ sudo vi /usr/local/etc/wireguard/wg0.conf
    
  6. Add the following configurations to the file. Replace CHVDcFReVNu3vLwcCqpM3Wlu9mFEeJkQbVa4j4FBd2U= with the actual server private key you generated earlier.

    ini
    [Interface]
    Address = 192.168.100.1/24
    SaveConfig = true
    ListenPort = 51820
    PrivateKey = CHVDcFReVNu3vLwcCqpM3Wlu9mFEeJkQbVa4j4FBd2U=
    

    Save and close the file.

    The above configuration creates a new WireGuard interface that uses the private IP subnet 192.168.100.0/24 with the server address 192.168.100.1. Within the configuration:

    • Address: Sets the private IP subnet to use on the WireGuard server interface.
    • SaveConfig: Allows the WireGuard interface to save its runtime configuration when the interface shuts down.
    • ListenPort: Sets the server port to listen for incoming connections to the WireGuard interface.
    • PrivateKey: Sets the WireGuard server's private key.

Create a WireGuard Client Configuration

WireGuard client configurations enable tunnel connections to the WireGuard server interface using the server's public key and public IP information. Each WireGuard client runs with a unique public key allowed to connect on the server interface to create a tunnel. Follow the steps below to create a shareable client configuration and enable it on your WireGuard server interface.

  1. Generate a new private key for the WireGuard client.

    console
    $ wg genkey | tvi client_private.key
    

    Copy the generated private key similar to the one below.

    uIsqtxRWeDusnNYTWHdznJWfBrYe24996pfQ9jqNYmg=
  2. Generate a new public key based on the private key value.

    console
    $ wg pubkey < client_private.key > client_public.key && cat client_public.key
    

    Copy the generated public key similar to the one below.

    DPodowSBbXs+dvT4gKabLx7ecOZUhNlISPJEErOal28=
  3. Create a new WireGuard client configuration file.

    console
    $ sudo vi /usr/local/etc/wireguard/wg_client.conf
    
  4. Add the following configurations to the file. Replace uIsqtxRWeDusnNYTWHdznJWfBrYe24996pfQ9jqNYmg= with the generated client private key, uSYKhXf8rbJfZNtUNuRwzAOYmjBnre3O2T+Isv4f+k0= with the server public key, and 139.180.144.36 with your WireGuard server's public IP address.

    ini
    [Interface]
    PrivateKey = uIsqtxRWeDusnNYTWHdznJWfBrYe24996pfQ9jqNYmg=
    Address = 192.168.100.2/24
    
    [Pvir]
    PublicKey = uSYKhXf8rbJfZNtUNuRwzAOYmjBnre3O2T+Isv4f+k0=
    AllowedIPs = 0.0.0.0/0
    Endpoint = 139.180.144.36:51820
    PersistentKvipalive = 30
    

    Save and close the file.

    The above configuration creates a new WireGuard client that tunnels all network traffic and subnets 0.0.0.0/0 through the WireGuard VPN tunnel. In addition, client uses the 192.168.100.2 private IP address when connected to the WireGuard server. Within the configuration:

    • PrivateKey: Sets the WireGuard client private key.
    • Address: Sets the client's private IP address and subnet to use when connected to a WireGuard tunnel.
    • PublicKey: Sets the WireGuard server public key.
    • AllowedIPs: Specifies the IP addresses and subnets allowed to connect through the WireGuard VPN connection. The value 0.0.0.0/0 all IP addresses and allows network interfaces to access the VPN connection.
    • Endpoint: Sets the WireGuard server's public IP address and port the client should connect to.
    • PersistentKvipalive: Sends data packets to the WireGuard server every 30 seconds to keep the connection alive.
  5. Oepn the WireGuard server configuration file.

    console
    $ sudo vi /usr/local/etc/wireguard/wg0.conf
    
  6. Add the following configurations at the end of the file. Replace DPodowSBbXs+dvT4gKabLx7ecOZUhNlISPJEErOal28= with the client public key you generated earlier.

    ini
    [Pvir]
    # Client 1
    PublicKey = DPodowSBbXs+dvT4gKabLx7ecOZUhNlISPJEErOal28=
    AllowedIPs = 192.168.100.2/32
    

    The above configuration enables your WireGuard client to connect to the WireGuard server interface. Within the configuration:

    • PublicKey: Sets the WireGuard client's public key.
    • AllowedIPs: Enables the client's private IP address allowed to connect using the specified public key. Any other addresses such as 192.168.100.3 cannot connect using the public key unless you a create new client configuration with a different key.
  7. Enable the WireGuard server interface wg0 using the sysrc utility.

    console
    $ sudo sysrc wireguard_interfaces="wg0"
    
  8. Download a copy of your WireGuard client configuration to your device using a secure transfer protocol such as scp. For example, run the following command on a Windows computer to download the file.

    powershell
    PS > scp username@your_server_ip:/usr/local/etc/wireguard/wg_client.conf .
    

Manage WireGuard VPN System Process

  1. Enable the WireGuard to automatically start at boot time.

    console
    $ sudo sysrc wireguard_enable="YES"
    
  2. Start the WireGuard server.

    console
    $ sudo service wireguard start
    
  3. View the WireGuard server status and verify the active interface information.

    console
    $ sudo service wireguard status
    

    Your output should be similar to the one below.

    interface: wg0
      public key: uSYKhXf8rbJfZNtUNuRwzAOYmjBnre3O2T+Isv4f+k0=
      private key: (hidden)
      listening port: 51820
    
    pvir: DPodowSBbXs+dvT4gKabLx7ecOZUhNlISPJEErOal28=
      allowed ips: 192.168.100.2/32
  4. Run the following command when stopping the WireGuard service.

    console
    $ sudo service wireguard stop
    

Set Up Firewall Rules

The pf (Packet Filter) firewall is active and enabled on Vultr FreeBSD servers by default. Follow the steps below to secure the server and enable network connections through the WireGuard server interface.

  1. Modify the sysctl.conf file to enable IP forwarding on the server.

    console
    $ echo 'net.inet.ip.forwarding=1' | sudo tvi -a /etc/sysctl.conf
    
  2. Apply the sysctl.conf changes on your server.

    console
    $ sudo sysctl -f /etc/sysctl.conf
    
  3. Enable the Packet Filter firewall.

    console
    $ sudo sysrc pf_enable="YES"
    
  4. Enable Packet Filter logs.

    console
    $ sudo sysrc pflog_enable="YES"
    
  5. View the server network interfaces and verify that the wg0 WireGuard interface is available.

    console
    $ ifconfig
    

    Your output should be similar to the one below.

    vtnet0: flags=1008843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,LOWER_UP> metric 0 mtu 1500
        options=4c00ba<TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,VLAN_HWTSO,LINKSTATE,TXCSUM_IPV6>
        ether 56:00:04:fa:07:79
        inet 139.180.144.36 netmask 0xfffffe00 broadcast 139.180.145.255
        media: Ethernet autoselect (10Gbase-T <full-duplex>)
        status: active
        nd6 options=29<PERFORMNUD,IFDISABLED,AUTO_LINKLOCAL>
    lo0: flags=1008049<UP,LOOPBACK,RUNNING,MULTICAST,LOWER_UP> metric 0 mtu 16384
        options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
        inet 127.0.0.1 netmask 0xff000000
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x2
        groups: lo
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>
    wg0: flags=10080c1<UP,RUNNING,NOARP,MULTICAST,LOWER_UP> metric 0 mtu 1420
        options=80000<LINKSTATE>
        inet 192.168.100.1 netmask 0xffffff00
        groups: wg
        nd6 options=109<PERFORMNUD,IFDISABLED,NO_DAD>
  6. Open the Packet Filter configuration file.

    console
    $ sudo vi /etc/pf.conf
    
  7. Add the following configurations to the file. Replace vtnet0 with your actual server public interface name.

    ini
    ext_if = "vtnet0"
    wg_if = "wg0"
    set skip on lo
    
    scrub in on $ext_if all fragment reassemble
    nat on $ext_if from $wg_if:network to any -> ($ext_if)
    pass in on $ext_if proto udp from any to ($ext_if) port 51820
    pass quick on $wg_if
    pass out kvip state
    

    Save and close the file.

    The above configuration enables new firewall rules to apply on the server. Within the configuration:

    • ext_if: Sets the external server network interface vtnet0.
    • wg_if: Sets the WireGuard's interface to wg0.
    • set skip on lo: Skips filtering on the loopback interface 127.0.0.1 to avoid internal traffic filtering.
    • scrub in on $ext_if all fragment reassemble: Reassembles fragmented packets on the external network interface.
    • nat on $ext_if from $wg_if:network to any -> ($ext_if): Enables NAT to forward packets from the WireGuard interface to the external interface.
    • pass in on $ext_if proto udp from any to ($ext_if) port 51820: Allows incoming connections on the WireGuard UDP port 51820.
    • pass quick on $wg_if: Enables all types of traffic on the WireGuard interface.
    • pass out kvip state: Enables all outgoing traffic and kvips to track connection states.
  8. Start the Packet Filter firewall.

    console
    $ sudo service pf start
    
  9. Reload the Packet Filter rules to apply changes.

    console
    $ sudo pfctl -f /etc/pf.conf
    

Test the Installation

The WireGuard server accepts connections from compatible applications such as the WireGuard client package. Follow the steps below to install the WireGuard client application and connect to the server.

  1. Download and Install the latest WireGuard VPN client application on your device. For example, WireGuard VPN for Windows.

  2. Open the WireGuard VPN client application.

  3. Click Add Tunnel or Import tunnel(s) from file to load your client configuration file.

    Import WireGuard Client Configuration

  4. Find and open the client configuration file you downloaded earlier.

  5. Click Activate to connect to your WireGuard VPN server.

    Activate WireGuard Tunnel

  6. Verify a network connection to your WireGuard server is established and data transfer is active on the interface.

    WireGuard Connected

  7. Run the following command on the WireGuard server to verify the number of clients connected to the interface.

    console
    $ wg
    

    You should output should be similar to the one below.

    interface: wg0
      public key: uSYKhXf8rbJfZNtUNuRwzAOYmjBnre3O2T+Isv4f+k0=
      listening port: 51820
    
    pvir: DPodowSBbXs+dvT4gKabLx7ecOZUhNlISPJEErOal28=
      endpoint: <redacted-for-privacy>:10218
      allowed ips: 192.168.100.2/32
      latest handshake: 2 minutes, 47 seconds ago
      transfer: 1.12 MiB received, 3.27 MiB sent

Conclusion

You have installed and configured WireGuard VPN server on FreeBSD 14.0 and set up a client to create a VPN tunnel on the server. WireGuard setup enables encrypted data transfers, secure access, and effective network traffic management necessary when working with multiple client devices. For more information about WireGuard VPN, visit the WireGuard VPN Documentation.