ssh(6)公钥交换过程
在 Linux 中,SSH(Secure Shell)使用公钥认证是一种安全且常见的身份验证方式。公钥认证依赖于非对称加密技术,涉及一对密钥:公钥和私钥。
1. 前提条件
- 客户端:用户在本地生成了一对密钥(公钥和私钥),通常使用
ssh-keygen
命令。- 私钥(例如
~/.ssh/id_rsa
):保存在客户端本地,需妥善保管。 - 公钥(例如
~/.ssh/id_rsa.pub
):可以共享给服务器。
- 私钥(例如
- 服务器:服务器上需要配置接受公钥认证,并且用户的公钥已添加到服务器的
~/.ssh/authorized_keys
文件中。
2. SSH 公钥认证过程
当客户端尝试通过 SSH 连接到服务器(例如 ssh user@server
)并使用公钥认证时,会经历以下步骤:
步骤 1:建立 TCP 连接
- 客户端与服务器在默认端口(22)上建立 TCP 连接。
步骤 2:协议版本协商
- 客户端和服务器交换 SSH 协议版本信息(例如 SSH-2.0),确认双方支持的协议版本。
如果没有一致的协议,需要添加兼容协议
步骤 3:密钥交换和会话加密
- 双方通过 Diffie-Hellman(或类似算法)协商一个对称会话密钥,用于加密后续通信。
- 这部分不直接涉及公钥认证,而是为通信通道提供加密。
步骤 4:客户端发起认证请求
- 客户端向服务器表明希望使用公钥认证(
publickey
方法)。 - 客户端发送其公钥的标识(而不是完整公钥),询问服务器是否接受该公钥。
步骤 5:服务器验证公钥
- 服务器检查用户主目录下的
~/.ssh/authorized_keys
文件,看是否存在与客户端提供的公钥标识匹配的公钥。 - 如果找到匹配的公钥,服务器生成一个随机挑战(challenge),使用客户端的公钥对其加密,并将加密后的挑战发送给客户端。
步骤 6:客户端解密挑战
- 客户端收到加密的挑战后,使用对应的私钥解密该挑战。
- 客户端将解密后的结果(或其哈希值,取决于协议实现)发送回服务器。
步骤 7:服务器验证响应
- 服务器验证客户端返回的结果是否与原始挑战匹配。
- 如果匹配,证明客户端拥有与公钥对应的私钥,认证成功。
- 如果不匹配,认证失败,服务器可能会拒绝连接或尝试其他认证方法(如密码认证)。
步骤 8:会话建立
- 认证成功后,双方使用协商好的会话密钥加密通信,进入交互式会话或执行命令。
3. 关键点
- 安全性:私钥从不离开客户端,服务器仅存储公钥,因此即使服务器被攻破,也无法直接获取私钥。
- 文件权限:服务器上的
~/.ssh/authorized_keys
和客户端的私钥文件需要严格的权限设置(通常为 600 或 644),否则 SSH 会拒绝认证。 - 调试:如果认证失败,可以使用
ssh -v
查看详细日志,检查问题所在。
4. 实际操作示例
客户端生成密钥对:
1 | ssh-keygen -t rsa -b 4096 |
- 生成后,公钥在
~/.ssh/id_rsa.pub
,私钥在~/.ssh/id_rsa
。
将公钥上传到服务器:
1 | ssh-copy-id user@server |
或者手动将公钥追加到服务器的 ~/.ssh/authorized_keys
。
连接测试:
1 | ssh user@server |
如果配置正确,将无需输入密码即可登录。
5. 总结
SSH 公钥认证通过非对称加密和挑战-响应机制,确保了客户端身份的安全验证。整个过程依赖于密钥对的正确生成、分发和存储,以及服务器的配置支持。这种方式比密码认证更安全,尤其适合自动化脚本或远程管理场景。