OpenVPN server and CentOS

OpenVPN is the de facto standard VPN free open source software; it is widely used, tested, well documented and also included in the CentOS repos (EPEL).

.:. Server side configuration

yum install openvpn easy-rsa dnsmasq

Once it’s installed, copy the sample config file.

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

Uncomment/edit the following lines in /etc/openvpn/server.conf:

port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1 bypass-dhcp"
push "dhcp-option DNS"
keepalive 10 120
tls-auth ta.key 0 # This file is secret
key-direction 0
tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA256
auth SHA256
cipher AES-256-CBC
status openvpn-status.log
;log         openvpn.log   # disable log, optional
;log-append  openvpn.log   # disable log, optional
user nobody
group nobody

Now, create two folders easy-rsa/keys in /etc/openvpn and copy some files into them:

mkdir -p /etc/openvpn/easy-rsa/keys
cp -rf /usr/share/easy-rsa/2.0/* /etc/openvpn/easy-rsa

Open with a text editor vars file…

vi /etc/openvpn/easy-rsa/vars

…and edit these lines at the bottom of it:

export KEY_COUNTRY="***"
export KEY_PROVINCE="***"
export KEY_CITY="***"
export KEY_ORG="***"
export KEY_EMAIL="***"
export KEY_CN=***
export KEY_NAME=***
export KEY_OU=***

Now it’s time to build our own Certificate Authority:

cd /etc/openvpn/easy-rsa
source ./vars

NOTE: in case CentOS fail to detect OpenSSL version manually copy openssl-version_used.cnf file to /etc/openvpn/easy-rsa/:

cp /etc/openvpn/easy-rsa/openssl-1.0.0.cnf /etc/openvpn/easy-rsa/openssl.cnf

The next step consist in creating the certificate for the server, a Diffie Hellman key and then copy them in to the parent folder (/etc/openvpn):

./build-key-server server
cd /etc/openvpn/easy-rsa/keys
cp dh2048.pem ca.crt server.crt server.key /etc/openvpn
cd /etc/openvpn
openvpn --genkey --secret ta.key

Build a certificate for each client (replace “client” with the hostname of the client or something that can be used to identify it):

cd /etc/openvpn/easy-rsa
./build-key client

Enable IPv4 forwarding in /etc/sysctl1.conf:

vi /etc/sysctl.conf
net.ipv4.ip_forward = 1

Configure dnsmasq to resolve domain names:

vi /etc/dnsmasq.conf

Edit systemd unit script to instruct dnsmasq to wait for tun0 to be up:

cp /usr/lib/systemd/system/dnsmasq.service /etc/systemd/system
vi /etc/systemd/system/dnsmasq.service

Apply settings, start dnsmasq, start OpenVPN daemon and set it to automatically start at boot with:

/sbin/sysctl -p
service openvpn start
chkconfig openvpn on

## or, if using CentOS 7
systemctl enable dnsmasq
systemctl start dnsmasq
systemctl enable openvpn@server
systemctl start openvpn@server

Last thing to do is instruct iptables to allow connections on UDP ports 53 and 1194 and properly route requests:

iptables -A FORWARD -i tun0 -o eth0 -j ACCEPT 
iptables -A FORWARD -i eth0 -o tun0 -j ACCEPT 
iptables -A POSTROUTING -s -o eth0 -j MASQUERADE 
iptables -A INPUT -p udp -m udp --dport 53 -j ACCEPT
iptables -A INPUT -p udp -m udp --dport 1194 -j ACCEPT
service iptables save
service iptables restart

Other useful commands are:

### list the current rules, tables and chains
service iptables status
### delete the first (1) line of Table=nat and Chain=POSTROUTING
iptables -t nat -D POSTROUTING 1
### search and delete the matching rule
iptables -D INPUT -p udp -m udp --dport 1194 -j ACCEPT
### check open connections
netstat -lnptu

.:. Client side configuration

First of all we have to retrieve the certificates from the server and put them in a folder called “.cert” located in the user’s home folder, I suggest using SCP to move the files from server to client (an SSH server must be installed and configured).

scp file... user@host.domain:path
scp user@host.domain:path ... dest

In Fedora 18 + XFCE configuration is all done via GUI, open the Network Manager (from the tray or from Applications Menu) and add a new VPN.
Set a VPN name, a gateway (IP address of the server), import the keys and, from Advanced menu, enable LZO data compression.
If SELinux is enabled we should also apply the correct security context to our keys, in my case the keys are in “/home/mafio/.cert”, so “chcon -t cert_t /home/mafio/.cert/*”.
This is it, you should now be able to connect to the VPN server and reach the internet through it.

The standalone way to connect to an OpenVPN server is create a file called “client.ovpn” with what follow in it:

dev tun
proto udp
remote 1194
resolv-retry infinite

# Downgrade privileges after initialization (non-Windows only)
# If enabled doest not work anymore because of insufficient privileges
#user nobody
#group nobody


key-direction 1
ns-cert-type server
# openvpn --show-ciphers
cipher AES-256-CBC
# openvpn --show-tls
tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA256
# openvpn --show-digests
auth SHA256
verb 3

# Non windows only
script-security 2
up /etc/openvpn/
down /etc/openvpn/


### keys ###
;ca ca.crt
;tls ta.key
;cert client.crt
;key client.key
### Content of ca.crt
### Content of ta.key
### Content of client.crt
### Content of client.key

Script client.down and client.up can be found in /usr/share/doc/openvpn/contrib/pull-resolv-conf/ and are used to enforce DNS pushed by OpenVPN server.
To use the VPN simply run the following command.

sudo openvpn --config ~/path/to/client.ovpn
look at the "About me" page.


  1. Did you have to enable or download a particular repo? I just installed CentOS 6.4 and openvpn isn’t in the default enabled repos.

Leave a Comment

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