SSH 证书颁发机构和密钥签名
先决条件¶
- 能够使用命令行工具
- 从命令行管理内容
- 具备 SSH 密钥生成经验会有帮助,但非必需
- 对 SSH 和公钥基础设施有基本了解会有帮助,但非必需
- 运行 sshd 守护进程的服务器。
简介¶
如果无法验证远程主机密钥的指纹,则初始 SSH 连接是不安全的。使用证书颁发机构签名远程主机的公钥,可以确保信任 CA 的每个用户进行初始连接的安全。
CA 还可以用于签名用户 SSH 密钥。无需将密钥分发到每个远程主机,只需一个签名即可授权用户登录多个服务器。
目标¶
- 提高 SSH 连接的安全性。
- 改进入职流程和密钥管理。
备注¶
- Vim 是作者选择的文本编辑器。使用其他文本编辑器,如 nano 或其他编辑器,也是完全可以接受的。
- 使用
sudo
或root
意味着提升了权限。
初始连接¶
为了确保初始连接的安全,您需要事先了解密钥指纹。您可以优化和集成此部署过程以用于新主机。
显示远程主机的密钥指纹
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