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.
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.
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...)
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 <email@example.com> # 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
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.
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.
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....
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
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 :
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.
- 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).
- stunnel : <https://www.stunnel.org/index.html> - socat : <http://www.dest-unreach.org/socat/> - cygwin : <http://www.cygwin.com/>