Securing my Microsoft Remote Desktop connection over the Internet?

Solution 1:

It is really good decision since Microsoft still can't figure out how to prevent brute-forcing attack to RDP sessions. There is Account Lockout policy(that has some disadvantage, read further) that described very well in nice @harrymc answer, so those who having at lest Windows Pro version can use such workflow.

If you are an owner of home version then you can activate Account Lockout policy by editing directly registry in followed Key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\RemoteAccess\Parameters\AccountLockout
  • Double-click the MaxDenials value and enter the number of failed attempts before you want the account to be locked out.
  • Double-click the ResetTime (mins) value and change default value 0xB40 which is hexadecimal for 2,880 minutes (two days) to something reasonable, say 15-20 minutes.

The problem with Windows Account Lockout Policy is that your computer would be locked if someone else trying to brute force password. Policy isn't depended on IP of originator, just counting login attempts and trigger account lockout event, so effectively disabling access to both - the owner and attacker as well.

Another IMHO much more stronger protection is to use SSH public key authentication that is much more stronger than password based authentication.

You almost answered your question by mentioning SSH. Set cygwin on the windows PC, run SSH service and enable in sshd_config tunneling and set public key authentication while disabling plain password authentication(test ssh connection while you are on your home LAN if it successfully work).
On your router forward some non default SSH port (22) for example 20202 as you did it for RDP to this windows machine to port 22 on Windows PC (Don't forget also to DISABLE forwarding to RDP). When you going to connect to RDP, start first SSH session to remote Windows PC using script below:
(script for Unix based OS, such as Linux, BSD, MacOS as well for those who using cygwin. Those who using Windows as a client see "Connecting" section below)

#!/bin/sh

# Script that can be use on remote client that running Unix based OS

RemotePC_IP=1.2.3.4  # Public IP address of your home
WindowsUserName=Gates  # Windows user name on remote computer
RDPlocalListenPort=12345  # Local port that that will be forwarded to RDP
Path2prvKey='/path/to/private/key' # Path to private key
RemoteSSHport=20202 # The port that opened on your home router
                    # and forwarded to SSH service port on Windows PC

ssh -N -L ${RDPlocalListenPort}:localhost:3389 \
    -i ${Path2prvKey} -p ${RemoteSSHport} ${WindowsUserName}@${RemotePC_IP}                   

# If you also want to use bunch of useful Unix utilites (that doesn't
# exist natively on Windows) besides of port forwarding, you can remove
# `-N` option from this script and use cygwin's terminal to run Windows's
# and Unix's console base programs remotely without starting RDP session. 

it will forward your local port 12345 to RDP(3389) port on remote windows machine over securely encrypted SSH session and then finally connect to RDP using connection string localhost:12345

Advantage of such method securing RDP session is that channel encrypted using asymmetric cryptography that is much stronger than any complicated password. Besides of strong encryption one can use rich Unix's utilities to manage over secure channel remote Windows PC.

One more neat thing that you can do by utilizing SSH, - if you don't have static IP address at home OR you don't want to fully trust companies like LogMeIn or TeamViewer OR your PC located behind strict firewall where you can't setup port forwarding OR you don't have control over primary gateway/firewall then one can setup SSH in reverse mode where Windows PC automatically connecting to a intermediate server with static IP you control. This way you don't need to connect directly to Windows PC but connecting instead to intermediate server that can serve many computers. Such setup is very convenient when one need to support mobile customers which IP is unknown and when IT support should support company's mobile PC without using 3rd party services due to high company's secret that reduce risk of data be compromised.

While installation process below looks kind of long to read, in practice such installation takes 10-15 minutes when you get concept how it's works.

Details:

Installing Cygwin

Update: Beginning from Windows 10 v.1803 Microsoft shipped with already preinstalled OpenSSH server and client, so steps below are for those who don't have Windows 10 or not upgraded yet to Windows 10 v.1803 and above.

To install SSH on Windows, follow documentation from Oracle that describes in details and with screenshots how to setup SSH service.
You only need to follow sections 5.3, 5.4, 5.5 here

I'll post bellow most important steps, that need to be done to install SSH service.

  • Download executable setup file from cygwin primary site. There're two versions of setup files: setup-x86.exe and setup-x86_64.exe. Choose appropriate file for your machine. If you want to use other Unix base utilities besides of SSH, then my advise is to use x86 version even if your machine is 64bit because not all utilities ported to 64bits version.
  • Setup process is pretty simple and intuitive:
    On the Choose Installation Type screen, select Install from Internet, then click Next.
  • On the Choose Installation Directory screen, enter C:\cygwin as the Root Directory, then click Next. Set Install for radio button to All users
  • On the Select Local Package Directory screen, select a directory on your local machine where you want to store the downloaded installation files, then click Next. (You can keep default c:\packages )
  • On the Select Connection Type screen, select appropriate settings to connect to the internet, then click Next. If you PC have direct access to internet without any proxies, then choose Direct connections
  • On the Choose Download Site(s) screen, select any site from the available list, then click Next. Choose there closest to you site. On the select packages screen, ensure that you select at least the following packages, then click Next:
    • openssh, openssl, unzip, xz, zip, mc
  • After selecting the packages and clicking Next, the Resolving Dependencies screen is displayed. Click Next to proceed.
  • If you think you would use Unix based utilities then on the Installation Status and Create Icons screen, do not make any changes. Click Finish to complete the installation process, otherwise unset checkboxes.

Configuring SSH

  • After you install Cygwin, navigate to the C:\cygwin directory, open the Cygwin.bat file in edit mode using any editor, and add the following line before invoking the bash shell.
    set CYGWIN=binmode ntsec as in example below:

    @echo off C: chdir C:\cygwin\bin set CYGWIN=binmode ntsec bash --login -i

  • To verify if Cygwin (cygrunsrv) is installed properly, run
    C:\cygwin\Cygwin.bat, and execute the following command:
    cygrunsrv -h
    If Cygwin is installed properly, then all the Cygwin help options are displayed on the screen. However, if this command returns an error message, then you may have to reinstall Cygwin.

  • To configure the SSHD service, run C:\cygwin\Cygwin.bat, and execute the following command:
    ssh-host-config
    After running the command, you are prompted the following questions:
    *** Query: Should privilege separation be used? <yes/no>: yes *** Query: New local account 'sshd'? <yes/no>: yes *** Query: Do you want to install sshd as a service? *** Query: <Say "no" if it is already installed as a service> <yes/no>: yes *** Query: Enter the value of CYGWIN for the deamon: [] binmode ntsec *** Query: Do you want to use a different name? (yes/no) yes/no
    At this point, if you want to use the same name, that is cyg_server, enter no. You are then prompted the following questions:
    *** Query: Create new privileged user account 'cyg_server'? (yes/no) yes *** Query: Please enter the password: *** Query: Renter:
    However, if you want to use a different name, enter yes. You are then prompted the following questions:
    *** Query: Enter the new user name: cyg_server1 *** Query: Reenter: cyg_server1 *** Query: Create new privileged user account 'cyg_server1'? (yes/no) yes *** Query: Please enter the password: *** Query: Reenter:
    If the configuration is successful, you will see the following message:
    Host configuration finished. Have fun!
  • Backup the c:\cygwin\etc\passwd file (if it exist) and run following command:
    /bin/mkpasswd -l >/etc/passwd
    then edit passwd by running mcedit /etc/passwd
    Remove all users that won't connect over SSH, especially:
    SYSTEM, LOCAL SERVICE, NETWORK SERVICE, NT SERVICE+TrustedInstaller, Guest

Fine tuning of SSHD service

  • Edit sshd_config file (SSH service) by running:
    mcedit /etc/sshd_config
  • Add to the end of file following content:

########################### Customization ##########################
Ciphers [email protected],[email protected],[email protected],aes256-ctr,aes192-ctr,aes128-ctr
KexAlgorithms [email protected],diffie-hellman-group-exchange-sha256
MACs [email protected],[email protected],[email protected],[email protected],hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,[email protected]
#
UseDNS no
UsePAM yes
LoginGraceTime 20
#
PermitRootLogin prohibit-password
PubkeyAuthentication yes
ChallengeResponseAuthentication no
PasswordAuthentication no
HostbasedAuthentication no
#
PermitTunnel yes
TCPKeepAlive no
ClientAliveInterval 30
ClientAliveCountMax 10
GatewayPorts no
AllowTcpForwarding yes

  • Now one need to generate keys for public key authentication
    In cygwin terminal run following commands:
    mkdir -p ~/.ssh && chmod 700 ~/.ssh
    cd ~/.ssh
    echo > ~/.ssh/authorized_keys

    • Generate keys Unix way: (Replace "UserName" with Windows account that will be connected over SSH)
      In cygwin terminal run following commands:
      cd ~/.ssh
      ssh-keygen -t ed25519 -o -a 127 -C "UserName" -f "UserName.ed25519.key"
      cp -f UserName.ed25519.key.pub ~/.ssh/authorized_keys
    • Windows way:
      Download PuTTY and run puttygen.exe. Select key to generate as ED25519 and press Generate. Save private key to a file that later can be used as a key for authorization. Select public key on the top from field marked as (Public key for passing into OpenSSH), make right click on selection and choose copy then paste copied content to
      ~/.ssh/authorized_keys
  • Finally start SSH service by running following command:
    cygrunsrv -S sshd

Connecting from remote client to RDP over SSH connection

  • To connect on Unix based operation systems such as Linux, FreeBSD, MacOS one can use shell script posted on a top of answer. Edit variables on the top of script, use private key generated in previous steps.
  • To connect from computers running Windows one can use PuTTY client program. Before connecting to remote computer over RDP(remote desktop connection), run first PuTTY and set port forwarding and private key:
    • On the left tree panel go to
      Connection->SSH->Auth and by clicking Browse button add path to private key that was generated in previous steps.
    • On the left tree panel go to
      Connection->SSH->Tunnels and enter in field Source port 12345 and put localhost:3389 in field destination then set radio buttons to Local and Auto and press Add button.
    • On the left tree panel go to Session and enter in the Host Name field IP address of remote Windows PC running SSH as well set remote listening port of home router in the field Port.
    • Add descriptive name of your session in the field Saved Sessions and save configuration.
  • When connection over SSH established, run Remote Desktop Connection program and use localhost:12345 to connect to remote computer over RDP via SSH tunnel.

Solution 2:

Microsoft’s Remote Desktop uses encryption and communications are therefore reasonably protected. The weak point is that of brute-force attack against your user-name and password.

To secure RDP you may do the following :

  1. Change the default port that Remote Desktop listens on
    This one you already did.

  2. Strong credentials
    Use a non-default user-name and a long and complicated password

  3. Restricted user accounts
    Limit severely the users that can use RDP by running secpol.msc > Local Policies > User Rights Assignment, double-click on "Allow log on through Remote Desktop Services" and remove all displayed groups, then add your one user.

  4. High security level
    Run gpedit.msc > Local Computer Policy > Administrative Templates > Windows Components > Remote Desktop Services > Remote Desktop Session Host > Security.

    • "Set client connection encryption level" -> Enabled and High Level, for your sessions to be secured with 128-bit encryption
    • "Require use of specific security layer for remote (RDP) connections" -> SSL
    • "Require user authentication for remote connections by using Network Level Authentication" -> Enabled
  5. Set an account lockout policy
    To lock an account for a period of time after a number of incorrect guesses, go to Administrative Tools > Local Security Policy > Account Policies > Account Lockout Policies, and set values for all three options (3 invalid attempts with 3 minute lockout durations is reasonable).

  6. keep track of logging into your PC
    Periodically go to Event Viewer > Applications and Services Logs > Microsoft > Windows > TerminalServices-LocalSessionManger > Operational, to see login information.