# SSH keys (简体中文)

From ArchWiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.
翻译状态：本文是 SSH keys 的翻译。上次翻译日期：2021-2-16。如果英文版本有所更改，则您可以帮助同步翻译。

对于使用公钥加密与质询-应答式认证的 SSH 服务器，SSH 密钥可以为您提供证明身份的方法。基于密钥的认证主要优点在于，与密码认证相比，它不易遭受暴力破解攻击，且在服务器被攻破的情况下也不会泄露您的有效凭证。[1]

不仅如此，与传统的密码认证相比，SSH 密钥认证也可以更加便利。当与被称作 SSH agent 的程序共用时，SSH 密钥可以让您无需记住或输入每个系统的密码，就能够连接到一个或多个服务器。

基于密钥的认证并非没有缺点，可能也并非适用于一切环境，但在很多情况下可以提供一些有力的优势。对 SSH 密钥如何工作的概略理解会帮助您决定如何以及何时使用它们，以满足您的需求。

本文假定您已经对于 SSH 有了基本理解，并安装了 openssh 软件包。

## 背景

SSH 密钥都是成对生成的，其一称为公钥，另一则称为私钥。私钥只由您所知，必须安全保管。相对地，公钥可以向您想连接的任何 SSH 服务器自由地共享。

如果一个 SSH 服务器在文件中存有您的公钥，并收到了您的连接请求，就会使用您的公钥构建一个质询问题并发送给您。这一质询问题是一条加密信息，必须得到正确应答，服务器才能允许您访问。这条编码信息特别安全是在于，只有私钥持有者才能理解它。公钥可以用来加密信息，但不能用来解密同一条信息。只有您，私钥的持有者，能够正确理解这一质询问题并产生合适的应答。

这一质询-应答过程发生在后台，对用户不可见。只要您持有私钥（一般存放在 `~/.ssh/` 目录下），您的 SSH 客户端就应当能够向服务器回复正确的应答。

私钥是受保护的秘密，因此建议以加密形式将其存储在磁盘上。当需要被加密的私钥时，为了解密它，需要先输入密码。虽然这在表面上可能像是您在向 SSH 服务器提供登录密码，但该密码只用于解密本地系统上的私钥。该密码并未通过网络传输。

## 生成密钥对

通过运行 `ssh-keygen` 命令可以生成密钥对，默认为3072位的 RSA（以及 SHA256），ssh-keygen(1) 手册页称其“一般被认为充足”且应当兼容于几乎所有客户端和服务器：

    $ ssh-keygen

    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/<username>/.ssh/id_rsa):
    Enter passphrase (empty for no passphrase):
    Enter same passphrase again:
    Your identification has been saved in /home/<username>/.ssh/id_rsa.
    Your public key has been saved in /home/<username>/.ssh/id_rsa.pub.
    The key fingerprint is:
    SHA256:gGJtSsV8BM+7w018d39Ji57F8iO6c0N2GZq3/RY2NhI username@hostname
    The key's randomart image is:
    +---[RSA 3072]----+
    |   ooo.          |
    |   oo+.          |
    |  + +.+          |
    | o +   +     E . |
    |  .   . S . . =.o|
    |     . + . . B+@o|
    |      + .   oo*=O|
    |       .   ..+=o+|
    |           o=ooo+|
    +----[SHA256]-----+

randomart 图像作为一种简便的密钥指纹视觉辨识方式在 OpenSSH 5.1 中引入。

注意： 可以使用 `-a` 开关来指定密码加密的 KDF rounds 数量。

也可以用 `-C` 开关对公钥添加可选的注释栏，从而在 `~/.ssh/known_hosts`、`~/.ssh/authorized_keys` 以及 `ssh-add -L` 输出等处更轻松地辨识它。例如：

    $ ssh-keygen -C "$(whoami)@$(uname -n)-$(date -I)"

会添加一条注释，说明是哪个用户何时在哪台机器上创建的密钥。

### 选择认证密钥种类

OpenSSH（对于认证密钥）支持数种签名算法，按照所采用的数学性质可分为两类：

1. DSA 以及 RSA，依赖于对两个大质数之积进行分解的实际困难；
2. ECDSA 以及 Ed25519，依赖于椭圆曲线离散对数问题。（例）

椭圆曲线密码学（ECC）算法是对于公钥密码体制的较新发展。其主要优势之一是以较小密钥提供同等安全性的能力，使得计算密集操作更少（也就是密钥创建、加密及解密更快）且存储及传输的要求更低。

由于已发现的漏洞，OpenSSH 7.0废弃并禁用了对 DSA 密钥的支持，因此密码体制的选择范围就限定在了 RSA 或两种 ECC 之一当中。

#RSA 密钥会提供最大的可移植性，而 #Ed25519 会提供最佳的安全性，但需要新版本的客户端与服务器[2]。. #ECDSA 兼容性可能比 Ed25519 更好（虽然还是不如 RSA），但存在对于其安全性的怀疑（见下文）。

注意： 这些密钥只用于认证您的身份；选择更强的密钥并不会在通过SSH传输数据时加重 CPU 负担。

#### RSA

`ssh-keygen` 默认使用 RSA，因此无需使用 `-t` 选项指定它。它提供所有算法当中最佳的兼容性，但提供充足安全性所需的密钥尺寸较大。

密钥尺寸最小为1024位，默认为3072（见 ssh-keygen(1)），最大为 16384。

如果您想生成较强的 RSA 密钥对（例如为了防范先进或未知攻击以及较高级的攻击者），只需为 `-b` 选项指定比默认高一点的值：

    $ ssh-keygen -b 4096

需要明白的是，使用更长的密钥存在收益递减。[3][4] GnuPG 常见问答记载：“如果你需要的安全性比 RSA-2048 所提供的更强，应该做的是改用椭圆曲线密码学——而不是接着使用 RSA。”[5]

另一方面，最新版本的 NSA Fact Sheet Suite B Cryptography 建议对于 RSA 使用最少3072位的模，同时“为即将到来的抗量子算法迁移（做准备）”。[6]

#### ECDSA

椭圆曲线数字签名算法（ECDSA）在 OpenSSH 5.7中作为首选的认证算法被引入。一些提供商也由于潜在的专利问题禁用了所需的实现。

对于它的担忧有两种：

1. 政治上的担忧：在 NSA（美国国家安全局）被曝在软件、硬件组件及发布的标准中蓄意植入后门之后，由 NIST（美国国家标准技术研究所）产生的曲线的可信性受到了质疑；密码领域的知名人士对于 NIST 曲线的设计方式表示 了 怀疑[失效链接 2021-05-17 ⓘ]，并且之前已经有主动的污染被 证实。
2. 技术上的担忧：对于正确实现该标准的困难以及在实现不够谨慎情况下降低安全性的迟缓与设计缺陷。

libssh curve25519 介绍当中很好地总结了上述担忧。尽管政治上的担忧仍受到争议，但有明确的共识认为 #Ed25519 技术上更优越，因此应当优先采用。

#### Ed25519

Ed25519 在2014年1月被引入 OpenSSH 6.5：“Ed25519 是一种能够提供比 ECDSA 及 DSA 更佳安全性及良好性能的椭圆曲线签名体系”。其主要长处在于速度、时间恒定运行时（从而能够对抗侧信道攻击）以及无需晦暗不明的硬编码常数。[7] 关于其工作方式，参见由一位 Mozilla 开发者撰写的博客文章。

它已经在众多应用及库中得到实现，并且在 OpenSSH 中是默认的密钥交换算法（与密钥签名不同）。

Ed25519 密钥对生成方法如下：

    $ ssh-keygen -t ed25519

所有 Ed25519 密钥都是256位，故无需设置密钥尺寸。

注意较老的 SSH 客户端与服务器可能不支持这些密钥。

### 选择密钥存储位置以及密码短语

运行 `ssh-keygen` 时，它会询问您希望的私钥文件名称及位置。默认情况下，密钥保存到 `~/.ssh` 目录下，并根据所使用的加密类型命名。为使下文中的示例代码正确工作，建议您接受默认的名称和位置。

当系统向您询问密码短语时，如果您在乎私钥的安全性，请选择难以猜到的密码。更长、更随机的密码一般会更强，当私钥落入贼人之手时更不容易被破解掉。

在没有密码短语的情况下生成私钥也是可能的。虽然也许很方便，但您需要明白随之而来的风险。在没有密码短语的情况下，您的私钥会以未加密形式存储在硬盘上。任何能接触到您私钥文件的人之后都能够在您使用基于密钥认证连接的任何 SSH 服务器面前冒用您的身份。更进一步，没有密码短语，您也必须信任 root 用户，因为他可以绕过文件权限并能够随时访问您未加密的私钥文件。

注意： 从前，私钥密码都是以一种不安全的方式编码的：仅一遍 MD5 散列。OpenSSH 6.5及之后版本支持一种新的、更安全的格式来编码您的私钥。从 OpenSSH 版本7.8开始默认使用该格式。Ed25519 密钥一直采用新的编码格式。只需按下节所述更改密钥的密码短语即可升级到新格式。

#### 不修改密钥对的情况下修改密码短语

如果不希望使用原本选择的 SSH 密钥密码短语或者必须更换，可以使用 `ssh-keygen` 命令来修改密码短语，而无需改动实际密钥。此法也可用于将密码编码格式改为新标准。

    $ ssh-keygen -f ~/.ssh/id_rsa -p

#### 管理多组密钥对

对多台主机使用同一 SSH 密钥对是可能的，尽管受到争议[8] [9]。

另一方面，使用您 OpenSSH 配置文件中的 `IdentityFile` 指令，为多台主机管理不同的密钥对就比较容易了：

    ~/.ssh/config

    Host SERVER1
       IdentitiesOnly yes
       IdentityFile ~/.ssh/id_rsa_SERVER1

    Host SERVER2
       IdentitiesOnly yes
       IdentityFile ~/.ssh/id_ed25519_SERVER2

对于这些选项的完整描述见 ssh_config(5)。

#### 在硬件令牌上存储 SSH 密钥

SSH 密钥也可以存储在智能卡或 USB 令牌等安全令牌上。这样做的好处是私钥安全地存储在令牌上，而不是存储在磁盘中。当使用安全令牌时，敏感的私钥也从来不会存在于 PC 的内存当中；密码学操作在令牌自身上进行。密码学令牌还有一点好处是，它不与单台电脑绑定；可以将其从一台电脑上轻松取下，四处携带之后在其他电脑上使用。

硬件令牌的例子如下所述：

- YubiKey#SSH notes 用于 FIDO/U2F keys 的原生 OpenSSH 支持
- YubiKey#SSH keys
- Trusted Platform Module#Securing SSH keys

## 将公钥复制到远程服务器上

This article or section needs expansion.

Reason: 在强制公钥认证的情况下如何实现？ (Discuss in Talk:SSH keys (简体中文)#)

创建好密钥对之后，您需要将公钥上传到远程服务器上，以便用于 SSH 密钥认证登录。公钥文件名和私钥文件名相同，只不过公钥文件带有扩展名 `.pub` 而私钥文件名则没有。千万不要将私钥上传，私钥应该保存在本地。

注意： 如果使用以下两种方法外的方法请不要忘记注册公钥文件，您只需要命令

    $ cat ~/.ssh/id_ecdsa.pub >> ~/.ssh/authorized_keys

### 简易方式

注意： 如果您的远程服务器默认使用的是 non-`sh` 的 shell，比如 `tcsh`，且使用早于6.6.1p1版本的 OpenSSH，则此方法可能不奏效。见 该 bug 报告。

如果您的公钥文件为 `~/.ssh/id_rsa.pub`，您只需要输入命令

    $ ssh-copy-id remote-server.org

如果您的远程服务器用户名与本地的不同，您需要指明用户名

    $ ssh-copy-id username@remote-server.org

如果您的公钥文件名不是默认的 `~/.ssh/id_rsa.pub`，您会得到错误 `/usr/bin/ssh-copy-id: ERROR: No identities found`。这种情况下，您需要显式提供公钥的位置：

    $ ssh-copy-id -i ~/.ssh/id_ecdsa.pub username@remote-server.org

如果远程服务器监听端口不是默认的22，请在主机参数中指明：

    $ ssh-copy-id -i ~/.ssh/id_ecdsa.pub -p 221 username@remote-server.org

### 手动方式

对于 OpenSSH，默认需要将公钥添加到 `~/.ssh/authorized_keys`。先从复制公钥到远程服务器开始。

    $ scp ~/.ssh/id_ecdsa.pub username@remote-server.org:

以上示例通过 `scp` 将公钥（`id_ecdsa.pub`）复制到您在远程服务器上的主目录。别忘了加上服务器地址末尾的 `:`。并请注意，您的公钥名称可能与此例所示不同。

在远程服务器上，如果还没有 `~/.ssh` 目录，您需要创建一个；然后将您的公钥追加到 `authorized_keys`。

    $ ssh username@remote-server.org
    username@remote-server.org's password:
    $ mkdir ~/.ssh
    $ chmod 700 ~/.ssh
    $ cat ~/id_ecdsa.pub >> ~/.ssh/authorized_keys
    $ rm ~/id_ecdsa.pub
    $ chmod 600 ~/.ssh/authorized_keys

上面最后两个命令将公钥文件从服务器上删除，并设置 `authorized_keys` 文件的权限，这样只有作为文件拥有者的您能够读取及写入。

## SSH agents

如果您的私钥使用密码短语来加密了的话，每一次试图连接到使用公钥认证的 SSH 服务器的时候，您都必须输入密码短语。每次唤起 `ssh` 或 `scp` 时都需要密码短语来解密您的私钥以便认证能够继续。

而 SSH agent 程序能够将您的已解密的私钥缓存起来，并代表您将其提供给 SSH 客户端。这样子，您就只需要将私钥加入 SSH agent 缓存的时候输入一次密码短语就可以了。这为您经常使用 SSH 连接提供了不少便利。

SSH agent 一般会设置成在登录会话的时候自动启动，并在整个会话中保持运行。有多种 agent、前端及配置都能够达成这一效果。本节概述了多种不同的解决方案，能够适应以满足您的特定需求。

### ssh-agent

ssh-agent 是 OpenSSH 自带的默认 agent。它可以直接使用，或者作为下文所述的几种前端解决方案的后端。`ssh-agent` 运行时会自动 fork 到后台，然后打印出其所需的环境变量。如

    $ ssh-agent

    SSH_AUTH_SOCK=/tmp/ssh-vEGjCM2147/agent.2147; export SSH_AUTH_SOCK;
    SSH_AGENT_PID=2148; export SSH_AGENT_PID;
    echo Agent pid 2148;

要使用这些环境变量，请使用 `eval` 命令来运行它。

    $ eval $(ssh-agent)

    Agent pid 2157

`ssh-agent` 运行起来之后，您还需要将您的私钥加入它的缓存。

    $ ssh-add ~/.ssh/id_ed25519

    Enter passphrase for /home/user/.ssh/id_ed25519:
    Identity added: /home/user/.ssh/id_ed25519 (/home/user/.ssh/id_ed25519)

如果您的私钥已加密，`ssh-add` 会提示您输入密码短语。一旦您的私钥被成功添加到 agent，您不需要再输入密码短语就能够建立 SSH 连接了。

提示： 要让包括 `git` 在内的所有 `ssh` 客户端在第一次使用时就把密钥存储在 agent 中，请将配置 `AddKeysToAgent yes` 添加到 `~/.ssh/config`。其他可能的值有 `confirm`、`ask` 和 `no`（默认）。

为了自动启动 agent 并确保同一时间只有一个 `ssh-agent` 进程在运行，添加以下内容到您的 `~/.bashrc`：

    if ! pgrep -u "$USER" ssh-agent > /dev/null; then
        ssh-agent -t 1h > "$XDG_RUNTIME_DIR/ssh-agent.env"
    fi
    if [[ ! "$SSH_AUTH_SOCK" ]]; then
        source "$XDG_RUNTIME_DIR/ssh-agent.env" >/dev/null
    fi

如果还没有 `ssh-agent` 进程在运行的话，该脚本会自动启动一个，并保存其输出。如果已经有一个在运行了，就会读取缓存的 `ssh-agent` 输出并执行之，从而设置必要的环境变量。解密密钥的存活时间设置为1小时。

本节后面会介绍几种 `ssh-agent` 的前端及其他 agent，也能够避免这一问题。

#### 用 systemd user 启动 ssh-agent

通过 Systemd (简体中文)/User (简体中文) 机制来启动 agent 同样可行。如果想要在登录时运行 SSH agent 而不论 X 是否在运行的话，可用此法。

    ~/.config/systemd/user/ssh-agent.service

    [Unit]
    Description=SSH key agent

    [Service]
    Type=simple
    Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket
    # DISPLAY required for ssh-askpass to work
    Environment=DISPLAY=:0
    ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK

    [Install]
    WantedBy=default.target

然后在您的登录 shell 初始化文件（如 `~/.bash_profile`）中 export 环境变量 `SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/ssh-agent.socket"`。

最后，加上 `--user` 标志 enable 或 start 服务。

注意： 如果您使用 GNOME，该环境变量默认会被覆盖。见 GNOME (简体中文)/Keyring (简体中文)#禁用钥匙环的守护进程组件。
提示： 当按上述方法通过 systemd 启动 agent 时，可以自动输入您默认密钥的密码短语并将其添加到 agent。详见 systemd-user-pam-ssh。

#### ssh-agent 作为包装程序运行

加州大学伯克利分校实验室的这份 ssh-agent 教程还介绍了一种随每个 X 会话启动 `ssh-agent` 的方法。基本用法是，如果您使用命令 `startx` 正常启动 X，您可以改成像这样在前面加上 `ssh-agent`：

    $ ssh-agent startx

您也可以在 `.bash_aliases` 或等同文件中设置别名，就不用再费心了：

    alias startx='ssh-agent startx'

这样做可以避免多个会话中存在多余的 `ssh-agent` 进程。整个 X 会话中只会有一个 `ssh-agent` 在运行。

注意： 作为调用 `ssh-agent startx` 的替代方案，可以将 `eval $(ssh-agent)` 添加到 `~/.xinitrc`。

见下文有关协同使用 x11-ssh-askpass 与 ssh-add 的说明了解如何立即将密钥添加到 agent。

### GnuPG Agent

gpg-agent 提供对 OpenSSH agent 的模拟。必要配置见 GnuPG (简体中文)#SSH agent。

### Keychain

Keychain 是一个用来方便管理 SSH 密钥对的程序，它能尽最大努力去减少对用户的打扰。实际上，它就是一个 shell 脚本，驱动 `ssh-agent` 或者 `gpg-add` 来工作。一个值得注意的特性是，keychain 在多个会话中重复使用同一个 `ssh-agent` 进程。这意味着您只需要在机器启动时输入一次密码短语即可。

#### 安装

安装 keychain 软件包。

#### 配置

警告： 2015-09-26时情况，`-Q, --quick` 选项存在预期之外的副作用，导致 keychain 在重新登陆时切换到新产生的 ssh-agent （至少在使用 GNOME 的系统上如此），使您不得不重新添加所有先前注册的密钥。

将类似以下的行加入到您 shell 的 配置文件中，例如若您使用Bash：

    ~/.bashrc

    eval $(keychain --eval --quiet id_ed25519 id_rsa ~/.keys/my_custom_key)

注意： 之所以使用 `~/.bashrc` 而非上游建议的 `~/.bash_profile`，是因为在 Arch 上登录与非登录 shell 都会使用它，因此同样适用于文字与图形环境。关于二者之间差异的更多信息见Bash (简体中文)#调用。

上例当中，

- `--eval` 开关可以输出供 `eval` 命令执行的行；这样可以设置必要的环境变量，让 SSH 客户端能够找到您的 agent。
- `--quiet` 会把输出限制为只包含警告、错误及用户提示。

如例子所示，可在命令行中指定多个密钥。keychain 默认会在 `~/.ssh/` 目录中寻找密钥对，但对于位于非标准位置的密钥可以使用绝对路径。也可使用 `--confhost` 选项告知 keychain 在 `~/.ssh/config` 中寻找为特定主机定义的 `IdentityFile` 设置，并使用这些路径来定位密钥。

关于如何为其他 shell 设置keychain的详情见 `keychain --help` 或者 keychain(1)。

要测试 keychain，只需打开一个终端模拟器，或注销当前会话再重新登录。它应该会使用 `$SSH_ASKPASS` 中设置的程序或在终端上提示您输入指定私钥的密码短语（如果有）。

因为 keychain 重新使用之前的登录中的 ssh-agent 进程，所以您再次登录或打开新终端时应该就无需输入密码短语了。每当您重启机器时，您才会被要求再次输入密码短语。

#### 提示

- keychain 需要公钥文件与相应私钥存放在同一目录下，带有 `.pub` 扩展名。如私钥为符号链接，公钥与符号链接一起存放或与符号链接目标在同一目录都能找得到（该功能需要系统上有 `readlink` 命令）。

- 要禁用图形提示，始终在终端中输入密码短语，请使用 `--nogui` 选项。举例来说，这样可以从密码管理器中复制粘贴长密码。

- 如果您想要等到需要时再提示解锁密钥，而不是一开始就提示，请使用 `--noask` 选项。

注意： Keychain 能够以同样的方式管理 GPG 密钥。它默认只会尝试启动 ssh-agent，但使用 `--agents` 选项可以改变这一行为，例如 `--agents ssh,gpg`。见 keychain(1)。

### envoy

注意： 注意: envoy作者已经不再维护该项目，请慎重使用

Envoy 算是 keychain 的一个替代品，您可以从 官方软件仓库 下载安装 envoyAUR，或者从 AUR 安装 envoy-gitAUR。

安装完成之后，使用以下命令启用 envoy 套接字 (socket)：

    # systemctl enable envoy@ssh-agent.socket

加入您的外壳 rc 文件：

     envoy -t ssh-agent -a ssh_key
     source <(envoy -p)

如果您的私钥为 `~/.ssh/id_rsa`, `~/.ssh/id_dsa`, `~/.ssh/id_ecdsa`，或者 `~/.ssh/identity`，则不需要 `-a ssh_key` 参数。

#### 利用 KDE 电子钱包存储密码短语并和 envoy 配合工作

如果您的密码短语很长很复杂，那记忆起来是有点痛苦。您可以让 KDE 电子钱包来为您记住密码短语哦！

安装位于 官方软件仓库 的 ksshaskpass 和 kwalletmanager，然后按照上文介绍的方法启用 envoy 套接字。

添加一个脚本到 `~/.kde4/Autostart/`，输入以下内容：

    ~/.kde4/Autostart/ssh-agent.sh

    #!/bin/sh
    envoy -t ssh-agent -a ssh_key

记得加上可执行权限：

    $ chmod +x ~/.kde4/Autostart/ssh-agent.sh

添加一个脚本到 `~/.kde4/env/`，加入以下内容：

    ~/.kde4/env/ssh-agent.sh

    #!/bin/sh
    eval $(envoy -p)

同样不要忘记加上可执行权限：

    $ chmod +x ~/.kde4/env/ssh-agent.sh

当您登录到 KDE 桌面环境时，它就会自动运行脚本 `ssh-agent.sh`。这样子就能够调用 `ksshaskpass`，当 `envoy` 调用 `ssh-agent` 时，`ksshaskpass` 就会请求您输入 KDE 电子钱包的密码了。而 KDE 电子钱包则会保存您的密码短语，在 `ssh-agent` 需要的时候由 KDE 电子钱包提供。

### pam_ssh

pam_ssh 项目为 SSH 私钥提供了一个 插入式验证模块 (PAM)。当您的密码短语与系统登录用户密码相同的时候，可以为您减去再次输入密码的麻烦。开机登录时，您需要输入您的登录密码，如有需要，还要输入 ssh 密钥的密码短语。您成功登录系统之后，`ssh-agent` 则会在整个会话期间缓存您已解密的私钥。

要在 tty 模式下使用 pam_ssh，您需要安装位于 AUR 的 pam_sshAUR 。

注意： pam_ssh 2.0 要求所有用于认证的私钥文件必须保存在 `~/.ssh/login-keys.d/` 下。

您可以为您的私钥文件创建一个软链接，并放到 `~/.ssh/login-keys.d/`：

    $ mkdir ~/.ssh/login-keys.d/
    $ cd ~/.ssh/login-keys.d/
    $ ln -s ../id_rsa

注意将上述例子中的 `id_rsa` 换成您对应的私钥文件。

编辑 `/etc/pam.d/login`，将下面例子中高亮加粗的那几行加进去。请注意配置内容的顺序会影响到登录行为，应当按照例子中的来。

警告： PAM 配置丢失会导致系统中所有的用户被锁定。因此，您必须在保存任何 PAM 配置并生效之前，做好配置文件的备份，准备好一份 live CD，以防万一用户被锁定时还有办法恢复原样。您可以参阅 IBM 的 这篇文章 详细了解一下 PAM 的配置。

    /etc/pam.d/login

    #%PAM-1.0

    auth       required     pam_securetty.so
    auth       requisite    pam_nologin.so
    auth       include      system-local-login
    auth       optional     pam_ssh.so        try_first_pass
    account    include      system-local-login
    session    include      system-local-login
    session    optional     pam_ssh.so

在上面的例子中，登录认证初始化进程如平常那样启动，用户要输入登录密码。`try_first_pass` 选项传递给 `pam_ssh` 模块，它会尝试使用用户密码作为密码短语去解密 `~/.ssh/login-keys.d/` 下的私钥。如果用户密码与密码短语一致，那么私钥可以被解密，用户就无需再次输入相同的密码。如果两者不同，ssh_pam 模块会在用户正确输入登录密码之后输入密码短语。`optional` 可以保证 `~/.ssh/login-keys.d/` 下没有私钥时，用户也能够正常登录系统。这种情况下，ssh_pam 模块对于没有私钥的用户来说就等于无。

如果您使用其他方式登录，比如使用登录管理器 SLiM (简体中文) 或者 XDM (简体中文)，您必须按照类似的方法来编辑 PAM 配置文件，才能正常工作。`/etc/pam.d/` 目录下保存有默认的配置文件，您可以参考默认配置文件来进行配置。

#### pam_ssh 已知问题

pam_ssh 并不广泛使用，其提供的文档也比较少。您应该注意一下该软件包的一些使用限制，比如：

- pam_ssh < 2.0 不支持 ECDSA，您必须使用 RSA 或者 DSA。
- pam_ssh 调用的 `ssh-agent` 进程仅限于当前会话，不能在多个会话中共享。上文提到的 keychain 前端可以避免这个问题。

### GNOME Keyring

如果您使用 Gnome，您也可以使用 Gnome 钥匙圈 (GNOME Keyring) 作为 SSH agent。详情请参考 GNOME Keyring。

## 疑难排解

如果您的 SSH 服务器忽略了您的 SSH 密钥对，您需要检查一下相关文件的权限是否正确。

本地机器上：

    $ chmod 700 ~/
    $ chmod 700 ~/.ssh
    $ chmod 600 ~/.ssh/id_ecdsa

服务器上：

    $ chmod 700 ~/
    $ chmod 700 ~/.ssh
    $ chmod 600 ~/.ssh/authorized_keys

如果这样还不能解决您的问题，您可以试试将 `sshd_config` 中的 `StrictModes` 设为 `no`。如果将 `StrictModes` 关闭就能够顺利认证的话，说明相关文件的权限还没有改对。

提示： 为保证安全，记得把 `StrictModes` 设为 `yes`。

请确认您的 SSH 服务器支持您所使用的密钥类型， 可以实施 RSA 或者 DSA。某些服务器可能不支持 ECDSA 密钥。

如果还不行，打开 sshd 的 debug 模式，查看连接时的日志输出，查找原因吧：

    # /usr/bin/sshd -d

### 使用 kdm

KDM 并不能直接启动 `ssh-agent`，KDM 要用 kde-agent[断开的链接：package not found] 来启动 `ssh-agent`，但是 `kde-agent` 自 20140102-1 开始已经被 移除[失效链接 2020-07-28 ⓘ]。

为了让 KDE 启动时启动 `ssh-agent`，您可以创建一个脚本用于登录时启动 `ssh-agent`，还有一个脚本用于注销时杀死进程：

    echo -e '#!/bin/sh\n[ -n "$SSH_AGENT_PID" ] || eval "$(ssh-agent -s)"' > ~/.kde4/env/ssh-agent-startup.sh
    echo -e '#!/bin/sh\n[ -z "$SSH_AGENT_PID" ] || eval "$(ssh-agent -k)"' > ~/.kde4/shutdown/ssh-agent-shutdown.sh
    chmod 755 ~/.kde4/env/ssh-agent-startup.sh ~/.kde4/shutdown/ssh-agent-shutdown.sh

Category:

- Secure Shell (简体中文)

Hidden categories:

- Pages with dead links
- Pages or sections flagged with Template:Expansion
- Pages with broken package links