Skip to content

Instantly share code, notes, and snippets.

@asheroto
Last active March 29, 2024 17:00
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save asheroto/80d5f85e90d92e7f8e40e9d1a3dea7ad to your computer and use it in GitHub Desktop.
Save asheroto/80d5f85e90d92e7f8e40e9d1a3dea7ad to your computer and use it in GitHub Desktop.
OpenSSH on Windows - working sshd_config for public key authentication

Public key authentication troubleshooting

Make sure you don't have ANY instances of sshd or ssh-agent running (important):

  • Run PowerShell as Administrator:
Stop-Service sshd
Stop-Service ssh-agent
taskkill /f /im sshd.exe
taskkill /f /im ssh-agent.exe
  • Make sure you have these in your config and do not have duplicate lines
PubkeyAuthentication yes
PasswordAuthentication no
  • Starting with Win 10 build 1809 and later, apparently you need to comment out these lines (matching administrators and its authorized_keys file):
       Match Group administrators
              AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
  • administrators_authorized_keys needs to include the lines from your user's id_rsa.pub file (your public key file that contains the ssh-rsa command)

  • id_rsa and id_rsa.pub and administrators_authorized_keys need to be in UTF-8 (without BOM) character encoding. You can use this script to ensure all of them are.

function UTF8NoBom($filter) {
    $Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
    foreach($i in ls -Recurse -Filter $filter) {
        $MyFile = Get-Content $i.fullname 
        [System.IO.File]::WriteAllLines($i.fullname, $MyFile, $Utf8NoBomEncoding)
    }
}

Set-Location "~/.ssh"
UTF8NoBom("id_rsa*")

Set-Location "$ENV:ProgramData\ssh"
UTF8NoBom("*authorized_keys*")
  • administrators_authorized_keys needs to have ONLY TWO permissions: SYSTEM and Administrators (important). You can run this script in PowerShell as Administrator to fix the permissions on the file.
$ak = "$ENV:ProgramData\ssh\administrators_authorized_keys"
$acl = Get-Acl $ak
$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
  • Ensure those are the only two users:
Get-Acl "$ENV:ProgramData\ssh\administrators_authorized_keys" | Format-List

If you have more than SYSTEM and Administrators, go to the file and remove everything else.

  • id_rsa and id_rsa.pub need to have ONLY TWO permissions: SYSTEM and your username (important). You can run this script in PowerShell. Open PowerShell as the user but running as Administrator to fix the permissions on the file.
$userRule = New-Object system.security.accesscontrol.filesystemaccessrule("$(whoami)","FullControl","Allow")
$systemRule = New-Object system.security.accesscontrol.filesystemaccessrule("SYSTEM","FullControl","Allow")

$idrsa = "~/.ssh/id_rsa"
$acl1 = Get-Acl $idrsa
$acl1.SetAccessRuleProtection($true, $false)
$acl1.SetAccessRule($userRule)
$acl1.SetAccessRule($systemRule)
$acl1 | Set-Acl

$idrsapub = "~/.ssh/id_rsa.pub"
$acl2 = Get-Acl $idrsapub
$acl2.SetAccessRuleProtection($true, $false)
$acl2.SetAccessRule($userRule)
$acl2.SetAccessRule($systemRule)
$acl2 | Set-Acl

  • Ensure those are the only two users:
Get-Acl "~/.ssh/id_rsa" | Format-List

Get-Acl "~/.ssh/id_rsa.pub" | Format-List

If you have more than SYSTEM and your username, go to the file and remove everything else.

  • Remaining in PowerShell as the user but running as Administrator, start the authentication agent:
Start-Service ssh-agent
  • Add the user account to the authentication agent:
ssh-add
  • Start the sshd service:
Start-Service sshd

It should be working now. 👍

If you are still having issues, run:

FixHostFilePermissions.ps1
FixUserFilePermissions.ps1

Both of these scripts should be located in the OpenSSH installation folder, although you should be able to execute them from anywhere if it's installed correctly. For me, that path is C:\Program Files\OpenSSH-Win64.

After completing the above steps using this sshd_config file, I am able to log in using public key authentication.

# Article: http://bit.ly/openssh-publickeyauthentication-windows
#
# This is the sshd server system-wide configuration file. See
# sshd_config(5) for more information.
# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented. Uncommented options override the
# default value.
Port 22
AddressFamily any
ListenAddress 0.0.0.0
#ListenAddress ::
#HostKey __PROGRAMDATA__/ssh/ssh_host_rsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_dsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ecdsa_key
#HostKey __PROGRAMDATA__/ssh/ssh_host_ed25519_key
# Ciphers and keying
#RekeyLimit default none
# Logging
#SyslogFacility AUTH
#LogLevel INFO
# Authentication:
#LoginGraceTime 2m
#PermitRootLogin yes
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10
PubkeyAuthentication yes
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys
#AuthorizedPrincipalsFile none
# For this to work you will also need host keys in %programData%/ssh/ssh_known_hosts
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes
# To disable tunneled clear text passwords, change to no here!
PasswordAuthentication no
#PermitEmptyPasswords no
# GSSAPI options
#GSSAPIAuthentication no
#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#PermitUserEnvironment no
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/sshd.pid
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory unspecified
#VersionAddendum none
# no default banner path
#Banner none
# override default of no subsystems
Subsystem sftp sftp-server.exe
# Example of overriding settings on a per-user basis
#Match User anoncvs
# AllowTcpForwarding no
# PermitTTY no
# ForceCommand cvs server
Match Group administrators
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment