Setting up your own VPN Server Using OpenVPN

Upendra Kumarage
8 min readMay 3, 2020

Recently, I was assigned with a task to build a VPN server using OpenVPN. OpenVPN itself provided an extensive set of documentation on how to built your own VPN server using OpenVPN. But for someone who is new to Linux and related networking domain may feel these documentations are overwhelming. Also, I had to refer some other resources apart from the OpenVPN documentation since some of the tools which were used have been updated and so forth.

So, I thought that it would be better if I can share the steps I followed in building the VPN Server with others in a simplified manner. Specially, there are techies who would like to try out such implementations on their own for testing and to gain additional knowledge. This high level guide lines will help them in such cause. The learning curve is always flattened when it is begin with simple steps.

A VPN, or Virtual Private Network is used to create a secure connection to another network over the internet. They originally were a way to connect business networks together securely over the internet or allow users to access a business network from different geographical locations. The main benefits of using a VPN connection in a business domain are improved security and the remote access.

The steps are followed here, have been performed in an instance deployed in Google cloud compute engine. There could be many alternative methods apart from these steps as well. Reference [1] was the main document followed in configuring and deploying the VPN Server using OpenVPN.

VM Instance specifications

These specifications are provided based on Google Cloud Compute Engine Instances. Here, it has not discussed on how to create a VM in GCP compute engine and on the GCP firewall rule implementation for the VM as it would increase the length of this article. You can refer GCP documentation on spinning up a VM instance and applying Firewall rules.

  • n1-standard-1 (1 vCPU, 3.5 GB memory) Instance.
  • CentOS 7 or higher
  • Specific region where you want your instance in
  • IP forwarding should be enabled when you are launching the instance
  • Public IP address which is being allocated to the VM instance should make static
  • If it is planning to direct the vpn log files to different partition other than boot disk, then it is required to attach an additional persistent disk.
  • Ports 22 tcp and 1194 udp must be allowed through the firewall

Downloading and installing OpenVPN

Let’s start with updating the package manager

yum update

Since we are going to install OpenVPN from the source, the following dependencies must be installed first,

  1. Development Tools
  2. openssl-devel
  3. lzo-devel
  4. pam-devel
yum groupinstall “Development Tools”
yum install openssl-devel lzo-devel pam-devel

Once completed installing the required dependencies, the next step is to download OpenVPN. Here, we have several choices of downloading OpenVPN. In this documentation, it has been proceeded with downloading the source package and build. One can also use the methods like rpm install and so forth. Also we can choose different versions to download as well. I have used the OpenVPN version 2.4.8 for setting up the VPN Server.

wget command used to download OpenVPN tarball. If your VM instance does not have wget installed, then it is required to install wget as well.

wget https://swupdate.openvpn.org/community/releases/openvpn-2.4.8.tar.gz

Once the download is completed, extract the tar ball,

tar -xvf openvpn-2.4.8.tar.gz

cd into the extracted directory and check the files. You will receive an output similar to below,

We can follow the README guide to build OpenVPN. Alternatively, mentioned below is the step you need to take

  • ./configure
  • make
  • make install

Once the installation is completed, you can find the documentation related to OpenVPN in the location /usr/local/share/doc/openvpn. This location can be depend upon the OS.

Optionally you can copy these docs to /etc as it would be much easier to access and continue to setup server configurations and keys. Here, I have copied these docs to /etc for the ease of use and reference.

cp -r /usr/local/share/doc/openvpn /etc

Setting up your own certificate authority (CA) and generating certificates and keys

In order to build a VPN service, it is required to establish a PKI (public key infrastructure). This is the first step in setting up a VPN.

The PKI consists of,

  1. A separate certificate (also known as a public key) and private key for the server and each client
  2. A master Certificate Authority (CA) certificate and key which is used to sign each of the server and client certificates

To proceed with establishing PKI, easy-rsa is used. If easy-rsa is not already installed, then the first step should be installing easy-rsa. In older version of easy-rsa, configuration settings are different than the ones provided below. So you need to be mindful on that as well.

yum install easy-rsa

Then copy easy-rsa directory to our previously copied OpenVPN directory in /etc

cp -r /usr/share/easy-rsa/ /etc/openvpn/

If easy-rsa is a fresh install, you might find several versions there. If so, move the newest one directly easy-rsa/ directory. This would be easy work with, and remove the older versions so that working directory would be clear.

Initialization of PKI,

./easyrsa init-pki

Generate CA (Certificate Authority),

Here, it will be prompted for CA name, passphrase for CA and several other content. It is suggested to provide the appropriate CA name and a strong passphrase for CA. Also passphrase for the CA should be well secured and if required to communicate, it is recommended to use a secure method for this as well.

./easyrsa build-ca

Generate the certificate and the key for VPN server,

Here, the keys are generated with nopass option to avoid providing a passphrase since these keys will be used for VPN server itself.

./easyrsa gen-req server nopass
./easyrsa sign-req server server
(sign the created server certificate using the created CA)

Generate certificates and keys for clients,

The server can enforce client-specific access rights based on embedded certificate fields such as the Common Name. It is suggested to use a proper naming convention when you use a common name for your client certificates.

./easyrsa gen-req client1
./easyrsa sign-req client1

On the PKI for the OpenVPN server, this command will generate DH parameters used during the TLS handshake with connecting clients

./easyrsa gen-dh

Generate tls-auth key for hardening OpenVPN security,

It is recommended to move the created tls key to ../easy-rsa/pki/private directory as all the generated keys will be stored in the same location and it would make ease in managing the keys

openvpn — genkey — secret ta.key or /usr/local/sbin/openvpn — genkey — secret ta.key

VPN Server Configuration

The VPN Server configuration is the most important part of VPN Server. Here, it is defined how the VPN Server should work. You can find a sample server configuration and client configuration files in the extracted OpenVPN directory which you downloaded originally. Copy a sample server.conf file to your copied OpenVPN directory in /etc directory. It is much convenience to edit the sample configuration file rather than creating a new one from the scratch.

Here, it is only mentioned about the core configurations which were used to create a VPN Server using OpenVPN. However you can refer OpenVPN documentation for further customization which you may feel necessary.

Which TCP/UDP port should OpenVPN listen on?
port 1194
TCP or UDP server?
proto udp
“dev tun” will create a routed IP tunnel
dev tun
CA, Server Certificate and Server Key locations
ca /etc/openvpn/easy-rsa/pki/ca.crt
cert /etc/openvpn/easy-rsa/pki/issued/server.crt
key /etc/openvpn/easy-rsa/pki/private/server.key
Diffie hellman parameters
dh /etc/openvpn/easy-rsa/pki/dh.pem
Configure server mode and supply a VPN subnet
server 10.8.0.0 255.255.255.0

In here, you can choose your required subnet range from the following. However it is recommended to setup the subnet as per your requirement. If you are doing this for testing purposes, then you can directly use the subnet in example server configuration file which we copied earlier

10.0.0.0 10.255.255.255 (10/8 prefix)
172.16.0.0 172.31.255.255 (172.16/12 prefix)
192.168.0.0 192.168.255.255 (192.168/16 prefix)

If clients to be able to “see” each other,
client-to-client
tls-authentication key file location
tls-auth /etc/openvpn/easy-rsa/3.0.6/pki/private/ta.key 0 (The second parameter should be ‘0’ on the server and ‘1’ on the clients)
Output a short status file showing current connections, truncated and rewritten every minute
status openvpn-status.log
By default, log messages will go to the syslog use log or log-append to override this default
log-append /log/file/location/openvpn.log
Set the appropriate level of log
verb 3
Routing all traffic, including web traffic through the VPN server
push “redirect-gateway autolocal def1”
push “dhcp-option DNS 8.8.4.4”
push “dhcp-option DNS 8.8.8.8”

Create a custom Systemd Service for OpenVPN

Create a file named vpnserver.service and add the following content. You can customize this as well for your preference,

[Unit]
Description=OpenVPN connection
After=network.target
[Service]
Type=forking
ExecStart=/usr/local/sbin/openvpn — daemon ovpn — status /run/openvpn.tatus 10 — cd /etc/openvpn — config /etc/openvpn/server.conf
ExecReload=/bin/kill -HUP $MAINPID
WorkingDirectory=/etc/openvpn
[Install]
WantedBy=multi-user.target

Once completed, copy the created vpnserver.service file to

/etc/systemd/system

Now, using the systemctl command the VPN Server can be start, stop and check status.

systemcl status vpnserver
systemcl start vpnserver
systemcl stop vpnserver

VPN Client Configuration

Here also, it has only mentioned the configuration which needed to establish a connection with the VPN Server. However you can refer OpenVPN documentation for further customization which you may feel necessary.

Furthermore, it has used the sample client.conf file provided with the OpenVPN bundle as it is more convenient to use rather than building the file from the scratch.

Here, CA, Client Certificate, Client Key and tls-auth key have been used by embedding their content. These files can be used separate as well.

Specify that we are a client
client
“dev tun” will create a routed IP tunnel. Use the same setting as you are using on server
dev tun
Are we connecting to a TCP or UDP server
proto udp
The hostname/IP and port of the server
remote server_public_ip or DNS 1194
Try to preserve some state across restarts
persist-key
persist-tun
SSL/TLS parms
key-direction 1
remote-cert-tls server
Set log file verbosity
verb 4
<ca>
Add CA output here. The content start and end with
— — -BEGIN CERTIFICATE — — -
— — -END CERTIFICATE — — -
</ca>
<cert>
Add client certificate output here. The content start and end with
— — -BEGIN CERTIFICATE — — -
— — -END CERTIFICATE — — -
</cert>
<key>
Add client key output here. The content start and end with
— — -BEGIN ENCRYPTED PRIVATE KEY — — -
— — -END ENCRYPTED PRIVATE KEY — — -
</key>
<tls-auth>
Add ta.key output here. The content start and end with
— — -BEGIN OpenVPN Static key V1 — — -
— — -END OpenVPN Static key V1 — — -
</tls-auth>

OS Level Network Configuration for Routing traffic

Once server configuration is completed, it is required to setup network configurations. This allows VPN Server to route traffic. You can refer iptable rules for further understanding.

It was mentioned that the IP forwarding should be enabled when the VM is being launched. Following commands can be used to check and enable IP forwarding.

sysctl net.ipv4.ip_forward
sysctl -w net.ipv4.ip_forward=1

The following iptables rules were used for network configuration.

iptables -t nat -A POSTROUTING -s v.v.v.v/V -o venet0 -j SNAT — to x.x.x.x
iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

Here,

v.v.v.v is the vpn subnet defined in server.conf (etc 10.8.0.0)
V refers to the subnet mask defined in server.conf ( etc /24)
x.x.x.x refers to the public IP address of the VM

References

[1] https://openvpn.net/community-resources/how-to/

[2] https://openvpn.net/community-resources/setting-up-your-own-certificate-authority-ca/

[3] https://openvpn.net/community-resources/hardening-openvpn-security/

[4] https://ipwithease.com/snat-vs-dnat/

[5] https://cloud.google.com/compute/docs/instances/create-start-instance

[6] https://cloud.google.com/vpc/docs/using-firewalls

[7] https://www.howtoforge.com/nat_iptables

--

--

Upendra Kumarage

Cloud & DevOps enthusiast, Cloud Operations professional