Windows OpenSSH 公钥登录的一个常见陷阱
背景
最近为了让 VPS 能直接查看 PC 上的文件,我把两边通过 Tailscale 打通,并在 Windows 上启用了 OpenSSH Server。目标很明确:让 VPS 可以通过 SSH 免密登录到 PC,这样后续无论是查看文件还是做轻量自动化,都会顺手很多。
这件事表面上很简单:在 Windows 上开启 OpenSSH,再把 VPS 的公钥加入目标用户的 authorized_keys。但真正动手之后会发现,Windows 的 OpenSSH 兼容了 SSH 的基本习惯,却没有完全沿用 Linux 上那套最直觉的行为,尤其是在目标用户属于管理员组时。
先做一个最小测试
这类问题最容易陷进去的地方,是还没分清楚到底是客户端没拿对 key,还是服务端没有接受它。最简单的办法是先跑一个带详细日志的最小测试:
ssh -v <user>@<host> -i /path/to/private_key如果输出里出现下面这种组合:
debug1: Offering public key: /path/to/private_key ...debug1: Authentications that can continue: publickey,password,keyboard-interactivedebug1: Next authentication method: password就可以先得到一个很重要的判断:
- 客户端确实在使用这把私钥
- SSH 连接本身已经打通
- 服务端没有接受这把公钥
这样一来,排查范围就会立刻缩小到服务端配置,而不需要继续怀疑 GitHub、ssh-agent 或客户端命令本身。
先检查 sshd_config
Windows 上 OpenSSH 的主配置文件在:
C:\ProgramData\ssh\sshd_config这里至少要确认两行:
PubkeyAuthentication yesAuthorizedKeysFile .ssh/authorized_keys其中 PubkeyAuthentication yes 最好显式写出来,不要只依赖默认值。因为当你已经在排公钥登录问题时,显式配置会比“应该默认是开着的”更容易判断。
真正卡人的地方:Match Group administrators
这次真正把问题卡住的,不是 PubkeyAuthentication,而是 sshd_config 里常见的这一段:
Match Group administrators AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys这段配置的影响很直接:如果登录用户属于管理员组,那么 sshd 不再使用这个用户家目录下的:
C:\Users\<username>\.ssh\authorized_keys而是改去读:
C:\ProgramData\ssh\administrators_authorized_keys这也解释了为什么表面上所有步骤都像是对的:
- 公钥已经放进
C:\Users\pzx20\.ssh\authorized_keys - 路径也没写错
- 客户端确实在 offering key
但服务端依旧只给密码登录。因为对管理员组用户来说,sshd 根本没有在看那个文件。
怎么确认目标用户是不是管理员
最直接的办法是在 Windows 上检查用户组,或者登录后执行:
whoami /groups如果输出里包含:
BUILTIN\Administrators那这个用户就会落进 Match Group administrators 这套逻辑里。
这个判断比单纯盯着 authorized_keys 更关键,因为它决定了 sshd 到底会去哪个位置找公钥。
两种解法
确认问题出在管理员组逻辑之后,解法其实就比较清楚了。
方案一:沿用管理员组默认规则
如果你打算继续用管理员用户登录,最快的办法就是把公钥放进:
C:\ProgramData\ssh\administrators_authorized_keys然后重启 sshd:
Restart-Service sshd这种做法的优点是快,适合先把链路打通。
方案二:改用普通用户
如果你只是想让 VPS 查看某个目录,或者做一些低风险的自动化,更稳妥的做法其实是单独建一个普通用户,不让它属于 administrators。这样 sshd 就会回到普通用户逻辑,使用:
C:\Users\<username>\.ssh\authorized_keys这也是后续更适合长期使用的方式,因为没有必要为了一个文件访问入口直接开放管理员权限账号。
最后怎么验证是真的配通了
当配置正确后,客户端日志会出现一个非常关键的变化:
debug1: Offering public key: ...debug1: Server accepts key: ...Authenticated to <host> using "publickey".只要出现:
Server accepts keyAuthenticated ... using "publickey"
就说明这次不是“SSH 连上了”,而是服务端真正接受了你的公钥。
后面我又额外创建了一个普通用户做测试,并确认它可以通过 SSH 登录、读取指定目录内容。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!