SSH原理与实践(二)

主页

引言

在上一篇文章【ssh原理与实践(一)】中我们详细介绍了SSH两种常用的认证方式,在认证流程中,我们简单提到了建立安全通道的流程,安全通道的建立是客户端和服务端通信安全的基础,本文我们将主要介绍安全通道建立的流程。

本文内容组织结构如下:

  1. SSH安全通道简介
  2. SSH1安全通道的建立
  3. SSH2安全通道的建立

SSH安全通道简介

SSH协议提供了一种在不可信网络建立安全通信的方式,保证了SSH客户端和服务端在通信过程中数据的安全性。SSH建立安全通信的过程,其实就是客户端和服务端协商会话密钥的过程, 后文我们简称为密钥协商

SSH协议目前主要有SSHv1SSHv2两个版本,这两个版本在密钥协商流程上存在着较大的差异。在介绍具体协议之前,我们首先介绍下密钥协商过程中用到的几个关键密钥:

名称 生命周期 创建者 密钥类型 用途
User Key 永久 用户/客户端 非对称 客户端身份标识
Host Key 永久 管理员/服务端 非对称 服务端身份标识
Server Key 临时(定时更新) 服务端 非对称 加密会话密钥(仅用于SSH1)
Session Key 临时(会话) 客户端和服务端 对称 保密通信

说明:

  • User Key:客户端SSH公钥,由用户生成,代表SSH客户端身份,用于客户端身份认证,存储在~/.ssh/id_rsa
  • Host Key:服务端SSH公钥,由管理员生成,代表服务端身份,用于服务端身份认证,存储在/etc/ssh/ssh_host_rsa
  • Server Key:仅在SSH1中使用,定时更新(一般为一个小时),主要用于保证通信消息的前向安全, 存储在内存
  • Session Key:会话密钥与会话绑定,只在客户端和服务端本次会话中有效,用于加密通信数据。在SSH1中会话密钥为一个对称密钥,在SSH2中为一组密钥,逻辑功能上与SSH1会话密钥一致,但是提供了更高的安全性。存储在内存

上述密钥在SSH中存储和应用示意图:

  • User Key、Host Key、Server Key用于密钥协商
  • Session Key用于加密通信

SSH1安全通道的建立

SSH1密钥协商流程如下:

  1. 客户端Client访问服务端Server,触发密钥协商
  2. 客户端和服务端对SSH协议版本进行协商,并进行兼容性检查,如果不兼容,则密钥协商失败。
  3. 服务端生成Server Key和随机数,这里的Server Key用于保证前向安全,随机数用于防止重放攻击
  4. 服务端将Host Key公钥、Server Key公钥以及随机数发送给客户端,同时基于上述数据本地生成会话ID(会话ID用于标识本次会话,在【ssh原理与实践(一)】的公钥认证流程中有应用)
  5. 客户端本地生成会话ID和会话密钥(在SSH1密钥协商中,会话密钥由客户端生成,并发送给服务端)
  6. 客户端对会话密钥加密,并发送给服务端。(这里的加密用到了服务端的Server Key,由于Server Key为临时密钥,每次协商会变化,因此即使服务端Host Key被窃取,也无法恢复历史会话密钥,解密通信数据)
  7. 服务端首先使用Server Key私钥解密密文,然后使用Host Key私钥进一步解密,得到会话密钥
  8. 服务端发送确认消息,并使用会话密钥加密;客户端进行解密验证
  9. 密钥协商成功后,后续通信使用会话密钥进行加密通信

SSH2安全通道的建立

由于SSH2在安全性、扩展性以及架构上具有更大的优势,目前服务器已广泛支持SSH2版本,这里我们重点介绍下SSH2的密钥协商流程:

  1. 客户端和服务端对SSH协议版本进行协商,并进行兼容性检查,如果不兼容,则密钥协商失败。
  2. 客户端和服务端对加密套件进行协商,对后续使用的签名算法、加密算法、MAC算法进行共识。该步骤中客户端和服务端会分别发送临时随机数Cookie(Cookie用于生成会话ID)
  3. 客户端本地生成EC密钥对,并将公钥(DH密钥协商参数)发送给服务端
  4. 服务端本地生成EC密钥对,并基于客户端DH参数生成DH共享密钥(运行DH算法得到,略),最后基于DH共享密钥生成一组会话密钥,该组会话密钥又分为3组:
    • 对称加密算法的初始向量IV
    • 对称算法的密钥
    • MAC算法密钥

由于SSH2中不同方向使用的会话密钥不同,因此密钥协商一共🈶6个输出参数。

我们借助wireshark对SSH2密钥协商流程进行分析:

概览图

从上图我们可以看到,服务端和客户端正在进行SSHv2密钥协商:

  1. 首先客户端访问服务端,触发密钥协商
  2. 客户端和服务端通过Protocol消息进行版本协商,客户端支持的版本号为SSH-2.0_OpenSSH_9.0,服务端支持的版本号为SSH-2.0_OpenSSH_8.0,并且从后续流程上看,这两个实现版本是兼容的。
  3. 客户端和服务端通过Key Exchange Init消息进行加密套件协商
  4. 客户端和服务端通过Elliptic Curve Diffie-Hellman Key Exchange InitElliptic Curve Diffie-Hellman Key Exchange Reply进行了会话密钥协商和生成。
  5. 客户端和服务端通过New Keys发送确认消息并验证,声明后续进行加密通信。
  6. 客户端和服务端进行加密通信,消息类型Encrypted packet

客户端Key Exchange Init

由于Key Exchange Init成对出现,我们这里仅对Client: Key Exchange Init进行介绍,该消息主要用于加密套件协商。

从上图我们可以看到:

  1. 随机数Cookie,这里的Cookie主要辅助生成会话ID。(注:服务端也会生成随机数Cookie)
  2. 支持的加密套件,从客户端发送的加密套件列表中,我们可以看到不仅包含不同方向的加密算法MAC算法, 同时还包含压缩算法等。

客户端Elliptic Curve Diffie-Hellman Key Exchange Init

从上图我们可以了解到:

  1. DH密钥协商使用的密码算法,客户端生成的DH参数基于curve25519椭圆曲线算法
  2. 客户端DH参数, 在本次交互中,客户端主要发送了自己的DH参数, 图中显示为Q_C

服务端 Elliptic Curve Diffie-Hellman Key Exchange Reply

当服务端收到客户端的DH参数时,会本地生成自己的DH参数,并基于双方的DH参数,运行DH算法生成DH共享密钥; 最后基于DH共享密钥和协商的MAC算法,生成一组会话密钥。

从上图中我们可以分析得到:

  1. 服务端使用了curve25519生成了自己的DH参数(该算法与客户端使用的一致)
  2. 服务端返回了自己的身份公钥Host Key,同时我们也可以了解到服务端Host Key密钥类型为RSA密钥。(注:在ssh原理与实践(一)一文中,我们介绍到服务端Host Key在客户端首次访问服务器时需要人工认证。)
  3. 服务端DH参数(与客户端类似,不再赘述)
  4. 服务端数字签名,该签名值通过使用服务端Host Key私钥历史消息以及客户端和服务端的身份公钥等信息的哈希值签名得到。用于对服务端进行身份验证。
  5. 服务端发送了New Keys`确认消息,声明后续进行加密通信。(后续客户端会发送相同的消息,不再赘述)

结论

本文主要介绍了SSH密钥协商的流,并对SSH1和SSH2不同版本密钥协商的详细流程和关键参数进行了介绍。SSH2与SSH1相比,提供了更加安全的密码算法,具有更强的安全性。

同时我们也可以看到,SSH密钥协商流程与我们TLS原理与实践系列提到的TLS握手流程 (TLS密钥协商),虽然细节上差别较大,但是整体流程上是一致的。实际上SSH也有基于TLS进行实现的,但由于TLS涉及到复杂的PKI数字证书分发的复杂流程,在SSH具体应用中较笨重,未普及。

参考资料

posted @ 2023-07-22 20:48  warm3snow  阅读(674)  评论(0编辑  收藏  举报