Windows SSH + Headscale/Tailscale 组网及免密登录完整配置教程
一、操作目标
完成以下配置:
- 检查 Windows 是否安装 OpenSSH 客户端。
- 检查 Tailscale/Headscale 网络连接情况。
- 获取本机计算机名称、局域网 IP 和 Headscale 内网 IP。
- 将 Windows 计算机接入 Headscale 网络。
- 检查目标 Windows 服务器的 SSH 服务。
- 配置 SSH 公钥认证。
- 正确配置管理员账户的
administrators_authorized_keys。 - 验证 SSH 配置是否生效。
- 实现通过 Headscale 内网 IP 免密码 SSH 登录。
示例环境:
| 项目 | 示例 |
|---|---|
| 操作系统 | Windows 10 / Windows 11 |
| Headscale 服务地址 | https://47.104.30.197:9445 |
| Headscale 用户 | CuiCan |
| 目标 Windows 内网 IP | 100.64.0.16 |
| SSH 端口 | 22 |
| 目标登录账户 | Administrator |
| 命令执行终端 | PowerShell(涉及服务和系统配置时使用管理员权限) |
注意:以上 IP、用户名均以实际设备为准。
二、第一步:检查 Windows SSH 客户端
在 Windows PowerShell 中执行:
powershell
ssh -V
正常情况下会显示类似:
text
OpenSSH_for_Windows_9.x
如果出现 OpenSSH_for_Windows,说明 SSH 客户端已经安装,可以继续使用。
如果提示无法识别 ssh,可以在管理员 PowerShell 中安装:
powershell
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
安装完成后,重新执行:
powershell
ssh -V
三、第二步:检查 Headscale/Tailscale 网络
3.1 检查 Tailscale 是否可用
powershell
tailscale version
如果正常显示版本号,说明 Tailscale 客户端已安装。
3.2 查看当前网络状态
powershell
tailscale status
主要确认:
- 本机是否已经连接网络。
- 是否可以看到其他 Headscale 节点。
- 其他节点是否具有
100.64.x.x类型的内网 IP。
3.3 查看计算机名称
powershell
hostname
输出示例:
text
DESKTOP-XXXXXXX
该名称可用于识别不同的 Windows 设备。
3.4 查看本机 Headscale/Tailscale IP
powershell
tailscale ip -4
输出示例:
text
100.64.0.16
这个地址是通过 Headscale/Tailscale 网络访问本机时使用的 IPv4 地址。
3.5 查看所有本机 IPv4 地址和对应网卡
powershell
Get-NetIPAddress -AddressFamily IPv4 |
Select-Object InterfaceAlias,IPAddress
输出示例:
text
InterfaceAlias IPAddress
-------------- ---------
Ethernet 192.168.1.100
Wi-Fi 192.168.1.101
Tailscale 100.64.0.16
Loopback 127.0.0.1
重点关注 Tailscale 网卡对应的 IP。
3.6 检查 Headscale 控制服务器地址
powershell
tailscale debug prefs | Select-String "ControlURL"
查看当前 Tailscale 使用的控制服务器配置。
如果没有匹配输出,可进一步查看完整的偏好设置或客户端版本。
四、第三步:连接 Headscale 服务器
4.1 登录 Headscale
在需要加入网络的 Windows 计算机上执行:
powershell
tailscale login --login-server=https://47.104.30.197:9445
该命令会尝试通过指定的 Headscale 控制服务器进行认证。
如果控制服务器使用域名证书,应使用与 TLS 证书匹配的服务器域名,避免证书不匹配。
4.2 注册 Headscale 节点
如果 Headscale 要求手动注册节点,需要在 Headscale 服务器终端 执行:
bash
headscale nodes register --key <注册密钥> --user CuiCan
其中 <注册密钥> 应替换为本次登录生成的实际有效注册密钥。
注意:
- 此命令在安装了
headscale服务端程序的服务器上执行。 - 不应在普通 Windows Tailscale 客户端中执行。
- 注册密钥具有授权作用,不建议直接公开或长期保存在共享文档中。
- 如果使用预授权密钥加入节点,则按照预授权密钥的流程操作,不需要重复手动注册。
4.3 查看已注册节点
在 Headscale 服务器执行:
bash
headscale nodes list
确认新设备是否出现在节点列表中。
4.4 返回 Windows 检查网络
powershell
tailscale status
然后执行:
powershell
tailscale ip -4
确认已经获得 Headscale 内网 IP。
五、第四步:检查目标 Windows SSH 服务
以下操作在 目标 Windows 服务器 100.64.0.16 上执行。
建议使用管理员 PowerShell。
5.1 检查 SSH 服务状态
powershell
Get-Service sshd
正常情况下显示:
text
Status Name DisplayName
------ ---- -----------
Running sshd OpenSSH SSH Server
如果出现 Running,说明 SSH 服务正在运行。
如果提示找不到 sshd 服务,先安装 Windows OpenSSH Server:
powershell
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
5.2 启动 SSH 服务
powershell
Start-Service sshd
5.3 设置 SSH 开机自动启动
powershell
Set-Service -Name sshd -StartupType Automatic
5.4 再次检查服务状态
powershell
Get-Service sshd
5.5 检查 SSH 服务实际使用的程序路径
powershell
sc.exe qc sshd
重点查看:
text
BINARY_PATH_NAME
Windows OpenSSH 可能位于:
text
C:\Windows\System32\OpenSSH\sshd.exe
也可能位于:
text
C:\Program Files\OpenSSH\sshd.exe
后续执行 sshd -t 和 sshd -T 时,应使用 SSH 服务实际对应的程序版本,避免检查了错误的可执行文件。
5.6 检查 22 端口是否监听
powershell
Get-NetTCPConnection -LocalPort 22 -State Listen
如果存在监听记录,说明有程序正在监听 TCP 22 端口。
还可以检查 Windows 防火墙是否允许来自 Headscale 网络的 SSH 入站连接。
六、第五步:从其他电脑测试 SSH 连接
在另一台已经加入同一个 Headscale 网络的 Windows 设备上执行:
powershell
tailscale status
然后检查目标 SSH 端口:
powershell
Test-NetConnection 100.64.0.16 -Port 22
如果实际目标是 100.64.0.2,则使用:
powershell
Test-NetConnection 100.64.0.2 -Port 22
正常输出应包含:
text
TcpTestSucceeded : True
如果显示:
text
TcpTestSucceeded : False
需要检查:
- 目标计算机是否在线。
- 两台设备是否都已加入 Headscale 网络。
- SSH 服务是否正在运行。
- SSH 是否监听 TCP 22 端口。
- Windows 防火墙是否阻止入站连接。
- Headscale/Tailscale 的访问控制规则是否允许这两个节点通信。
只有端口连通后,才能继续检查 SSH 公钥认证。
七、第六步:配置 SSH 公钥免密登录
7.1 在发起连接的计算机上检查 SSH 公钥
powershell
Get-ChildItem "$HOME\.ssh"
如果已经存在:
text
id_ed25519
id_ed25519.pub
说明可能已经生成过 SSH 密钥。
如果没有密钥,可以执行:
powershell
ssh-keygen -t ed25519
按照提示选择保存路径及是否设置密钥口令。
7.2 查看 SSH 公钥
powershell
Get-Content "$HOME\.ssh\id_ed25519.pub"
输出类似:
text
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... user@computer
复制完整的公钥内容。
注意:只复制 .pub 公钥,绝对不要把私钥 id_ed25519 复制到服务器。
7.3 在目标 Windows 服务器中创建管理员公钥文件
使用管理员 PowerShell:
powershell
New-Item -ItemType Directory -Path "C:\ProgramData\ssh" -Force
然后打开:
powershell
notepad "C:\ProgramData\ssh\administrators_authorized_keys"
将刚才复制的 SSH 公钥粘贴进去,每个公钥单独占一行。
保存文件。
7.4 配置管理员公钥文件权限
在目标 Windows 管理员 PowerShell 执行:
powershell
$KeyFile = "C:\ProgramData\ssh\administrators_authorized_keys"
icacls $KeyFile /inheritance:r
icacls $KeyFile /grant:r "*S-1-5-32-544:F" "*S-1-5-18:F"
以上两个 SID 分别对应 Windows 内置 Administrators 组和 SYSTEM 账户,可以避免中文系统与英文系统的组名差异。
然后检查权限:
powershell
icacls "C:\ProgramData\ssh\administrators_authorized_keys"
管理员公钥文件应仅允许符合 Windows OpenSSH 要求的受信任主体访问,不应开放给普通用户写入。
八、第七步:配置 sshd_config
8.1 打开配置文件
在目标 Windows 服务器的管理员 PowerShell 中执行:
powershell
notepad "C:\ProgramData\ssh\sshd_config"
8.2 检查公钥认证是否启用
确保配置中允许:
text
PubkeyAuthentication yes
如果存在注释:
text
#PubkeyAuthentication yes
可以改成:
text
PubkeyAuthentication yes
8.3 配置管理员公钥文件路径
找到:
text
#Match Group administrators
# AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
如果目标是让属于 Administrators 组的账户使用统一管理员公钥文件,则去掉注释,修改为:
text
Match Group administrators
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
注意:
Match Group administrators针对 Windows Administrators 组中的用户。- 其下的
AuthorizedKeysFile指定管理员账户使用的公钥文件。 - 建议将这一段放在配置文件末尾。
- 不要在该段后面随意添加原本希望全局生效的 SSH 配置项。
- 如果文件已有相同的有效配置,不要重复添加。
保存文件。
九、第八步:检查 SSH 配置语法
9.1 确认 sshd.exe 的实际路径
先执行:
powershell
sc.exe qc sshd
如果实际 SSH 服务使用的是系统自带版本,则可以使用:
powershell
$sshdExe = "$env:WINDIR\System32\OpenSSH\sshd.exe"
如果服务使用的是其他路径,例如 C:\Program Files\OpenSSH\sshd.exe,则将 $sshdExe 修改为对应路径。
9.2 检查配置是否有错误
powershell
& $sshdExe -t
$LASTEXITCODE
如果结果是:
text
0
说明配置语法检查通过。
如果不是 0,应查看报错并修复,暂时不要重启 SSH 服务。
十、第九步:重启 SSH 服务
配置语法无误后执行:
powershell
Restart-Service sshd
然后检查:
powershell
Get-Service sshd
应该显示:
text
Running sshd OpenSSH SSH Server
也可以将语法检查和重启合并执行:
powershell
& $sshdExe -t
if ($LASTEXITCODE -eq 0) {
Restart-Service sshd
Get-Service sshd
} else {
Write-Host "SSH 配置检查失败,未重启 SSH 服务"
}
这段代码的作用:
- 先检查 SSH 配置。
- 只有配置语法正确时才重启服务。
- 重启后输出服务状态。
- 如果配置存在错误,则避免直接重启导致服务无法正常启动。
修改 SSH 配置时,建议保留一个已登录的管理员终端,直到新的 SSH 连接验证成功。
十一、第十步:确认管理员公钥路径已真正生效
这是整个配置中需要重点检查的一步。
在目标 Windows 管理员 PowerShell 执行:
powershell
& $sshdExe -T -C "user=administrator,host=localhost,addr=100.64.0.4" |
Select-String "authorizedkeysfile|pubkeyauthentication"
这里:
user=administrator:模拟目标登录用户。host=localhost:本次配置检查使用的客户端主机名条件。addr=100.64.0.4:模拟客户端来源地址,实际使用时可替换。
如果管理员匹配配置正确,应包含类似:
text
pubkeyauthentication yes
authorizedkeysfile __PROGRAMDATA__/ssh/administrators_authorized_keys
这代表:
- SSH 公钥认证已启用。
- 对当前模拟的 Administrator 登录条件,已启用管理员公钥文件路径。
如果仍然显示:
text
pubkeyauthentication yes
authorizedkeysfile .ssh/authorized_keys
说明对于此次模拟的登录条件,管理员专用的 AuthorizedKeysFile 设置没有生效。
依次检查:
检查 A:sshd_config 是否修改正确
powershell
notepad "C:\ProgramData\ssh\sshd_config"
确认存在未注释的配置:
text
Match Group administrators
AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys
检查 B:是否修改了 SSH 服务实际使用的配置
powershell
sc.exe qc sshd
确认正在使用的 sshd.exe,并检查服务是否指定了其他配置文件。
检查 C:Administrator 是否属于本机 Administrators 组
powershell
whoami /groups
此命令显示当前终端用户的组信息。如果要核对其他登录账户,需要查看那个账户的实际组成员关系。
检查 D:重新进行配置检查并重启服务
powershell
& $sshdExe -t
if ($LASTEXITCODE -eq 0) {
Restart-Service sshd
}
然后重新执行:
powershell
& $sshdExe -T -C "user=administrator,host=localhost,addr=100.64.0.4" |
Select-String "authorizedkeysfile|pubkeyauthentication"
直到输出与预期配置一致。
特别注意:.ssh/authorized_keys 本身并不是错误路径。对于普通用户,以及没有启用管理员专用匹配规则的 SSH 配置,它可能就是正确的有效路径。只有确定要使用 administrators_authorized_keys 方案时,才需要将输出调整为管理员专用路径。
十二、第十一步:测试 Headscale SSH 免密登录
在另一台 Windows 计算机上执行:
powershell
Test-NetConnection 100.64.0.16 -Port 22
确认:
text
TcpTestSucceeded : True
然后执行:
powershell
ssh Administrator@100.64.0.16
如果配置正确,并且客户端公钥与服务器授权公钥匹配,应能使用公钥认证登录。
首次连接可能要求确认目标主机指纹,应核对指纹后再接受。
如果 SSH 私钥设置了口令,仍可能提示输入私钥口令,这并不代表公钥认证失败。
检查认证是否真的使用了公钥
执行:
powershell
ssh -v Administrator@100.64.0.16
观察调试信息中是否包含公钥被接受的记录,例如:
text
Authenticated to 100.64.0.16 using "publickey".
如果想指定特定私钥:
powershell
ssh -i "$HOME\.ssh\id_ed25519" Administrator@100.64.0.16
如果出现远程命令提示符,说明连接成功。
十三、常见问题排查
| 问题 | 常见原因 | 处理方法 |
|---|---|---|
ssh 不是有效命令 |
SSH 客户端未安装 | 安装 OpenSSH Client |
tailscale status 无法使用 |
Tailscale 未安装或服务异常 | 检查客户端和服务 |
| Headscale 登录失败 | 服务端地址、TLS 证书或网络异常 | 核对服务器地址与证书 |
TcpTestSucceeded : False |
网络、ACL、防火墙、服务或端口问题 | 检查连接和 TCP 22 |
Connection refused |
目标 SSH 服务未监听或连接被拒绝 | 检查 sshd 与监听端口 |
Permission denied (publickey) |
公钥未匹配、路径错误或文件权限不正确 | 检查公钥文件及权限 |
sshd -t 不为 0 |
SSH 配置语法错误等 | 根据错误信息修复 |
authorizedkeysfile 仍是 .ssh/authorized_keys |
管理员匹配规则未生效或检查条件不匹配 | 复核 Match Group administrators |
| 修改配置后无法登录 | 配置未生效、密钥位置不一致或权限错误 | 在目标服务器本地重新检查 |
十四、最终完整验收
完成配置后,依次执行以下命令。
在目标 Windows 服务器上:
powershell
hostname
tailscale status
tailscale ip -4
Get-Service sshd
sc.exe qc sshd
然后根据 SSH 服务实际路径设置 $sshdExe,并执行:
powershell
& $sshdExe -t
$LASTEXITCODE
& $sshdExe -T -C "user=administrator,host=localhost,addr=100.64.0.4" |
Select-String "authorizedkeysfile|pubkeyauthentication"
检查管理员公钥文件:
powershell
Test-Path "C:\ProgramData\ssh\administrators_authorized_keys"
icacls "C:\ProgramData\ssh\administrators_authorized_keys"
在发起连接的 Windows 客户端上:
powershell
ssh -V
tailscale status
tailscale ip -4
Test-NetConnection 100.64.0.16 -Port 22
ssh -v Administrator@100.64.0.16
最终成功标准
- Windows OpenSSH 客户端正常。
- Tailscale/Headscale 客户端连接正常。
- 本机已获得
100.64.x.x内网 IP。 - Headscale 服务端可以看到该节点。
- 目标 Windows 的
sshd服务处于 Running。 - 目标服务器 TCP 22 端口可以访问。
- SSH 配置语法检查返回 0。
- 目标管理员公钥文件存在且权限正确。
-
sshd -T -C显示预期的管理员公钥路径。 - 客户端通过 SSH 公钥认证成功登录目标 Windows 服务器。
最终目标:
在两台计算机都连接 Headscale 网络的情况下,通过以下命令:
powershell
ssh Administrator@100.64.0.16
即可使用 SSH 密钥安全登录远程 Windows 服务器,不需要输入 Windows 账户密码。
**补充说明:**如果当前机器已经能够通过 .ssh/authorized_keys 成功使用公钥登录,那么并非必须将其改为 C:\ProgramData\ssh\administrators_authorized_keys。优先保持已经验证成功的方案;只有明确需要统一管理员公钥管理时,再切换到管理员专用文件方案。