Skip to content

Instantly share code, notes, and snippets.

@enricmcalvo
Last active February 21, 2024 19:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save enricmcalvo/6151178 to your computer and use it in GitHub Desktop.
Save enricmcalvo/6151178 to your computer and use it in GitHub Desktop.
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 = /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

[rdp]
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 <speedblue@debian.org>
# September 2003

# Change to one to enable stunnel automatic startup
ENABLED=1
FILES="/etc/stunnel/*.conf"
OPTIONS=""

# Change to one to enable ppp restart scripts
PPP_RESTART=0

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 my_name.no-ip.biz 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 my_name.info domain, and create an alias betwee, www.my_name.info and my-name.no-ip.biz....

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
[rdp]
client = yes
accept = 127.0.0.1:3390
connect = 127.0.0.1:81

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 :

nano tunnel.sh

and add start commands in it :

read -s -p "Password:" password
stunnel
socat -d -d  TCP-LISTEN:81,reuseaddr,fork \
    PROXY:proxy_address:www.my_name.info:443,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 www.my_name.info 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.

Troubleshooting

  • 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 : <https://www.stunnel.org/index.html>
- socat : <http://www.dest-unreach.org/socat/>
- cygwin : <http://www.cygwin.com/>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment