Stunnel
Encapsulate VPN connections with plain TLS to workaround firewall restrictions.
Most of corporate firewalls have a feature called Deep Packet Inspection (DPI), which blocks VPN connections.
When you OpenVPN client is trying to connect to the server using UDP, it returns the following error.
OpenVPN 2.4.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Sep 5 2018
library versions: OpenSSL 1.1.0g 2 Nov 2017, LZO 2.08
Outgoing Control Channel Authentication: Using 256 bit message hash 'SHA256' for HMAC authentication
Incoming Control Channel Authentication: Using 256 bit message hash 'SHA256' for HMAC authentication
TCP/UDP: Preserving recently used remote address: [AF_INET]X.X.X.X:1194
Socket Buffers: R=[212992->212992] S=[212992->212992]
UDP link local: (not bound)
UDP link remote: [AF_INET]X.X.X.X:1194
NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay
TLS Error: Unroutable control packet received from [AF_INET]X.X.X.X:1194 (si=3 op=P_ACK_V1)
When you OpenVPN client is trying to connect to the server using TCP, it returns the following error.
OpenVPN 2.4.4 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] built on Sep 5 2018
library versions: OpenSSL 1.1.0g 2 Nov 2017, LZO 2.08
Outgoing Control Channel Authentication: Using 256 bit message hash 'SHA256' for HMAC authentication
Incoming Control Channel Authentication: Using 256 bit message hash 'SHA256' for HMAC authentication
TCP/UDP: Preserving recently used remote address: [AF_INET]X.X.X.X:1294
Socket Buffers: R=[87380->87380] S=[16384->16384]
Attempting to establish TCP connection with [AF_INET]X.X.X.X:1294 [nonblock]
TCP connection established with [AF_INET]X.X.X.X:1294
TCP_CLIENT link local: (not bound)
TCP_CLIENT link remote: [AF_INET]X.X.X.X:1294
NOTE: UID/GID downgrade will be delayed because of --client, --pull, or --up-delay
TLS Error: TLS key negotiation failed to occur within 60 seconds (check your network connectivity)
TLS Error: TLS handshake failed
Fatal TLS error (check_tls_errors_co), restarting
SIGUSR1[soft,tls-error] received, process restarting
Restart pause, 5 second(s)
To encapsulate VPN connections with plain TLS to workaround firewall restrictions.
The main idea is to create the following architecture:
Server | Client
Openvpn (port 1194) <---> Stunnel (port 443) <---> | <---> Stunnel (port 443) <---> Openvpn (port 1194)
|
You need to have OpenVPN already running with TCP protocol.
apt update
apt install stunnel4
openssl req -new -newkey rsa:2048 -days 3650 \
-nodes -x509 -sha256 -subj '/CN=127.0.0.1/O=localhost/C=US' \
-keyout /etc/stunnel/stunnel.pem -out /etc/stunnel/stunnel.pem
Create the file
/etc/stunnel/stunnel.conf
nano /etc/stunnel/stunnel.conf
With the following content:
/etc/stunnel/stunnel.conf
[openvpn]
client = no
accept = 443
connect = localhost:1194
cert = /etc/stunnel/stunnel.pem
What the config does is:
- Line 3: Stunnel will accept (listen) connections on port 443;
- Line 4: Stunnel will redirect all connections to Openvpn which is running on localhost port 1194.
Why Stunnel is running on port 443? Because most likely the client will be able to connect to it since most firewalls allow outbout connections on port 443. Although you can change it to any port you want.
Configure iptables to accept incoming traffic on port 443
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
Make sure your iptables config is persisted:
apt install iptables-persistent
Edit
/etc/default/stunnel4
nano /etc/default/stunnel4
Replace
ENABLED=0
with ENABLED=1
systemctl restart stunnel4
systemctl enable stunnel4
Check stunnel process is up and running and listening to the correct port
netstat -ntulp |grep stunnel
Output example:
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 13784/stunnel4
apt update
apt install stunnel4
Copy
/etc/stunnel/stunnel.pem
from your server and paste it in your client in the same path.Create the file
/etc/stunnel/stunnel.conf
nano /etc/stunnel/stunnel.conf
With the following content:
/etc/stunnel/stunnel.conf
[openvpn]
client = yes
accept = 443
connect = PUT-YOUR-SERVER-HOST-HERE:443
cert = /etc/stunnel/stunnel.pem
What the config does is:
- Line 3: Stunnel will accept (listen) connections on port 443;
- Line 4: Stunnel will redirect all connections to Stunnel server. Replace
PUT-YOUR-SERVER-HOST-HERE
with your server domain or IP.
Edit
/etc/default/stunnel4
nano /etc/default/stunnel4
Replace
ENABLED=0
with ENABLED=1
systemctl restart stunnel4
systemctl enable stunnel4
Edit your OpenVPN client config as follows:
/etc/openvpn/client.conf
...
proto tcp
...
remote localhost 443
...
Your OpenVPN client will actually connect to Stunnel running localhost on port 443, which will redirect to Stunnel server, then it will redirect to the OpenVPN server.
systemctl restart openvpn@client
systemctl enable openvpn@client
On your client run
ifconfig
. You should see your OpenVPN interface tunnel.Last modified 4yr ago