How to Set Up an OpenVPN Server on CentOS 7
Updated on
•6 min read

Whether you want to access the Internet safely and securely while connected on an untrusty public Wi-Fi network, bypass Geo-restricted content or allow your coworkers to connect securely to your company network when working remotely, using a VPN is the best solution.
A VPN allows you to connect to remote VPN servers, making your connection encrypted and secure and surf the web anonymously by keeping your traffic data private.
There are many commercial VPN providers you can choose from, but you can never be truly sure that the provider is not logging your activity. The safest option is to set up your own VPN server.
This tutorial will cover the process of setting up your own VPN server by installing and configuring OpenVPN. We will also show you how to generate clients certificates and create configuration files
OpenVPN is a fully featured, open-source Secure Socket Layer (SSL) VPN solution. It implements OSI layer 2 or 3 secure network extension using the SSL/TLS protocol.
Prerequisites
To complete this tutorial, you will need:
- Sudo access to a CentOS 7 server to host your OpenVPN instance.
- The server should have a firewall configured.
- Separate dedicated machine to serve as your CA (certificate authority). If you don’t want to use a dedicated machine for your CA, you can build the CA on your OpenVPN server or your local machine. Once you are done building the CA it’s recommended to move the CA directory somewhere secure or offline.
This tutorial assumes that the CA is on a separate Linux machine. The same steps (with small modifications) will apply if you’re using your server as a CA.
The reason why we are using a separate CA machine is to prevent attackers to infiltrate the server. If an attacker manages to access the CA private key they could use it to sign new certificates, which will give them access to the VPN server.
Building CA with EasyRSA
When setting up a new OpenVPN server the first step is to build a Public Key Infrastructure (PKI ). To do so we’ll need to create the following:
- A Certificate Authority (CA) certificate and private key.
- A separate certificate and private key pair for the server issued by our CA.
- A separate certificate and private key pair for each client issued by our CA.
As mentioned in the prerequisites for security reasons, we’ll build the CA on a standalone machine.
To create CA, certificates requests and sign certificates we will use a CLI utility named EasyRSA.
Perform the following steps on your CA machine.
Start by downloading the latest release of EasyRSA from the project Github repository with the following wget command:
cd && wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.5/EasyRSA-nix-3.0.5.tgz
Once the download is complete extract the archive by typing:
tar xzf EasyRSA-nix-3.0.5.tgz
Navigate to the EasyRSA directory and create a configuration file named
vars
by copying thevars.example
file:cd ~/EasyRSA-3.0.5/
cp vars.example vars
Open the file and uncomment and update the following entries to match your information.
nano ~/EasyRSA-3.0.5/vars
~/EasyRSA-3.0.5/varsset_var EASYRSA_REQ_COUNTRY "US" set_var EASYRSA_REQ_PROVINCE "Pennsylvania" set_var EASYRSA_REQ_CITY "Pittsburgh" set_var EASYRSA_REQ_ORG "Linuxize" set_var EASYRSA_REQ_EMAIL "[email protected]" set_var EASYRSA_REQ_OU "Community"
Save and close the file.
Before generating a CA keypair first we need to initialize a new PKI with:
./easyrsa init-pki
init-pki complete; you may now create a CA or requests. Your newly created PKI dir is: /home/causer/EasyRSA-3.0.5/pki
The next step is to build the CA:
./easyrsa build-ca
If you don’t want to be prompted for a password each time you sign your certificates, run the
build-ca
command using thenopass
option:./easyrsa build-ca nopass
.... Enter PEM pass phrase: Verifying - Enter PEM pass phrase: ----- ... ----- 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: /home/causer/EasyRSA-3.0.5/pki/ca.crt
You’ll be asked to set a password for the CA key and enter a common name for your CA.
Once completed, the script will create two files — CA public certificate
ca.crt
and CA private keyca.key
.Now that the Certificate Authority (CA) is created, you can use it to sign certificate requests for one or multiple OpenVPN servers and clients.
Installing OpenVPN and EasyRSA
Our next step is to install the OpenVPN package which is available in EPEL’s repositories and download the latest version of EasyRSA.
The following steps are performed on the OpenVPN server.
Enable the EPEL repository by typing:
sudo yum install epel-release
Once the repository is enabled install OpenVPN with the following command:
sudo yum install openvpn
Download the latest release of EasyRSA:
cd && wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.5/EasyRSA-nix-3.0.5.tgz
Once the download is completed type the following command to extract the archive:
tar xzf EasyRSA-nix-3.0.5.tgz
Although we have already initialized a PKI on the CA machine, we also need to create a new PKI on the OpenVPN server. To do so, use the same commands as before:
cd ~/EasyRSA-3.0.5/
./easyrsa init-pki
If you still wonder why we need two EasyRSA installations, it is because we will use this EasyRSA instance to generate certificate requests which will be signed using the EasyRSA instance on the CA machine.
It may sound complicated, and little confusing but once you read the whole tutorial you’ll see that it really isn’t complicated.
Creating Diffie-Hellman and HMAC keys
In this section, we will generate a strong Diffie-Hellman key which will be used during the key exchange and a HMAC signature file to add an additional layer of security to the connection.
Navigate to the EasyRSA directory on your OpenVPN server anf generate a Diffie-Hellman key:.
cd ~/EasyRSA-3.0.5/
./easyrsa gen-dh
The script will generate 2048-bit long DH parameters. This can take some time, especially on servers with little resources. Once completed the following message will be printed on your screen:
DH parameters of size 2048 created at /home/serveruser/EasyRSA-3.0.5/pki/dh.pem
Copy the
dh.pem
file to the/etc/openvpn
directory:sudo cp ~/EasyRSA-3.0.5/pki/dh.pem /etc/openvpn/
Next, generate a HMAC signature using the
openvpn
binary:openvpn --genkey --secret ta.key
Once completed copy the
ta.key
file to the/etc/openvpn
directory:sudo cp ~/EasyRSA-3.0.5/ta.key /etc/openvpn/
Creating Server Certificate and Private Key
This section describes how to generate a private key and certificate request for the OpenVPN server.
Navigate to the EasyRSA directory on your OpenVPN server and generate a new private key for the server and a certificate request file:
cd ~/EasyRSA-3.0.5/
./easyrsa gen-req server1 nopass
We are using the
nopass
argument because we want to start the OpenVPN server without a password input. Also in this example, we are usingserver1
as a server name (entity) identifier. If you choose a different name for your server don’t forget to adjust the instructions below where the server name is used.The command will create two files, a private key (
server1.key
) and a certificate request file (server1.req
).----- Common Name (eg: your user, host, or server name) [server1]: Keypair and certificate request completed. Your files are: req: /home/serveruser/EasyRSA-3.0.5/pki/reqs/server1.req key: /home/serveruser/EasyRSA-3.0.5/pki/private/server1.key
Copy the private key to the
/etc/openvpn
directory:sudo cp ~/EasyRSA-3.0.5/pki/private/server1.key /etc/openvpn/
Transfer the certificate request file to your CA machine:
scp ~/EasyRSA-3.0.5/pki/reqs/server1.req causer@your_ca_ip:/tmp
In this example we are using
scp
to transfer the file, you can also usersync
over ssh or any other secure method.Login to your CA machine, switch to the EasyRSA directory and import the certificate request file:
cd ~/EasyRSA-3.0.5
./easyrsa import-req /tmp/server1.req server1
The first argument is the path to the certificate request file and the second one is the server short (entity) name. In our case the server name is
server1
.The request has been successfully imported with a short name of: server1 You may now use this name to perform signing operations on this request.
This command just copies the request file into the
pki/reqs
directory.While still in the EasyRSA directory on CA machine run the following command to sign the request:
cd ~/EasyRSA-3.0.5
./easyrsa sign-req server server1
The first argument can either be
server
orclient
and the second one is the server short (entity) name.You’ll be prompted to verify that the request comes from a trusted source. Type
yes
and pressEnter
to confirm: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 1080 days: subject= commonName = server1 Type the word 'yes' to continue, or any other input to abort. Confirm request details: yes ...
If your CA key is password protected, you’ll be prompted to enter the password. Once verified the script will generate the SSL certificate and print the full path to it.
... Certificate is to be certified until Sep 17 10:54:48 2021 GMT (1080 days) Write out database with 1 new entries Data Base Updated Certificate created at: /home/causer/EasyRSA-3.0.5/pki/issued/server1.crt
Next step is to transfer the signed certificate
server1.crt
andca.crt
files back to your OpenVPN server. Again you can usescp
,rsync
or any other secure method:scp ~/EasyRSA-3.0.5/pki/issued/server1.crt serveruser@your_server_ip:/tmp
scp ~/EasyRSA-3.0.5/pki/ca.crt serveruser@your_server_ip:/tmp
Login to your OpenVPN server, and move the
server1.crt
andca.crt
files into the/etc/openvpn/
directory:sudo mv /tmp/{server1,ca}.crt /etc/openvpn/
Upon completing the steps outlined in this section, you should have the following new files on your OpenVPN server:
/etc/openvpn/ca.crt
/etc/openvpn/dh.pem
/etc/openvpn/ta.key
/etc/openvpn/server1.crt
/etc/openvpn/server1.key
Configuring the OpenVPN Service
Now that you have the server certificate signed by your CA and transferred to your OpenVPN server, it’s time to configure the OpenVPN service.
We will use the sample configuration file provided with OpenVPN installation package as a starting point and then add our own custom configuration options to it.
Start by extracting the configuration file to the /etc/openvpn/
directory:
sudo cp /usr/share/doc/openvpn-*/sample/sample-config-files/server.conf /etc/openvpn/server1.conf
Open the file with your favorite text editor:
sudo nano /etc/openvpn/server1.conf
Find the Certificate, Key and DH parameters directives and change the file names:
/etc/openvpn/server1.confcert server1.crt key server1.key dh dh.pem
To redirect the clients traffic through the VPN find and uncomment the
redirect-gateway
anddhcp-option
options:/etc/openvpn/server1.confpush "redirect-gateway def1 bypass-dhcp" push "dhcp-option DNS 208.67.222.222" push "dhcp-option DNS 208.67.220.220"
By default OpenDNS resolvers are used. You can change it and use CloudFlare, Google or any other DNS resolvers you want.
Find the
user
andgroup
directives and uncomment these settings by removing the “;
” at the beginning of each line:/etc/openvpn/server1.confuser nobody group nogroup
Append the following line at the end of the file. This directive will change the message authentication algorithm (HMAC) from SHA1 to SHA256
/etc/openvpn/server1.confauth SHA256
Once you are done, the server configuration file (excluding comments) should look something like this:
port 1194
proto udp
dev tun
ca ca.crt
cert server1.crt
key server1.key # This file should be kept secret
dh dh.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS 208.67.222.222"
push "dhcp-option DNS 208.67.220.220"
keepalive 10 120
tls-auth ta.key 0 # This file is secret
cipher AES-256-CBC
user nobody
group nobody
persist-key
persist-tun
status openvpn-status.log
verb 3
explicit-exit-notify 1
auth SHA256
Starting OpenVPN Service
In this tutorial, we’ve used server1.conf
as a configuration file. To start the OpenVPN service with this configuration we need to specify the configuration file name after the systemd unit file name:
On your OpenVPN server run the following command to start the OpenVPN service:
sudo systemctl start openvpn@server1
Verify whether the service has started successfully by typing:
sudo systemctl status openvpn@server1
If the service is active and running, the output will look something like this:
● [email protected] - OpenVPN Robust And Highly Flexible Tunneling Application On server1
Loaded: loaded (/usr/lib/systemd/system/[email protected]; disabled; vendor preset: disabled)
Active: active (running) since Tue 2018-11-06 10:07:35 UTC; 7s ago
Main PID: 19912 (openvpn)
Status: "Initialization Sequence Completed"
CGroup: /system.slice/system-openvpn.slice/[email protected]
└─19912 /usr/sbin/openvpn --cd /etc/openvpn/ --config server1.conf
Enable the service to automatically start on boot with:
sudo systemctl enable openvpn@server1
Created symlink /etc/systemd/system/multi-user.target.wants/[email protected] → /lib/systemd/system/[email protected].
sudo journalctl -u openvpn@server1
When starting, the OpenVPN Server creates a tun device tun0
. To check if the device is available, type the following ip command
:
ip a show tun0
The output should look something like this:
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 100
link/none
inet 10.8.0.1 peer 10.8.0.2/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::f421:f382:3158:138f/64 scope link flags 800
valid_lft forever preferred_lft forever
At this point, your OpenVPN server is configured and running properly.
Firewall and Server Networking Configuration
In order to forward network packets properly, we need to enable IP forwarding.
The following steps are performed on the OpenVPN server.
Open the /etc/sysctl.conf
file and add the following line:
sudo nano /etc/sysctl.conf
net.ipv4.ip_forward = 1
Once you are finished, save and close the file.
Apply the new settings by running the following sysctl
command:
sudo sysctl -p
net.ipv4.ip_forward = 1
If you followed the prerequisites, you should already have firewalld running on your server.
Now we need to add firewall rules open OpenVPN port and to enable masquerading.
Start by adding the tun0
interface to the trusted
zone:
sudo firewall-cmd --permanent --zone=trusted --add-interface=tun0
Open the default openvpn port 1194
by adding the openvpn service to the list of services allowed by firewalld :
sudo firewall-cmd --permanent --add-service openvpn
Set IP masquerading on trusted
zone:
sudo firewall-cmd --permanent --zone=trusted --add-masquerade
Before adding the nat rule you need to know the public network interface of your CentOS OpenVPN Server. You can easily find the interface by running the following command:
ip -o -4 route show to default | awk '{print $5}'
In our case, the interface is named eth0
as shown on the output below. Your interface may have a different name.
eth0
The following command will allow the traffic to leave the VPN, giving your VPN clients access to the Internet. Don’t forget to replace eth0
to match the name of public network interface you found in the previous command.
sudo firewall-cmd --permanent --direct --passthrough ipv4 -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE
Finally reload the firewall rules for changes to take effect:
sudo firewall-cmd --reload
Creating the Client Configuration Infrastructure
In this tutorial, we’ll create a separate SSL certificate and generate a different configuration file for each VPN client.
The client private key and certificate request can be generated either on the client machine or on the server. For simplicity, we will generate the certificate request on the server and then send it to the CA to be signed.
The whole process of generating the client certificate and configuration file is as follows:
- Generate a private key and certificate request on the OpenVPN server.
- Send the request to the CA machine to be signed.
- Copy the signed SSL certificate to the OpenVPN server and generate a configuration file.
- Send the configuration file to the VPN client’s machine.
Start by creating a set of directories to store the clients files:
mkdir -p ~/openvpn-clients/{configs,base,files}
base
directory will store the base files and configuration that will be shared across all client files.configs
directory will store the generated client configuration.files
directory will store client-specific certificate/key pair.
Copy
the ca.crt
and ta.key
files to the ~/openvpn-clients/base
directory:
cp ~/EasyRSA-3.0.5/ta.key ~/openvpn-clients/base/
cp /etc/openvpn/ca.crt ~/openvpn-clients/base/
Next copy the sample VPN client configuration file into the client-~/openvpn-clients/base
directory. We will use this file as a base configuration:
sudo cp /usr/share/doc/openvpn-*/sample/sample-config-files/client.conf ~/openvpn-clients/base/
Now we need to edit the file to match our server settings and configuration. Open the configuration file with your text editor:
nano ~/openvpn-clients/base/client.conf
Find the remote directive and change the default placeholder with the public IP address of your OpenVPN server:
~/openvpn-clients/base/client.conf# The hostname/IP and port of the server. # You can have multiple remote entries # to load balance between the servers. remote YOUR_SERVER_IP 1194
Locate and comment the
ca
,cert
, andkey
directives. The certs and keys will be added within the configuration file:~/openvpn-clients/base/client.conf# SSL/TLS parms. # See the server config file for more # description. It's best to use # a separate .crt/.key file pair # for each client. A single ca # file can be used for all clients. # ca ca.crt # cert client.crt # key client.key
Append the following lines at the end of the file to match the server settings:
~/openvpn-clients/base/client.confauth SHA256 key-direction 1
Once you are done, the server configuration file should look something like this:
client
dev tun
proto udp
remote YOUR_SERVER_IP 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
cipher AES-256-CBC
verb 3
auth SHA256
key-direction 1
Next, create a simple bash script that will merge the base configuration and files with the client certificate and key, and store the generated configuration in the ~/openvpn-clients/configs
directory.
Open your text editor and create the following script:
nano ~/openvpn-clients/gen_config.sh
#!/bin/bash
FILES_DIR=$HOME/openvpn-clients/files
BASE_DIR=$HOME/openvpn-clients/base
CONFIGS_DIR=$HOME/openvpn-clients/configs
BASE_CONF=${BASE_DIR}/client.conf
CA_FILE=${BASE_DIR}/ca.crt
TA_FILE=${BASE_DIR}/ta.key
CLIENT_CERT=${FILES_DIR}/${1}.crt
CLIENT_KEY=${FILES_DIR}/${1}.key
# Test for files
for i in "$BASE_CONF" "$CA_FILE" "$TA_FILE" "$CLIENT_CERT" "$CLIENT_KEY"; do
if [[ ! -f $i ]]; then
echo " The file $i does not exist"
exit 1
fi
if [[ ! -r $i ]]; then
echo " The file $i is not readable."
exit 1
fi
done
# Generate client config
cat > ${CONFIGS_DIR}/${1}.ovpn <<EOF
$(cat ${BASE_CONF})
<key>
$(cat ${CLIENT_KEY})
</key>
<cert>
$(cat ${CLIENT_CERT})
</cert>
<ca>
$(cat ${CA_FILE})
</ca>
<tls-auth>
$(cat ${TA_FILE})
</tls-auth>
EOF
Save the file and make it executable with chmod
:
chmod u+x ~/openvpn-clients/gen_config.sh
Creating Client Certificate Private Key and Configuration
The process of generating a client private key and certificate request is the same as we did when generating a server key and certificate request.
As we already mentioned in the previous section, we’ll generate the client private key and certificate request on the OpenVPN server. In this example the name of the first VPN client will be client1
.
Navigate to the EasyRSA directory on your OpenVPN server and generate a new private key and a certificate request file for the client:
cd ~/EasyRSA-3.0.5/
./easyrsa gen-req client1 nopass
The command will create two files, a private key (
client1.key
) and a certificate request file (client1.req
).Common Name (eg: your user, host, or server name) [client1]: Keypair and certificate request completed. Your files are: req: /home/serveruser/EasyRSA-3.0.5/pki/reqs/client1.req key: /home/serveruser/EasyRSA-3.0.5/pki/private/client1.key
Copy the private key
client1.key
to the~/openvpn-clients/files
directory you created in the previous section:cp ~/EasyRSA-3.0.5/pki/private/client1.key ~/openvpn-clients/files/
Transfer the certificate request file to your CA machine:
scp ~/EasyRSA-3.0.5/pki/reqs/client1.req causer@your_ca_ip:/tmp
In this example we are using
scp
to transfer the file, you can also usersync
over ssh or any other secure method.Login to your CA machine, switch to the EasyRSA directory and import the certificate request file:
cd ~/EasyRSA-3.0.5
./easyrsa import-req /tmp/client1.req client1
The first argument is the path to the certificate request file and the second one is the client name.
The request has been successfully imported with a short name of: client1 You may now use this name to perform signing operations on this request.
From within the EasyRSA directory on CA machine run the following command to sign the request:
cd ~/EasyRSA-3.0.5
./easyrsa sign-req client client1
You’ll be prompted to verify that the request comes from a trusted source. Type
yes
and pressEnter
to confirm:If your CA key is password protected, you’ll be prompted to enter the password. Once verified the script will generate the SSL certificate and print the full path to it.
... Certificate created at: /home/causer/EasyRSA-3.0.5/pki/issued/client1.crt
Next, transfer the signed certificate
client1.crt
file back to your OpenVPN server. You can usescp
,rsync
or any other secure method:scp ~/EasyRSA-3.0.5/pki/issued/client1.crt serveruser@your_server_ip:/tmp
Login to your OpenVPN server, and move the
client1.crt
file into the~/openvpn-clients/files
directory:mv /tmp/client1.crt ~/openvpn-clients/files
The final step is to generate a client configuration using the
gen_config.sh
script. Switch to the~/openvpn-clients
directory and run the script using the client name as an argument:cd ~/openvpn-clients
./gen_config.sh client1
The script will create a file named
client1.ovpn
in the~/client-configs/configs
directory. You can check by listing the directory:ls ~/openvpn-clients/configs
client1.ovpn
At this point the client configuration is created. You can now transfer the configuration file to the device you intend to use as a client.
For example to transfer the configuration file to your local machine with scp
you should run the following command:
scp ~/openvpn-clients/configs/client1.ovpn your_local_ip:/
To add additional clients, just repeat the same steps.
Connecting Clients
Linux
Your distribution or desktop environment may provide a tool or graphic user interface to connect to OpenVPN servers. In this tutorial, we will show you how to connect to the server using the openvpn
tool.
Install OpenVPN on Ubuntu and Debian
sudo apt update
sudo apt install openvpn
Install OpenVPN on CentOS and Fedora
sudo yum install epel-release
sudo yum install openvpn
Once the package is installed, to connect to the VPN server use the openvpn
command and specify the client configuration file:
sudo openvpn --config client1.ovpn
macOS
Tunnelblick is a free, open-source graphic user interface for OpenVPN on OS X and macOS.
Windows
Download and install the latest build of OpenVPN application the OpenVPN’s Downloads page .
Copy the .ovpn
file to the OpenVPN config folder (\Users\<Name>\OpenVPN\Config
or \Program Files\OpenVPN\config
).
Launch the OpenVPN application.
Right click on the OpenVPN system tray icon and the name of OpenVPN configuration file you copied will be listed on the menu. Click Connect.
Android & iOS
A VPN application developed by OpenVPN is available for both Android and iOS. Install the application and import the client .ovp
file.
Revoking Client Certificates
Revoking a certificate means to invalidate a signed certificate so that it can no longer be used for accessing the OpenVPN server.
To revoke a client certificate follow the steps below:
Login to your CA machine and switch to the EasyRSA directory:
cd EasyRSA-3.0.5
Run the easyrsa script using the
revoke
argument, followed by the client name you want to revoke:./easyrsa revoke client1
You’ll be prompted to verify that you wish to revoke the certificate. Type
yes
and pressenter
to confirm:Please confirm you wish to revoke the certificate with the following subject: subject= commonName = client1 Type the word 'yes' to continue, or any other input to abort. Continue with revocation: yes ...
If your CA key is password protected, you’ll be prompted to enter the password. Once verified the script will revoke the certificate.
... Revocation was successful. You must run gen-crl and upload a CRL to your infrastructure in order to prevent the revoked cert from being accepted.
Use the
gen-crl
option to generate a certificate revocation list (CRL):./easyrsa gen-crl
An updated CRL has been created. CRL file: /home/causer/EasyRSA-3.0.5/pki/crl.pem
Upload the CRL file to the OpenVPN server:
scp ~/EasyRSA-3.0.5/pki/crl.pem serveruser@your_server_ip:/tmp
Login to your OpenVPN server server and move the file to the
/etc/openvpn
directory:sudo mv /tmp/crl.pem /etc/openvpn
Open the OpenVPN server configuration file:
sudo nano /etc/openvpn/server1.conf
Paste the following line at the end of the file
/etc/openvpn/server1.confcrl-verify crl.pem
Save and close the file.
Restart the OpenVPN service for the revocation directive to take effect:
sudo systemctl restart openvpn@server1
At this point, the client should no longer be able to access the OpenVPN server using the revoked certificate.
If you need revoke additional client certificates just repeat the same steps.
Conclusion
In this tutorial, you learned how to install and configure an OpenVPN server on a CentOS 7 machine.
If you are facing any problems, feel free to leave a comment.