Skip to content

SSH Authentication with GPG Keys on Linux

以下是如何在 Linux 上设置使用 GPG 进行 SSH 认证的步骤:

核心概念

  • GPG (GNU Privacy Guard): 一种加密工具,常用于签名和加密数据。我们可以利用 GPG 密钥对进行身份验证。
  • SSH (Secure Shell): 一种加密的网络协议,用于在不安全的网络上安全地执行命令和传输文件。
  • gpg-agent: 一个守护进程,用于管理您的 GPG 私钥,避免每次使用时都输入密码。
  • ssh-agent: 一个守护进程,用于管理您的 SSH 私钥,同样避免重复输入密码。
  • libpam-gnome-keyring (可选但推荐): 一个 PAM 模块,可以在您登录时自动启动 gpg-agentssh-agent
  • gnupg-agent: 提供使用 GPG 密钥进行 SSH 认证所需的功能。

1. 安装必要的软件包:

根据您的 Linux 发行版,安装以下软件包:
* **Debian/Ubuntu:**
    ```bash
    sudo apt update
    sudo apt install gnupg2 gpg-agent openssh-server openssh-client libpam-gnome-keyring
    ```
* **Fedora/CentOS/RHEL:**
    ```bash
    sudo dnf install gnupg2 gpg-agent openssh-server openssh-clients pam_gnome_keyring
    ```
* **Arch Linux:**
    ```bash
    sudo pacman -S gnupg openssh libgnome-keyring
    ```

2. 生成或导入 GPG 密钥对:

如果您还没有 GPG 密钥对,可以使用以下命令生成一个新的:
```bash
gpg --full-generate-key
```
按照提示操作,选择密钥类型、密钥长度、有效期,并设置您的真实姓名、电子邮件地址和注释。请务必记住您的密码。
如果您已经有 GPG 密钥对,可以跳过此步骤。

3. 确认 GPG 密钥用途并获取指纹:

需要确认您拥有一个用途设置为 `Authenticate` 的 GPG 密钥或者子密钥。用以下的命令确认并获取该密钥或子密钥的指纹(40位 HEX):
```bash
gpg --with-keygrip -K
```

4. 将 GPG 密钥指纹添加到 sshcontrol 文件:

将上一步获取的指纹放入 `~/.gnupg/sshcontrol` 文件中。每行放置一个指纹。
```
# 示例 (将 YOUR_FINGERPRINT 替换为实际的指纹)
YOUR_FINGERPRINT
```

5. 配置 gpg-agent

编辑或创建 `~/.gnupg/gpg-agent.conf` 文件,并添加以下行:
```
enable-ssh-support
default-cache-ttl 3600
max-cache-ttl 7200
```
* `enable-ssh-support`: 启用 SSH 支持。
* `default-cache-ttl`: 设置默认的密码缓存时间(以秒为单位)。
* `max-cache-ttl`: 设置最大密码缓存时间。

6. 配置 PAM (可选但推荐):

如果您安装了 `libpam-gnome-keyring` (或类似的软件包),可以配置 PAM 以在登录时自动启动 `gpg-agent` 和 `ssh-agent`。
编辑 `/etc/pam.d/login` 和 `/etc/pam.d/sshd` 文件,并添加以下行(如果不存在):
在 `auth` 部分添加:
```
auth optional pam_gnome_keyring.so skel
```
在 `session` 部分添加:
```
session optional pam_gnome_keyring.so auto_start
```
**注意:** 具体的文件和行可能因您的 Linux 发行版和 PAM 配置而有所不同。您可能需要在其他 PAM 配置文件(如 `sudo` 或图形界面登录管理器)中进行类似的更改。

7. 导出 SSH 公钥:

使用以下命令从您的 GPG 私钥中导出 SSH 公钥。将 `YOUR_GPG_KEY_ID` 替换为您的 GPG 密钥 ID。您可以使用 `gpg --list-secret-keys --keyid-format long` 命令找到您的密钥 ID。
```bash
gpg --export-ssh-key YOUR_GPG_KEY_ID > ~/.ssh/id_ed25519.pub
```
**注意:**
* 导出的公钥默认保存为 `~/.ssh/id_ed25519.pub`。您可以根据需要更改文件名。
* 确保您的 GPG 私钥受到密码保护。

8. 将 SSH 公钥复制到远程服务器:

将您导出的 SSH 公钥 (`~/.ssh/id_ed25519.pub`) 的内容复制到您要进行 SSH 认证的远程服务器上的 `~/.ssh/authorized_keys` 文件中。
您可以使用 `ssh-copy-id` 命令来简化此过程(如果您的本地机器已经配置了基于密码或密钥的 SSH 访问):
```bash
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@remote_server
```
或者,您可以手动将 `~/.ssh/id_ed25519.pub` 的内容追加到远程服务器上的 `~/.ssh/authorized_keys` 文件中:
```bash
cat ~/.ssh/id_ed25519.pub | ssh user@remote_server "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
```

9. 配置 SSH 客户端:

编辑或创建 `~/.ssh/config` 文件,并添加以下内容以配置您的 SSH 客户端以使用 GPG 进行身份验证:
```
Host remote_server_alias  # 您可以为远程服务器设置一个别名
    Hostname remote_server_ip_or_hostname
    User your_username
    IdentityFile ~/.ssh/id_ed25519
    PubkeyAcceptedKeyTypes +ssh-ed25519-cert-v01@openssh.com,ssh-ed25519
```
* `Host`: 您为远程服务器设置的别名。
* `Hostname`: 远程服务器的 IP 地址或主机名。
* `User`: 您在远程服务器上的用户名。
* `IdentityFile`: 您导出的 SSH 公钥文件的路径(不带 `.pub` 扩展名)。
* `PubkeyAcceptedKeyTypes`: 指定接受的公钥类型。添加 `+ssh-ed25519-cert-v01@openssh.com` 以启用基于证书的认证。

10. 启动 gpg-agentssh-agent

如果您没有配置 PAM,您需要在登录后手动启动 `gpg-agent` 和 `ssh-agent`。将以下内容添加到您的 shell 配置文件(例如 `~/.bashrc`、`~/.zshrc`):
```bash
if [ -z "$SSH_AUTH_SOCK" ]; then
  eval "$(ssh-agent -s)"
fi

if ! gpg-connect-agent /bye > /dev/null 2>&1; then
  eval "$(gpg-agent --daemon --enable-ssh-support)"
fi

export SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
```
然后,重新加载您的 shell 配置文件:
```bash
source ~/.bashrc  # 或 source ~/.zshrc
```

11. 将 GPG 私钥添加到 gpg-agent

您可能需要将您的 GPG 私钥添加到 `gpg-agent` 中。这将提示您输入密码:
```bash
gpg --import-ownertrust
gpg --card-status  # 如果您使用智能卡
```
或者,您可以在第一次尝试 SSH 连接时输入密码。

12. 测试 SSH 连接:

现在,您应该可以使用配置的别名通过 SSH 连接到远程服务器,而无需输入密码(除非您的 GPG 私钥尚未解锁):
```bash
ssh remote_server_alias
```
如果这是您第一次使用该 GPG 密钥进行 SSH 连接,您可能会被要求输入 GPG 密钥的密码。之后,密码将被缓存在 `gpg-agent` 中,直到缓存过期。

重要注意事项

  • 安全性: 确保您的 GPG 私钥受到强密码保护。
  • 备份: 务必备份您的 GPG 私钥。
  • gpg-agentssh-agent: 确保这两个代理程序正在运行。您可以使用 ps aux | grep gpg-agentps aux | grep ssh-agent 命令来检查。
  • 权限: 确保 ~/.ssh 目录和 ~/.ssh/authorized_keys 文件的权限设置正确(通常 ~/.ssh700~/.ssh/authorized_keys600)。
  • 服务器配置: 确保远程服务器上的 sshd_config 文件中启用了公钥认证 (PubkeyAuthentication yes)。

通过以上步骤,您应该能够成功配置 Linux 系统以使用 GPG 密钥进行 SSH 认证,从而提高安全性并简化您的工作流程。

Ref

[1]. SSH-Configuration

[2]. OpenPGP-初探