How To Set Up and Configure an OpenVPN Server on CentOS

A Virtual Private Network (VPN) is a physical trusted network in a remote location that you can virtually connect to and become part of as if you are physically present there. VPN has many use cases but it is mostly used to traverse untrusted networks as if you were on a private network. It gives you the freedom to access the internet safely and securely from your smartphone or laptop when connected to an untrusted network, like the WiFi at a hotel or coffee shop. More information about What is a virtual private network (VPN)?

OpenVPN is open-source commercial software that implements virtual private network (VPN) techniques to create secure point-to-point or site-to-site connections in routed or bridged configurations and remote access facilities. It uses a custom security protocol that utilizes SSL/TLS for key exchange. It is capable of traversing network address translators (NATs) and firewalls. More information about OpenVPN can be found on wikipedia.

Prerequisites:

Procedures:

Installing OpenVPN and Easy-RSA
In this section OpenVPN will be installed, and Easy-RSA will be installed to generate the needed certificates and keys to use for authentication, security, and encryption.

1.1. Create non root sudo user.

1.2. Install EPEL, OpenVPN, and Easy-RSA use yum or dnf depending on how your operating system was setup.

sudo yum install epel-release
sudo yum install openvpn easy-rsa

1.3. Make "vpn" directory and place it inside the home directory, example "/home/vpn". Add another directory for "easy-rsa" in the newly created vpn directory, example "/home/vpn/easy-rsa".

sudo mkdir /home/vpn
sudo mkdir /home/vpn/easy-rsa

1.4. Create a symlink from the easyrsa script that the package installed into the "/home/vpn/easy-rsa" directory that you just created. Do not copy the easy-rsa directory or install it manually by downloading and extracting the files in the "/home/vpn/easy-rsa" directory. This will prevent you from getting future updates automatically.

sudo ln -s /usr/share/easy-rsa/3/* /home/vpn/easy-rsa/

1.5. Secure the directory by changing the ownership to the non root sudo user in this example greens247 and restrict access to the directory using chmod.

sudo chown greens247 /home/vpn/easy-rsa
sudo chmod 700 /home/vpn/easy-rsa

 

Creating a PKI for OpenVPN
Easy-RSA is a public key infrastructure (PKI) management tool, we will use it to generate the server and user public and private certificates and keys. We will setup a local PKI directory to handle the management of the public key infrastructure.

In this section you will need to use a text editor, CentOS by default comes with vi text editor. If vi is too advanced for you, you can try another the more user friendly nano text editor. We will use the default vi text editor in this knowledge base article to setup the local PKI directory.

2.1.  Populate PKI vars file with default values which will be used repeatedly later on. This will reduce the manual input for repeated tasks when generating certificates.

cd /home/vpn/easy-rsa
vi /home/vpn/easy-rsa/vars

Once the file is opened press the insert button on your keyboard to allow input in the file. Enter the following values as shown in the example below. These values will ensure that your private keys and certificate requests are configured to use modern Elliptic Curve Cryptography (ECC) to generate keys and secure signatures for your clients and OpenVPN server. This will improve security and performance becasuse using ECC for key exchange is significantly faster than other methods like using plain Diffie-Hellman with the classic RSA algorithm. After adding the values to the file, save the file by pressing "shift+;" or ":" then typing "wq" (write and quit) and hit enter.

/home/vpn/easy-rsa

set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"

2.2. Initialize the PKI inside the "/home/vpn/easy-rsa" directory

cd /home/vpn/easy-rsa
./easyrsa init-pki

Output

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

2.3. This step is can be done on this server or a more advanced (optional) approach is doing all the above without installing OpenVPN on another server to be a private Certificate Authority (CA) server. You can refer to the optional prerequisite step for more information on the advanced approach. We need to add some lines to the vars file we created earlier because we are setting up the CA server and the OpenVPN server on the same server.

cd /home/vpn/easy-rsa
vi /home/vpn/easy-rsa/vars

/home/vpn/easy-rsa

set_var EASYRSA_REQ_COUNTRY "EG"
set_var EASYRSA_REQ_PROVINCE "Cairo"
set_var EASYRSA_REQ_CITY "Cairo City"
set_var EASYRSA_REQ_ORG "Greens247"
set_var EASYRSA_REQ_EMAIL "admin@example.com"
set_var EASYRSA_REQ_OU "HeadOffice"
set_var EASYRSA_ALGO "ec"
set_var EASYRSA_DIGEST "sha512"

After adding the variables, save the file. The file can be saved by pressing "shift+;" or ":" then typing "wq" (write and quit) and hit enter. Now we create the root public and private key pair for your Certificate Authority.

cd /home/vpn/easy-rsa
./easyrsa build-ca

Output

Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017

Enter New CA Key Passphrase:

Your OpenSSL version and date maybe different and that is alright. Choose a strong passphrase, and note it down somewhere safe. You will need to input the passphrase any time that you need to interact with your CA, for example to sign or revoke a certificate.If you do not want to type a passphrase everytime you interact with the CA replace the "./easyrsa build-ca" line above with "./easyrsa build-ca nopass" instead.

You will be asked for a  a common name, input "Greens247 CA" as an example or hit enter to use the default value "Easy-RSA CA".

Output

Common Name (eg: your user, host, or server name) [Easy-RSA CA]: Greens247 CA

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

 

Creating an OpenVPN Server Certificate Request and Private Key

3.1. In this section we will generate a private key and a Certificate Signing Request (CSR) on the OpenVPN server. (Optional) if you are following the advance approach, you will have to transfer the request over to your CA Server to be signed to create the required certificate and transfer it back to the OpenVPN server. In this example we will import the request to the CA directly on the same server, since we have both OpenVPN and the CA on the same server. Once you have a signed certificate, we will is it directly in the OpenVPN configuration.

The nopass option will be included in the next command to avoid password protection for the request file which could lead to permissions issues later on.

cd /home/vpn/easy-rsa
./easyrsa gen-req server nopass

You will have to input your common name, use your server's IP address. The server key will be generated once you hit enter.

Common Name (eg: your user, host, or server name) [server]:

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

 

Signing the OpenVPN Server’s Certificate Request

4.1. If you are using the (optional) advanced approach, you will need to transfer the above keys to the CA server and use the following command to import the server request. In this example we do not need to import the server.req because it is alreay there. Skip the next command, if you are not using the (optional) advanced approach.

cd /home/vpn/easy-rsa
./easyrsa import-req /home/vpn/easy-rsa/pki/reqs/server.req server

4.2. Sign the server request, you will be asked to confirm the signing request by typing "yes". When you do that, you will be asked to input the passphrase you created for the CA certificate to approve signing the request of the server certificate.

cd /home/vpn/easy-rsa
./easyrsa sign-req server server

Output

Using SSL: openssl OpenSSL 1.0.2k-fips 26 Jan 2017

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

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

subject=
commonName = server ip

Type the word 'yes' to continue, or any other input to abort.
Confirm request details: yes
Using configuration from /home/vpn/easy-rsa/pki/easy-rsa-1528.M9ARya/tmp.YQIxi0
Enter pass phrase for /home/vpn/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:'server'Certificate is to be certified until Sep 26 21:53:37 2022 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /home/vpn/easy-rsa/pki/issued/server.crt


The resulting server.crt file contains the OpenVPN server’s public encryption key, as well as a signature from the CA server. This will tell any device who trusts the CA server that they can also trust the OpenVPN server when they connect to it. If you are using the (optional) advanced approach, you will need to copy the server.crt and ca.crt from the CA server to the OpenVPN sever. In this example, we will not do that.

Configuring OpenVPN Cryptographic Material

5.1. We will use OpenVPN tls-crypt directive in order to protect the OpenVPN server from unauthenticated traffic, port scans, and Denial of Service attacks, which can tie up server resources. The tls-crypt directive is used to obfuscate the TLS certificate and makes it harder to identify OpenVPN network traffic. Use the following command to generate the tls-crypt pre-shared key. 

cd /etc/openvpn/server
sudo openvpn --genkey --secret tlscrypt.key

Configuring OpenVPN

6.1. Copy the sample server.conf file as a starting point and amend it as necessary. You may replace the "*" with the version number. Just make sure you are copying from the latest OpenVPN release directory on your system.

sudo cp /usr/share/doc/openvpn*/sample/sample-config-files/server.conf /etc/openvpn/server/

6.2. Copy the certificates to the OpenVPN server directory, and open the config file with the vi text editor. 

cp /home/vpn/easy-rsa/pki/ca.crt /etc/openvpn/server
cp /home/vpn/easy-rsa/pki/issued/server.crt /etc/openvpn/server
cp /home/vpn/easy-rsa/pki/private/server.key /etc/openvpn/server
sudo vi /etc/openvpn/server/server.conf

6.3. Make sure you change the following variables in the file to match below, any variable having ";" gets disabled

/etc/openvpn/server/server.conf

port 443 # TCP Port 443 is used for browsing via https so it will be open on most firewalls, other ports may cause issues.
proto tcp # Change this to tcp, because port 443 is mostly open for tcp connections on firewalls and public internet.
ca /etc/openvpn/server/ca.crt # Change the ca to this location unless you used a custom configuration.
cert /etc/openvpn/server/server.crt # Change the cert location to this unless you used a custom configuration.
key /etc/openvpn/server/server.key # Change the key location to this unless you used a custom configuration.
;dh dh2048.pem # Add ";" to disable this line
dh none # Add this line below it.
topology subnet # Remove the ";" to enable this variable.
;ifconfig-pool-persist ipp.txt # Add ";" to disable this line.
push "redirect-gateway def1 bypass-dhcp" # Remove the ";" to enable this variable to allow full tunneling.
push "dhcp-option DNS 8.8.8.8" # Remove the ";" to enable this variable and change the dns IP to google or any other.
push "dhcp-option DNS 8.8.4.4" # Remove the ";" to enable this variable and change the dns IP to google or any other.
;tls-auth ta.key 0 # Add ";" to disable this line.
tls-crypt /etc/openvpn/server/tlscrypt.key # Add this line to use the more advanced tls-crypt generated key.
;cipher AES-256-CBC # Add ";" to disable this line.
cipher AES-256-GCM # Add this line to use the most advanced cipher
auth SHA512 # Add the following line
user nobody # Remove the ";" to enable this variable.
group nobody # Remove the ";" to enable this variable.
log-append openvpn.log # Remove the ";" to enable this variable.
explicit-exit-notify 0 # Remove the ";" to enable this variable if disabled and replace "1" with "0".

Save the file by pressing "shift+;" or ":" then typing "wq" (write and quit) and hit enter.

Adjusting the OpenVPN Server Networking Configuration

7.1. In order for OpenVPN to function properly at routing traffic, we need to enable IP Forwarding, edit the following file. We are using an ipv4 public IP in this example.

sudo vi /etc/sysctl.conf

7.2. Add the following lines in the file and add "#" at the begining of any other line in the file to disable it.

/etc/sysctl.conf

net.ipv4.ip_forward = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

Save the file by pressing "shift+;" or ":" then typing "wq" (write and quit) and hit enter.

7.3. To ensure that the values were properly saved and reload them, using the following command.

sudo sysctl -p

Output

net.ipv4.ip_forward = 1
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1

Firewall Configuration

8.1 Make sure firewalld is installed and running as stated in the prerequisits earlier. OpenVPN needs the firewall to be configured to allow OpenVPN traffic and route traffic to VPN clients properly. Add the VPN tunnel interface "tun0" and the OpenVPN service to the firewall trusted zone. We also need to allow https because we are using tcp port 443 in this guide as the OpenVPN port. After adding the firewall rules, reload the firewall for the changes to take effect.

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


8.2. Check that the service was added correctly

sudo firewall-cmd --list-services --zone=trusted

Output

openvpn

8.3 Because the clients are sharing the public IP address of the server, we need to configure Network Address Translation (NAT). This can be achieved on firewalld using masquerade. The last line will test that if masquerade was enabled properly.

sudo firewall-cmd --add-masquerade
sudo firewall-cmd --add-masquerade --permanent
sudo firewall-cmd --reload
sudo firewall-cmd --query-masquerade

Output

yes

8.4. A specific masquerade rule needs to be added for the OpenVPN subnet used in the OpenVPN configuration file used previously "server.conf" in this example the subnet used is "10.8.0.0/24". Create a shell variable (DEVICE in this example) which will represent the primary network interface used by the server, and then using that variable to permanently add the routing rule. After adding the rule, reload the firewall for changes to take effect using the last line in the following commands.

DEVICE=$(ip route | awk '/^default via/ {print $5}')
sudo firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o $DEVICE -j MASQUERADE
sudo firewall-cmd --reload

Starting OpenVPN

9.1. Enable and start the OpenVPN service, and confirm that the service is active by using the last command line. If the output contains "Active: active (running)" then we have setup OpenVPN successfully.

sudo systemctl -f enable openvpn-server@server.service
sudo systemctl start openvpn-server@server.service
sudo systemctl status openvpn-server@server.service

Output

openvpn-server@server.service - OpenVPN service for server
Loaded: loaded (/usr/lib/systemd/system/openvpn-server@.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2020-06-23 21:21:21 EDT; 4min 31s ago

 

Congratulations, you have now successfully completed setting up OpenVPN Server.

Start generating OpenVPN client configuration files, including certificate, and keys by opening How to Generate OpenVPN Client Configuration Files.

Last update: June 24th, 2020

  • CentOS, Security, VPN, Firewall, OpenVPN
  • 111 Users Found This Useful
Was this answer helpful?

Related Articles

CLI CSF Firewall Whitelist an IP Address

ConfigServer Firewall (CSF) is a powerful software firewall. All managed servers at Greens247...

How to change Private Key Format to Use with PuTTY

This guide will show you how to change your private key format, to use with PuTTY, which is a...

How to Disable SELinux on CentOS

SELinux (Security Enhanced Linux) is a Linux kernel security module that allows administrators...

How to Generate OpenVPN Client Configuration Files

A Virtual Private Network (VPN) is a physical trusted network in a remote location that you can...

How to ssh to a server with a private key using putty

This article will describe how to connect to your server using ssh and a private key on a windows...