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

When yum is done installing the required packages, copy the sample config file.

cp /usr/share/doc/openvpn-*/sample/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 dh4096.pem
ifconfig-pool-persist ipp.txt
push "redirect-gateway def1"
push "dhcp-option DNS"
keepalive 10 120
tls-auth ta.key 0 # This file is secret
key-direction 0
tls-version-min 1.2
tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA256
auth SHA512
cipher AES-256-GCM
#comp-lzo # Disable LZO compression
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/3/* /etc/openvpn/easy-rsa

Edit the following file and add these lines at the bottom of it:

vi /etc/openvpn/easy-rsa/vars
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 is 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 dh4096.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 certificate revoke/unrevoke

To revoke a client’s certificate run the following commands:

cd [easy-rsa path]
source ./vars
./revoke-all [certificate name]

Unrevoke a client’s certificate requires a few steps to be completed:

cd [easy-rsa path]
source ./vars
cd keys

# Unervoke a specific certificate
vi index.txt
# R in the first column means that the cert is revoked, V stands for verified
# To UNREVOKE a certificate replace the R with a V and then rebuild the CRL

# Rebuild the CRL
openssl ca -gencrl -out "crl.pem" -config "$KEY_CONFIG"

.:. 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 directory, I suggest using SCP or rsync 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, set LZO data compression to “no”.
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” containing what follows:

dev tun
remote vpn_server_IP_address 1194 udp
connect-retry 2 300
resolv-retry 60

# Downgrade privileges after initialization (non-Windows only)
user nobody
group nobody


key-direction 1
remote-cert-tls server
cipher AES-256-GCM
tls-cipher TLS-DHE-RSA-WITH-AES-256-CBC-SHA256
auth SHA512
verb 3

script-security 2
up /etc/openvpn/client.up
down /etc/openvpn/client.down


### keys ###
;ca ca.crt
;tls ta.key
;cert op3.crt
;key op3.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