使用公钥身份验证为 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_rsa
和 id_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
点击“禁用继承”;
出现提示时选择“将继承的权限转换为此对象的显式权限”;
(非常非常重要)删除文件上的所有权限,SYSTEM
和 yourself 除外。文件上必须有恰好两个权限条目。一些指南建议运行Repair-AuthorizedKeyPermission $env:USERPROFILE\.ssh\authorized_keys
- 这将尝试将sshd
用户添加到权限列表中,它将破坏身份验证,所以,不要这样做,或者至少不要这样做同意添加sshd
用户)。 SYSTEM
和您自己都应该完全控制该文件。
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:r
和 get-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)