Windows OpenSSH 管理员账号免密登录配置与排错

Windows OpenSSH 免密登录配置记录

目标:让本机 Windows 通过 SSH 免密登录远端 Windows 主机。

本次目标主机:

powershell 复制代码
ssh XXXX@100.111.103.11

1. 确认网络和 SSH 服务可达

先确认 Tailscale 中目标机器在线:

powershell 复制代码
tailscale status | Select-String -Pattern '100\.111\.103\.11|036-XXXX|XXXX'

确认结果显示目标为 Windows 主机,且在线:

text 复制代码
100.111.103.11   036-XXXX   windows   active

然后用禁止密码的方式测试当前是否已经支持公钥登录:

powershell 复制代码
ssh -o BatchMode=yes -o PasswordAuthentication=no -o ConnectTimeout=8 XXXX@100.111.103.11 "whoami; hostname"

如果返回:

text 复制代码
Permission denied (publickey,password,keyboard-interactive).

说明网络和 SSH 服务没问题,但远端还没有接受当前本机公钥。

2. 确认本机公钥

本机使用的公钥文件:

text 复制代码
C:\Users\23670\.ssh\id_rsa.pub

查看公钥指纹:

powershell 复制代码
ssh-keygen -lf $env:USERPROFILE\.ssh\id_rsa.pub

本次使用的指纹:

text 复制代码
3072 SHA256:eodo4aAZ1+itnrF8kBmEersYFUNvbssvTI7QpCQ5R4c vscode-Linux (RSA)

3. 判断远端账号是否为管理员

用密码临时登录一次远端,检查远端用户信息:

powershell 复制代码
powershell -NoProfile -ExecutionPolicy Bypass -Command "$u=$env:USERNAME; $profileDir=$env:USERPROFILE; $isAdmin=([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator); $cfg='C:\ProgramData\ssh\sshd_config'; $matchAdmins=$false; if (Test-Path $cfg) { $matchAdmins = Select-String -Path $cfg -Pattern '^\s*Match\s+Group\s+administrators' -Quiet }; Write-Output ('USERNAME=' + $u); Write-Output ('USERPROFILE=' + $profileDir); Write-Output ('IS_ADMIN=' + $isAdmin); Write-Output ('MATCH_ADMINS=' + $matchAdmins); Write-Output ('WHOAMI=' + (whoami));"

本次远端结果:

text 复制代码
USERNAME=XXXX
USERPROFILE=C:\Users\XXXX
IS_ADMIN=True
MATCH_ADMINS=True
WHOAMI=desktop-ktb9jj1\XXXX

这说明 XXXX 是 Windows 管理员账号,并且 OpenSSH 配置了:

text 复制代码
Match Group administrators

这种情况下,Windows OpenSSH 通常不读取:

text 复制代码
C:\Users\XXXX\.ssh\authorized_keys

而是读取管理员专用文件:

text 复制代码
C:\ProgramData\ssh\administrators_authorized_keys

4. 追加公钥到远端

将本机 id_rsa.pub 的内容追加到远端:

text 复制代码
C:\ProgramData\ssh\administrators_authorized_keys

为了兼容后续配置变化,也可以同时追加到:

text 复制代码
C:\Users\XXXX\.ssh\authorized_keys

注意:只追加公钥内容,不要上传私钥。

5. 修复 Windows OpenSSH ACL 权限

管理员专用公钥文件需要严格 ACL,否则 OpenSSH 可能拒绝读取。

在远端执行:

powershell 复制代码
icacls C:\ProgramData\ssh\administrators_authorized_keys /inheritance:r /grant Administrators:F /grant SYSTEM:F

用户目录下的备用 authorized_keys 可以这样设置:

powershell 复制代码
icacls C:\Users\XXXX\.ssh /inheritance:r /grant "XXXX:(OI)(CI)F" /grant "SYSTEM:(OI)(CI)F" /grant "Administrators:(OI)(CI)F"
icacls C:\Users\XXXX\.ssh\authorized_keys /inheritance:r /grant "XXXX:F" /grant "SYSTEM:F" /grant "Administrators:F"

必要时重启远端 SSH 服务:

powershell 复制代码
Restart-Service sshd

6. 验证免密登录

从本机执行:

powershell 复制代码
ssh -o BatchMode=yes -o PasswordAuthentication=no -o ConnectTimeout=8 XXXX@100.111.103.11 "cmd /c whoami && hostname && echo %USERPROFILE%"

本次验证结果:

text 复制代码
desktop-ktb9jj1\XXXX
DESKTOP-KTB9JJ1
C:\Users\XXXX

BatchMode=yesPasswordAuthentication=no 能成功,说明已经是纯公钥免密登录。

之后可以直接登录:

powershell 复制代码
ssh XXXX@100.111.103.11

常见坑

  1. Windows 管理员账号要优先检查 C:\ProgramData\ssh\administrators_authorized_keys
  2. C:\Users\<用户名>\.ssh\authorized_keys 对管理员账号不一定生效。
  3. ACL 权限不正确时,即使公钥内容正确,OpenSSH 也可能拒绝。
  4. 免密登录用的是本机私钥加远端公钥,不能把 .pub 当作私钥使用。
  5. 验证时建议使用 BatchMode=yesPasswordAuthentication=no,这样可以确认没有偷偷退回密码登录。