Connect to Remote Desktop from Outside Your Home Securely with SSH
I have a Windows workstation sitting under my desk at home. This is where I do all of my professional development. I like this setup because it keeps my work completely separate from my personal stuff. If I’m honest, though, my main reason for buying it was because I poured a glass of water over my development laptop. But now that I have it, I highly recommend it.
When I’m working at home, I connect to this workstation using Remote Desktop (RDP). It’s a fantastic protocol for accessing a Windows machine across a network. It’s built in to the operating system, and it’s generally pretty smooth. Most times I can’t even tell that I’m using it.
When I’m working remotely, however, accessing that workstation under the desk is a lot harder.
You could share the RDP port on the workstation through your router, but I don’t recommend this. Windows isn’t really hardened to be on the open internet. I suggest instead exposing an SSH server, authenticating with a certificate (and not allowing any other methods), and using that to tunnel RDP through to your Windows workstation nestled safely within your firewall.
In this post I’ll walk you through setting that up.
Quick version
You can use this command to set up the SSH connection with RDP being routed through it:
1 | ssh user@fully_qualified_ddns_name -p ssh_port -i ~/.ssh/home_server -L 127.0.0.2:3389:windows_private_ip:3389 |
Substitute the values:
user- your username on your home server (where SSH is running)fully_qualified_ddns_name- the full ddns name of yours router (ex:myhome.duckdns.org)ssh_port- the public port you use to expose SSH to the internet (ex: 2299)home_server- the certificate file you set up for SSH authenticationwindows_private_ip- the private network ip (from the point of view of your home server) of the Windows workstation you want to connect to
Once the connection is established, open the standard Remote Desktop client, and connect to: 127.0.0.2. Then log in to the workstation with your normal credentials.
How it works
Setting up SSH
I’m running sshd (the service that hosts SSH) on a little home server I use to run a number of services in my home. I’m using Debian, so I was able to install sshd easily using the built-in package manager. There are SSH servers for all the platforms, so you don’t need to use Debian if you don’t want to.
If you do use Debian however, this is how I’ve got mine configured:
1 | sudo groupadd server-access |
This creates a group called server-access, and adds the current user to it. Later on, we’re allowing anyone in this group to access the sshd server. We are also requiring all users to authenticate with a certificate. You can add as many users to this group as you’d like.
Creating a certificate and adding it to a user
Run this command to generate a certificate on the computer you’re connecting from. Note that it should work in both Linux and modern versions of Windows. Probably on Macs too, but I haven’t tried.
1 | ssh-keygen -t rsa -f ~/.ssh/home_server |
You can use any filename you like for the certificate, but remember what you choose because you’ll need it later. If you like, you can also add a comment inside the file with -C "home server". This can help keep them straight if you have multiple certificates.
This command generates two files: the private key (the name you chose), and the public key (the name you chose with .pub added to the end). Open the public key file and copy its contents. You can use cat ~/.ssh/home_server.pub to read the file in a console.
If you’re using a Debian machine for your Home Server, you can find (or create) a file at ~/.ssh/authorized_keys, and paste the whole contents of the .pub file as a new line. If you’re setting this up for multiple users, make sure to create one of these files for each home directory. I suggest different keys for each user.
If you have multiple computers to connecting to your home network all for the same user, I also suggest using a different key pair for each connecting computer. This way, if one of your computers is lost or stolen, you can delete its key while continuing to use the others. If you’re doing this, I also suggest adding comments to the end of public keys in the authorized_keys file so you can tell them all apart.
Now you can test your SSH authentication. Running this inside your home network is fine.
1 | ssh user@home_server_ip -i ~/.ssh/home_server |
If it works, you should be logged in to the home server.
Exposing SSH to the Internet
You have to set up port forwarding on your router/firewall to allow SSH on your home server to be accessible from outside your home. Look to the documentation for your particular router if you need help with this.
The default port for SSH is 22. You should be forwarding to port 22 at the local ip address of your home server. I don’t recommend, however, using port 22 as the public port on the outside of your router. There are a lot of robots crawling every IP address on the internet. Since port 22 is a commonly used port, it could be a target for automated attacks.
It’s ideal to choose a port about 2000 as this is well past the range of the most commonly used protocols on the internet. You can refer to a listing of commonly used port numbers (such as https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers) to make extra sure it’s not something standard.
Set up dynamic DNS for your router
Depending on your Internet Provider (ISP), your home network may get an IP address that never changes, or you might have one that changes every day. Even if it happens infrequently, Dynamic DNS can make connecting to your home environment a lot simpler.
Many consumer routers have a Dynamic DNS (DDNS) option built in. If your router does, this will likely be the easiest method. If not, you can set up up a service like ddns-updater on your home server. I personally run it inside a Podman container.
Once this is working, you’ll now have a convenient name to reach your home network instead of needing to look up its public ip every time you want to connect.
Connecting to SSH
With all of the above configured, you should now be able to connect to SSH from outside your network. Depending on your router, you may not be able to test this from inside your home network.
When I want to test external connections, I enable hotspot mode on my phone and connect the client computer I’m using to its wifi. If you don’t want to do this, it could also be a good excuse to visit your local coffee shop.
You can use this command to connect to the SSH server:
1 | ssh user@external_ip_address -p ssh_port -i ~/.ssh/home_server |
Enable RDP on your workstation
You need to enable Remote Desktop on the Windows workstation before you can use it. If you haven’t done this already, open Settings and search for Remote Desktop.
You’ll also need to know your username and password to log into Windows.
Connecting RDP to localhost
If your client computer happens to be a Windows computer, you have to use a trick to get around a weird limitation in the Microsoft Remote Desktop Client.
If you try to connect it to 127.0.0.1, you get this error:
1 | Your computer could not connect to another console session on the remote computer because you already have a console session in progress. |
Unfortunately, you really want to open sharing on localhost (as opposed to the wifi ip) so that only RDP connections from on your computer will be able to reach the SSH tunnel. This is especially important when using public networks like a coffee shop wifi.
One little-known trick is that all the IP addresses in the 127.0.0.1/8 block (anything starting with 127.) are all valid localhost IP addresses. The check in the Microsoft RDP client only looks for 127.0.0.1, so you can use 127.0.0.2 and get around it.
To forward the port through the SSH connection, you add this to the SSH command: -L 127.0.0.2:3389:windows_private_ip:3389
The first 3389 is the port that’s opened up on your local computer. You don’t have to use 3389 here, but it’s convenient. If you had multiple workstations inside your home network you can add -L multiple times with a different local port for each one.
The second 3389 is the port on the computer you’re connecting to. This will pretty much always be 3389, so don’t try to change it.
Putting it all together
Refer to Quick version near the top of this post for all the steps together.
With everything set up, you should now be able to work remotely with ease and peace of mind. Maybe it’s time to finally do some real work on your laptop from that coffee shop?