{"id":348,"date":"2020-10-01T00:24:21","date_gmt":"2020-10-01T00:24:21","guid":{"rendered":"https:\/\/dft.wiki\/?p=348"},"modified":"2026-06-09T14:39:10","modified_gmt":"2026-06-09T18:39:10","slug":"openvpn-server-on-ubuntu-20-04","status":"publish","type":"post","link":"https:\/\/dft.wiki\/?p=348","title":{"rendered":"OpenVPN Server + Monitoring on Ubuntu"},"content":{"rendered":"<p style=\"text-align: center;\">This post was last tested and updated for Ubuntu 24.04 LTS.<\/p>\n<p>A VPN encrypts data traffic between two points. For general internet browsing, it is NOT necessarily end-to-end encrypted.<\/p>\n<p>There are many reasons why a VPN may be necessary:<\/p>\n<ul>\n<li>Connect from home to the office over the public internet (sensitive information),<\/li>\n<li>Hide your traffic from the network administrator (ISP, hotel, Wi-Fi, etc),<\/li>\n<li>Access region-restricted content (streaming, ACL, etc),<\/li>\n<li>Download copyrighted or censored material,<\/li>\n<li>And more.<\/li>\n<\/ul>\n<p>What are the alternatives to VPN and what type of &#8220;protection&#8221; do they offer?<\/p>\n<table border=\"1\">\n<tbody>\n<tr>\n<th><strong>Expected<\/strong><\/th>\n<th><strong>Internet Service Provider<\/strong><\/th>\n<th><strong>Incognito Mode<\/strong><\/th>\n<th><strong>Public VPN<\/strong><\/th>\n<th><b>Private VPN (truly end-to-end)<\/b><\/th>\n<th><strong>Tor Network Only<\/strong><\/th>\n<th><strong>Tor Browser<\/strong><\/th>\n<th><strong>Observations<\/strong><\/th>\n<\/tr>\n<tr>\n<td>Tracking Protection<\/td>\n<td>NO<\/td>\n<td><\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td><\/td>\n<td>Tunneling your traffic over an encrypted network does not make tracking any harder. All identifiable information still passes through the tunnel.<\/td>\n<\/tr>\n<tr>\n<td>Fingerprinting Protection<\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td><\/td>\n<td>Only the Tor Browser removes or replaces identifiable information (fingerprints), making all users appear the same.<\/td>\n<\/tr>\n<tr>\n<td>Geo-blocking Evasion<\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td><\/td>\n<td><\/td>\n<td><\/td>\n<td><\/td>\n<td>Geo-blocking is usually based on IP address (e.g. streaming services). This is one of the most common uses of VPN for the general public.<\/td>\n<\/tr>\n<tr>\n<td>Man-in-the-middle Protection<\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td><\/td>\n<td>NO<\/td>\n<td>NO<\/td>\n<td>Tunneling traffic over third-party networks is always susceptible to MITM attacks. Even Tor exit nodes should never be trusted.<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>NOTE:<\/strong> Websites with SSL\/TLS (HTTPS) are end-to-end encrypted between the browser and the server (e.g. internet banking via browser or app). Your ISP or network administrator may know you are connecting to your bank or email provider, but they cannot see the content or tamper with it. On the other hand, if you are torrenting through a public VPN, the VPN provider can see your traffic in plain text, though the rest of the internet cannot see you behind the VPN server, and your traffic is mixed with that of many other users. Keep this in mind!<\/p>\n<hr \/>\n<p><strong>DEPLOYING A PRIVATE VPN SERVER<\/strong><\/p>\n<p>Download the installation script:<\/p>\n<pre>wget https:\/\/git.io\/vpn -O openvpn-install.sh<\/pre>\n<p>If the command above does not work, get the script directly from GitHub &#8211; Nyr\/OpenVPN Install [<a href=\"https:\/\/github.com\/Nyr\/openvpn-install\">Link<\/a>] or [<a href=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/openvpn-install.zip\">OpenVPN-Install<\/a>].<\/p>\n<pre>chmod -v +x openvpn-install.sh\r\nsudo .\/openvpn-install.sh<\/pre>\n<p>The script will ask a few questions. It is recommended to use:<\/p>\n<pre>First question: <strong>UDP<\/strong>;\r\nSecond question: default port <strong>1194<\/strong>;\r\nThird question: <strong>Google<\/strong> DNS;\r\nThe fourth question is the <strong>name<\/strong> you want to give to the specific client you are creating, for example: <em>client1<\/em><\/pre>\n<p>The script creates a configuration file at <strong>\/root\/client1.ovpn<\/strong> (the filename matches the name you gave).<\/p>\n<p>This file must be transferred to the client machine. It is recommended to use an encrypted transfer method such as:<\/p>\n<pre>scp [<strong>user<\/strong>]@[<strong>ip or hostname of the server<\/strong>]:\/root\/client1.ovpn .<\/pre>\n<p>The service starts automatically on the server and can be managed with:<\/p>\n<pre>sudo systemctl <strong>stop<\/strong> openvpn-server@server.service\r\nsudo systemctl <strong>start<\/strong> openvpn-server@server.service\r\nsudo systemctl <strong>restart<\/strong> openvpn-server@server.service\r\nsudo systemctl <strong>status<\/strong> openvpn-server@server.service<\/pre>\n<p>From the <strong>client side<\/strong> (a Linux desktop, for example), run the following commands:<\/p>\n<pre>dig +short myip.opendns.com @resolver1.opendns.com\r\nsudo apt install openvpn\r\nsudo cp client1.ovpn \/etc\/openvpn\/client.conf\r\nsudo systemctl start openvpn@client\r\nping 10.8.0.1 -c 2\r\ndig +short myip.opendns.com @resolver1.opendns.com<\/pre>\n<p>If you run these commands in order: the first checks your current public IP (your home ISP or the public Wi-Fi you are on); the fourth connects to the VPN; the fifth pings the VPN server twice through the tunnel; and the sixth checks your public IP again, this time returning the IP of your VPN server. Verify that it changed!<\/p>\n<p>Note that on the client side, the <strong>VPN runs as a service and starts automatically on boot<\/strong>. To enable or disable this behaviour:<\/p>\n<pre>sudo nano \/etc\/default\/openvpn<\/pre>\n<p>Find and uncomment the line <strong>AUTOSTART=&#8221;none&#8221;<\/strong> to prevent it from starting automatically.<\/p>\n<p>For configuring <strong>OpenVPN Client in pfSense<\/strong>, see the next post [<a href=\"https:\/\/dft.wiki\/?p=1135\">Link<\/a>].<\/p>\n<hr \/>\n<p><strong>CUSTOMIZING CLIENT-SIDE<\/strong>: \/etc\/openvpn\/client.conf<\/p>\n<ul>\n<li><strong>pull-filter ignore &#8220;redirect-gateway&#8221;<\/strong>\n<ul>\n<li>Prevents all traffic from being tunneled. Only traffic destined for the VPN network will go through the tunnel.<\/li>\n<\/ul>\n<\/li>\n<li><strong>dhcp-option DNS 10.8.0.254<\/strong>\n<ul>\n<li>Forces a specific DNS server for this client over the VPN connection. DNS servers received during the connection will have lower priority.<\/li>\n<\/ul>\n<\/li>\n<li><strong>dhcp-option Domain test.local<\/strong>\n<ul>\n<li>Forces a specific domain for this client over the VPN connection. Useful for Active Directory environments and can be combined with the DNS option.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<hr \/>\n<p><strong>CUSTOMIZING SERVER-SIDE<\/strong>: \/etc\/openvpn\/server\/server.conf<\/p>\n<ul>\n<li><strong>#server-ipv6 fddd:1194:1194:1194::\/64<\/strong>\n<ul>\n<li>Comment this line to prevent IPv6 address assignment.<\/li>\n<\/ul>\n<\/li>\n<li><strong>#ifconfig-pool-persist ipp.txt<\/strong>\n<ul>\n<li>Comment this line to allow dynamic IP assignment, or edit the file to assign static IPs per client.<\/li>\n<\/ul>\n<\/li>\n<li><strong>push &#8220;dhcp-option DNS 8.8.4.4&#8221;<\/strong>\n<ul>\n<li>Add or comment out as many of these lines as needed, listed in the desired priority order.<\/li>\n<\/ul>\n<\/li>\n<li><strong>duplicate-cn<\/strong>\n<ul>\n<li>Adding this line allows the same client certificate to be used for multiple simultaneous connections.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><strong>IMPORTANT<\/strong>: <strong>Stop the service<\/strong> before editing configuration files, and <strong>start it again<\/strong> afterward.<\/p>\n<hr \/>\n<p><strong>OPENVPN MONITOR<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1720\" src=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-14-51-18.png\" alt=\"\" width=\"1582\" height=\"967\" srcset=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-14-51-18.png 1582w, https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-14-51-18-300x183.png 300w, https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-14-51-18-1024x626.png 1024w, https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-14-51-18-768x469.png 768w, https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-14-51-18-1536x939.png 1536w, https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-14-51-18-1200x734.png 1200w\" sizes=\"auto, (max-width: 1582px) 100vw, 1582px\" \/><\/p>\n<pre>sudo nano \/etc\/openvpn\/server\/server.conf<\/pre>\n<p>Add the following line at the end:<\/p>\n<pre>management 127.0.0.1 17562<\/pre>\n<p>Before restarting the service, verify that port <strong>17562<\/strong> is not already in use, then confirm the service starts correctly.<\/p>\n<pre>lsof -i :17562\r\nsudo systemctl restart openvpn-server@server.service\r\nsudo systemctl status openvpn-server@server.service<\/pre>\n<p>Install all dependencies:<\/p>\n<pre>sudo apt install git apache2 libapache2-mod-wsgi python3-geoip2 python3-ipaddr python3-humanize python3-bottle python3-semantic-version geoip-database geoipupdate\r\nsudo git clone https:\/\/github.com\/furlongm\/openvpn-monitor.git \/var\/www\/openvpn-monitor<\/pre>\n<p>Configure the monitor:<\/p>\n<pre>sudo cp \/var\/www\/openvpn-monitor\/openvpn-monitor.conf{.example,}\r\ncd \/var\/www\/openvpn-monitor\r\n<strong>grep -irl 5555 . | xargs -I {} sed -i 's\/5555\/17562\/' {} (double check)<\/strong><\/pre>\n<p>Adjust the configuration to match your location:<\/p>\n<pre>sudo nano \/var\/www\/openvpn-monitor\/openvpn-monitor.conf<\/pre>\n<p>Example:<\/p>\n<pre>[openvpn-monitor]\r\nsite=DFTorres\r\nlogo=logo.jpg\r\nlatitude=43.6655\r\nlongitude=-79.4204\r\nmaps=True\r\nmaps_height=500\r\ngeoip_data=\/var\/lib\/GeoIP\/GeoLite2-City.mmdb\r\ndatetime_format=%d\/%m\/%Y %H:%M:%S\r\n\r\n[VPN1]\r\nhost=localhost\r\nport=17562\r\nname=Staff VPN\r\nshow_disconnect=False<\/pre>\n<p>Download and place the GeoLite2-City.mmdb file from the GitHub repository [<a href=\"https:\/\/github.com\/texnikru\/GeoLite2-Database\">Link<\/a>].<\/p>\n<p>Configure Apache:<\/p>\n<pre>sudo nano \/etc\/apache2\/sites-available\/openvpn-monitor.conf<\/pre>\n<p>Paste the following into the new file:<\/p>\n<pre>ScriptAlias \/ \/var\/www\/html\/openvpn-monitor\/openvpn-monitor.py\r\n&lt;Directory \/var\/www\/html\/openvpn-monitor&gt;\r\nOptions +ExecCGI\r\nAddHandler cgi-script .py\r\nDirectoryIndex openvpn-monitor.py\r\n\r\nAllowOverride None\r\nRequire ip <strong>192.168.0.0\/16<\/strong>\r\n&lt;\/Directory&gt;<\/pre>\n<p>Replace <strong>192.168.0.0\/16<\/strong> with your allowed network.<\/p>\n<p>Set ownership to the www-data user:<\/p>\n<pre>sudo chown -R www-data: \/var\/www\/openvpn-monitor\/<\/pre>\n<p>Check the configuration syntax, enable the new site, and disable the default site:<\/p>\n<pre>sudo apachectl -t\r\nsudo a2ensite openvpn-monitor.conf\r\nsudo a2dissite 000-default.conf\r\nsudo a2enmod cgi\r\nsudo systemctl restart apache2<\/pre>\n<p>Try accessing your server in a browser at http:\/\/server-ip-or-name\/<\/p>\n<p>If the Python script is not executing and instead displays its source code, you may need to update the first line of the .py file (<strong>#!\/usr\/bin\/env python<\/strong>) to match your server&#8217;s Python configuration:<\/p>\n<pre>sudo nano \/var\/www\/openvpn-monitor\/openvpn-monitor.py<\/pre>\n<p>Replace the first line with:<\/p>\n<pre>#!\/usr\/bin\/python3<\/pre>\n<p>Or if that does not work:<\/p>\n<pre>#!\/usr\/bin\/python<\/pre>\n<p>If this server hosts other websites, customize <strong>openvpn-monitor.conf<\/strong> using a VirtualHost block as shown below, and skip the step to disable the default site (<strong>sudo a2dissite 000-default.conf<\/strong>):<\/p>\n<pre>&lt;VirtualHost *:80&gt;\r\nServerAdmin your-email@gmail.com\r\nServerName openvpn-server-name-or-ip\r\nDocumentRoot \/var\/www\/html\/openvpn-monitor\r\nErrorLog ${APACHE_LOG_DIR}\/error.log\r\nCustomLog ${APACHE_LOG_DIR}\/access.log combined\r\n&lt;\/VirtualHost&gt;\r\n\r\n&lt;Directory \/var\/www\/html\/openvpn-monitor&gt;\r\nOptions +ExecCGI\r\nAddHandler cgi-script .py\r\nDirectoryIndex openvpn-monitor.py\r\nAllowOverride None\r\nRequire ip 192.168.0.0\/16\r\n&lt;\/Directory&gt;<\/pre>\n<p>Instead of restricting access by IP (<strong>Require ip 192.168.0.0\/16<\/strong>), you can expose the monitor on the internet using password authentication:<\/p>\n<pre>sudo apt-get install apache2-utils\r\nsudo htpasswd <strong>-c<\/strong> \/etc\/apache2\/.htpasswd user1\r\nsudo htpasswd \/etc\/apache2\/.htpasswd user2\r\n...<\/pre>\n<p><strong>NOTE:<\/strong> use the -D argument to delete a user.<\/p>\n<p>Repeat the third line for each additional user you want to create.<\/p>\n<pre>sudo nano \/etc\/apache2\/sites-available\/openvpn-monitor.conf<\/pre>\n<p>Add the bold lines to the existing configuration:<\/p>\n<pre>&lt;Directory \/var\/www\/openvpn-monitor\/&gt;\r\nOptions +ExecCGI\r\nAddHandler cgi-script .py\r\nDirectoryIndex openvpn-monitor.py\r\nAllowOverride None\r\n\r\n<strong>AuthType Basic<\/strong>\r\n<strong>AuthName \"Restricted Content\"<\/strong>\r\n<strong>AuthUserFile \/etc\/apache2\/.htpasswd<\/strong>\r\n<strong>Require valid-user<\/strong>\r\n&lt;\/Directory&gt;<\/pre>\n<p>Restart Apache and test the page.<\/p>\n<p>OpenVPN Monitor provides real-time information about connected users. IPFM complements it by acting as an IP Flow Meter, logging total data usage per user.<\/p>\n<hr \/>\n<p><strong>IP FLOW METER<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1724\" src=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-16-00-44.png\" alt=\"\" width=\"742\" height=\"148\" srcset=\"https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-16-00-44.png 742w, https:\/\/dft.wiki\/wp-content\/uploads\/sites\/15\/2020\/10\/Screenshot-from-2021-04-07-16-00-44-300x60.png 300w\" sizes=\"auto, (max-width: 742px) 100vw, 742px\" \/><\/p>\n<pre>sudo apt install ipfm\r\nsudo systemctl stop ipfm\r\nsudo cp \/etc\/ipfm.conf \/etc\/ipfm.conf.bkp\r\nsudo nano \/etc\/ipfm.conf<\/pre>\n<p>Since the VPN network is <strong>10.8.0.0\/24<\/strong>, configure it as follows:<\/p>\n<pre>DEVICE tun0\r\nNEWLOG\r\nLOG 10.8.0.0\/255.255.255.0\r\nFILENAME \"\/var\/log\/ipfm\/vpn-%Y-%m-%d\"\r\nDUMP EVERY 1 minute\r\nCLEAR NEVER\r\nSORT TOTAL<\/pre>\n<p>Restart the service and watch the folder for reports:<\/p>\n<pre>sudo systemctl start ipfm\r\nwatch -n 1 \"ls -l \/var\/log\/ipfm\/\"<\/pre>\n<p>Log files will appear in the directory and be updated every minute. A new file is created at the start of each month.<\/p>\n<hr \/>\n<p><strong>CHECK FOR CONNECTED CLIENTS<\/strong><\/p>\n<p>Add the following lines to <strong>\/etc\/openvpn\/server\/server.conf<\/strong>:<\/p>\n<pre>management 127.0.0.1 7505\r\nlog-append \/var\/log\/openvpn.log\r\nstatus \/var\/log\/openvpn-status.log\r\nverb 3<\/pre>\n<p>Restart the service and test the management interface with <code>netcat<\/code> or <code>telnet<\/code>:<\/p>\n<pre>nc 127.0.0.1 7505<\/pre>\n<pre>echo \"status 3\" | timeout 1 nc 127.0.0.1 7505 | grep -E \"^CLIENT_LIST\"<\/pre>\n<pre>sudo cat \/var\/log\/openvpn-status.log<\/pre>\n<pre>sudo tail -f \/var\/log\/openvpn.log<\/pre>\n<hr \/>\n<p>If you only need a secure connection for up to 2 simultaneous devices, such as a smartphone and a laptop, consider using the OpenVPN Access Server [<a href=\"https:\/\/openvpn.net\/access-server\/\">Link<\/a>]. Licensing details are available at [<a href=\"https:\/\/openvpn.net\/access-server\/pricing\/\">Link<\/a>].<\/p>\n<p>OpenVPN-AS is a full-featured web-based GUI that simplifies the setup considerably. The only limitation is that more than 2 users requires a paid license.<\/p>\n<p><strong>Read Also<\/strong><\/p>\n<p>Performance OpenVPN vs WireGuard [<a href=\"https:\/\/dft.wiki\/?p=1378\">Link<\/a>]<\/p>\n<p>Setting Up WireGuard VPN [<a href=\"https:\/\/dft.wiki\/?p=1380\">Link<\/a>]<\/p>\n<p>pfSense with OpenVPN Client [<a href=\"https:\/\/dft.wiki\/?p=1135\">Link<\/a>]<\/p>\n<p>GRE VPN Tunnel on Cisco [<a href=\"https:\/\/dft.wiki\/?p=593\">Link<\/a>]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This post was last tested and updated for Ubuntu 24.04 LTS. A VPN encrypts data [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-348","post","type-post","status-publish","format-standard","hentry","category-linux"],"_links":{"self":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/348","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=348"}],"version-history":[{"count":43,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/348\/revisions"}],"predecessor-version":[{"id":5831,"href":"https:\/\/dft.wiki\/index.php?rest_route=\/wp\/v2\/posts\/348\/revisions\/5831"}],"wp:attachment":[{"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=348"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=348"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dft.wiki\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=348"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}