This post was last tested and updated for Ubuntu 24.04 LTS.

A VPN is a way to encrypt the data traffic from A to B. For Internet browsing, it is NOT necessarily end-to-end encrypted.

There are many reasons why a VPN is necessary:

  • Connect from home to the office over the public Internet (sensitive information),
  • Hide your communication from the network administrator (ISP, Hotel, WiFi, etc),
  • Access content restricted by region (streaming, ACL, etc),
  • Download copyrighted/censored material,
  • More

What are the alternatives to VPN and what type of “protection” do they offer?

Expected Internet Service Provider Incognito Mode Public VPN Private VPN (truly end-to-end) Tor Network Only Tor Browser Observations
Tracking Protection NO NO NO NO Tunneling your traffic over an encrypted network does not make tracking any more difficult at all! All the identifiable information goes through the tunnel anyway.
Fingerprinting Protection NO NO NO NO NO Only the Tor Browser removes/replaces identifiable information (fingerprints) and makes all users look the same.
Geo-blocking Evasion NO NO Geo-blocking is usually done by IP (e.g. streaming). This is one of the most popular uses of VPN for the general public.
Man-in-the-middle Protection NO NO NO NO NO Tunneling your traffic over third-party networks is always susceptible to MITM attacks. Even Tor Exit nodes should never be trusted.

NOTE: websites with SSL/TLS (HTTPS) are end-to-end encrypted between the browser and the server (e.g. internet banking via browser or app). Even though, your ISP or network administrator may know you are connecting to your bank, email, etc they cannot see the content of the communication or tamper the information. On the other hand, if you are torrenting using a Public VPN service, the VPN provider can see what you are doing in plain text, but the whole internet can’t see you behind the VPN server, and your traffic is mixed with the traffic of many other users. Keep this in mind!


DEPLOYING A PRIVATE VPN SERVER

Begin downloading the installation script:

wget https://git.io/vpn -O openvpn-install.sh

If the command above does not download the script, try getting it from the source GitHub – Nyr/OpenVPN Install [Link] or [OpenVPN-Install]

chmod -v +x openvpn-install.sh
sudo ./openvpn-install.sh

Just answer a few questions the script will ask. It is recommended to use:

First question: UDP;
Second question: default port 1194;
Third question: Google DNS;
The fourth question is the name you want to give to the specific client you are creating, for exemple: client1

The script created one configuration file that is located in /root/client1.ovpn (note the given name identifies the file).

This file has to be sent to configure the client’s computer. It is recommended to use one encrypted transfer method such as:

scp [user]@[ip or hostname of the server]:/root/client1.ovpn .

The service is already running in the server and can be commanded:

sudo systemctl stop [email protected]
sudo systemctl start [email protected]
sudo systemctl restart [email protected]
sudo systemctl status [email protected]

From the client-side (a desktop Linux computer, for example), issue the following commands:

dig +short myip.opendns.com @resolver1.opendns.com
sudo apt install openvpn
sudo cp client1.ovpn /etc/openvpn/client.conf
sudo systemctl start openvpn@client
ping 10.8.0.1 -c 2
dig +short myip.opendns.com @resolver1.opendns.com

If you follow the commands in the same order, the first will request the public IP that you are physically connected to (your residential internet provider or the public wifi you are connected to the internet).

The fourth command will connect to the VPN.

The fifth command will try to ping twice the VPN server through the VPN tunnel that just started.

The Sixth command will check again the public IP, but this time will give you the public IP of your VPN server. Check it!

Note that on the client-side the VPN will run as a service and will always start on boot. You can enable or disable the auto startup of this service by issuing:

sudo nano /etc/default/openvpn

Look for and uncomment the line AUTOSTART=”none” to prevent it from autostarting.

For configuring OpenVPN Client in pfSense see the next post [Link].


CUSTOMIZING CLIENT-SIDE: /etc/openvpn/client.conf

  • pull-filter ignore “redirect-gateway”
    • Use this line to ignore the tunneling of all traffic. Only traffic to the VPN network will be tunneled.
  • dhcp-option DNS 10.8.0.254
    • Force the DNS server to the VPN connection only for this client. The DNS servers acquired during the connection will have lower priority.
  • dhcp-option Domain test.local
    • Force the Domain server to the VPN connection only for this client. It is useful for Active Directory and also can be used with the Domain option.

CUSTOMIZING SERVER-SIDE: /etc/openvpn/server/server.conf

  • #server-ipv6 fddd:1194:1194:1194::/64
    • Comment on this line to prevent IPv6 leasing.
  • #ifconfig-pool-persist ipp.txt
    • Comment this line to allow dynamic IP leasing or edit this file to define the static IPs for each client.
  • push “dhcp-option DNS 8.8.4.4”
    • Add or comment as many lines as necessary but list them on the desired order or priority.
  • duplicate-cn
    • Adding this line will allow the same client to have multiple simultaneous connections.

IMPORTANT: stop the service before editing the configuration files and start it again after.


OPENVPN MONITOR

sudo nano /etc/openvpn/server/server.conf

Add the following line at the end.

management 127.0.0.1 17562

Check if port 17562 is being used before restarting the service, then check if the service is running properly.

lsof -i :17562
sudo systemctl restart [email protected]
sudo systemctl status [email protected]

Install all dependencies by issuing:

sudo apt install git apache2 libapache2-mod-wsgi python3-geoip2 python3-ipaddr python3-humanize python3-bottle python3-semantic-version geoip-database geoipupdate
sudo git clone https://github.com/furlongm/openvpn-monitor.git /var/www/openvpn-monitor

Configuring the monitor.

sudo cp /var/www/openvpn-monitor/openvpn-monitor.conf{.example,}
cd /var/www/openvpn-monitor
grep -irl 5555 . | xargs -I {} sed -i 's/5555/17562/' {} (double check)

Adjust the configuration according to your location.

sudo nano /var/www/openvpn-monitor/openvpn-monitor.conf

Example:

[openvpn-monitor]
site=DFTorres
logo=logo.jpg
latitude=43.6655
longitude=-79.4204
maps=True
maps_height=500
geoip_data=/var/lib/GeoIP/GeoLite2-City.mmdb
datetime_format=%d/%m/%Y %H:%M:%S

[VPN1]
host=localhost
port=17562
name=Staff VPN
show_disconnect=False

Download and place the GeoLite2-City.mmdb in place from the GitHub repository [Link].

Configuring Apache.

sudo nano /etc/apache2/sites-available/openvpn-monitor.conf

Paste the content to the new file:

ScriptAlias / /var/www/html/openvpn-monitor/openvpn-monitor.py
<Directory /var/www/html/openvpn-monitor>
Options +ExecCGI
AddHandler cgi-script .py
DirectoryIndex openvpn-monitor.py

AllowOverride None
Require ip 192.168.0.0/16
</Directory>

Customize the permitted network replacing 192.168.0.0/16.

Give the ownership to the www-data user.

sudo chown -R www-data: /var/www/openvpn-monitor/

Check the configuration syntax, enable the new site, and disable the default site.

sudo apachectl -t
sudo a2ensite openvpn-monitor.conf
sudo a2dissite 000-default.conf
sudo a2enmod cgi
sudo systemctl restart apache2

Try to access your server with the web browser http://server-ip-or-name/

If the Python program does not run but actually prints all the source code you may need to change the first line of the .py (#!/usr/bin/env python) to meet your server configuration.

sudo nano /var/www/openvpn-monitor/openvpn-monitor.py

Replace the first line by:

#!/usr/bin/python3

Or if does not work replace by:

#!/usr/bin/python

If this is not your unique website running on this server you may customize the openvpn-monitor.conf, follow the example below, and do not disable the default site (sudo a2dissite 000-default.conf).

<VirtualHost *:80>
ServerAdmin [email protected]
ServerName openvpn-server-name-or-ip
DocumentRoot /var/www/html/openvpn-monitor
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

<Directory /var/www/html/openvpn-monitor>
Options +ExecCGI
AddHandler cgi-script .py
DirectoryIndex openvpn-monitor.py
AllowOverride None
Require ip 192.168.0.0/16
</Directory>

Instead of just restrict access by the network IP (Require ip 192.168.0.0/16) you can also make it available on the internet using credentials.

sudo apt-get install apache2-utils
sudo htpasswd -c /etc/apache2/.htpasswd user1
sudo htpasswd /etc/apache2/.htpasswd user2
...

NOTE: you can use the -D argument to delete.

Repeat the third line for as many users as you want to create.

sudo nano /etc/apache2/sites-available/openvpn-monitor.conf

Add the bold lines in the current configuration:

<Directory /var/www/openvpn-monitor/>
Options +ExecCGI
AddHandler cgi-script .py
DirectoryIndex openvpn-monitor.py
AllowOverride None

AuthType Basic
AuthName "Restricted Content"
AuthUserFile /etc/apache2/.htpasswd
Require valid-user
</Directory>

Now restart the apache and test it.

While the OpenVPN-Monitor will give real-time information of the connected users, the IPFM works as an IP Flow Meter, making a log of the total data used by each of the users.


IP FLOW METER

sudo apt install ipfm
sudo systemctl stop ipfm
sudo cp /etc/ipfm.conf /etc/ipfm.conf.bkp
sudo nano /etc/ipfm.conf

Since our VPN network is 10.8.0.0/24, configure it as follows:

DEVICE tun0
NEWLOG
LOG 10.8.0.0/255.255.255.0
FILENAME "/var/log/ipfm/vpn-%Y-%m-%d"
DUMP EVERY 1 minute
CLEAR NEVER
SORT TOTAL

Restart the service and monitor the folder for the reports.

sudo systemctl start ipfm
watch -n 1 "ls -l /var/log/ipfm/"

The files will start to show up in the directory and will be overwritten every time until the end of the month when a new file will be created.


CHECK FOR CONNECTED CLIENTS

Add the following line to /etc/openvpn/server/server.conf

management 127.0.0.1 7505
log-append /var/log/openvpn.log
status /var/log/openvpn-status.log
verb 3

Restart the service and test the management interface with netcator or telnet:

nc 127.0.0.1 7505
echo "status 3" | timeout 1 nc 127.0.0.1 7505 | grep -E "^CLIENT_LIST"
sudo cat /var/log/openvpn-status.log
sudo tail -f /var/log/openvpn.log

If your utilization is just to get a secure connection for no more than 2 simultaneous connections, like your smartphone and laptop, consider using the OpenVPN Access Server [Link]. Licensing page at [Link].

OpenVPN-AS is a great full-featured Web-based GUI that makes everything very easy, but the only drawback is that for more than 2 users you have to pay for a license.

Read Also

Performance OpenVPN vs WireGuard [Link]

Setting Up WireGuard VPN [Link]

pfSense with OpenVPN Client [Link]

GRE VPN Tunnel on Cisco [Link]