Setting up OpenSSH for Windows using public key authentication

I am having issues setting up OpenSSH for Windows, using public key authentication.

I have this working on my local desktop and can ssh with a key from Unix machines or other OpenSSH for Windows machines.

I have replicated the build onto a server, I can get password authentication working fine, but when I use the keys I get the following issue:

debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug3: start over, passed a different list publickey,password,keyboard-interactive
debug3: preferred publickey,keyboard-interactive,password
debug3: authmethod_lookup publickey
debug3: remaining preferred: keyboard-interactive,password
debug3: authmethod_is_enabled publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /cygdrive/c/sshusers/jsadmint2232/.ssh/id_rsa
debug3: send_pubkey_test
debug2: we sent a publickey packet, wait for reply
Connection closed by 127.0.0.1

So for the purposes of testing, I have been just trying to SSH to localhost, but even when tried remotely I get the same issue.

Even more strange, is that when I have both password and public key enabled in sshd_config, it will only attempt to use keys and then bomb out with the above message and won't even try to use password.

Here are the steps I have taken:

  1. Install OpenSSH for Windows
  2. mkgroup -l >>..\etc\group (added local groups)
  3. mkgroup -d >>..\etc\group (added domain groups)
  4. mkpasswd -L -u openssh >>..\passwd (added my local user)
  5. mkpasswd -D -u jsadmint2232 >>..\passwd (added my domain user)
  6. Edited the homedir in file passwd to point to c:\sshusers%USER% - where %USER% is the user name
  7. Enabled password authentication, disabled key authentication
  8. Created SSH keys for both jsadmint2232 / OpenSSH and ensured that the files were created in home directories
  9. Added authorized_keys files into .ssh directories for each user and added keys for incoming connecting users
  10. net stop opensshd / net start opensshd
  11. Test if password authentication works both locally and remotely
  12. Updated sshd_config, to enabled key auth - restart opensshd
  13. Test connection and get above error. Also, it doesn't even try password authentication.
  14. Updated sshd_config, to disable password authentication completely - restart opensshd
  15. Test connection and still get above error

It appears the server is killing the connection for some reason.


Solution 1:

Following are setup steps for OpenSSH shipped with Windows 10 v.1803 (April 2018 update. See comments to this post, it might not work with 1809).

Server setup (elevated powershell):

  1. Install OpenSSH server: Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0.

  2. Start agent and sshd services: Start-Service ssh-agent; Start-Service sshd (this will generate host keys and default configuration automatically in $env:ProgramData\ssh).

  3. [Optional] Install OpenSSHUtils powershell module: Install-Module -Force OpenSSHUtils

Client setup (non-elevated powershell):

  1. Generate user key: cd $env:USERPROFILE\.ssh; ssh-keygen.exe, follow prompts, agree to the default suggested file location. This will create 2 files: id_rsa and id_rsa.pub;

  2. [Optional] add key to authentication agent, so you don't have to enter password each time you use it: ssh-add .\id_rsa (or whatever file was generated);

Server setup continued (non-elevated powershell):

  1. Log in as a user, for which public key auth to be used
  2. cd $env:USERPROFILE; mkdir .ssh; cd .ssh; New-Item authorized_keys;
  3. Paste the contents of the id_rsa.pub file from the client to the .ssh\authorized_keys file from the previous step.
  4. Setup permissions properly (important!!!):
    1. Run start . to open explorer with the current folder ($env:USERPROFILE\.ssh);
    2. Right click authorized_keys, go to Properties -> Security -> Advanced
    3. Click "Disable inheritance";
    4. Choose "Convert inherited permissions into explicit permissions on this object" when prompted;
    5. (really, really important) Remove all permissions on file except for the SYSTEM and yourself. There must be exactly two permission entries on the file. Some guides suggest running the Repair-AuthorizedKeyPermission $env:USERPROFILE\.ssh\authorized_keys - this will try to add the sshd user to the permission list and it will break the authentication, so, don't do that, or at least do not agree on adding the sshd user). Both SYSTEM and yourself should have full control over the file.
  5. If your Windows build is 1809 or later, it is required to comment out the following lines in C:\ProgramData\ssh\sshd_config file. Then restart the sshd service.
    # Match Group administrators                                                    
    #       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys  
    

Client:

  1. Run ssh <serverusername>@<serverhostname>. It should work at this point.

Tried that with Windows 10 as server and both itself and a Debian Linux as a client.

Solution 2:

Use this sequence of commands in PowerShell to correct permission of administrators_authorized_keys

$acl = Get-Acl C:\ProgramData\ssh\administrators_authorized_keys
$acl.SetAccessRuleProtection($true, $false)
$administratorsRule = New-Object system.security.accesscontrol.filesystemaccessrule("Administrators","FullControl","Allow")
$systemRule = New-Object system.security.accesscontrol.filesystemaccessrule("SYSTEM","FullControl","Allow")
$acl.SetAccessRule($administratorsRule)
$acl.SetAccessRule($systemRule)
$acl | Set-Acl

Only SYSTEM and Administrators group must be have permission in file without inherited.

Permission set of administrators_authorized_keys

Solution 3:

One more tip, if you are stuck, is to run sshd in debug mode. I did this:

  1. Stop the sshd service
  2. Open a PowerShell console with administrator privileges
  3. Type 'sshd -d'
  4. Type login from my client machine

It turns out the key need to be in e.g. C:\ProgramData\ssh\administrators_authorized_keys instead of C:\Users\yourUsser.ssh\authorized_keys.