Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
RDP SSL tunneling

RDP SSL tunneling with stunnel

stunnel utility can be used to tunnel RDP connexions through HTTPS/SSL in order to pass through proxies. It served the same purpose as the Microsoft RDP gateway, but without requirements for Windows Server and licences. I use it for connections to my home PC from work.

General configuration

The 2 sides for the RDP connexion are :

  • The server side :

    • The server is the PC you want to connect to (typically your home PC). Remote connections have to be enabled in the computer properties of that machine, and the local firewall adjusted for corresponding traffic (TCP 3389).
    • On this network, I also use a Ubuntu server as gateway. This server will run the stunnel utility. stunnel can be hosted directly on the server PC also (open relevant port on the firewall also). I use this always-on gateway for several other purposes, one being waking up the other machines on the network with wakeonlan.
    • The last component on the server network is the network router/NAT used to connect to the internet (DSL box). The traffic needs to be routed from the router to the gateway then to the server.
  • The client side :

    • The client is typically a PC (or any device with RDP client and stunnel available) with which you want to access to the server PC.
    • On the client side, there's a proxy server with HTTPS proxying (if there's no proxy, there's not much reason to tunnel...).

The end to end connexion chain will be this one :

  • On the client, the RDP client is started with a target address of localhost:3390
  • On the client, stunnel intercepts port 3390 traffic and encapsulate it into HTTPS and redirect it to localhost:81
  • Still on the client, socat utility is used to redirect locahost:81 to server_public_address:443 through proxy. socat is necessary because stunnel doesn't support socks proxies natively.
  • The data can then go through the proxy, the internet and to the router port 443 in the server network.
  • The router routes the request to the gateway port 81, where stunnel can decapsulate the RDP traffic from HTTPS
  • stunnel can then finally send the packet to the server_private_address:3389 port.

Server configuration

  • Enable remote desktop service

  • Check firewall configuration

  • Check that the users used for remote connection all have a password

  • Use one of the non official patch to allow multiple RDP connection on Windows client if you feel the need (this is not allowed by the product license...)

Gateway configuration

I'm using an Ubuntu gateway. If you don't use a gateway at all or use a Windows gateway, stunnel is available on Windows and can be installed as a service to start automatically.

On Ubuntu :

  • Install stunnel
 sudo apt-get install stunnel4
  • Create a certificate configuration file

The following is a basic default configuration to generate SSL certificates with openssl. It doesn't protect the private key, so it's potentailly vulnerable. stunnel requires certificates to start. We're not going to fully check them, their only use will be to encrypt the tunnel, not to secure the communication : we're tunneling RDP which is itself encrypted and reasonably protected...

[ req ]
default_bits                    = 2048
encrypt_key                     = no
distinguished_name              = req_dn
x509_extensions                 = cert_type

[ req_dn ]
countryName = Country Name (2 letter code)
countryName_default             = FR
countryName_min                 = 2
countryName_max                 = 2
stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = NA
localityName                    = Locality Name (eg, city)
localityName_default            = Paris
organizationName                = Organization Name (eg, company)
organizationName_default        = My Organization
organizationalUnitName          = Organizational Unit Name (eg, section)
organizationalUnitName_default  = Myself
0.commonName                    = Common Name (FQDN of your server)
0.commonName_default            = localhost

[ cert_type ]
nsCertType                      = server
  • Create a certificate using the configuration file
 sudo apt-get install openssl
 openssl req -new -x509 -days 3650 -nodes -config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
 sudo mv stunnel.pem /etc/stunnel
  • Configure stunnel Copy the stunnel configuration
sudo cp /usr/share/doc/stunnel4/examples/stunnel.conf-sample /etc/stunnel/stunnel.conf
sudo nano /etc/stunnel/stunnel.conf

Update the configuration file as folllowing

chroot = /var/lib/stunnel4/
setuid = stunnel4
setgid = stunnel4
pid = /

;debug = 7
;output = /var/log/stunnel4/stunnel.log
; foreground = yes

cert = /etc/stunnel/stunnel.pem
key = /etc/stunnel/stunnel.pem
options = NO_SSLv2

accept = 81
connect = server_internal_address:3389

The 3 commented lines are debug parameters that can be used to troubleshoot the configuration. The [rdp] section is where the decapsulation happens : traffic is received as SSL on port 81 and resent to the target server on the RDP port. I'm using port 81 here to leave standard HTTP port available.

  • Enable stunnel automatic start

For troubleshooting configuration, you should start stunnel from a command prompt with the "foreground = yes" parameter in its configuration. Be aware that it should be launched with "stunnel4" command, not stunnel.

When everything works, start it as a service for continuous operations. By default, stunnel is not allowed to start automatically. Edit the configuration with

sudo nano /etc/default/stunnel4

And set the "ENABLED" line to 1 :

# /etc/default/stunnel
# Julien LEMOINE <>
# September 2003

# Change to one to enable stunnel automatic startup

# Change to one to enable ppp restart scripts

And then start the service :

sudo service stunnel4 start

Router configuration

  1. On your router (typically your DSL router), route the external port 443 to gateway_internal_address:81 (as configured previously). You want to use the well knwown 443 port externally, non standard port will mostly be filtered out by proxies.

  2. If you have a dynamic IP address, you'll need to configure a public dynamic DNS entry. I'm using a address as it's free and directly managed by my router. If your router doesn't natively support this function, there are utilities to provide automatic dynamic DNS updates on Linux or Windows.

  3. As some proxies also filter out addresses of well known free dynamic DNS services, I had to get a personal domain. For a few dollar par year, I used GoDaddy to get a domain, and create an alias betwee, and

Client configuration

My clients are all corporate PCs running Windows, but the steps would be very similar on a Linux client.

  • Install cygwin

openssl, stunnel and socat are available directly from cygwin repository and have to be selected during setup.exe installation.

  • Create a certificate

Use the same configuration file as on the server (described earlier), and generate a similar certificate.

 openssl req -new -x509 -days 3650 -nodes -config stunnel.cnf -out stunnel.pem -keyout stunnel.pem
 mv stunnel.pem /etc/stunnel
  • Configure stunnel
nano /etc/stunnel/stunnel.conf

Update the configuration file as following :

; debug = 7
; foreground = yes
; output = s/etc/stunnel/tunnel.log

cert = /etc/stunnel/stunnel.pem
options = NO_SSLv2
client = yes
accept =
connect =

The 3 commented lines can be used for troubleshooting. The [rdp] section describes the encapsulation process (client = yes for encapsulation). Traffic from port 3390 is encapsulated and redirected locally to port 81 where it will be captured by socat. The port numbers are chosen to keep standard ports available.

  • Create a script to launch stunnel & socat on demand

Create a new script with :


and add start commands in it :

read -s -p "Password:" password
socat -d -d  TCP-LISTEN:81,reuseaddr,fork \,resolve,proxyport=proxy_port,proxyauth=proxy_user:$password

The second line launch stunnel. the third one launch socat and instruct it to relay traffic addressed to local TCP port 81 to port 443 (this is to be replaced with your public DNS name). It uses the corporate proxy defined by its IP address, port, username (proxy_address, proxy_port and proxy_user to be replaced by your values, user & password may not be necessary in your configuration).

  • Launch script and start the RDP client and point it to localhost:3390. If you have launched everything interactively, you see see messages in client stunnel, socat and then server stunnel logs.


  • Add foreground = yes is stunnel config file so the it runs interactively instead of forking.
  • Test stunnel & socat by poiting a browser on the same machine to localhost:port_to_test, then pointing a remote browser there (connection will fail but you should see some activity in logs).

Download links

- stunnel : <>
- socat : <>
- cygwin : <>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment