How to set up Wireguard VPN on CentOS 8

Wireguard is an open-source cross-platform VPN implementation that uses state of the art cryptography. It is faster, simpler and more functional than IPSec and OpenVPN protocols. It is designed as a general-purpose VPN to run on embedded interfaces and supercomputers and runs on Linux, Windows, macOS, iOS, Android, BSD and various other platforms.

This tutorial will cover how to install Wireguard VPN on a CentOS 8 based server and to connect to it using a Linux(CentOS/Fedora/Ubuntu) client.

Step 1 - Update System

Before proceeding any further, it's imperative to update your system to install the latest updates.

$ sudo dnf update

Step 2 - Install and Enable EPEL repo

The required Wireguard packages can be found in the EPEL repository so we need to install and enable it.

$ sudo dnf install epel-release
$ sudo dnf config-manager --set-enabled PowerTools

We also enabled the PowerTools repository since EPEL packages depend on it.

Step 3 - Install Wireguard

Enable the Wireguard repository.

$ sudo dnf copr enable jdoss/wireguard

Install Wireguard.

$ sudo dnf install wireguard-dkms wireguard-tools

This step also installs GNU GCC compiler needed to build the Linux Kernel modules.

Step 4 - Configure Wireguard Server

Create an empty configuration file on the server for Wireguard settings with proper permissions.

$ sudo mkdir /etc/wireguard
$ sudo sh -c 'umask 077; touch /etc/wireguard/wg0.conf'

Touch command creates the file wg0-server.conf file in the /etc/wireguard directory.

Next, create a private/public key pair for the Wireguard server.

$ cd /etc/wireguard
$ sudo sh -c 'umask 077; wg genkey | tee privatekey | wg pubkey > publickey'

This creates both public and private key for the Wireguard and writes them to the respective files.

View the private key that we just created.

$ sudo cat privatekey

Note the key and copy it because we will need it to configure Wireguard.

Next, edit the configuration file.

$ sudo nano /etc/wireguard/wg0.conf

Add the following code.

[Interface]
## VPN server private IP address ##
Address = 192.168.10.1/24
 
## VPN server port - You can choose any port ##
ListenPort = 37822
 
## VPN server's private key i.e. /etc/wireguard/privatekey - the one from above ##
PrivateKey = GCEXafeZKqSsuLfvuHE+zLzMYwoH4qQyBh7MZ4f/3kM=
 
## Save and update this config file when a new peer (vpn client) added ##
SaveConfig = true

Each configuration has one section called [Interface] where the server-part is defined.

It contains the private key of the local WireGuard server, the UDP port it should listen for incoming connections and its own VPN IP addresses.

We also set SaveConfig to true. This will tell the Wireguard service to automatically save its active configuration to this file at shutdown.

Press Ctrl + W to close the file and enter Y when prompted to save the file.

Step 5 - Configure Firewall

We need to open the port we chose for Wireguard.

First, we need to define Wireguard service for the firewall. To do that, create a file wireguard.xml with the Nano editor.

$ sudo nano /etc/firewalld/services/wireguard.xml

Paste the following code in the file.

<?xml version="1.0" encoding="utf-8"?>
<service>
  <short>wireguard</short>
  <description>WireGuard open UDP port 37822 for client connections</description>
  <port protocol="udp" port="37822"/>
</service>

Press Ctrl + W to close the file and enter Y when prompted to save the file.

Next, enable the Wireguard service in the firewall.

$ sudo firewall-cmd --permanent --add-service=wireguard

Turn on masquerading so all traffic coming and going out from 192.168.10.0/24 routed via our public IP address of the server 203.1.114.98/24.

$ sudo firewall-cmd --permanent --add-masquerade

Finally, reload the firewall to activate the rules.

$ sudo firewall-cmd --reload

List the current firewall rules to confirm.

$ sudo firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: eth0
  sources: 
  services: wireguard ssh
  ports: 
  protocols: 
  masquerade: yes
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

Step 6 - Turn on IPv4 Forwarding

Create /etc/sysctl.d/99-custom.conf file.

$ sudo nano /etc/sysctl.d/99-custom.conf

Paste the following code in the file.

## Turn on bbr ##
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
 
## for IPv4 ##
net.ipv4.ip_forward = 1
 
## Turn on basic protection/security ##
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.tcp_syncookies = 1

## for IPv6 ##
net.ipv6.conf.all.forwarding = 1

Press Ctrl + W to close the file and enter Y when prompted to save the file.

The scope of the code in the file above is outside the scope of this tutorial so for now, just use it as it is.

Reload the changes.

$ sudo sysctl -p /etc/sysctl.d/99-custom.conf

By default, the firewall won't let wg0 and eth0 interfaces talk to each other. So we need to add the Wireguard interface to the internal network and turn on masquerading.

$ sudo firewall-cmd --add-interface=wg0 --zone=internal
$ sudo firewall-cmd --permanent --zone=internal --add-masquerade

Step 7 - Enable and Start the Wireguard Service

Next, we need to enable and start the Wireguard service.

$ sudo systemctl enable wg-quick@wg0
$ sudo systemctl start wg-quick@wg0

You can verify if the Wireguard interface, wg0 is up and running by using the following command.

$ sudo wg
interface: wg0
  public key: VWndJ4oB7ZJwC/7UOm++OLDrbAxMPsR2yd0cl3sEkUI=
  private key: (hidden)
  listening port: 37822

$ sudo ip a show wg0
3: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN group default qlen 1000
    link/none
    inet 192.168.10.1/24 scope global wg0
       valid_lft forever preferred_lft forever

Step 8 - Install and Configure WireGuard Client

You can find the install instructions for Wireguard client for your Linux distribution from their official install page.

Once you install the client, you need to create the client configuration file.

$ sudo mkdir /etc/wireguard
$ sudo sh -c 'umask 077; touch /etc/wireguard/wg0.conf'
$ cd /etc/wireguard/
$ sudo sh -c 'umask 077; wg genkey | tee privatekey | wg pubkey > publickey'
$ sudo cat privatekey

Note the private key you get at the end. Next, we need to edit the configuration file we just created.

$ sudo nano /etc/wireguard/wg0.conf

Add the following directives to the file.

[Interface]
## client private key ##
PrivateKey = OEM6D/zt2fVWOepVv3iEDD430V0gAshKp4+5oVVt5EE=
 
## client ip address ##
Address = 192.168.10.2/24
 
[Peer]
## CentOS 8 server public key ##
PublicKey = VWndJ4oB7ZJwC/7UOm++OLDrbAxMPsR2yd0cl3sEkUI=
 
## set ACL ##
AllowedIPs = 192.168.10.0/24
 
## Your CentOS 8 server's public IPv4/IPv6 address and port ##
Endpoint = 203.1.114.98:37822
 
##  Key connection alive ##
PersistentKeepalive = 15

Note that we assigned the private IP 192.168.10.1 to the server and 192.168.10.2 to the client. We also added the client's private key to the file.

The [Peer] section is where you enter the server's configuration to which the client will connect to. Here we have added the public key, public IP and a set of Allowed IPs which contains the private IP of our server. PersistentKeepalive tells WireGuard to send a UDP packet every 15 seconds, this is useful if you are behind a NAT and you want to keep the connection alive.

Press Ctrl + W to close the file and enter Y when prompted to save the file.

Now is the time to enable and start the VPN client.

$ sudo systemctl enable wg-quick@wg0
$ sudo systemctl start wg-quick@wg0
$ sudo systemctl status wg-quick@wg0

Step 9 - Configure Server to Add the Client

Now, we need to add the client's configuration to the server again to let it know about the client.

Stop the Wireguard service first.

$ sudo systemctl stop wg-quick@wg0

Open the file wg0.conf for editing.

$ sudo nano /etc/wireguard/wg0.conf

Append the following code at the end of the file.

[Peer] 
## client VPN public key ## 
PublicKey = dmfO9pirB315slXOgxXtmrBwAqPy07C57EvPks1IKzA=  

## client VPN IP address (note /32 subnet) ## 
AllowedIPs = 192.168.10.2/32

Press Ctrl + W to close the file and enter Y when prompted to save the file.

The [Peer] sections define the other members of the VPN network. You can add as many as needed.

They contain their public key, which must match the peers private key in its [Interface] section.

Note that any incoming connection is first authenticated against one of the public keys. If the connection is not from a verified peer, the incoming packets are just silently ignored. Since connections from hosts who don’t own a matching private key are not answered at all, a WireGuard VPN does not only provide encrypted communication, it also remains hidden from outsiders.

Start the Wireguard service again.

$ sudo systemctl start wg-quick@wg0

Step 10 - Test

Let us check if both the client and the server are connected securely using VPN. To test the connection, run the following commands on your client.

$ ping -c 192.168.10.1
PING 192.168.10.1 (192.168.10.1) 56(84) bytes of data.
64 bytes from 192.168.10.1: icmp_seq=1 ttl=64 time=44.2 ms
64 bytes from 192.168.10.1: icmp_seq=2 ttl=64 time=45.8 ms
64 bytes from 192.168.10.1: icmp_seq=3 ttl=64 time=46.7 ms
64 bytes from 192.168.10.1: icmp_seq=4 ttl=64 time=44.1 ms

--- 192.168.10.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2800ms
rtt min/avg/max/mdev = 41.729/47.829/48.953/5.046 ms

$ sudo wg
interface: wg0
  public key: dmfO9pirB315slXOgxXtmrBwAqPy07C57EvPks1IKzA= 
  private key: (hidden)
  listening port: 
 
peer: VWndJ4oB7ZJwC/7UOm++OLDrbAxMPsR2yd0cl3sEkUI=
  endpoint: 203.1.114.98:37822
  allowed ips: 192.168.10.0/24
  latest handshake: 1 minute, 40 seconds ago
  transfer: 938 B received, 45.67 KiB sent
  persistent: keepalive: every 15 seconds

Conclusion

That is all that there is to this tutorial. You should now have a Wireguard based VPN server based off a CentOS 8 Server. If you have any questions, ask them in the comments below.

Share this page:

2 Comment(s)