over 5 years ago

SSH对于大多数同学都不陌生,目前主流的云服务提供上也是通过SSH来提供链接的安全保障,比如AWS通过使用下载的私钥(private key)实现与EC2实例安全连接、GitHub通过上传的公钥(public key)实现基于git协议(底层使用SSH)远程库管理。

很多童鞋希望了解这些方式的背后,SSH是如何工作的:

  • SSH如何保证客户端与服务端通行的安全
  • SSH采用什么加密协议
  • SSH是通过对称加密还是非对称加密数据在传输过程的安全
  • SSH如何保证数据完整性
  • SSH的密码认证方式和密钥认证方式分别如何实现,有何差异
  • ......

这里我们对SSH的流程进行简单说明,其中会描述在SSH流程中是如何通过加密等技术解决安全和数据一致性问题,希望对解答某些童鞋的疑问和更进一步了解SSH有所帮助。

对密码学基础知识和数字签名了解,可以参考阮一峰的博文

SSH从安全和性能两方面综合考虑,结合使用了Public Key和Secret Key。

  • Public Key:非对称加密,安全,但效率低,不适合大规模进行数据的加密和解密操作
  • Secret Key:对称机密,高效,但安全性相对较低,Key的分发尤其不方便

特性

SSH(Secure Shell)是一个提供数据通信安全、远程登录、远程指令执行等功能的安全网络协议,由芬兰赫尔辛基大学研究员Tatu Ylönen,于1995年提出,其目的是用于替代非安全的Telnet、rsh、rexec等远程Shell协议。之后SSH发展了两个大版本SSH-1和SSH-2。

SSH的主要特性

  • 加密:避免数据内容泄漏
  • 通信的完整性:避免数据被篡改,以及发送或接受地址伪装
    (检查数据是否被篡改,数据是否来自发送者而非攻击者) SSH-2通过MD5和SHA-1实现该功能,SSH-1使用CRC-32
  • 认证:识别数据发送者和接收者身份 客户端验证SSH服务端的身份:防止攻击者仿冒SSH服务端身份,避免中介人攻击和重定向请求的攻击;OpenSSH通过在know-hosts中存储主机名和host key对服务端身份进行认证 服务端验证请求者身份:提供安全性较弱的用户密码方式,和安全性更强的per-user public-key signatures;此外SSH还支持与第三方安全服务系统的集成,如Kerberos等
  • 授权:用户访问控制
  • Forwarding or tunneling to encrypt other TCP/IP-based sessions 可以通过SSH为Telnet、FTP等提供通信安全保障,支持三种类型的Forwarding操作:Port Forwarding;X Forwarding;Agent Forwarding

本文只涉及加密、通信完整性、认证三个方面内容。

几种不同的Key

首先,我们来了解一下SSH中几种不同的Key。

SSH结合使用了Public Key和Secret Key,Public Key用于在建立安全通道前在客户端和服务端之间传输Secret Key和进行身份认证;Secret Key则用来作为SSH会话的安全保证,对数据进行加密和解密。

名称 生命周期 创建 类型 描述
Host Key 持久化 服务端 Public Key 对服务端进行认证
User Key 持久化 用户 Public Key 对客户端(用户)进行认证
Server Key 默认为1小时 服务端 Public Key 用于对Session Key进行加密(仅SSH-1协议有,SSH-2对其进行了增强,这里Server Key作为一个概念便于在流程中进行描述)
Session Key 客户端 会话(Session) Secret Key 用于对传输的数据进行加密

SSH处理过程

SSH处理过程可以分解成几个主要阶段:

  • 协议协商阶段
  • 服务端认证阶段
  • 客户端认证阶段
  • 数据传输阶段

每个阶段均涉及到客户端与服务端的多次交互,通过这些交互过程完成包括证书传输、算法协商、通道加密等过程。

协议协商阶段
  1. 服务端打开服务端口(默认为22),等待客户端连接
  2. 客户端发起TCP连接请求,服务端接收到该请求后,向客户端发送包括SSH协议版本信息
  3. 客户端接根据该版本信息与自己的版本,决定将要使用的SSH版本,并向服务端发送选用的SSH版本信息
  4. 服务端检查是否支持客户端的决定使用的SSH版本

至此,双方完成协议协商。如果该过程中,客户端或服务端发送SSH版本无法兼容,任何一方都可以断开连接。

服务端认证阶段

完成协议协商阶段后,客户端与服务端已经建立明文的通信通道,之后进入服务端认证阶段。

SSH协议中没有明确的服务端认证过程,而通过一系列的服务端与客户端的交互来确定服务端的身份,该过程还会完成Host Key、User Key、Session Key等在客户端与服务端之间的传输。

  1. 建立连接后,服务端向客户端发送:
    • Host Key:用于认证服务端的身份
    • Server Key:用于帮助建立安全的数据传输通道
    • 8字节的随机数:客户端通过在下一次响应中包含该随机数,防止IP地址欺诈
    • 服务端支持的加密算法、压缩方式和认证方式

这个时候,客户端和服务端使用Host Key、Server Key和8字节的随机数生成一个128位的MD5值,作为此次会话的session id。

  1. 客户端在接收到服务端Host Key后,会检查自己的knows host数据库中(一般为~/.ssh/know_hosts文件),是否已经包含当前服务端的Host Key,如果有则继续下一步;如果没有或包含当前服务端的其他Host Key则,有用户决定是否信任该服务端,或终止当前连接。

  2. 客户端向服务端发送session Key

出于性能考虑,SSH采用对称加密(Secret Key),对实际通信内容进行加密,即Session Key。因此Session Key的安全尤为重要,一旦Session Key泄漏给攻击者,那所有的通信数据都可能被攻击者截获。
由于当前通道还是采用明文方式,客户端采用Host Key和Server Key对Session Key进行两次加密来加强安全性。

  1. 服务端得到Session Key后,客户端和服务端就可以通过Session Key对数据进行加密解密操作,到此,双方完成安全(加密)通道的建立。 Host Key和Server Key都是Public Key(非对称加密),只有通过服务端的私钥(Private Key)才能对其解密,以得到Session Key。在正式使用安全通道前,客户端要求服务端发送使用Session Key加密的确认信息,以验证服务端的身份。 为避免Session Key的泄漏,SSH还采取了其他安全措施,Session Key仅保存在内存避免其泄漏;周期性更换Server Key,默认为1小时(SSH 2对Server Key安全进一步增强)。
客户端认证阶段

SSH提供多种客户端认证方式。

SSH-1:

  • Password
  • Public Key
  • Kerberos
  • Rhosts && RhostsRSA
  • TIS

SSH-2:

  • Password
  • Public Key
  • hostbased 在SSH-2中考虑Rhosts存在安全漏洞,废弃了这种方式。

这里之讨论我们经常使用的的Password和Public Key方式。

此时安全通道已经及建立,之后的所有内容都通过Session Key加密后进行传输。

Password

Password方式既客户端提供用户和密码,服务端对用户和密码进行匹配,完成认证。类Unix系统中,如OpenSSH的框架,一般通过系统的本地接口完成认证。

Password的优势是简单,无需任何而外的配置就可以使用。缺点密码不便于记忆,过于简单的密码容易被暴力破解。

Public Key

Public Key认证的基本原理是基于分对称加密方式,分别在服务端对一段数据通过公钥进行加密,如果客户端能够证明其可以使用私钥对这段数据进行解密,则可以说明客户端的身份。因为服务端需要使用客户端生成的密钥对的公钥对数据首先加密,所以需要先将公钥存储到服务端的密钥库(Auhtorized Key)。还记得Github中使用git协议push代码前需要先添加SSH KEY吗?

下面详细介绍一个通过Public Key进行客户端认证的过程。

  1. 客户端发起一个Public Key的认证请求,并发送RSA Key的模数作为标识符。(如果想深入了解RSA Key详细 --> 维基百科
  2. 服务端检查是否存在请求帐号的公钥(Linux中存储在~/.ssh/authorized_keys文件中),以及其拥有的访问权限。如果没有则断开连接
  3. 服务端使用对应的公钥对一个随机的256位的字符串进行加密,并发送给客户端
  4. 客户端使用私钥对字符串进行解密,并将其结合session id生成一个MD5值发送给服务端。 结合session id的目的是为了避免攻击者采用重放攻击(replay attack)。
  5. 服务端采用同样的方式生成MD5值与客户端返回的MD5值进行比较,完成对客户端的认证。
数据传输阶段

该阶段通过Session Key提供的对称加密(Secret Key)算法,保证需要传输的任何数据的安全。

推荐

简单对SSH原理进行的说明,其中很多内容来自O‘RELLY的《SSH: The Secure Shell - The Definitive Guide》,如果想更深入了解SSH,这是一本非常不错的书。