跳至内容

SSH 证书颁发机构和密钥签名

先决条件

  • 能够使用命令行工具
  • 从命令行管理内容
  • 具备 SSH 密钥生成经验会有帮助,但非必需
  • 对 SSH 和公钥基础设施有基本了解会有帮助,但非必需
  • 运行 sshd 守护进程的服务器。

简介

如果无法验证远程主机密钥的指纹,则初始 SSH 连接是不安全的。使用证书颁发机构签名远程主机的公钥,可以确保信任 CA 的每个用户进行初始连接的安全。

CA 还可以用于签名用户 SSH 密钥。无需将密钥分发到每个远程主机,只需一个签名即可授权用户登录多个服务器。

目标

  • 提高 SSH 连接的安全性。
  • 改进入职流程和密钥管理。

备注

  • Vim 是作者选择的文本编辑器。使用其他文本编辑器,如 nano 或其他编辑器,也是完全可以接受的。
  • 使用 sudoroot 意味着提升了权限。

初始连接

为了确保初始连接的安全,您需要事先了解密钥指纹。您可以优化和集成此部署过程以用于新主机。

显示远程主机的密钥指纹

user@rocky-vm ~]$ ssh-keygen -E sha256 -l -f /etc/ssh/ssh_host_ed25519_key.pub 
256 SHA256:bXWRZCpppNWxXs8o1MyqFlmfO8aSG+nlgJrBM4j4+gE no comment (ED25519)

从客户端建立初始 SSH 连接。此时将显示密钥指纹,可以与先前获取的指纹进行比较。

[user@rocky ~]$ ssh user@rocky-vm.example.com
The authenticity of host 'rocky-vm.example (192.168.56.101)' can't be established.
ED25519 key fingerprint is SHA256:bXWRZCpppNWxXs8o1MyqFlmfO8aSG+nlgJrBM4j4+gE.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])?

创建证书颁发机构

创建 CA(私钥和公钥),并将公钥放在客户端的 known_hosts 文件中,以识别属于 example.com 域的所有主机。

[user@rocky ~]$ ssh-keygen -b 4096 -t ed25519 -f CA
[user@rocky ~]$ echo '@cert-authority *.example.com' $(cat CA.pub) >> ~/.ssh/known_hosts

其中

  • -b:密钥长度(字节)
  • -t:密钥类型:rsa、ed25519、ecdsa 等...
  • -f:输出密钥文件

或者,您可以通过编辑 SSH 配置文件 /etc/ssh/ssh_config 来全局指定 known_hosts 文件。

Host *
    GlobalKnownHostsFile /etc/ssh/ssh_known_hosts

签名公钥

创建用户 SSH 密钥并签名

[user@rocky ~]$ ssh-keygen -b 4096 -t ed2119
[user@rocky ~]$ ssh-keygen -s CA -I user -n user -V +55w  id_ed25519.pub

通过 scp 获取服务器的公钥并签名

[user@rocky ~]$ scp user@rocky-vm.example.com:/etc/ssh/ssh_host_ed25519_key.pub .
[user@rocky ~]$ ssh-keygen -s CA -I rocky-vm -n rocky-vm.example.com -h -V +55w ssh_host_ed25519_key.pub

其中

  • -s:签名密钥
  • -I:用于登录目的的标识证书的名称
  • -n:标识与证书关联的名称(主机或用户,一个或多个)(如果未指定,证书对所有用户或主机均有效)
  • -h:将证书定义为主机密钥,而非客户端密钥
  • -V:证书的有效期

建立信任

复制远程主机的证书,以便远程主机在连接时与公钥一起呈现。

[user@rocky ~]$ scp ssh_host_ed25519_key-cert.pub root@rocky-vm.example.com:/etc/ssh/

将 CA 的公钥复制到远程主机,使其信任由 CA 签名的证书。

[user@rocky ~]$ scp CA.pub root@rocky-vm.example.com:/etc/ssh/

/etc/ssh/sshd_config 文件添加以下行,以指定服务器先前复制的密钥和证书,并信任 CA 来识别用户。

[user@rocky ~]$ ssh user@rocky-vm.example.com
[user@rocky-vm ~]$ sudo vim /etc/ssh/sshd_config
HostKey /etc/ssh/ssh_host_ed25519_key
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
TrustedUserCAKeys /etc/ssh/CA.pub

重新启动服务器上的 sshd 服务

[user@rocky-vm ~]$ systemctl restart sshd

测试连接

known_hosts 文件中移除远程服务器的指纹,并通过建立 SSH 连接来验证设置。

[user@rocky ~]$ ssh-keygen -R rocky-vm.example.com
[user@rocky ~]$ ssh user@rocky-vm.example.com

密钥撤销

撤销主机或用户密钥可能对整个环境的安全至关重要。因此,存储先前签名的公钥以便以后撤销它们非常重要。

创建空的撤销列表并撤销 user2 的公钥

[user@rocky ~]$ sudo ssh-keygen -k -f /etc/ssh/revokation_list.krl
[user@rocky ~]$ sudo ssh-keygen -k -f /etc/ssh/revokation_list.krl -u /path/to/user2_id_ed25519.pub

将撤销列表复制到远程主机,并在 sshd_config 文件中指定它。

[user@rocky ~]$ scp /etc/ssh/revokation_list.krl root@rocky-vm.example.com:/etc/ssh/
[user@rocky ~]$ ssh user@rocky-vm.example.com
[user@rocky ~]$ sudo vim /etc/ssh/sshd_config

以下行指定了撤销列表

RevokedKeys /etc/ssh/revokation_list.krl

重新启动 SSHD 守护进程以加载配置是必需的。

[user@rocky-vm ~]$ sudo systemctl restart sshd

User2 被服务器拒绝

[user2@rocky ~]$ ssh user2@rocky-vm.example.com
user2@rocky-vm.example.com: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

也可以撤销服务器密钥。

[user@rocky ~]$ sudo ssh-keygen -k -f /etc/ssh/revokation_list.krl -u /path/to/ssh_host_ed25519_key.pub

/etc/ssh/ssh_config 中的以下行全局应用主机撤销列表。

Host *
        RevokedHostKeys /etc/ssh/revokation_list.krl

尝试连接到该主机将导致以下结果。

[user@rocky ~]$ ssh user@rocky-vm.example.com
Host key ED25519-CERT SHA256:bXWRZCpppNWxXs8o1MyqFlmfO8aSG+nlgJrBM4j4+gE revoked by file /etc/ssh/revokation_list.krl

维护和更新撤销列表很重要。您可以自动化此过程,以确保所有主机和用户都能访问最新的撤销列表。

结论

SSH 是管理远程服务器最有价值的协议之一。实施证书颁发机构可能很有帮助,尤其是在拥有大量服务器和用户的更大环境中。维护撤销列表很重要。它可以轻松撤销受损的密钥,而无需替换整个关键基础设施。

作者:Julian Patocki

贡献者:Steven Spencer, Ganna Zhyrnova