---
title: "SSH 免密登录实战：Windows / macOS / Linux 密钥认证完全指南"
slug: "ssh-key-auth-windows-macos-linux"
kind: "runbook"
version: "1.1"
status: "reviewed"
compatibility: "Windows 10/11（自带 OpenSSH 客户端）、macOS 及主流 Linux 发行版；远程主机为运行 sshd 的 Linux 服务器。需要处理两类受限场景：服务器未开启 PubkeyAuthentication（不允许密钥登录）、服务器设置 PermitRootLogin no（不允许 root 登录）。"
risk_level: "low"
requires_approval: false
updated_at: "2026-08-12T13:24:31.562Z"
verified_at: ""
source: "https://blog.atlankj.com/posts/ssh-key-auth-windows-macos-linux"
---

# Runbook: SSH 密钥免密登录配置（Windows / macOS / Linux）

## 目标

在本地生成 SSH 密钥对，将公钥安装到远程主机的 `~/.ssh/authorized_keys`，使本地可免密码登录远程主机；并给出不允许密钥登录、不允许 root 登录时的服务端配置调整方案。

## 前置条件

- 本地系统：Windows 10/11（自带 OpenSSH）、macOS 或 Linux。
- 远程主机：Linux，当前可用密码方式 SSH 登录，已知用户名与 IP。
- 本地可通过 `ssh user@host` 建立连接。

## 操作步骤

### 1. 生成本地密钥对

所有平台执行相同命令：

```bash
ssh-keygen -t ed25519 -C "you@example.com"
```

- 保存路径：回车使用默认。Windows 为 `C:\Users\<USER>\.ssh\id_ed25519`，macOS/Linux 为 `~/.ssh/id_ed25519`。
- passphrase：可选，建议设置；留空则直接回车。
- 兼容性备选：远程主机不支持 Ed25519 时改用 `ssh-keygen -t rsa -b 4096`。

验证产物：

```bash
ls -la ~/.ssh/id_ed25519 ~/.ssh/id_ed25519.pub
```

### 2. 安装公钥到远程主机

**macOS / Linux（首选）：**

```bash
ssh-copy-id user@host
```

**Windows（PowerShell，无 ssh-copy-id）：**

```powershell
type $env:USERPROFILE\.ssh\id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
```

**任意平台手动方式：**

```bash
cat ~/.ssh/id_ed25519.pub
ssh user@host
```

远程主机上执行：

```bash
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "<PASTE_PUBLIC_KEY>" >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
```

### 3. 建立免密连接

```bash
ssh user@host
```

### 4. 服务端配置调整（按需）

**场景 A：服务器不允许密钥登录（仅密码可用）**

`sshd_config` 中 `PubkeyAuthentication` 为 `no` 或未开启时，公钥无法用于认证：

1. 用密码登录，或经云控制台 VNC / 网页终端进入远程主机。
2. 编辑 `/etc/ssh/sshd_config`，设置 `PubkeyAuthentication yes`。
3. 重启 SSH 服务：`sudo systemctl restart sshd`；旧系统用 `sudo service sshd restart`，Ubuntu/Debian 亦可用 `sudo service ssh restart`。

**场景 B：不允许 root 登录**

`PermitRootLogin no` 时 root 无法 SSH 登录（含密钥登录），选择其一：

- 使用普通用户登录并 `sudo` 提权（推荐），公钥安装到该普通用户。
- 必须 root 密钥登录：设置 `PermitRootLogin prohibit-password`（仅密钥、禁密码），重启 sshd，并将公钥写入 root 的 `~/.ssh/authorized_keys`。
- 若仍失败，检查 `AllowUsers` / `AllowGroups` / `DenyUsers` 是否限制了登录用户。

## 输出结果

- 本地执行 `ssh user@host` 不再提示账户密码（passphrase 除外）。
- 远程 `~/.ssh/authorized_keys` 包含本地公钥；`~/.ssh` 权限 700、`authorized_keys` 权限 600。
- 若调整过服务端配置：`sshd_config` 中 `PubkeyAuthentication yes`、`PermitRootLogin` 符合预期，且 sshd 已重启生效。

## 验证方法

- 执行 `ssh user@host`，预期不提示账户密码（若设了 passphrase 需输入 passphrase）。
- 远程执行 `grep -F "$(cat ~/.ssh/id_ed25519.pub)" ~/.ssh/authorized_keys` 确认公钥存在且为整行。
- 远程执行 `ls -ld ~/.ssh && ls -l ~/.ssh/authorized_keys`，预期权限为 700 / 600。
- 无法连接时执行 `ssh -v user@host` 查看 `Authentications that can continue` 输出。
- 服务端调整后执行 `sshd -t` 检查配置语法，再重启 sshd。

## 故障排除

| 症状 | 处理 |
| --- | --- |
| 仍要求密码 | `ssh -v user@host` 检查认证方式；确认 authorized_keys 为整行且权限正确 |
| 服务器不允许密钥登录，只认密码 | 密码/VNC 登录后确认 `PubkeyAuthentication yes`，重启 sshd |
| 不允许 root 登录 | 改用普通用户 + sudo；或设 `PermitRootLogin prohibit-password` 并重启 sshd；检查 AllowUsers/AllowGroups/DenyUsers |
| Permissions too open（Windows） | `icacls $env:USERPROFILE\.ssh\id_ed25519 /inheritance:r /grant:r "$($env:USERNAME):R"` |
| Permission denied (publickey) | 通过 VNC 等带外通道登录，确认 `PubkeyAuthentication yes` 后重启 sshd |
| 多主机免密 | 同一公钥分发到各主机；不同密钥用 `~/.ssh/config` 的 `IdentityFile` |

## 回滚方式

- 删除本地密钥对：删除 `~/.ssh/id_ed25519` 与 `~/.ssh/id_ed25519.pub`。
- 撤销远程授权：登录远程主机，从 `~/.ssh/authorized_keys` 中删除对应行后保存。
- 恢复服务端配置：将 `sshd_config` 中被修改的 `PubkeyAuthentication` / `PermitRootLogin` 恢复原值并重启 sshd。
- 本 runbook 默认不改动 `sshd_config`，服务端调整仅按需执行，风险为低。
