Why someone should use this approach

This method adds additional security by encrypting VPN Tunnel traffic again. But apart from security tightening you can get additional benefits depending on your scenario.

Common use cases are:
  • Bypass the networks that have restrictions for using VPN or any technologies that uses TCP Protocol(Except HTTPS).
  • Bypass your ISP's usage meter if your ISP has zero rated websites or if your data plan has excessive or unlimited data for specific websites(such as unlimited social medias or XXGB for Netflix, but you wanted to visit other sites too) - You could use HTTP/HTTPS Proxy (with SNI) (such as Squid Proxy). But not all the application supports Proxy and some applications bypasses system proxy.


TL;DR;

  • We are going to use OpenVPN (Community Edition) for VPN and Stunnel for SSL/TLS Tunnel
  • We will be using a Ubuntu 22.04 VPS to run OpenVPN Server and Stunnel (in Server Mode)
  • Client will be a Windows 10 System.
  • But you can use any Operating System since OpenVPN and Stunnel are Open Source Software and you can compile it in any OS as long as that OS has necessary compiler and dependencies


Design

This is the overall deign of the setup we are going to implement to achieve our goal.

In the above Diagram, I have marked important things only. Let's implement it.

Server(Virtual Private Server) Setup

I recommend to get a VPS with minimum specifications. I usually use a VPS with 1vCPU and 512MB RAM. And automated all the setup via User Data Script (This is supported by all cloud providers). 

Install OpenVPN Community edition

This is bit hard setup for the beginners. Therefore you can use one of the below scripts to install and configure a ready-to-use OpenVPN Server.
  • https://github.com/Nyr/openvpn-install
  • https://github.com/angristan/openvpn-install
You just need to answer few questions. Once it is done, you will see .ovpn configuration file in your home directory. Copy it to your client machine(Your Computer/Mobile/Hotspot Device). 

While answering the questions, you have to set protocol as TCP. Because at this time passing UDP over TCP is not implemented yet because of technical difficulties. Also use the port other than 443. Let's configure it using the port 8443.

You have to modify above script to install and configure everything automatically if you don't want any of your interaction(This is very helpful when you use User Data Script).

If you have trouble installing community Edition, you could also install OpenVPN Access Server, which is their enterprise version. It is super easy for installation and configuration. But it has some limitations for the free usage.

Stunnel Installation

Stunnel is a proxy, that is designed to wrap TCP Connection with TLS encryption. That's why we need to have Stunnel running in the server mode in our Server to unwrap the TCP Connection wrapped by Stunnel running in our Computer(as you can see in the above diagram).

You can install in your Ubuntu 22.02 using the following commands:
sudo apt-get -y install stunnel4

If for some reasons, if you ever wanted to compile Stunnel on your Ubuntu 22.04, this is how you can do it.
  • First install the dependencies
    sudo apt-get -y update
    sudo apt-get -y install openvpn libssl-dev openssl build-essential
  • Download the Latest Version from here: https://www.stunnel.org/downloads.html or Download your preferred version from here: https://www.stunnel.org/archive/
    wget "https://www.stunnel.org/archive/5.x/stunnel-5.69.tar.gz" -O stunnel.tar.gz
  • Un archive it.
    tar -xf stunnel.tar.gz -C stunnel --strip-components 1
  • Change directory
    cd stunnel
  • Then execute ./configure
    ./configure
  • Then install it.
    sudo make install
Once you installed stunnel, it's time to configure it as Server Mode. To make it easier, let's store our configuration files in /etc/stunnel/ directory.
  1. Create the directory
    mkdir -p /etc/stunnel/
  2. Now we need to create X.509 Public Key and Private key. Because it's essential to encrypt & decrypt SSL/TLS  Communication. Self signed certificate is enough, because we can configure Stunnel client to ignore certificate verification.

    1. Create Certificate configuration file(If not, you have to answer prompted questions, it's difficult to answer those questions if you are setting up an automated script).
      [ req ]
      prompt                 = no
      days                   = 3650
      distinguished_name     = req_distinguished_name
      req_extensions         = v3_req
      
      
      [ req_distinguished_name ]
      countryName            = US
      stateOrProvinceName    = CA
      localityName           = My City Name
      organizationName       = My Company LLC
      organizationalUnitName = Research Team
      commonName             = internet.org
      
      [ v3_req ]
      basicConstraints       = CA:
      extendedKeyUsage       = clientAuth
      subjectAltName         = @sans
      
      [ sans ]
      DNS.0 = localhost
      DNS.1 = *.internet.org
      It's just a sample configuration file, If you wish, you can replace any of the part you want(such as countryName, commonName, sans etc.) and save the file as stunnel.cnf

    2. Now you can generate certificate using below command:
      openssl req -new -x509 -days 3650 -nodes -config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
      Note that we are using same file name(stunnel.pem) to store Public and Private keys in the above command. That's totally fine and Stunnel can recognize it. You can store private key using different name too.
  3. Certificate is ready! Now it's time to do the Stunnel configuration. Save the following file as stunnel.conf
    [https service - you can use any name here]
    accept  = 443
    connect = 8443
    cert = /etc/stunnel/stunnel.pem
    TIMEOUTclose = 0
    accept port should be 443. Other ports also fine, but if you are using this to bypass something using SNI, then port 443 is must(Because firewalls may filter the port).
    connect port should be the TCP port of OpenVPN. Since OpenVPN server and Stunnel are running on same machine you can just use the port. If not, you have to specify the host and port. 
    If you didn't export private key in the same file(stunnel.pem), then you have to add key argument and provide the path of private key in the above config file.

    More information and options can be found here: https://www.stunnel.org/static/stunnel.html

  4. Now you can run the Stunnel using the below command. You won't see any output if there are no errors.
    stunnel /etc/stunnel/stunnel.conf
Our Server Setup is Ready. Let's configure Client(Our Device).

Client(Your Computer/Mobile/Hotspot Device) Setup

I'm going to use Windows 10 Machine as client. So need to download OpenVPN Windows Client and Stunnel for Windows.

Stunnel Configuration

You can download Stunnel from here: https://www.stunnel.org/downloads.html
Same stunnel application can be used as both Server mode and Client mode. There is no need to download separate executables as we are going to do with OpenVPN.

Once you installed Stunnel, you need to edit it's configuration file. Run the Stunnel. Then click on Configuration >>> Edit Configuration.

Then, it will open the configuration using your default text editor. You can find the same file in the Stunnel installation folder(Inside config folder. File name is stunnel.conf)

It will contain default configuration. You don't need all of that. Therefore delete all of it's content and paste the following content.
[vpn service - you can use any name here]
sni = internet.org
client = yes
accept = 127.0.0.1:8443
connect = <your-vps-ip>:443
verifyChain = no
sni is the name of the whitelisted host in the firewall or zero rated website by your ISP. But it's optional. You don't need SNI, if you are going to use Stunnel for additional security. You have to put your VPS's IP in the connect directive. Since we don't need to verify the certificate we set verifyChain as no. As per above configuration, Stunnel will be listening on the port 8443(will be accepting all connections from 127.0.0.1) and will forward all the traffic to the VPS IP on the port 443. And Stunnel running on server mode will do the decryption and will forward to OpenVPN Server as mentioned in the above Diagram. 

More information and options can be found here: https://www.stunnel.org/static/stunnel.html

In order for the changes to take effect, you have to reload the configuration from Configuration >>>  Reload Configuration

OpenVPN Client Configuration

You can download OpenVPN Client from here: https://openvpn.net/vpn-client/

When configuring OpenVPN Server, you might have downloaded, .ovpn file, that's the file you need to connect with the OpenVPN Server. But you need to do one modification to it. Sometimes it might have your VPS IP. In this case, we don't want to directly connect to the VPN. We need to connect through the Stunnel, then only it can wrap it using TLS/SSL Encryption. Therefore you need to edit the .ovpn file. Open .ovpn file with a text editor and replace the IP and the port you see in the remote parameter with 127.0.0.1 8443 (That's the listening IP and port in the Stunnel Client configuration).

Screenshot:

Then you can import that file to the OpenVPN Client and you can connect.

That's all! Hope this helps. Please let me know in the comments, if you have any issues. Thank you!