使用公钥身份验证为 Windows 设置 OpenSSH

Posted

技术标签:

【中文标题】使用公钥身份验证为 Windows 设置 OpenSSH【英文标题】:Setting up OpenSSH for Windows using public key authentication 【发布时间】:2013-04-19 05:36:09 【问题描述】:

我在 时遇到问题。

我在我的本地桌面上工作,并且可以使用来自 Unix 机器或其他适用于 Windows 机器的 OpenSSH 的密钥进行 ssh。

我已将构建复制到服务器上,我可以让密码验证正常工作,但是当我使用密钥时,我遇到了以下问题:

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

因此,出于测试目的,我一直在尝试通过 SSH 连接到 localhost,但即使远程尝试,我也会遇到同样的问题。

更奇怪的是,当我在sshd_config 中同时启用了密码和公钥时,它只会尝试使用密钥,然后用上述消息轰炸,甚至不会尝试使用密码。

以下是我采取的步骤:

    为 Windows 安装 OpenSSH mkgroup -l >>..\etc\group(添加本地组) mkgroup -d >>..\etc\group(添加域组) mkpasswd -L -u openssh >>..\passwd(添加了我的本地用户) mkpasswd -D -u jsadmint2232 >>..\passwd(添加了我的域用户) 编辑文件 passwd 中的 homedir 以指向 c:\sshusers%USER% - 其中 %USER% 是用户名 启用密码验证,禁用密钥验证 为 jsadmint2232 / OpenSSH 创建 SSH 密钥并确保在主目录中创建文件 为每个用户在 .ssh 目录中添加了 authorized_keys 文件,并为传入的连接用户添加了密钥 net stop opensshd / net start opensshd 测试密码验证是否在本地和远程都有效 更新了 sshd_config,以启用密钥身份验证 - 重新启动 opensshd 测试连接并得到上述错误。此外,它甚至不尝试密码验证。 更新了 sshd_config,完全禁用密码验证 - 重新启动 opensshd 测试连接仍然出现上述错误

似乎服务器出于某种原因正在终止连接。

【问题讨论】:

【参考方案1】:

以下是 Windows 10 v.1803 随附的 OpenSSH 的设置步骤(2018 年 4 月更新。请参阅这篇文章的 cmets,它可能不适用于 1809)。

服务器设置(提升的 powershell):

    安装 OpenSSH 服务器:Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0

    启动代理和sshd服务:Start-Service ssh-agent; Start-Service sshd(这将在$env:ProgramData\ssh中自动生成主机密钥和默认配置)。

    [可选] 安装 OpenSSHUtils powershell 模块:Install-Module -Force OpenSSHUtils

客户端设置(非提升的 powershell):

    生成用户密钥:cd $env:USERPROFILE\.ssh; ssh-keygen.exe,按照提示,同意默认建议的文件位置。这将创建 2 个文件:id_rsaid_rsa.pub

    [可选] 将密钥添加到身份验证代理,因此每次使用时不必输入密码:ssh-add .\id_rsa(或生成的任何文件);

服务器设置继续(非提升的 powershell):

    以用户身份登录,要使用的公钥身份验证 cd $env:USERPROFILE; mkdir .ssh; cd .ssh; New-Item authorized_keys; 将id_rsa.pub文件的内容从客户端粘贴到上一步的.ssh\authorized_keys文件中。 正确设置权限(重要!!!):
      运行start .以使用当前文件夹($env:USERPROFILE\.ssh)打开资源管理器; 右键authorized_keys,转到Properties -> Security -> Advanced 点击“禁用继承”; 出现提示时选择“将继承的权限转换为此对象的显式权限”; (非常非常重要)删除文件上的所有权限,SYSTEMyourself 除外。文件上必须有恰好两个权限条目。一些指南建议运行Repair-AuthorizedKeyPermission $env:USERPROFILE\.ssh\authorized_keys - 这将尝试将sshd 用户添加到权限列表中,它破坏身份验证,所以,不要这样做,或者至少不要这样做同意添加sshd 用户)。 SYSTEM 和您自己都应该完全控制该文件。
    如果您的 Windows 版本是 1809 或更高版本,则需要在 C:\ProgramData\ssh\sshd_config 文件中注释掉以下行。然后重启sshd服务。
    # Match Group administrators                                                    
    #       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys  
    

客户:

    运行ssh <serverusername>@<serverhostname>。此时它应该可以工作了。

尝试将 Windows 10 作为服务器,并将其本身和 Debian Linux 作为客户端。

【讨论】:

你是我的英雄@n0rd... 已经为设置权限而苦苦挣扎了几个小时,但似乎 Repair-AuthorizedKeyPermission 设置了 sshd 用户,这确实破坏了它! (我虽然它应该在那里供 OpenSSH SSH 服务器进程查看它)。非常感谢! 谢谢!我一直在处理这个问题,直到我读到你的答案! 我的问题的另一个跟进和解决方案:在 Windows 10 1809 中,C:\ProgramData\ssh\sshd_config 中有一个新的特殊配置条目,它定义了对于管理员用户,密钥是从 __PROGRAMDATA__/ssh/administrators_authorized_keys 读取的。同样,此文件需要特殊权限。只有系统用户和管理员组必须有权访问它。 这是一个巨大的帮助,但权限仍然是一个问题。这 3 个命令修复了它:icacls C:\ProgramData\ssh\administrators_authorized_keys /remove "NT AUTHORITY\Authenticated Users"icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:rget-acl C:\ProgramData\ssh\ssh_host_dsa_key | set-acl C:\ProgramData\ssh\administrators_authorized_keys source 谢谢!为了能够使用无密码密钥认证,在“user/.ssh”中使用authorized_keys文件,我需要注释掉# Match Group administrators # AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys 这行,并重新启动服务“OpenSSH SSH Server”。【参考方案2】:

在 PowerShell 中使用此命令序列来更正 administrators_authorized_keys 的权限

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

只有 SYSTEM 和 Administrators 组必须具有文件中的权限而不被继承。

【讨论】:

看起来多么令人惊讶,上述解决方案仅适用于语言设置为英语的系统。例如,在法语的 Windows 10 上,您必须将“Administrators”替换为“Administrateurs”,将“System”替换为“Système”。令人惊讶,对吧?【参考方案3】:

如果您遇到困难,还有一个提示是在调试模式下运行 sshd。我这样做了:

    停止sshd服务 使用管理员权限打开 PowerShell 控制台 键入“sshd -d” 从我的客户端计算机输入 login

事实证明,关键需要在例如C:\ProgramData\ssh\administrators_authorized_keys 而不是 C:\Users\yourUsers.ssh\authorized_keys

【讨论】:

对我来说非常有用的答案。它不仅有助于回答问题是什么,而且有助于下次如何解决类似的问题。【参考方案4】:

我已经解决了这个问题...

这与启动服务的帐户有关 - 它正在使用 Local System 帐户 - 这会阻止它访问公钥和授权密钥文件。

一旦我停止服务并以我试图连接的用户身份启动,它就可以工作了!

所以基本上,您需要从服务帐户开始,然后外部用户以该用户身份连接。

【讨论】:

您“停止服务并以我试图连接的用户身份启动”是什么意思?我不认为你的意思是我使用我的实际域用户帐户。那你建议我从一个服务帐户开始,但是哪个? 我建议先阅读下面@n0rd 的答案,然后再研究这个答案。【参考方案5】:

这只是我的 @n0rds great answer 的脚本版本。

将此脚本放在带有您的私钥/公钥/对的目录中并运行!

PowerShell.exe -ExecutionPolicy Bypass -File "C:\bypass\prompt\standard.ps1" 2>&1>$null

Add-WindowsCapability -Online -Name OpenSSH.Server
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH SSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 -Program "%WINDIR%\System32\OpenSSH\sshd.exe"

#Must Enable ssh-agent before starting
Set-Service -Name ssh-agent -StartupType Automatic
Set-Service -Name sshd -StartupType Automatic
Start-Service ssh-agent; Start-Service sshd

$sshdir="$env:USERPROFILE\.ssh"
mkdir $sshdir
copy .\id_rsa $sshdir\
cat  $sshdir\id_rsa
copy .\*.pub  $sshdir\authorized_keys
cat $sshdir\authorized_keys
ssh-add $sshdir\id_rsa

$sshd_config="C:\ProgramData\ssh\sshd_config" 
(Get-Content $sshd_config) -replace '#PubkeyAuthentication', 'PubkeyAuthentication' | Out-File -encoding ASCII $sshd_config
(Get-Content $sshd_config) -replace 'AuthorizedKeysFile __PROGRAMDATA__', '#AuthorizedKeysFile __PROGRAMDATA__' | Out-File -encoding ASCII $sshd_config
(Get-Content $sshd_config) -replace 'Match Group administrators', '#Match Group administrators' | Out-File -encoding ASCII $sshd_config
cat C:\ProgramData\ssh\sshd_config

Restart-Service ssh-agent; Restart-Service sshd

Write-Host "Use this to Login/test Now"
write-host ssh $env:UserName@localhost

【讨论】:

【参考方案6】:

如果您使用的是 mls-software.com 的 OpenSSH 版本,请注意。

如果您使用 SSHD_SERVER 帐户和权限分离进行安装,您将能够使用公钥身份验证(根据 http://www.mls-software.com/opensshd-pki.html)。但是,如果启用 UAC,您将无法成功安装。将无法正确创建用户,也不会创建服务。事后手动尝试获取这些项目非常困难。在安装前简单地禁用 UAC 将允许安装过程正确创建用户和服务。安装后,您可以重新启用 UAC。

当我手动创建 SSHD_SERVER 帐户时,使用密码验证时验证成功,但客户端以“/bin/bash: Operation not allowed”终止连接。服务器关闭了使用公钥的身份验证(Cambolie 发布的原始错误)。

【讨论】:

mls-software 的反馈指出,情况并非总是如此。在我的情况下禁用 UAC 解决了这个问题,但在所有情况下都可能没有必要。我会更多地调查我的情况,看看是否可以发布更多详细信息。 MLS OpenSSH 为什么重要?为什么它不能作为本地系统(或其他一些,甚至是域、帐户)运行?【参考方案7】:

我解决了这个问题:

    以 SSHD_SERVER + 权限分离模式安装。我还在配置中手动将权限分离设置为“是”。这对我来说很长时间没有用,用户没有被创建。然后它起作用了,我不知道为什么。我只去了控制面板中的用户帐户来检查 UAC 是否关闭。我还拥有 /var/empty,每个人都可以完全访问。 对于 C:\openssh\var\empty,我已将“属性获取/设置”权限设置为所有人和我自己,并将“完全”权限设置为 .\sshd_server。我也让它成为了所有者。

【讨论】:

【参考方案8】:

我已经在多台 Windows Pro 1809 和 2004 计算机上彻底测试了 n0rd's solution。我同意他的大部分步骤。

服务器设置(提升的 PowerShell):完全同意。

客户端设置(非提升的 PowerShell):完全同意。

服务器设置继续(非提升的 PowerShell):步骤 1、2、3:同意

服务器设置继续(非提升的 PowerShell):第 4 步:不要在第 4 步中执行任何操作。

服务器设置继续(非提升的 PowerShell):第 5 步:同意

服务器设置继续(非提升的 PowerShell):第 6 步:(添加)从 C:\ProgramData\ssh\sshd_config 取消注释(删除 #):#PasswordAuthentication yes

服务器设置继续(非提升的 PowerShell):第 7 步:(添加)在服务中,重新启动 OpenSSH SSH 服务器。

我没有发现任何文件存在任何关于安全性、权限或 Unicode 的问题。它们都是开箱即用的。

【讨论】:

我使用的是 Win 10.0.18363,但无法进行基于密钥的身份验证工作。我可以使用密码进行连接,但是当切换到基于密钥时,即使来自本地主机,我也会通过 ::1 端口 22 重置连接【参考方案9】:

我遇到了不同的情况。

首先,按照gWay所说的进行调试,用另一个终端窗口连接到服务器。

我得到read_keyfile_line: C:\\Users\\yieatn\\.ssh/authorized_keys line 1 exceeds size limit

将 authorized_keys 重新编码为 utf-8

原因是我用cat id_rsa >> authorized_keys创建了authorized_keys,而powershell中文使用UTF-16创建文件。

【讨论】:

【参考方案10】:

n0rd 的解决方案很划算,但对于同样属于管理员组的用户来说,还有一个复杂的问题。如果您正在为涉及以下情况的情况寻找解决方案:

您希望针对每个用户使用公钥(或者您不想使用administrators_authorized_keys 文件)。 而您不想想要使用 PasswordAuthentication。 有些用户也属于 admin 组。

我遇到的问题是,当我尝试 n0rd 的解决方案时,它在上述条件下对用户不起作用。经过一番修修补补,我找到了一个对我始终有效的解决方案。按照 n0rd 的解决方案,只需更改以下内容

ssh_config 中确保设置了以下设置:

AuthorizedKeysFile  .ssh/authorized_keys 
PasswordAuthentication no
PubkeyAuthentication yes

另外,请务必注释掉匹配组管理员设置:

#Match Group administrators
#       AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys

确保在服务器C:\Users\username\.ssh\authorized_keys 文件中包含客户端的公钥。

最后,为了帮助将用户与帐户进行匹配,我发现更具体地使用客户端上的用户数据很有帮助。我没有使用普通用户名,而是使用了用户名以及服务器上用户的域。就我而言,我客户的 C:\Users\UserName\.ssh\config 文件如下所示:

Host my_short_name
  HostName my.serveraddress.net
  User serversname\username
  IdentityFile .ssh\id_rsa

在这种情况下,我的 Windows 10 服务器将被称为服务器名称(在设备名称下)。通过以这种方式指定用户,我可以避免密码验证。

作为额外的奖励,这与 PowerShell 7 的默认 shell 配合得非常好。甚至我的默认 PowerShell 配置文件也可以通过 ssh 运行,并且我完全支持 posh-git 和 oh-my-posh。但是,我发现建议将 PowerShell 设置为默认 shell 环境的默认方法(通过编辑 ssh_conf 以包含 'Subsystem powershell c:/progra~1/powershell/7/pwsh.exe -sshs -NoLogo')确实为我工作。相反,在服务器上使用提升的 PowerShell 窗口中的命令:

New-ItemProperty -Path "HKLM:\SOFTWARE\OpenSSH" -Name DefaultShell -Value "c:/progra~1/powershell/7/pwsh.exe" -PropertyType String -Force

这只是创建一个注册表项。如果需要,您可以随时弹出注册表以稍后将其删除。

【讨论】:

【参考方案11】:

这是一个非常以英语为中心的默认 Microsoft 使用。 组匹配行当前检查名为“管理员”的管理员组的英语语言版本字符串,这在 Windows 的许多其他语言安装中失败。在德语安装中,该行需要改为“administratoren”。它们更好地使 le 可以按 SID 匹配组。 (这在 DenyGroups 匹配功能中更为重要 - 尚未对此进行测试 - 但如果他们在那里检查字符串而不是 SID,那么拒绝是没有意义的,并且很容易通过使用不同的 Windows 语言安装来规避)

(另见https://github.com/MicrosoftDocs/windowsserverdocs/issues/1911#issuecomment-771552030)

【讨论】:

以上是关于使用公钥身份验证为 Windows 设置 OpenSSH的主要内容,如果未能解决你的问题,请参考以下文章

git 生成公钥 使用命令行无需输入用户名密码(windows)

Spring通过Eureka从身份验证服务获取公钥

再次使用公钥进行身份验证的问题 GCP Source Repository

【Linux】SSH 使用密码/公钥远程登录总结

使用 vertx 在 JWT 公钥/私钥身份验证中握手

如何使用公钥在本地验证 keycloak 访问令牌