Set up your SSH server in Windows 10 native way
Tags: openssh, sftp, rdp, windowsserver
Published: 2020-02-02 07:50:53

---
title: Set up your SSH server in Windows 10 native way
published: true
description: This article shows how you can set up a built-in SSH server provided with Windows 10 and Windows Server.
cover_image: https://miro.medium.com/max/2000/0*YQmX3btiV3GSIiaP
tags: OpenSSH, SFTP, RDP, Windows Server
---

[Continuing from the last post](https://dev.to/rkttu/set-up-ssh-key-and-git-integration-in-windows-10-native-way-o4i), we'll look at how to set up a built-in SSH server starting with Windows 10 and Windows Server 1709. This method allows Windows Server to connect remotely using SSH, just like a traditional Linux server. We will also look at how you can use Remote Desktop securely without modifying your firewall settings using SSH port tunneling.

# Installing and configuring OpenSSH Server

You can install OpenSSH Server the same way you installed the SSH client in the previous article.

```powershell
$OpenSSHServer = Get-WindowsCapability -Online | ? Name -like ‘OpenSSH.Server*’
Add-WindowsCapability -Online -Name $OpenSSHServer.Name
```

After installing the OpenSSH server program, start and stop the NT service once to create the necessary initial configuration files.

```powershell
$SSHDaemonSvc = Get-Service -Name ‘sshd’
Start-Service -Name $SSHDaemonSvc.Name
Stop-Service -Name $SSHDaemonSvc.Name
```

# Apply asymmetric key authentication

It is highly recommended that you use the public key authentication method and disable the password authentication method to prevent attacks through password assignment. To enable this authentication feature, start PowerShell as an administrator and open the file in the path below with notepad. (Or you can use another text editor of your choice.)

```powershell
notepad.exe $env:PROGRAMDATA\ssh\sshd_config
```

For the following items, uncomment the items and apply the value as follows:

- `PubkeyAuthentication yes`
- `PasswordAuthentication no`
- `PermitEmptyPasswords no`

Then choose your preferred method of managing SSH public keys. Starting with Windows Server 2019 (or 1809), there are two ways to describe SSH public keys. One of which is the traditional way of creating an authorized_keys file in the user's home directory.

## Using `$HOME\.ssh\authorized_keys`

To use this method, comment out the following block of code at the bottom of the configuration file:

```
Match Group administrators
  AuthorizedKeysFile
  __PROGRAMDATA__/ssh/administrators_authorized_keys
```

Then go to the user home directory you want to log in to and create a `.ssh` directory.

```powershell
mkdir "$HOME\.ssh"
```

Create an `authorized_keys` file (without the extension) inside the newly created directory and open it with your favorite text editor.

```powershell
$authorizedKeyFilePath = “$HOME\.ssh\authorized_keys”
New-Item $authorizedKeyFilePath
notepad.exe $authorizedKeyFilePath
```

Add the SSH public key value you are using here.

When you save the file, you must change the file permission settings as described in the section **Setting File Permissions with Authentication Key Information**. If this setting is missing, the SSH connection will fail.

## Using `administrators_authorized_keys`

This is the default used by OpenSSH included in Windows Server 2019 (1809). Instead of registering a new SSH key for each user, you can manage your files in one place.

If you use this method, all public keys must be stored in the `$env: PROGRAMDATA\ssh\administrators_authorized_keys` file, except for non-administrative users (that is, users who do not belong to the Administrators group). If you try, this setting will be used instead of the setting in your home directory, so if there is no key here, the connection will fail.

The `administrators_authorized_keys` file does not exist by default and must be created.

```powershell
$authorizedKeyFilePath = “$env:ProgramData\ssh\administrators_authorized_keys”
New-Item $authorizedKeyFilePath
notepad.exe $authorizedKeyFilePath
```

Add the SSH public key value you are using here.

When you save the file, you must change the file permission settings as described in the section **Setting File Permissions with Authentication Key Information**. If this setting is missing, the SSH connection will fail.

# Setting File Permissions with Authentication Key Information

A common and very tough problem that you will face about using the OpenSSH server for Windows is this. SSH key file permission should have correct and limited file permission. Windows version of SSH also follows this rule, but especially in Windows, configuring file permission can be unintuitive.

Depending on the method you chose in the previous step, you must verify the path of the `authorized_keys` file or `administrators_authorized_keys` file and change the permissions so that only the system account can access it using the `icacls.exe` utility and the `Get-Acl` and `Set-Acl` commands.

```powershell
$authorizedKeyFilePath = "..."
icacls.exe $authorizedKeyFilePath /remove “NT AUTHORITY\Authenticated Users”
icacls.exe $authorizedKeyFilePath /inheritance:r
Get-Acl “$env:ProgramData\ssh\ssh_host_dsa_key” | Set-Acl $authorizedKeyFilePath
```

# Changing the SSH Default Shell

Basically, for compatibility reasons, the Windows operating system has provided a shell-based interpreter that recognizes DOS commands for a long time. But now, with more and more features than working with DOS commands, PowerShell is becoming a good alternative.

If necessary, you can specify that PowerShell as the default shell for SSH instead of the DOS interpreter. However, the settings here are specific to SSH sessions, not for the Remote Desktop or console session.

```powershell
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "$env:WINDIR\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force
```

# Staring SSH Server

You are now ready to start your SSH server. The SSH server is set to manual run by default, so you can change the startup mode to automatic. Then starts the service.

```powershell
$SSHDaemonSvc = Get-Service -Name ‘sshd’
Set-Service -Name $SSHDaemonSvc.Name -StartupType Automatic
Start-Service -Name $SSHDaemonSvc.Name
```

![SSH to Windows Server](https://miro.medium.com/max/4388/1*gJry9InM3arljQZjgdKP9A.png)

Congratulations! From now, you can connect to Windows with SSH-key authentication.

# How to Secure Remote Desktops

Unlike Linux, Windows still runs much of the system on a graphical interface rather than on the command line. So if you try to do something with a terminal like this, you may not have much to do as you might expect.

Remote Desktop, however, is a well-known food for many hackers and script kiddies as is well known. You may encounter the dilemma of choosing between convenience and security.

Fortunately, SSH provides the concept of tunneling, supporting the ability to relay other network connections securely. Remote desktop connections can also be protected in this way so that you can use them with confidence.

Start by blocking the TCP 3389 and UDP 3389 ports. You can do this because you will use Remote Desktop only with SSH tunneling.

```powershell
Set-NetFirewallRule -DisplayName “Remote Desktop - User Mode (UDP-In)” -Action Block
Set-NetFirewallRule -DisplayName “Remote Desktop - User Mode (TCP-In)” -Action Block
```

Next, you must change the registry flag value so that the remote desktop server can accept the connection.

```powershell
Set-ItemProperty -Path ‘HKLM:\System\CurrentControlSet\Control\Terminal Server’ -Name “fDenyTSConnections” -Value 0
```

And the part that I'm going to explain right now is really cool. As you saw earlier, you will not be asked for your password when you connect to OpenSSH, so you can set up a randomly generated strong password each time you use it. It is very useful to have a simple script in the system directory that can do this.

Choose the type of script you want to create a file called `ChangePassword.ps1`. We will keep the file in the system directory for your convenience.

```powershell
$change_pwd_script_path = “$env:WINDIR\ChangePassword.ps1”
Clear-Content $change_pwd_script_path -ErrorAction SilentlyContinue
notepad.exe $change_pwd_script_path
```

## Set your desired password

Create the contents of the `ChangePassword.ps1` file as follows:

```powershell
$Password = Read-Host -Prompt "Provide your new account password" -AsSecureString
Set-LocalUser -Name "$env:UserName" -Password $Password
Clear-Variable "Password"
Write-Host "Detailed settings such as remote desktop settings, WinRM connection settings, and Windows Update can be controlled using the sconfig command."
```

This script allows you to enter your own password. However, unless you change the policy, you can only use passwords that pass the Windows Server enhanced default password rules. You must specify a password that must meet all of the following conditions.

- English capital letters (A through Z)
- Lowercase English letters (a through z)
- Arabic numerals (0 to 9)
- Special symbols (e.g.!, $, #,%)

## Generate a new password every time

Create the contents of the `ChangePassword.ps1` file as follows:

```powershell
Add-Type -AssemblyName System.Web
$Password = [System.Web.Security.Membership]::GeneratePassword(30,10)
Set-LocalUser -Name "$env:UserName" -Password ($Password | ConvertTo-SecureString -AsPlainText -Force)
Write-Host "Your New Password is:`r`n`r`n$Password"
Write-Host "Detailed settings such as remote desktop settings, WinRM connection settings, and Windows Update can be controlled using the sconfig command."
Clear-Variable "Password"
```

This way, you can set a strong password every time. If you forget your password, you can rest assured that you can still use public key authentication as a secondary means of authentication.

## Try logging in to Remote Desktop with Tunneling

Now enter the following command to run the above script. After that, just set the password as guided by the script and verify that the remote desktop connection is working.

```powershell
ChangePassword
```

To log in to the remote desktop, run SSH as follows:

```bash
ssh -L 3389:localhost:3389 <user_id>@<host_address>
```

The first 3389 is the port number on the server-side, and the second address is the port number you want to use locally. If you have changed the remote desktop's port number from the registry to another number on the server, you can enter the changed port number instead of 3389.

![Access to remote desktop using SSH tunneling with Remote Desktop 10 on macOS](https://miro.medium.com/max/5912/1*O4WNnaXe9_LaeQ2Ed5s_6g.png)

If you try to connect to a remote desktop using only the `<host_address>` part as before, the firewall will block the connection as previously set up.  So no one can access the remote desktop directly unless the user has registered a public key that matches the SSH secret key with that server.

# Using secure file sending and receiving

Not surprisingly, it is possible to use SSH based SFTP. This feature can be used to securely handle large file transfers in place of the remote desktop's folder sharing feature.

![Access to Windows Server using FileZilla's SFTP feature](https://miro.medium.com/max/5080/1*D-5vXZxRln1qBEFrzX0ihQ.png)

Any client that supports the SFTP feature, such as FileZilla, is compatible and has an management advantage, as there is no need to apply complex firewall open policies like traditional FTP.

# Wrap-up

This walks you through all the new SSH features that have been added since Windows 10 1709. Both articles are available for Windows 10 and Windows Server 2019, so please take a moment to set them up for even more security.

# Credits

The following articles helped me as I wrote this article.

* https://ilovepowershell.com/2018/05/28/awesome-and-simple-way-to-generate-random-passwords-with-powershell/
* https://stackoverflow.com/questions/16212816/setting-up-openssh-for-windows-using-public-key-authentication