
{"id":3894,"date":"2022-12-26T22:36:31","date_gmt":"2022-12-26T22:36:31","guid":{"rendered":"https:\/\/blog.gordonbuchan.com\/blog\/?p=3894"},"modified":"2023-11-10T16:23:48","modified_gmt":"2023-11-10T16:23:48","slug":"integrating-open-source-software-in-the-enterprise-chapter-2-using-linux-and-openvpn-to-create-a-virtual-private-network-vpn-server-with-two-factor-authentication-2fa-enabled-using-google-authent","status":"publish","type":"post","link":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/2022\/12\/26\/integrating-open-source-software-in-the-enterprise-chapter-2-using-linux-and-openvpn-to-create-a-virtual-private-network-vpn-server-with-two-factor-authentication-2fa-enabled-using-google-authent\/","title":{"rendered":"Using Linux and OpenVPN to create a virtual private network (VPN) server with two-factor authentication (2FA) enabled using Google Authenticator"},"content":{"rendered":"\n<p>In this procedure we install the open source program OpenVPN on a server running on Linux to create a virtual private network (VPN) authenticated against Active Directory with two-factor authentication (2FA) enabled Google Authenticator.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Business case<\/h1>\n\n\n\n<p>A Linux server running OpenVPN server software can replace a Windows server or other commercial solution for the VPN server role in the enterprise, reducing software licensing costs and improving security and stability.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Authenticating connections to the VPN server using client certificates and Google Authenticator one-time passwords (OTPs)<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Verifying client-side VPN certificates to authenticate a VPN connection<\/h2>\n\n\n\n<p>The VPN server will verify client digital certificates as one of the authentication methods.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Using Google Authenticator to obtain a one-time password (OTP) to authenticate a VPN connection<\/h2>\n\n\n\n<p>The VPN server will verify the one-time password (OTP) generated by Google Authenticator as one of the authentication methods.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Entering the OTP from Google Authenticator as the password for the VPN connection<\/h2>\n\n\n\n<p>To access the network, help desk clients will:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Enter their local network file share or Active Directory username as the username for the VPN connection.<\/li>\n\n\n\n<li>Enter the OTP from Google Authenticator as the password for the VPN connection.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Not verifying a local password authentication module (PAM) or Active Directory password to authenticate a VPN connection<\/h2>\n\n\n\n<p>This procedure does not verify a PAM or Active Directory password to authenticate the VPN connection.<\/p>\n\n\n\n<p>There are ways of prompting for a username, and a password, and an OTP from Google Authenticator. However, some of these are difficult to integrate with with client VPN connector software, which do not support a second password field. Some approaches ask the help desk client to enter a system password and the OTP as a combined password, but this can be confusing for help desk clients.<span style=\"font-size: revert;\"><\/span><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">This procedure was tested on Ubuntu Linux 22.04 LTS<\/h1>\n\n\n\n<p>This procedure was tested on <a href=\"https:\/\/releases.ubuntu.com\/22.04\/\">Ubuntu Linux 22.04 LTS<\/a>.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Deploying the VPN server as a physical or virtual machine<\/h1>\n\n\n\n<p>Deploy OpenVPN on a physical Linux server or on a virtual Linux server hosted as a virtual machine (VM), using KVM on Linux, Hyper-V,  VMware, or VirtualBox on Windows, or Parallels using MacOS.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Adding a macvtap or bridge mode network adapter to a virtual machine<\/h1>\n\n\n\n<p>For KVM, add a macvtap network adapter to the automation server. For Hyper-V, VMware, VirtualBox or Parallels, add a bridge mode network adapter. This will allow the VPN server to access the same network as the server&#8217;s hypervisor host.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Assigning a static IP address to the server that will host the VPN<\/h1>\n\n\n\n<p>Assign a static IP to the VPN server.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Assigning a permanent host name to a dynamic host configuration protocol (DHCP) public-facing IP address<\/h1>\n\n\n\n<p>Most residential Internet connections have a dynamic host configuration protocol (DHCP) public-facing IP address, which can change over time. You can use a service like no-ip.com to associate a permanent host name such as permhostname.ddns.net to a host with a dynamic IP address:<\/p>\n\n\n\n<p><a href=\"https:\/\/no-ip.com\">https:\/\/no-ip.com<\/a><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Forwarding ports from the public-facing IP address to the internal IP address of the VPN host<\/h1>\n\n\n\n<p>Use the control panel of your router to forward a port from the public-facing IP address to the internal IP address of the VPN host.<\/p>\n\n\n\n<p>As an example, for the server described in this procedure, we are using the TCP port 443 to host the connection:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"597\" height=\"126\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-11.png\" alt=\"\" class=\"wp-image-4220\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-11.png 597w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-11-300x63.png 300w\" sizes=\"auto, (max-width: 597px) 100vw, 597px\" \/><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Entering commands as root<\/h1>\n\n\n\n<p>This procedure assumes that you are logged in as the root user of the Linux server.<\/p>\n\n\n\n<p>Escalate to the root user by entering the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sudo su<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Installing tools on the server<\/h1>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\napt install libpam-google-authenticator curl oath libqrencode4\n<\/pre><\/div>\n\n\n<h1 class=\"wp-block-heading\">Modifying the \/etc\/sysctl.conf file to enable network forwarding<\/h1>\n\n\n\n<p>From a root shell, enter the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cd \/etc<br>nano sysctl.conf<\/pre>\n\n\n\n<p>Add the following text to the bottom of the file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">net.ipv4.ip_forward=1<\/pre>\n\n\n\n<p>Press Ctrl-X to save and exit the file.<\/p>\n\n\n\n<p>Enter the following command to reload the sysctl settings:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">sysctl -a<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Creating the \/etc\/rc.local file<\/h1>\n\n\n\n<p>Enter the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cd \/etc<br>nano rc.local<\/pre>\n\n\n\n<p>Add the following text:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n!\/usr\/bin\/bash\niptables -t nat -A POSTROUTING -s 10.8.0.0\/24 -o enp3s0 -j MASQUERADE\n<\/pre><\/div>\n\n\n<p>If you are using the no-ip.com dynamic update client (DUC), add the following text:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n\/usr\/local\/bin\/noip2\n<\/pre><\/div>\n\n\n<p>Add the following text:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nexit 0\n<\/pre><\/div>\n\n\n<p>Press Ctrl-X to save and exit the file.<\/p>\n\n\n\n<p>Enter the following command<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">chmod 755 rc.local<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Starting the rc-local service<\/h1>\n\n\n\n<p>Enter the following command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">systemctl restart rc-local<\/pre>\n\n\n\n<h1 class=\"wp-block-heading\">Using a script to automate the installation of OpenVPN<\/h1>\n\n\n\n<p>The openvpn-install.sh from Angristan automates the installation of the OpenVPN server application:<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/Angristan\/OpenVPN-install\">https:\/\/github.com\/Angristan\/OpenVPN-install<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Downloading the OpenVPN installation script<\/h2>\n\n\n\n<p>To download the openvpn-install.sh script, enter the following commands:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\ncd \/root\ncurl -O https:\/\/raw.githubusercontent.com\/angristan\/openvpn-install\/master\/openvpn-install.sh\nchmod +x openvpn-install.sh\n<\/pre><\/div>\n\n\n<h2 class=\"wp-block-heading\">Running the OpenVPN installation script<\/h2>\n\n\n\n<pre class=\"wp-block-preformatted\">.\/openvpn-install.sh<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Modifying the OpenVPN server configuration file<\/h2>\n\n\n\n<p>From a root shell, enter the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cd \/etc\/openvpn\/server<br>nano server.conf<\/pre>\n\n\n\n<p>Locate the following line:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">push \"redirect-gateway def1 bypass-dhcp\"<\/pre>\n\n\n\n<p>Change the line to:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">push \"redirect-gateway def bypass-dhcp\"<\/pre>\n\n\n\n<p>Add the following text to the end of the file:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nauth-user-pass-verify &quot;\/etc\/openvpn\/server\/google-authenticator.sh&quot; via-env\nscript-security 3\nusername-as-common-name\n<\/pre><\/div>\n\n\n<p>Press Ctrl-X to save and exit the file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the google-authenticator.sh script<\/h2>\n\n\n\n<p>Enter the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cd \/etc\/openvpn\/server\nnano google-authenticator.sh<\/pre>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n#!\/usr\/bin\/bash\n# this script written by OpenAI ChatGPT\n# see References section for prompt\n# check if the user has provided a username and password\nif &#x5B; -z &quot;$username&quot; -o -z &quot;$password&quot; ]; then\n  exit 1\nfi\n\n# get the user&#039;s secret key from the Google Authenticator app\nsecret_key=$(grep &quot;^$username:&quot; \/etc\/openvpn\/server\/google-authenticator.keys | cut -d: -f2)\n\n# check if the user has a secret key\nif &#x5B; -z &quot;$secret_key&quot; ]; then\n  exit 1\nfi\n\n# generate a six-digit code using the secret key and the current time\ncode=$(oathtool --totp -b &quot;$secret_key&quot;)\n\n# compare the generated code with the password provided by the user\nif &#x5B; &quot;$code&quot; = &quot;$password&quot; ]; then\n  exit 0\nelse\n  exit 1\nfi\n\n<\/pre><\/div>\n\n\n<p>Press Ctrl-X to save and exit the file.<\/p>\n\n\n\n<p>Enter the following command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">chmod 755 google-authenticator.sh<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Restarting the OpenVPN server<\/h2>\n\n\n\n<p>From a root shell, enter the following command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">systemctl restart openvpn-server@server<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Downloading the OpenVPN client profile<\/h2>\n\n\n\n<p>Use the FileZilla file transfer client to download the OpenVPN client profile:<\/p>\n\n\n\n<p><a href=\"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/2021\/03\/07\/web-presence-step-by-step-chapter-7-configuring-the-ssh-server-on-an-ubuntu-linux-cloud-server-to-limit-sftp-directory-visibility-within-chroot-jail-directories\/#:~:text=Obtaining%20the%20FileZilla%20file%20transfer%20program\">https:\/\/blog.gordonbuchan.com\/blog\/index.php\/2021\/03\/07\/web-presence-step-by-step-chapter-7-configuring-the-ssh-server-on-an-ubuntu-linux-cloud-server-to-limit-sftp-directory-visibility-within-chroot-jail-directories\/#:~:text=Obtaining%20the%20FileZilla%20file%20transfer%20program<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Modifying the OpenVPN client profile<\/h2>\n\n\n\n<p>Use a text editor to load the OpenVPN client profile. Add the following text to the bottom of the file:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">auth-user-pass<\/pre>\n\n\n\n<p>Save and exit the file.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Downloading and Installing the Google Authenticator app on a help desk client&#8217;s smartphone<\/h1>\n\n\n\n<p>Visit the Apple App Store or the Google Play Store. Search for &#8220;google authenticator&#8221; and download the app:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"1024\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-1-474x1024.png\" alt=\"\" class=\"wp-image-4160\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-1-474x1024.png 474w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-1-139x300.png 139w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-1-710x1536.png 710w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-1.png 740w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/figure>\n\n\n\n<p>Click on &#8220;Get started&#8221;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"1024\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-2-474x1024.png\" alt=\"\" class=\"wp-image-4161\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-2-474x1024.png 474w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-2-139x300.png 139w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-2-710x1536.png 710w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-2.png 740w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Running the google-authenticator command on the server to enrol the help desk client&#8217;s Google Authenticator app<\/h2>\n\n\n\n<p>Open a terminal window as root, and make the terminal window full-screen. Enter the following command:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">google-authenticator<\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"644\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/Screenshot-from-2022-12-26-13-43-27-1024x644.png\" alt=\"\" class=\"wp-image-4153\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/Screenshot-from-2022-12-26-13-43-27-1024x644.png 1024w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/Screenshot-from-2022-12-26-13-43-27-300x189.png 300w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/Screenshot-from-2022-12-26-13-43-27-768x483.png 768w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/Screenshot-from-2022-12-26-13-43-27-1536x966.png 1536w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/Screenshot-from-2022-12-26-13-43-27-2048x1287.png 2048w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Scanning the QR code into the Google Authenticator smartphone app<\/h2>\n\n\n\n<p>Click on &#8220;Scan a QR code&#8221; then click on &#8220;OK&#8221; to allow the app to access the camera:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"1024\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-4-474x1024.png\" alt=\"\" class=\"wp-image-4163\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-4-474x1024.png 474w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-4-139x300.png 139w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-4-710x1536.png 710w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-4.png 740w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"1024\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-5-474x1024.png\" alt=\"\" class=\"wp-image-4164\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-5-474x1024.png 474w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-5-139x300.png 139w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-5-710x1536.png 710w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-5.png 740w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>Look at the one-time code shown on the Google Authenticator app:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"474\" height=\"1024\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-7-474x1024.png\" alt=\"\" class=\"wp-image-4166\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-7-474x1024.png 474w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-7-139x300.png 139w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-7-710x1536.png 710w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-7.png 740w\" sizes=\"auto, (max-width: 474px) 100vw, 474px\" \/><\/figure>\n\n\n\n<p>Enter the code in the Terminal window in the field: &#8220;Enter code from the app (-1 to skip):&#8221;<\/p>\n\n\n\n<p>Enter &#8220;n&#8221; to the question: &#8220;Do you want me to update your &#8220;\/root\/.google_authenticator file? (y\/n):&#8221;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the \/etc\/openvpn\/server\/google-authenticator.keys file and entering the secret key created during enrolment of the help desk client&#8217;s Google Authenticator app.<\/h2>\n\n\n\n<p>Enter the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">cd \/etc\/openvpn\/server<br>nano google-authenticator.keys<\/pre>\n\n\n\n<p>Add an entry to the file in with the format &#8220;username: yournewsecretkey&#8221;:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\nclient06a:NRX7VMDMIC6XSDFJNU3WVB3K2I\n<\/pre><\/div>\n\n\n<p>Press Ctrl-X to save and exit the file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A note re automation<\/h2>\n\n\n\n<p>Should this process be automated further? Yes. The google-authenticator program on the server could be scripted so that the client&#8217;s username and secret code could be added to the \/etc\/openvpn\/server\/google-authenticator.keys file.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Downloading the OpenVPN client application<\/h1>\n\n\n\n<p><a href=\"https:\/\/openvpn.net\/community-downloads\/\">https:\/\/openvpn.net\/community-downloads\/<\/a><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Importing the OpenVPN client profile<\/h1>\n\n\n\n<p>Import the OpenVPN client profile into the OpenVPN client application.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Connecting to the OpenVPN server<\/h1>\n\n\n\n<p>An example of a Windows client connecting to the OpenVPN server:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"480\" height=\"438\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-8.png\" alt=\"\" class=\"wp-image-4177\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-8.png 480w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-8-300x274.png 300w\" sizes=\"auto, (max-width: 480px) 100vw, 480px\" \/><\/figure>\n\n\n\n<p>For &#8220;Username&#8221; enter the username of the VPN connection. For &#8220;Password&#8221; enter the one-time password (OTP) displayed by the Google Authenticator app:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"574\" height=\"371\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/Screenshot-from-2022-12-26-17-02-39.png\" alt=\"\" class=\"wp-image-4179\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/Screenshot-from-2022-12-26-17-02-39.png 574w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/Screenshot-from-2022-12-26-17-02-39-300x194.png 300w\" sizes=\"auto, (max-width: 574px) 100vw, 574px\" \/><\/figure>\n\n\n\n<p>A successful connection:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"391\" height=\"136\" src=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-9.png\" alt=\"\" class=\"wp-image-4181\" srcset=\"https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-9.png 391w, https:\/\/blog.gordonbuchan.com\/blog\/wp-content\/uploads\/2022\/12\/image-9-300x104.png 300w\" sizes=\"auto, (max-width: 391px) 100vw, 391px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<h1 class=\"wp-block-heading\">References<\/h1>\n\n\n\n<p><a href=\"https:\/\/egonbraun.medium.com\/using-google-authenticator-mfa-with-openvpn-on-ubuntu-16-04-774e4acc2852\">https:\/\/egonbraun.medium.com\/using-google-authenticator-mfa-with-openvpn-on-ubuntu-16-04-774e4acc2852<\/a><br><a href=\"https:\/\/amilstead.com\/blog\/openvpn-with-google-authenticator-totp\/\n\">https:\/\/amilstead.com\/blog\/openvpn-with-google-authenticator-totp\/<br><\/a><a href=\"https:\/\/github.com\/evgeny-gridasov\/openvpn-otp\n\">https:\/\/github.com\/evgeny-gridasov\/openvpn-otp<br><\/a><a href=\"https:\/\/www.softether.org\/\n\">https:\/\/www.softether.org\/<br><\/a><a href=\"https:\/\/charlesreid1.com\/wiki\/Ubuntu\/OpenVPN_Server#Adding_MFA_to_VPN_Access\n\">https:\/\/charlesreid1.com\/wiki\/Ubuntu\/OpenVPN_Server#Adding_MFA_to_VPN_Access<br><\/a><a href=\"https:\/\/www.howtoforge.com\/how-to-set-up-openvpn-to-authenticate-with-linotp\n\">https:\/\/www.howtoforge.com\/how-to-set-up-openvpn-to-authenticate-with-linotp<br><\/a><a href=\"https:\/\/www.howtoforge.com\/securing-openvpn-with-a-one-time-password-otp-on-ubuntu\n\">https:\/\/www.howtoforge.com\/securing-openvpn-with-a-one-time-password-otp-on-ubuntu<br><\/a><a href=\"https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-configure-multi-factor-authentication-on-ubuntu-18-04\n\">https:\/\/www.digitalocean.com\/community\/tutorials\/how-to-configure-multi-factor-authentication-on-ubuntu-18-04<br><\/a><a href=\"https:\/\/warlord0blog.wordpress.com\/2022\/09\/01\/openvpn-mfa-and-pam\/\n\">https:\/\/warlord0blog.wordpress.com\/2022\/09\/01\/openvpn-mfa-and-pam\/<br><\/a><a href=\"https:\/\/binsec.wiki\/en\/security\/howto\/protect-hardening\/authorization-and-authentication\/openvpn-configure-2fa-google-authenticator\/\n\">https:\/\/binsec.wiki\/en\/security\/howto\/protect-hardening\/authorization-and-authentication\/openvpn-configure-2fa-google-authenticator\/<br><\/a><a href=\"https:\/\/forums.openvpn.net\/viewtopic.php?t=12886\n\">https:\/\/forums.openvpn.net\/viewtopic.php?t=12886<br><\/a><a href=\"https:\/\/www.freeipa.org\/page\/Windows_authentication_against_FreeIPA\n\">https:\/\/www.freeipa.org\/page\/Windows_authentication_against_FreeIPA<br><\/a><a href=\"http:\/\/pgina.org\/\n\">http:\/\/pgina.org\/<br><\/a><a href=\"https:\/\/www.ezeelogin.com\/kb\/article\/how-to-install-google-authenticator-on-centos-ubuntu-323.html\n\">https:\/\/www.ezeelogin.com\/kb\/article\/how-to-install-google-authenticator-on-centos-ubuntu-323.html<br><\/a><a href=\"https:\/\/askubuntu.com\/questions\/182498\/google-authenticator-for-desktop\n\">https:\/\/askubuntu.com\/questions\/182498\/google-authenticator-for-desktop<br><\/a><a href=\"https:\/\/unix.stackexchange.com\/questions\/341226\/samba-not-starting-on-ubuntu-server-16-10\n\">https:\/\/unix.stackexchange.com\/questions\/341226\/samba-not-starting-on-ubuntu-server-16-10<br><\/a><a href=\"https:\/\/www.linuxquestions.org\/questions\/linux-server-73\/samba-4-5-issues-4175597252\/\n\">https:\/\/www.linuxquestions.org\/questions\/linux-server-73\/samba-4-5-issues-4175597252\/<br><\/a><a href=\"https:\/\/serverfault.com\/questions\/1026344\/how-can-i-setup-nat-on-my-openvpn-server-for-the-client\n\">https:\/\/serverfault.com\/questions\/1026344\/how-can-i-setup-nat-on-my-openvpn-server-for-the-client<br><\/a><a href=\"https:\/\/arashmilani.com\/post?id=53\n\">https:\/\/arashmilani.com\/post?id=53<br><\/a><a href=\"https:\/\/unix.stackexchange.com\/questions\/283801\/iptables-forward-traffic-to-vpn-tunnel-if-open\n\">https:\/\/unix.stackexchange.com\/questions\/283801\/iptables-forward-traffic-to-vpn-tunnel-if-open<br><\/a><a href=\"https:\/\/aranel.net\/tech\/raspberrypi-openvpn\n\">https:\/\/aranel.net\/tech\/raspberrypi-openvpn<br><\/a><a href=\"https:\/\/forums.openvpn.net\/viewtopic.php?t=29880\n\">https:\/\/forums.openvpn.net\/viewtopic.php?t=29880<br><\/a><a href=\"https:\/\/superuser.com\/questions\/168128\/openvpn-can-connect-but-cant-ping-or-access-the-server\n\">https:\/\/superuser.com\/questions\/168128\/openvpn-can-connect-but-cant-ping-or-access-the-server<br><\/a><a href=\"https:\/\/chat.openai.com\">https:\/\/chat.openai.com<\/a> AI prompt: &#8220;create detailed instructions for the integration of google authenticator with openvpn&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this procedure we install the open source program OpenVPN on a server running on Linux to create a virtual private network (VPN) authenticated against Active Directory with two-factor authentication (2FA) enabled Google Authenticator. Business case A Linux server running OpenVPN server software can replace a Windows server or other commercial solution for the VPN &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/2022\/12\/26\/integrating-open-source-software-in-the-enterprise-chapter-2-using-linux-and-openvpn-to-create-a-virtual-private-network-vpn-server-with-two-factor-authentication-2fa-enabled-using-google-authent\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Using Linux and OpenVPN to create a virtual private network (VPN) server with two-factor authentication (2FA) enabled using Google Authenticator&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3894","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3894","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/comments?post=3894"}],"version-history":[{"count":187,"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3894\/revisions"}],"predecessor-version":[{"id":4967,"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/posts\/3894\/revisions\/4967"}],"wp:attachment":[{"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/media?parent=3894"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/categories?post=3894"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.gordonbuchan.com\/blog\/index.php\/wp-json\/wp\/v2\/tags?post=3894"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}