一、ssh是什么
SSH(Secure Shell)是一个提供数据通信安全、远程登录、远程指令执行等功能的安全网络协议,最初提出目的是替代非安全的Telnet、rsh、rexec等远程Shell协议。之后SSH发展了两个大版本SSH-1和SSH-2。
二、ssh的发展历史
1. 1.x版本
1995年,芬兰赫尔辛基理工大学的研究员Tatu Ylönen设计了ssh协议的第一个版本(现称SSH-1),目标是取代早期的rlogin, TELNET, ftp和rsh这些不安全的协议。同年七月,他以免费软件的形式发布了这个协议的一个实现,并迅速流行起来。
1995年12月,Ylonen创建了SSH Communications Security来发展和商业化SSH,SSH软件的原始版本使用了各种免费软件,如Gun libgmp,但是后来由SSH Communications Security发布的版本逐渐演化为私有软件。
2. 2.x版本
“Secsh”,IETF工作小组的官方互联网工程任务组,负责SSH协议的第二版本。在2006年,他们发布了SSH协议修订版,即SSH-2,并被采纳为标准。该版本与SSH-1不兼容,但在安全性和特性方面都优于SSH-1。更好的安全性,例如,通过Diffie-Hellman密钥交换和通过信息认证码进行强大的完整性检查。SSH-2的新特性,增加了在单个SSH连接上运行任意数量的shell会话的能力。由于SSH-2比SSH-1更有优势而且受欢迎,一些实现如Lsh和Dropbear仅支持SSH-2协议。
3. 1.99版本
在2006年1月,在2.1版本建立之后,RFC 4253指定一个支持ssh2.0以及兼容之前版本的SSH服务的协议版本为1.99。这不是一个实际的版本,而是一种识别向后兼容性的方法。
4. OpenSSH and OSSH
早在1999年,很多开发人员都很想要一个可用的免费版本,他们找到了SSH源程序的1.2.12发布版本,这是它在开放源码许可下发布的最后一个版本,Bjorn Gronvall的OSSH就是后来以这个为基础发展出来的。不久,OpenBSD开发人员在Gronvall的代码的基础上开了一个分支,并对其进行了大量的工作后,创建了OpenSSH,这是由2.6版本的OpenBSD发布的。在这个版本中,一个“可移植性”分支被创建了,目的是让OpenSSH能在其他操作系统中使用。
到了2005年,OpenSSH已经是最流行的SSH实现了,没有之一,在很多操作系统中都默认安装OpenSSH。与此同时,OSSH却过时了。OpenSSH一直在维护并支持SSH-2协议,在7.6版本的OpenSSH代码库中,去除了对SSH-1的支持。
三、ssh的主要特性
1. 加密
避免数据内容泄漏
2. 通信的完整性
避免数据被篡改,以及发送或接受地址伪装(检查数据是否被篡改,数据是否来自发送者而非攻击者) SSH-2 通过 MD5 和 SHA-1 实现该功能,SSH-1 使用 CRC-32
3. 认证
识别数据发送者和接收者身份 客户端验证SSH服务端的身份:防止攻击者仿冒SSH服务端身份,避免中间人攻击和重定向请求的攻击;OpenSSH 通过在 know-hosts 中存储主机名和 host key 对服务端身份进行认证 服务端验证请求者身份:提供安全性较弱的用户密码方式,和安全性更强的 per-user public-key signatures;此外SSH还支持与第三方安全服务系统的集成,如 Kerberos等
4. 授权
用户访问控制
5. 转发
可以通过SSH为Telnet、FTP等提供通信安全保障,支持三种类型的转发操作:Port Forwarding,X Forwarding,Agent Forwarding
四、ssh基本框架
SSH协议框架中最主要的部分是三个协议:
- 传输层协议(The Transport Layer Protocol)提供服务器认证,数据机密性,信息完整性 等的支持;
- 用户认证协议(The User Authentication Protocol) 则为服务器提供客户端的身份鉴别;
- 连接协议(The Connection Protocol) 将加密的信息隧道复用成若干个逻辑通道,提供给更高层的应用协议使用; 各种高层应用协议可以相对地独立于SSH基本体系之外,并依靠这个基本框架,通过连接协议使用SSH的安全机制。
同时SSH协议框架中还为许多高层的网络安全应用协议提供扩展的支持。它们之间的层次关系可以用如下图来表示:
五、ssh的加密
1. ssh加密方式
SSH从安全和性能两方面综合考虑,结合使用了 Public Key/Private key(公钥/私钥) 和 Secret Key(密钥)。
- Public Key/Private key:非对称加密,安全,但效率低,不适合大规模进行数据的加密和解密操作
- Secret Key:对称机密,高效,但安全性相对较低,Key的分发尤其不方便
对密码学基础知识和数字签名了解,可以参考阮一峰的博文
2. ssh中的key
名称 | 生命周期 | 创建 | 类型 | 描述 |
Host Key | 持久化 | 服务端 | Public Key | Host Key是服务器用来证明自己身份的一个永久性的非对称密钥 |
User Key | 持久化 | 用户 | Public Key | User Key 是客户端用来证明用户身份的一个永久性的非对称密钥(一个用户可以有多个密钥/身份标识) |
Server Key | 默认为1小时 | 服务端 | Public Key | Server Key 是SSH-1协议中使用的一个临时的非对称密钥,每隔一定的间隔(默认是一个小时)都会在服务器重新生成。用于对Session Key进行加密(仅SSH-1协议有,SSH-2对其进行了增强,这里Server Key作为一个概念便于在流程中进行描述) |
Session Key | 客户端 | 会话(Session) | Secret Key | Session Key是一个随机生成的对称密钥,用户SSH客户端和服务器之间的通信进行加密,会话结束时,被销毁 |
ssh框架图:
六、安全连接的建立过程
SSH处理过程可以分解成几个主要阶段:
- 协议协商阶段
- 服务端认证阶段
- 客户端认证阶段
- 数据传输阶段
每个阶段均涉及到客户端与服务端的多次交互,通过这些交互过程完成包括证书传输、算法协商、通道加密等过程。
1. 协议协商阶段
1)服务端打开服务端口(默认为22),等待客户端连接
2)客户端发起TCP连接请求,服务端接收到该请求后,向客户端发送包括SSH协议版本信息
3)客户端接根据该版本信息与自己的版本,决定将要使用的SSH版本,并向服务端发送选用的SSH版本信息
4)服务端检查是否支持客户端的决定使用的SSH版本
至此,双方完成协议协商。如果该过程中,客户端或服务端发送SSH版本无法兼容,任何一方都可以断开连接。
2. 服务端认证阶段
完成协议协商阶段后,客户端与服务端已经建立明文的通信通道,之后进入服务端认证阶段。
SSH协议中没有明确的服务端认证过程,而通过一系列的服务端与客户端的交互来确定服务端的身份,该过程还会完成Host Key、User Key、Session Key等在客户端与服务端之间的传输。
1)建立连接后,服务端向客户端发送:
- Host Key:用于认证服务端的身份
- Server Key:用于帮助建立安全的数据传输通道
- 8字节的随机数,即检测字节(check bytes):客户端通过在下一次响应中包含该随机数,防止IP地址欺诈
- 服务端支持的加密算法、压缩方式和认证方式
这个时候,客户端和服务端使用Host Key、Server Key和检测字节生成一个128位的MD5值,作为此次会话的session id。
2)客户端在接收到服务端Host Key后,会检查自己的knows host数据库中(一般为~/.ssh/know_hosts文件),是否已经包含当前服务端的Host Key,如果有则继续下一步;如果没有或包含当前服务端的其他Host Key,则由用户决定是否信任该服务端,或终止当前连接。
The authenticity of host 'ssh-server.example.com (12.18.429.21)' can't be established. RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d. Are you sure you want to continue connecting (yes/no)?
如果客户端拒绝接受这个主机密钥,那么连接就中止了。否则,继续。
3)客户端向服务端发送session Key
出于性能考虑,SSH采用对称加密(Secret Key),对实际通信内容进行加密,即Session Key。因此Session Key的安全尤为重要,一旦Session Key泄漏给攻击者,那所有的通信数据都可能被攻击者截获。由于当前通道还是采用明文方式,客户端采用Host Key和Server Key对Session Key进行两次加密来加强安全性,同时还会发送检测字节和所选定的算法(这些算法是从第1步中服务器支持的算法列表中挑选出来的)。
4)服务端得到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安全进一步增强)。
3. 客户端认证阶段
SSH提供多种客户端认证方式。
SSH-1:
- Password
- Public Key
- Kerberos
- Rhosts && RhostsRSA
- TIS
SSH-2:
- Password
- Public Key
- hostbased 在SSH-2中考虑Rhosts存在安全漏洞,废弃了这种方式。
这里之讨论我们经常使用的的Password和Public Key方式。
此时安全通道已经及建立,之后的所有内容都通过Session Key加密后进行传输。
1)Password
Password 方式既客户端提供用户和密码,服务端对用户和密码进行匹配,完成认证。类Unix系统中,如 OpenSSH 的框架,一般通过系统的本地接口完成认证。
Password 的优势是简单,无需任何而外的配置就可以使用。缺点密码不便于记忆,过于简单的密码容易被暴力破解。
2)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值进行比较,完成对客户端的认证。
4. 数据传输阶段
该阶段通过Session Key提供的对称加密(Secret Key)算法,保证需要传输的任何数据的安全。
整体过程如下:
七、参考
1. ssh(安全外壳协议)
2. Secure Shell
3. 《The Secure Shell: The Definitive Guide》
4. SSH 详解
5. SSH原理简介
6. SSH协议介绍
(完)