A VPN also is known as a “Virtual Private Network” is a technology that allows you to create a secure private network over the public internet. This will helps you to encrypt your internet traffic and protect your online identity. It is primarily used to connect two business networks securely over the internet and allows you to connect a business network from home.

In simple terms, a VPN connects your Mobile, Computer, and Tablet to another computer (server) over the internet and allows you to access the internet using that computer’s internet and also access the local network resource by bypassing internet censorship remotely.

In this tutorial, we will show you how to install and configure the OpenVPN server on CentOS 8.

Step 1 – Disable SELinux

Before starting, it is a good idea to disable the SELinux in your system.

To disable SELinux, open the /etc/selinux/config file:

nano /etc/selinux/config

Change the following line:

SELINUX=disabled

Save the file when you are finished. Next, restart your system to apply the SELinux changes.

Step 2 – Enable IP Forwarding

Next, you will need to enable IP forwarding in your system. IP forwarding allows your operating system to accept the incoming network packets and forward it to the other network if the destination is on another network.

To enable the IP forwarding, edit the file /etc/sysctl.conf:

nano /etc/sysctl.conf

Add the following line:

net.ipv4.ip_forward = 1

Save the file when you are finished. Then, run the following command to apply the changes:

sysctl -p

Step 3 – Install OpenVPN Server

By default, you will need to install the EPEL repository in your system in order to install the latest version of OpenVPN.

Run the following command to install the ELEP repository:

dnf install epel-release -y

Once installed, run the following command to install the latest version of OpenVPN:

dnf install openvpn -y

Once the installation has been completed, you will also need to download easy-rsa for managing SSL certificates.

Run the following command to download easy-rsa inside /etc/openvpn directory.

cd /etc/openvpn
wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.6/EasyRSA-unix-v3.0.6.tgz

Next, run the following command to extract the downloaded file:

tar -xvzf EasyRSA-unix-v3.0.6.tgz

Next, rename the extracted directory to the easy-rsa:

mv EasyRSA-v3.0.6 easy-rsa

Step 4 – Setup Certificate Authority

Easy RSA uses a set of scripts to generate keys and certificates. First, you will need to configure the Certificate Authority on your system.

To do so, change the directory to /etc/openvpn/easy-rsa and create a new Easy RSA’s configuration file:

cd /etc/openvpn/easy-rsa
nano vars

Add the following lines including your country, city, and preferred email address:

set_var EASYRSA                 "$PWD"
set_var EASYRSA_PKI             "$EASYRSA/pki"
set_var EASYRSA_DN              "cn_only"
set_var EASYRSA_REQ_COUNTRY     "INDIA"
set_var EASYRSA_REQ_PROVINCE    "Gujrat"
set_var EASYRSA_REQ_CITY        "Ahmedabad"
set_var EASYRSA_REQ_ORG         "Tecadmin CERTIFICATE AUTHORITY"
set_var EASYRSA_REQ_EMAIL		"[email protected]"
set_var EASYRSA_REQ_OU          "Tecadmin EASY CA"
set_var EASYRSA_KEY_SIZE        2048
set_var EASYRSA_ALGO            rsa
set_var EASYRSA_CA_EXPIRE		7500
set_var EASYRSA_CERT_EXPIRE     365
set_var EASYRSA_NS_SUPPORT		"no"
set_var EASYRSA_NS_COMMENT		"Tecadmin CERTIFICATE AUTHORITY"
set_var EASYRSA_EXT_DIR         "$EASYRSA/x509-types"
set_var EASYRSA_SSL_CONF        "$EASYRSA/openssl-easyrsa.cnf"
set_var EASYRSA_DIGEST          "sha256"

Save the file when you are finished.

Next, run the following command to initiate the PKI directory.

./easyrsa init-pki

Output:

Note: using Easy-RSA configuration from: ./vars

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /etc/openvpn/easy-rsa/pki

Next, build the CA certificates with the following command:

./easyrsa build-ca

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019

Enter New CA Key Passphrase: 
Re-Enter New CA Key Passphrase: 
Generating RSA private key, 2048 bit long modulus (2 primes)
....................................................................     
..........................................................................................................................................     
e is 65537 (0x010001)
Can't load /etc/openvpn/easy-rsa/pki/.rnd into RNG
140218549745472:error:2406F079:random number generator:RAND_load_file:Cannot open file:crypto/rand/randfile.c:98:Filename=/etc/openvpn/easy-rsa/pki/.rnd
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/etc/openvpn/easy-rsa/pki/ca.crt

The above command will generate two files named ca.key and ca.crt. These certificates will be used to sign your server and clients’ certificates.

Step 5 – Generate Server Certificate Files

Next, you will need to generate a keypair and certificate request for your server.

Run the following command to generate the server key named tecadmin-server:

./easyrsa gen-req tecadmin-server nopass

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019
Generating a RSA private key
...........................     
...............................................................................................................................................................................................................................................................................................     
writing new private key to '/etc/openvpn/easy-rsa/pki/private/tecadmin-server.key.kOlBTwtY6a'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [tecadmin-server]:

Keypair and certificate request completed. Your files are:
req: /etc/openvpn/easy-rsa/pki/reqs/tecadmin-server.req
key: /etc/openvpn/easy-rsa/pki/private/tecadmin-server.key

Step 6 – Sign the Server Key Using CA

Next, you will need to sign the tecadmin-server key using your CA certificate:

Run the following command to sign the server key:

./easyrsa sign-req server tecadmin-server

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019

You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 365 days:

subject=
    commonName                = tecadmin-server


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
Using configuration from /etc/openvpn/easy-rsa/pki/safessl-easyrsa.cnf
Enter pass phrase for /etc/openvpn/easy-rsa/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'tecadmin-server'
Certificate is to be certified until Feb 16 05:00:50 2021 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /etc/openvpn/easy-rsa/pki/issued/tecadmin-server.crt

Next, verify the generated certificate file with the following command:

openssl verify -CAfile pki/ca.crt pki/issued/tecadmin-server.crt 

If everything is fine, you should get the following output:

pki/issued/tecadmin-server.crt: OK

Next, run the following command to generate a strong Diffie-Hellman key to use for the key exchange:

./easyrsa gen-dh

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019
Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
.... ................................ ........................................ .....  *  *  *  *

DH parameters of size 2048 created at /etc/openvpn/easy-rsa/pki/dh.pem

After creating all certificate files, copy them to the /etc/openvpn/server/ directory:

cp pki/ca.crt /etc/openvpn/server/
cp pki/dh.pem /etc/openvpn/server/
cp pki/private/tecadmin-server.key /etc/openvpn/server/
cp pki/issued/tecadmin-server.crt /etc/openvpn/server/

Step 7 – Generate Client Certificate and Key File

Next, you will need to generate the key and certificate file for the client.

First, run the following command to build the client key file:

./easyrsa gen-req client nopass

You should see the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019
Generating a RSA private key
......................................................     
...     
writing new private key to '/etc/openvpn/easy-rsa/pki/private/client.key.e38GUtzHie'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [client]:

Keypair and certificate request completed. Your files are:
req: /etc/openvpn/easy-rsa/pki/reqs/client.req
key: /etc/openvpn/easy-rsa/pki/private/client.key

Next, sign the client key using your CA certificate:

./easyrsa sign-req client client

You should get the following output:

Note: using Easy-RSA configuration from: ./vars

Using SSL: openssl OpenSSL 1.1.1c FIPS  28 May 2019


You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a client certificate for 365 days:

subject=
    commonName                = client


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
Using configuration from /etc/openvpn/easy-rsa/pki/safessl-easyrsa.cnf
Enter pass phrase for /etc/openvpn/easy-rsa/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'client'
Certificate is to be certified until Feb 16 05:11:19 2021 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /etc/openvpn/easy-rsa/pki/issued/client.crt

Next, copy all client certificate and key file to the /etc/openvpn/client/ directory:

cp pki/ca.crt /etc/openvpn/client/
cp pki/issued/client.crt /etc/openvpn/client/
cp pki/private/client.key /etc/openvpn/client/

Step 8 – Configure OpenVPN Server

Next, create a new OpenVPN configuration file inside /etc/openvpn/client/ directory:

nano /etc/openvpn/server/server.conf

Add the following lines:

port 1194
proto udp
dev tun
ca /etc/openvpn/server/ca.crt
cert /etc/openvpn/server/tecadmin-server.crt
key /etc/openvpn/server/tecadmin-server.key
dh /etc/openvpn/server/dh.pem
server 10.8.0.0 255.255.255.0
push "redirect-gateway def1"

push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
duplicate-cn
cipher AES-256-CBC
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256
auth SHA512
auth-nocache
keepalive 20 60
persist-key
persist-tun
compress lz4
daemon
user nobody
group nobody
log-append /var/log/openvpn.log
verb 3

Save the file when you are finished.

Step 9 – Start OpenVPN Service

OpenVPN is now installed and configured. You can now start the OpenVPN service and enable it to start after the system reboot using the following command:

systemctl start [email protected]
systemctl enable [email protected]

Run the following command to verify the status of OpenVPN service:

systemctl status [email protected]

You should get the following output:

[email protected] - OpenVPN service for server
   Loaded: loaded (/usr/lib/systemd/system/[email protected]; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2020-02-17 00:29:26 EST; 39min ago
     Docs: man:openvpn(8)
           https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
           https://community.openvpn.net/openvpn/wiki/HOWTO
 Main PID: 32405 (openvpn)
   Status: "Initialization Sequence Completed"
    Tasks: 1 (limit: 12552)
   Memory: 1.9M
   CGroup: /system.slice/system-openvpnx2dserver.slice/[email protected]
           └─32405 /usr/sbin/openvpn --status /run/openvpn-server/status-server.log --status-version 2 --suppress-timestamps --cipher AES-256->

Feb 17 00:29:26 centos8 systemd[1]: Starting OpenVPN service for server...
Feb 17 00:29:26 centos8 systemd[1]: Started OpenVPN service for server.

Once the OpenVPN service started successfully, it will create a new network interface named tun0. You can check it with the following command:

ifconfig 

You should get the new interface tun0 in the following output:

eth0: flags=4163  mtu 1500
        inet 104.245.36.127  netmask 255.255.255.0  broadcast 104.245.36.255
        inet6 fe80::200:68ff:fef5:247f  prefixlen 64  scopeid 0x20
        ether 00:00:68:f5:24:7f  txqueuelen 1000  (Ethernet)
        RX packets 1926738  bytes 314886412 (300.2 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 174907  bytes 29557250 (28.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 216  bytes 40041 (39.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 216  bytes 40041 (39.1 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tun0: flags=4305  mtu 1500
        inet 10.8.0.1  netmask 255.255.255.255  destination 10.8.0.2
        inet6 fe80::4152:a673:b260:d9e6  prefixlen 64  scopeid 0x20
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4  bytes 304 (304.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Step 10 – Generate Client Configuration File

Next, create a new OpenVPN client configuration file named client.ovpn. You will require this file to connect your OpenVPN server from the client system.

nano /etc/openvpn/client/client.ovpn

Add the following lines:

client
dev tun
proto udp
remote vpn-server-ip 1194
ca ca.crt
cert client.crt
key client.key
cipher AES-256-CBC
auth SHA512
auth-nocache
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-GCM-SHA384:TLS-DHE-RSA-WITH-AES-256-CBC-SHA256:TLS-DHE-RSA-WITH-AES-128-GCM-SHA256:TLS-DHE-RSA-WITH-AES-128-CBC-SHA256
resolv-retry infinite
compress lz4
nobind
persist-key
persist-tun
mute-replay-warnings
verb 3

Save the file when you are finished.

Step 11 – Configure Routing using Firewalld

First, you will need to allow the OpenVPN service through firewalld.

To do so, add the OpenVPN service and tun0 interface to the trusted firewall zone:

firewall-cmd --permanent --add-service=openvpn
firewall-cmd --permanent --zone=trusted --add-service=openvpn
firewall-cmd --permanent --zone=trusted --add-interface=tun0

Next, add the MASQUERADE on the default zone:

firewall-cmd --add-masquerade
firewall-cmd --permanent --add-masquerade

Next, run the following command to masquerade the internet traffic coming from VPN network (10.8.0.0/24) to systems local network interface (eth0).

tecadmin=$(ip route get 8.8.8.8 | awk 'NR==1 {print $(NF-2)}')
firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o $tecadmin -j MASQUERADE

Finally, run the following command to implement the changes:

firewall-cmd --reload

Step 12 – Connect OpenVPN from Clients

First, log in to the client machine and install the OpenVPN package with the following command:

dnf install epel-release -y
dnf install openvpn -y

Next, you will need to download the OpenVPN client configuration files from OpenVPN server to the client machine.

On the client machine, run the following command to download all the client configuration file:

scp -r [email protected]:/etc/openvpn/client .

Once downloaded, change the directory to client and run the following command to connect to OpenVPN server:

cd client
openvpn --config client.ovpn

You should see the following output:

Mon Feb 17 00:54:17 2020 VERIFY OK: depth=0, CN=tecadmin-server
Mon Feb 17 00:54:17 2020 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, 2048 bit RSA
Mon Feb 17 00:54:17 2020 [tecadmin-server] Peer Connection Initiated with [AF_INET]104.245.36.127:1194
Mon Feb 17 00:54:18 2020 SENT CONTROL [tecadmin-server]: 'PUSH_REQUEST' (status=1)
Mon Feb 17 00:54:18 2020 PUSH: Received control message: 'PUSH_REPLY,redirect-gateway def1,dhcp-option DNS 208.67.222.222,dhcp-option DNS 208.67.220.220,route 10.8.0.1,topology net30,ping 20,ping-restart 60,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM'
Mon Feb 17 00:54:18 2020 OPTIONS IMPORT: timers and/or timeouts modified
Mon Feb 17 00:54:18 2020 OPTIONS IMPORT: --ifconfig/up options modified
Mon Feb 17 00:54:18 2020 OPTIONS IMPORT: route options modified
Mon Feb 17 00:54:18 2020 OPTIONS IMPORT: --ip-win32 and/or --dhcp-option options modified
Mon Feb 17 00:54:18 2020 OPTIONS IMPORT: peer-id set
Mon Feb 17 00:54:18 2020 OPTIONS IMPORT: adjusting link_mtu to 1625
Mon Feb 17 00:54:18 2020 OPTIONS IMPORT: data channel crypto options modified
Mon Feb 17 00:54:18 2020 Data Channel: using negotiated cipher 'AES-256-GCM'
Mon Feb 17 00:54:18 2020 Outgoing Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Mon Feb 17 00:54:18 2020 Incoming Data Channel: Cipher 'AES-256-GCM' initialized with 256 bit key
Mon Feb 17 00:54:18 2020 ROUTE_GATEWAY 45.58.38.1/255.255.255.0 IFACE=eth0 HWADDR=00:00:2d:3a:26:d9
Mon Feb 17 00:54:18 2020 TUN/TAP device tun0 opened
Mon Feb 17 00:54:18 2020 TUN/TAP TX queue length set to 100
Mon Feb 17 00:54:18 2020 /sbin/ip link set dev tun0 up mtu 1500
Mon Feb 17 00:54:18 2020 /sbin/ip addr add dev tun0 local 10.8.0.6 peer 10.8.0.5

After successfull connection, OpenVPN will assign an IP address to your system. You can check it with the following command:

ifconfig tun0

Output:

tun0: flags=4305  mtu 1500
        inet 10.8.0.6  netmask 255.255.255.255  destination 10.8.0.5
        inet6 fe80::c6b:2644:5142:8e7f  prefixlen 64  scopeid 0x20
        unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  txqueuelen 100  (UNSPEC)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 2  bytes 96 (96.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0

Congratulations! you have successfully installed and configured OpenVPN Server and Client on CentOS 8 server.