Secure RDP – Using SSH Tunneling With Built-In Windows Features


Who knew? I didn’t. This is the screen for Settings -> Apps and Features -> Optional Features for both Windows Server 2019 as well as Windows 10. This was a very pleasant surprise. With that, I am always looking for a way to connect to my home lab that is:

  1. Secure
  2. Minimizes the required HW/resource footprint

I was previously using Remote Desktop Services along with Azure App Proxy (here) to publish access securely, however, this meant that I had to have the RDS and AAD App Proxy footprints in my lab. I only have 48GB of RAM in my lab and I run out all the time – running AD along with a few additional services for demo purposes can really put the squeeze on quick. Stumbling across OpenSSH built right in seems like it might be the solution for which I have been looking. With that being said, the documentation….has room for improvement. I did finally find the answers I was looking for and was able to leverage SSH tunneling in order to RDP into my lab. I love this!

** Requires Windows 10 or Server 2019

I am going to save you some time and steer you away from the official docs. The documentation you need to get started is in an answer on Stack Overflow here: and was provided by this person:

High level, here are the condensed steps from his answer:

On the server:

  1. PS> Add-WindowsCapability -Online -Name OpenSSH.Server~~~~ or through the UI (pictured above)
  2. Start the services
    1. PS> Start-Service ssh-agent
    2. PS> Start-Service sshd

On the client:

  1. Mkdir .ssh in the C:\Users\<Username>\ directory. This is where the keys are going to land. For demo purposes, I am going to use administrator so the path would be C:\Users\Administrator\.ssh
  2. CD to that directory using CMD or PS
  3. Run ssh-keygen
    1. Give a password or not for the key file. I chose to do so for the sake of security
  4. In the window, run ssh-add .\id_rsa (assuming this is the private key that was generated). You will get prompted for the password – go ahead and enter it. This makes the key securely available without prompted for a password every time you use it to connect from this machine

The client is now configured.

Back to the server:

  1. Log into the server as the user you are wishing to connect as – for demo purposes this is the administrator account
  2. Mkdir C:\Users\<Username>\.ssh – in this case, C:\Users\Administrator\.ssh
  3. Copy and paste the contents of the .pub file from the client into a file named authorized_keys here in this directory on the server
  4. Right Mouse Click on autorized_keys and go to properties
  5. Properties -> Security -> Advanced -> Disable Inheritance
  6. There should be exactly 2 perms assigned to this file (probably has 3 right now).

    Get rid of the extra. You should have SYSTEM and your user account – in this case Administrator. Get rid of any other entries such as Administrators (group) here.

  7. Apply, Ok, Close, or whatevs to save the changes
  8. Open C:\ProgramData\ssh\sshd_config with notepad or your text editor of choice
  9. Comment out the bottom 2 lines

    NOTE: Put a # at the beginning of each line to comment it out

  10. Find this line and make sure it is not commented out:

    PubkeyAuthentication yes

  11. Save and close

At this point, you can SSH in with the key file. Sweet! For my lab, in order to further secure it, I want to make it such that you HAVE to use the keyfile in order to connect.

  1. Reopen sshd_config with notepad
  2. Find this line, uncomment it and set it to no:

    PasswordAuthentication no

  3. Save and close
  4. PS> Restart-Service sshd
    • This may or may not be necessary

Now, you HAVE to use the private key (which exists only on your machine) to SSH to the server. Sweet!

The next step depends on your environment and which port you want to use. For me, I grabbed a random high value port on my router and port fowarded it to 22 on my server. For demo purposes, I used 47474 (which I later changed). Now, on my machine I can either SSH to the Windows Server (which throws a CMD shell by default) or I can fire up tunneling to RDP into any machine in my lab.

Just doing a straight SSH:

Now, to do RDP instead we just need to fire up the tunnel with a slightly different command

Note the -f and the -N along with the 12345:HV01:3389. MyPublicIp is the public IP I currently have for my lab ommitted for security:

-f = for into the background
-N = do not execute a remote command
12345 = the local port to which we are going to RDP
HV01 = the server name to which we want to RDP in the lab
3389 = the port to which we are going to RDP

When you run this command, a listener (:12345) is established on the local machine which is routed through the secure tunnel (:47474 -> :22) to :3389 on HV01

RDPing to my localhost on port 12345 – MSTSC prompts me for creds. I provide valid creds for the HV01 machine in my lab and:

Boom. We now have a secure tunnel that can only be accessed with the private key on my local machine which then allows me to RDP into my lab.

Leave a Reply