Setup an OpenVPN server with certificate and two-factor authentication on CentOS 7


My goal was to have an OpenVPN server running, to which i can connect using different ports and by pipping it over an IP over ICMP tunnel (the latter will follow in another post).

Ports i want to use:

  • 1194/udp – The default OpenVPN port
  • 53/udp – If im lucky and the network has DNS open by default…
  • 1195/udp – A local port i use when pipping it over an ICMP tunnel (requires a slightly modified config and is not part of this tutorial)

You may also want to add port 443/tcp for example as another option. This is quite easy to achieve thanks to Systemd on CentOS 7.


First make sure you have the EPEL repository installed (i’m sure you will find out how).


(If you now think about disabling SELinux, stop here and install Windows…)

Allow the OpenVPN service to run on another than the default port (53/udp in my case):

To view which ports are currently allowed use this command:

Install required packages



Set all the values needed to generate the certificates within /etc/openvpn/rsa/vars:

Load the values we just set and build all the certificates we need:

OpenVPN configuration

Now open the OpenVPN configuration (/etc/openvpn/port1194udp.conf) and set all these values:


(If you want to install iptables, seriously, think about to move to Windows… 😉 )

Open the ports used for OpenVPN (The ones YOU finally will use):


Add the following config to /etc/sysctl.conf:

And apply it:

Google Authenticator

There’s no Google Authenticator package available for CentOS 7 (end 2016), but the package from Fedora 23 works just fine (check for the most current version!)

NOTE: Use the user and settings exactly as described below. PAM is very very sensible to wrong permissions and will block authentication if permissions and users are not set correctly.

Add the user to run google-authenticator as and set the correct permissions:

To allow updates of the users Google Authenticator config we have to set this additional SELinux context:

To make generating of Google Authenticator codes easier i wrote this script (/root/

Make it executable:

Create a new user and its password, and generate the GA token:

The output will be like this:

Install the GA token using the QR code or entering the secret manually.


Create the file /etc/pam.d/openvpn and add this configuration:


Enable and start OpenVPN:

Test it

Now it’s time to test if everything works fine.

Copy all required certificates to your client (“ca.crt”, “<username>.key” and “<username>.crt”).

Create a new OpenVPN config on your client, add the certificates and modify the config as i have it in my Viscosity client:
NOTE: is my local network i don’t want to be routed through the tunnel.
OpenVPN Settings - General OpenVPN Settings - Authentication OpenVPN Settings - Options OpenVPN Settings - Networking OpenVPN Settings - Proxy OpenVPN Settings - Advanced

NOTE: To enter the GA token you have to enter you password followed by the code (<password><token>)
Now try to connect and hope everything is fine. If the authentication fails, check these logs:

  • /var/log/audit/audit.log
  • /var/log/secure

Additional ports

If you want to run it on multiple ports you can do two things:

  1. Simply NAT different external ports to the same port (1194/udp) behind your firewall. This works fine if you can use the same configuration for all of them.
  2. If you want to be able to use UDP and TCP in parallel, or the configuration has to be different in any other way (f.ex. if using an additional ICPM tunnel in my case) you have to run multiple instances with different configurations.

Tasks you have to do to have an additional instance:

  • Copy the configuration (f.ex. to “port53udp.conf”) and change the port and whatever else you want to change
    IMPORTANT: Also change the tunX number and the IPv4 and IPv6 addresses (f.ex. to / 2001:aaaa:bbbb:13::X)
  • Allow OpenVPN to run on this port (see “semanage” commands above)
  • For IPv6 add the required firewalld rules (see “firewall-cmd” commands above)
  • Enable and start the additional service (f.ex. “openvpn@port53udp.service”, simply use the new configuration name behind the @)
  • Copy your config on your client and make the changes there too
This entry was posted in CentOS, Firewalls, Linux, OpenVPN, Security, VPN and tagged , , . Bookmark the permalink.

2 Responses to Setup an OpenVPN server with certificate and two-factor authentication on CentOS 7

Leave a Reply

Your email address will not be published. Required fields are marked *