Deployment of OpenVPN + ZID + Reverse Proxy with Multi Factor Authentication
Deployment of OpenVPN + ZID + Reverse Proxy with Multi Factor Authentication
ZWAN supports creating the SSL VPN in TUN mode to support configurations such as SITE to MOBILE or more commonly known as Road Warriors. Authentication for this tunnel can be done using various methods such as x509, LDAP, OAUTH and OAUTH + MFA. OAUTH (Open Authorization) offers a more distributed approach for OpenVPN authentication. The below deployment method focuses on deploying a setup with the OAUTH + MFA.
Setup Overview

The following components are necessary on the HQ location.
1) Reverse Proxy for a TLS endpoint termination
2) zWAN edge controllers on physical or virtual hardware
3) ZID as the OAUTH Identity provider ( Keycloak backend )
Setup the Reverse Proxy
We can use/generate self-signed certificates in a test environment or a import a trusted signed certificate onto the reverse proxy. If using self-signed certificates the end-user would face a security error on the browser which they would have to override. This is not recommended other than when running in a test environment.
Generating Self-Signed Certificates
Certificates can be generates using easy-rsa. Please note that these steps are just a guideline. Command line may change across platforms. So refer the online documentation for the latest.
Note: Please make sure you have elevated (root) privileges on this system.
Step 1: Install Easy-RSA
apt update
apt install easy-rsa
Step 2: Set up Your Easy-RSA Workspace
It’s best practice to copy the Easy-RSA scripts to a separate working directory to prevent any conflicts with future package updates. Create a dedicated directory for your Public Key Infrastructure (PKI). A good location is within your home directory.
mkdir ~/easy-rsa
Copy the necessary files from the installation directory to your new workspace.
cp -r /usr/share/easy-rsa/* ~/easy-rsa/
Change into your new workspace.
cd ~/easy-rsa
Modify the vars file
cp vars.example vars.custom
nano vars.custom
Edit the vars file to set the EASYRSA_DN to "org"
Step 3: Initialize the PKI
This step sets up the basic directory structure and files needed for your certificate authority.
./easyrsa --vars=~/easy-rsa/vars.custom --batch init-pki
The command will create a new pki subdirectory containing all the files for your certificate infrastructure.
Step 4: Create the Certificate Authority (CA)
The CA is the root of trust for all certificates you will generate. Use the build-ca command to create the private key and public certificate for your CA. Replace the variables with the appropriate entries
./easyrsa --vars=~/easy-rsa/vars.custom --dn-mode=org --req-cn= --req-org= --req-email= --req-c= --req-st= --req-city= --req-ou= --batch build-ca nopass
Example:
./easyrsa --vars=~/easy-rsa/vars.custom --dn-mode=org --req-cn="AmzettaCA" --req-org="AmZetta technologies" --req-email="[email protected]" --req-c=IN --req-st=TN --req-city=chennai --req-ou="CPEUnit" --batch build-ca nopass
The generated files are:
pki/ca.crt: The public certificate of your CA. This file is shared with any server or client that needs to verify the identity of certificates you’ve signed.
pki/private/ca.key: The private key of your CA. This file should be kept highly secure and never distributed.
Step 5: Generate two Server Certificate and Key for use with ZID and OpenVPN OAUTH servers. Sign the server’s certificate request using your CA.
A server certificate is used by a server to prove its identity to clients. Use a descriptive name for the server (e.g., openvpn_auth_customerA). The nopass option is often used here to allow the server to start without needing a password to decrypt its key.
./easyrsa --vars=~/easy-rsa/vars.custom --dn-mode=org --req-cn= --req-org= --req-email= --req-c= --req-st= --req-city= --req-ou= --subject-alt-name="IP:" --batch build-server-full nopass
./easyrsa --vars=~/easy-rsa/vars.custom --dn-mode=org --req-cn= --req-org= --req-email= --req-c= --req-st= --req-city= --req-ou= --subject-alt-name="IP:" --batch build-server-full nopass
Example
./easyrsa --vars=~/easy-rsa/vars.custom --dn-mode=org --req-cn="zid" --req-org="AmZetta Technologies" --req-email="[email protected]" --req-c=IN --req-st="TN" --req-city="Chennai" --req-ou="CPEUnit" --subject-alt-name="IP:10.200.3.87" --batch build-server-full zid nopass
./easyrsa --vars=~/easy-rsa/vars.custom --dn-mode=org --req-cn="openvpn_auth_customerA" --req-org="AmZetta Technologies" --req-email="[email protected]" --req-c=IN --req-st="TN" --req-city="Chennai" --req-ou="CPEUnit" --subject-alt-name="IP:10.200.3.87" --batch build-server-full openvpn_auth_customerA nopass
The generated files for the servers are:
pki/issued/openvpn_auth_customerA.crt: The server's public certificate.
pki/private/openvpn_auth_customerA.key: The server's private key.
pki/issued/zid.crt: The server's public certificate.
pki/private/zid.key: The server's private key.
Importing the Certificate Authority (CA) into Local CA Certificate Store
Copy the CA certificate to the system trust store: The standard location for a local CA on a Debian-based system like Ubuntu is /usr/local/share/ca-certificates/. Copy your ca.crt file to this directory. Make sure the file has a .crt extension.
cp ~/easy-rsa/pki/ca.crt /usr/local/share/ca-certificates/my_custom_ca.crt
Update the system’s trust store: Run the update-ca-certificates command. This command will integrate your new CA certificate into the system’s trust bundle.
update-ca-certificates
You should see output similar to this, indicating that your new certificate has been added:
Updating certificates in /etc/ssl/certs...
1 added, 0 removed; done.
Running hooks in /etc/ca-certificates/update.d...
...done.
Importing the Server Certificate into Nginx Store
Install nginx
apt install nginx
This step configures Nginx to use the server certificate and private key you generated to enable HTTPS.
Create the directory if it doesn’t exist
mkdir -p /etc/nginx/ssl
Copy the certificate and private key
cp ~/easy-rsa/pki/issued/openvpn_auth_customerA.crt /etc/nginx/ssl/
cp ~/easy-rsa/pki/private/openvpn_auth_customerA.key /etc/nginx/ssl/
cp ~/easy-rsa/pki/issued/zid.crt /etc/nginx/ssl/
cp ~/easy-rsa/pki/private/zid.key /etc/nginx/ssl/
Secure the private key
chmod 600 /etc/nginx/ssl/openvpn_auth.key
chmod 600 /etc/nginx/ssl/zid.key
Preparing the Nginx conf files
The provided sample NGINX reverse proxy configuration is for an on-premises Identity Provider and an OpenVPN OAUTH server hosted on the EC. To implement this, first update the NGINX files with the required certificates. Place these files in the /etc/nginx/sites-available/ directory.
Locally Hosted Identity Provider
Modify the certificate & key file names, and also edit the proxy_pass line for "IP address of locallty hosted IDP" in the below file
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /etc/ngnix/ssl/zid.crt;
ssl_certificate_key /etc/ngnix/ssl/zid.key;
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
error_page 497 https://$host:$server_port$request_uri;
location / {
proxy_pass http://<IP address of locallty hosted IDP>:9080/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
OpenVPN OAUTH Server
Modify the certificate & key file names, and also edit the proxy_pass line for the ip "IP of the Edge Controller " in the below file
server {
listen 9001 ssl;
listen [::]:9001 ssl;
ssl_certificate /etc/ngnix/ssl/openvpn_auth_customerA.crt;
ssl_certificate_key /etc/ngnix/ssl/openvpn_auth_customerA.key;
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
location / {
proxy_pass http://<IP of the Edge controller>:9000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host; # Crucial for some apps
proxy_set_header X-Forwarded-Port $server_port; # Crucial for some apps
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
}
}
Enable the sites
Create symbolic links to them in the /etc/nginx/sites-enabled/ directory so that the nginx server enables them for use.
ln -s /etc/nginx/sites-available/zid /etc/nginx/sites-enabled/zid
ln -s /etc/nginx/sites-available/openauth /etc/nginx/sites-enabled/openauth
Restart nginx server for the new changes to take effect
systemctl restart nginx
Setup the clients / users in ZID
Refer the ZID guide for the same
Import Reverse proxy CA onto the Edge Controller
View the CA certificate on the reverse proxy machine from the local CA store. Make sure you have elevated (root) privileges to view the file.
cat /usr/local/share/ca-certificates/customca/ca.crt
Copy all the contents and save it to the local desktop or laptop with the .pem or .crt file extension. Example reverseproxy-ca.pem or reverseproxy-ca.crt
The CA certificate used by the reverse proxy / Nginx server should be imported on the EC to validate the issuer of the certificate. This can be done from the UI of the Edge Controller -> Security->X.509->Trusted CAs. Click on the Import button. Click the Upload icon and select the reverseproxy-ca.pem file from your local drive location.

Configuring the Edge Controller VPN Server for OAUTH_MFA
Generate Local CA and Host Server Certificates for Tunnel
Generate a Local CA certificate if running as a standalone Edge Controller from the Security->X.509->Trusted CAs.


Proceed to generate a HOST Server certificate for use with the VPN tunnel Security->X.509->Certificates.


VPN Tunnel creation
The Remote Endpoint URL or OAUTH Provider Token URL is the address of your Identity Provider or the Reverse Proxy that handles the secure (TLS) connection. The Redirect URI is the URL of that same Reverse Proxy. When a reverse proxy is in use, it terminates the TLS connection for both URLs before forwarding traffic to the Identity Provider and the EC Authentication port. It is highly recommended to use a reverse proxy in production environments.
Create a Site to Mobile VPN tunnel by navigating to the Tunnels->SITE TO MOBILE VPN page.

Provide the following information
- Description
- Tunnel UUID
- Local Port
- Local IP
- Gateway if multiple ISP are present and Netbalancer is enabled.
- DHCP Pool
- Advertise the subnets that the clients can reach
- Select OAUTH_MFA from the Authentication Drop down.
- Select the HOST Server certificate which was generated above.
- Provide the
- ClientID (Configured in ZID),
- Client Secret (Configured in ZID),
- OAUTH Provider Token URL (Reverse proxy url for ZID),
- Select Reverse Proxy,
- Redirect UI (Reverse Proxy URL for OpenVPN OAUTH)
An example of the OAUTH_MFA settings is shown below

Click on create. On successful creation, the tunnel status will switch to connected in a few seconds. If it shows PROCESS_NOT_STARTED, refresh the page. If it is not able to switch to CONNECTED state after a minute, it likely is that the Authentication Settings are not accurate or the reverse proxy configuration is not configured correctly.

Export Client Profile .OVPN File
The .ovpn file can then be imported into the OpenVPN Connect. Click on "Export Client Profile" in the options

Selecting a certificate selection is not mandatory and is used for additional protection if need be. If the Edge Controller is hosted behind a firewall, please enter the Public IP and Port forwarded port.

The downloaded .ovpn file can be uploaded to the OpenVPN Connect Application

Connecting using OpenVPN Connect app via ZID + MFA
Once the .ovpn file is imported from above, slide the bar to connect to the VPN Server

The ZID Login page pops up. On entering the username/password and successful authentication, it prompts for the MFA setup. The MFA is setup during the first login to ZID. Use your phone to scan the QR code and the recommended applications to setup teh Mobile Authenticator. After setup is completed, it will prompt for the MFA code to continue login.


For subsequent logins, the OTP configuration page will not show up and instead the below screen requesting an OTP entry would be shown.


Connected OpenVPN Connect
