Mountain%20Landscape_edited_edited.jpg
  • Hannah Lee

Personal VPN Setup with OpenVPN 2.5.2 on CentOS



This tutorial will show you how to setup a basic self-maintaining VPN server with OpenVPN 2.5.2 and CentOS 7. I mean "self-maintaining" in that it will update packages and run anti-virus scans automatically on a schedule with crontab, so all you ever need to do is login to create new client profiles for your friends. And I guess troubleshoot if/when it crashes.


Why host your own VPN? It's not the best solution for everyone. Check out my article on VPN's here.




STARTING CONFIGURATION:


NOTE: This tutorial implements non-standard port 50001 as the OpenVPN port. Standard port is 1194.



Step 1: Update and Install


a. Login to your root account.



b. Update packages:

yum -y update

c. Install extras:

yum install -y epel-release yum-plugin-copr firewalld wget nano
yum copr -y enable dsommers/openvpn-release

d. Install OpenVPN and EasyRSA:

yum install openvpn easy-rsa

e. Copy server.conf example to /etc/openvpn/server:

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

Make sure you check your version of OpenVPN and update this line accordingly. Check

version with:

yum list openvpn	

f. Make easy-rsa directory:

mkdir /etc/openvpn/easy-rsa

g. Copy EasyRSA files to /etc/openvpn/easy-rsa/:

cp -r /usr/share/doc/easy-rsa-3.0.8/vars.example /etc/openvpn/easy-rsa/
cp -r /usr/share/easy-rsa/3.0.8/* /etc/openvpn/easy-rsa/

Also ensure you check your version of EasyRSA and update line accordingly:

yum list easy-rsa

Tip: "No such file or directory"?




Step 2: Configure server.conf


a. Open the server.conf file to edit:

nano /etc/openvpn/server/server.conf

b. Uncomment these lines:

topology subnet 
push "redirect-gateway def1 bypass-dhcp" 
user nobody 
group nobody 
push "dhcp-option DNS 208.67.222.222" 
push "dhcp-option DNS 208.67.220.220" 

NOTE: CHOOSE YOUR DNS SERVER WISELY. Some DNS servers log your data, and not all implement DNSSEC. In addition, make sure you implement DNS security to secure DNS traffic outgoing from your server. Check out my tutorial on encrypting your VPN server's DNS traffic.


OPTIONAL:

duplicate-cn 

c. Find and change these lines:

dh dh2048.pem --> dh /etc/openvpn/dh.pem
ca ca.crt --> ca /etc/openvpn/ca.crt
tls-auth ta.key 0 --> tls-crypt /etc/openvpn/myvpn.tlsauth
port 1194 --> port 50001

d. Add this line anywhere:

askpass

e. Save and exit server.conf




Step 3: Configure vars


a. Change directory into the easy-rsa directory:

cd /etc/openvpn/easy-rsa/

b. Change the name of the vars template to "vars":

mv vars.example vars

c. Open vars to edit:

nano vars

d. Uncomment these lines and fill in the fields with your info (or just leave as-is):


set_var EASYRSA_REQ_COUNTRY "US"
set_var EASYRSA_REQ_PROVINCE "New York"
set_var EASYRSA_REQ_CITY "New York City"
set_var EASYRSA_REQ_ORG "Organization"
set_var EASYRSA_REQ_EMAIL "email@email.com"
set_var EASYRSA_REQ_OU "Organizational Unit"

e. Add the following lines at the end:

export KEY_NAME="server"
export KEY_CN=openvpn.yourdomain.com		#optional

f. Save and exit vars.




Step 4: Generate certificates and keys


a. Change directory into the easy-rsa directory:

cd /etc/openvpn/easy-rsa

b. Run clean-all:

./easyrsa clean-all

c. Build the Certificate Authority (CA) certificate:

./easyrsa build-ca

Follow prompts to set CA common name and passphrase; you will need this

passphrase every time you do anything with Easy-RSA.


d. Build server certificate:

./easyrsa build-server-full server

Follow prompts to set server certificate passphrase and sign with CA passphrase.


e. Generate the Diffie-Hellman key exchange file:

./easyrsa gen-dh

f. Generate the TLS static key:

openvpn --genkey secret /etc/openvpn/myvpn.tlsauth


Step 5: Move all the files in place


a. Change directory into the pki directory:

cd /etc/openvpn/easy-rsa/pki/

b. Copy the Diffie-Helman key exchange file and the CA certificate to /etc/openvpn:

cp dh.pem ca.crt /etc/openvpn/

c. Change directory into the private directory:

cd /etc/openvpn/easy-rsa/pki/private

d. Copy the server private key to /etc/openvpn/server:

cp server.key /etc/openvpn/server

e. Change directory into the issued directory:

cd /etc/openvpn/easy-rsa/pki/issued

f. Copy the server certificate to /etc/openvpn/server:

cp server.crt /etc/openvpn/server


Step 6: Generate Clients


a. Install gen-ovpn-client script:

nano /usr/local/bin/gen-ovpn-client

Paste this script into the file:

#!/bin/sh

#*****MUST CHANGE***REPLACE WITH YOUR PUBLIC IP*****
PUBLICIP="0.0.0.0"

#SERVERPORT: OpenVPN Port on this server. Standard OpenVPN port is 1194.
SERVERPORT="50001"

#LOCALPORT: Client's outgoing port. Standard is 1194. If changed, alert 
#clients to adjust their
#firewalls accordingly.
LOCALPORT="50001"

echo "Client Name: "
read clientname

#EasyRSA Directory; update path if needed
cd /etc/openvpn/easy-rsa/

/etc/openvpn/easy-rsa/easyrsa build-client-full $clientname

#Generating client in /etc/openvpn/client/
profilename="$clientname.ovpn"
touch /etc/openvpn/client/$profilename

printf "client\nverb 4\nconnect-retry 2 300\nresolv-retry 60\ndev tun\nremote $PUBLICIP $SERVERPORT\n--float\nlport $LOCALPORT\n<ca>\n" >> /etc/openvpn/client/$profilename

#ca.crt; update path if needed
cat /etc/openvpn/ca.crt >> /etc/openvpn/client/$profilename

printf "</ca>\n<key>\n" >> /etc/openvpn/client/$profilename

#client private key; update path if needed
cat /etc/openvpn/easy-rsa/pki/private/$clientname* >> /etc/openvpn/client/$profilename

printf "</key>\n<cert>\n" >> /etc/openvpn/client/$profilename

#client certificate; update path if needed
cat /etc/openvpn/easy-rsa/pki/issued/$clientname* >> /etc/openvpn/client/$profilename

printf "</cert>\n<tls-crypt>\n" >> /etc/openvpn/client/$profilename

#static TLS auth key; update path if needed
cat /etc/openvpn/myvpn.tlsauth >> /etc/openvpn/client/$profilename

printf "</tls-crypt>\n" >> /etc/openvpn/client/$profilename

echo "The client profile is located at /etc/openvpn/client/$profilename"

b. Find "PUBLICIP" variable in gen-ovpn-client and update with your public IP:

PUBLICIP="0.0.0.0"

c. Save and exit gen-ovpn-client.


d. Update permissions to gen-ovpn-client to allow execution:

chmod 755 /usr/local/bin/gen-ovpn-client

e. Run gen-ovpn-client:

gen-ovpn-client

Follow the prompts to enter client name and client password. Client profiles will be

automatically generated in /etc/openvpn/client. This script can also be used to generate

profiles for existing clients; just enter the name of the client at the first prompt and it will

skip the client generation to generate the profile.




Step 7: Adjust Configurations



a. Start and enable firewalld:

systemctl start firewalld
systemctl enable firewalld

b. Add firewall configurations:

firewall-cmd --zone=public --add-port=50001/udp --permanent  
firewall-cmd --zone=public --add-masquerade --permanent
firewall-cmd --zone=public --add-interface=tun0 --permanent
firewall-cmd --reload


c. Enable port forwarding in sysctl.conf:

nano /etc/sysctl.conf

Add the following to the top of the file:

net.ipv4.ip_forward = 1

Restart the network service.

systemctl restart network.service

d. Enable OpenVPN to bind to port 50001 in SELINUX:

semanage port -a -t openvpn_port_t -p udp 50001

e. Open UDP port 50001 in any other firewalls between your server and the internet. For example, your router firewall or your cloud security firewall.


f. Start OpenVPN:

systemctl start openvpn-server@server

Enter server password when prompted.

Check status:

systemctl status openvpn-server@server -l

It should say "active (running)".




Step 8: Test VPN


a. Find your client profile at /etc/openvpn/client (file will have .ovpn extension).


b. Download it to your client machine (or just copy-and-paste if you're on puTTY).


c. Try it out:


Linux terminal:

	sudo openvpn /path/to/client.ovpn

GUI client for Windows/Mac/iOS/Android/Linux:

1. Download OpenVPN Client here.

2. Import client profile.

3. Connect to VPN.



Step 9: Install Antivirus Software and Add Cron Jobs


NOTE: ClamAV is a free, opensource antivirus software solution, but it's not perfect. If you have a preferred alternative, feel free to use that and skip this step. Antivirus software has a significant overhead, but it's important --especially if you have different users connecting to your VPN whose devices you can't control.


a. Install ClamAV:

yum install clamav

b. Update antivirus signatures:

freshclam

c. Test clamscan:

clamscan -r /home

This scans the home directory recursively and return a report on the files scanned.


d. Make log directory for clamscan:

mkdir /var/log/clamscan

e. Add cron jobs:

***This must be done on the root account so that all files can be scanned***

crontab -e

Add the following lines:



###################################################################
#THESE JOBS SCHEDULE ROUTINE UPDATES AND SCANS TO MAKE THE MOST
#EFFECTIVE USE OF LIMITED MEMORY TO AVOID MEMORY ALLOCATION ERRORS. 
#YOU MAY NEED TO SPLIT UP SCANS FURTHER DEPENDING ON THE LOAD
#ON YOUR SERVER. CLAMAV IS NOT A 100% SOLUTION, BUT SCHEDULING
#ROUTINE SCANS THAT SOMETIMES FAIL IS BETTER THAN NOT SCANNING AT ALL.
###################################################################

# Updates all packages every Monday at 1:01 AM
1 1 * * 1 yum -y update; echo "$(date) UPDATED" >> /var/log/update.log

# Runs antivirus scans every day at 2 AM. The / directory is split up into seven days, so the entire / directory is scanned once a week.

# Delete "--remove" if you want to review the files to ensure they are infected before removal

1 2 * * 1 clamscan --remove / | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 
08 2 * * 1 clamscan -r --remove /bin | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 
15 2 * * 1 clamscan -r --remove /boot /dev | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 
22 2 * * 1 clamscan -r --remove /tmp | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log

1 2 * * 2 clamscan -r --remove /etc | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 
08 2 * * 2 clamscan -r --remove /home /lib | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 

1 2 * * 3 clamscan -r --remove /lib64| tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 
8 2 * * 3 clamscan -r --remove /lost+found /media /mnt | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 

1 2 * * 4 clamscan -r --remove /opt | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 
08 2 * * 4 clamscan -r --remove /proc /root | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 

1 2 * * 5 clamscan -r --remove /run | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 
8 2 * * 5 clamscan -r --remove /sbin | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 
15 2 * * 5 clamscan -r --remove /srv | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 

1 2 * * 6 clamscan -r --remove /sys | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log 
8 2 * * 6 clamscan -r --remove /var| tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log

1 2 * * 7 clamscan -r --remove /usr/sbin | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log
8 2 * * 7 clamscan -r --remove /usr/bin | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log
15 2 * * 7 clamscan -r --remove /usr/include /usr/lib /usr/etc /usr/games| tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log
22 2 * * 7 clamscan -r --remove /usr/lib64 | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log
29 2 * * 7 clamscan -r --remove /usr/libexec /usr/local /usr/share /usr/src | tee -a /var/log/clamscan/$(date +"\%b-\%d-\%y-\%H-\%M").log


# Deletes all clamscan logs olders than 30 days
30 3 * * * find /var/log/clamscan/ -type f -mtime +30 -delete

IMPORTANT: The "--remove" option of clamscan is unpredictable. It may detect a false

positive and delete an important, uninfected file. If you remove this option, you must

ensure you are routinely checking the logs for infected files (although this means it's no

longer self-maintaining....)



Step 10: DONE!


Thanks for sticking it out with me. Again, this setup doesn't secure your VPN's DNS traffic. Head over to my DNSCrypt-Proxy tutorial to put your VPN security on-par with the big-name VPN services.


If you want recommendations on VPS hosting services, I personally use LunaNode and Vultr. I mainly selected these providers based on available server locations, low price, security features, and overall quality of service.


I hope this was useful. Let me know if I missed anything!