Starting with Windows 10 build 1709, Windows integrates a port of OpenSSH, client and server.
This note describes how to install and configure the OpenSSH server sshd
and run PowerShell scripts on a remote Windows server, from a Unix system, using SSH and public key authentication (no password).
Note: The way OpenSSH has been integrated in Windows 10 has changed a lot between versions 1709 and 21H2 of Windows 10. The Gist was updated several times to reflect the changes. This version applies to Windows 10 21H2.
First, open a PowerShell window with administrator privileges.
Check if OpenSSH server is installed:
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
Name : OpenSSH.Client~~~~0.0.1.0
State : Installed
Name : OpenSSH.Server~~~~0.0.1.0
State : NotPresent
Here, the client is installed but not the server. This is the default configuration.
Install the server package (use the displayed name if a more recent version is available):
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start the sshd
service:
Start-Service sshd
Enable sshd
automatic startup:
Set-Service -Name sshd -StartupType 'Automatic'
Check if the firewall rule for SSH is configured:
Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP"
In case of error, add the firewall rule:
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
To allow public key authentication, each user has to create the same type of authorized_keys
file as on any Unix system. On Windows, the name of the file is C:\Users\_user_name_\.ssh\authorized_keys
.
Create the .ssh
subdirectory and the authorized_keys
file with the list of allowed public keys.
On Unix systems, the authorized_keys
file must have the protection mask 0600 or -rw-------
. Similarly, the protection of the authorized_keys
file must be manually adjusted on Windows.
Open a PowerShell window using your own user account and run the following commands:
$acl = Get-Acl ${env:HOMEDRIVE}${env:HOMEPATH}\.ssh\authorized_keys
$acl.SetAccessRuleProtection($true, $false)
$rule = New-Object system.security.accesscontrol.filesystemaccessrule($env:USERNAME,"FullControl","Allow")
$acl.SetAccessRule($rule)
$acl | Set-Acl
Important: It the user is an administrator user, you need to append the public key in C:\ProgramData\ssh\administrators_authorized_keys
instead. Then, fix the protextion of the file from a PowerShell window with administrator privileges:
$acl = Get-Acl ${env:ProgramData}\ssh\administrators_authorized_keys
$acl.SetAccessRuleProtection($true, $false)
$rule1 = New-Object system.security.accesscontrol.filesystemaccessrule("Administrators","FullControl","Allow")
$rule2 = New-Object system.security.accesscontrol.filesystemaccessrule("SYSTEM","FullControl","Allow")
$acl.SetAccessRule($rule1)
$acl.SetAccessRule($rule2)
$acl | Set-Acl
Now you can log in from your remote Unix systems using public key authentication and no password. The default shell is cmd.exe
. To set Powershell as default shell, run the following command from a PowerShell window with administrator privileges:
New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force