在我刚刚学习开发和某大佬沟通时;大佬说了一句话;把你的 SSH Key 给我。我的内心是这样的;
想问什么是 SSH;又不敢问
网上搜索之后大致明白了 SSH 是一种安全协议。
SSH 为Secure Shell的缩写;由 IETF 的网络小组;Network Working Group;所制定;SSH 为建立在应用层基础上的安全协议。
SSH 是目前较可靠;专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。
SSH最初是UNIX系统上的一个程序;后来又迅速扩展到其他操作平台。SSH在正确使用时可弥补网络中的漏洞。
ssh客户端适用于多种平台。几乎所有UNIX平台—包括HP-UX、Linux、AIX、Solaris、DigitalUNIX、Irix;以及其他平台;都可运行SSH。
于是先把 Key 梭出来干活;但之后的一段时间对 SSH 只停留在使用阶段上;只知道有 Public Key 和 Private Key 这个机制;具体它是如何保证安全的;却模模糊糊不清楚。
每当使用 SSH 的时候我都在想;SSH 到底是如何保证安全的呢?既然 Public Key 加密的内容只有 Private Key 能解密;那客户端发给服务端的消息怎么解密呢?最重要的是;万一被人问倒了岂不是作为工程师的面子都没了?
现在就让我们一起开心地聊一聊 SSH 到底是怎么运作的。先抛开大家经常讲的 Public/Private Key;我们从其他角度来看看 SSH。SSH登录主要分为两个阶段;
协商客户端和服务端双方通信所使用的共享密钥;并用这个共享密钥实现后续会话过程的对称加密;使用非对称加密方式验证客户端的身份。在这一大步中;又分为以下几小步;
1.客户端发起tcp连接请求;
2.服务器返回其支持的协议版本以及服务器的公共主机密钥;该密钥用于判断服务器是否是预期的主机;
3.双方交换会话密钥;用于后续会话做对称加密。
我们可以通过下图更加形象的理解;
1.客户端联系服务端;双方沟通自己支持的 SSH 协议的版本;约定使用某个共同支持的版本。
2.服务端将自己的 Host Key 、加密方法和其他一些参数发给客户端。
3.客户端通过 Host Key 验证服务端身份;双方用服务端发来的参数和 Diffie-Hellman 算法生成 Session Key。
4.加密通道建立完成。
在这几步中;出现了两个 Key;Host Key 和 SessionKey。
Host Key 分为 Public 和 Private 两种。服务端拥有 Public Key 和 Private Key;并将 Public Key 发送给客户端。客户端用 Public Host Key 验证这台服务器确实是自己要连接的服务器后;双方使用 Diffie-Hellman 算法生成一致的 SessionKey。
Host Key 由 SSH 自行生成;不需要用户做什么。 如果客户端通过 Host Key 发现从来没有连接过这台服务器;会询问用户是否要继续连接;用户回答 yes 之后会在本地的 known_hosts 文件记录这台服务器;下次连接时客户端就不会再次询问。 由于仅靠服务端下发 Host Key 的方法无法防范中间人攻击;后来又出现了 Public Key Certificates;由一个可靠的第三方机构给服务端签发证书;从而确保了安全性。
Session Key 用于之后通讯时对消息进行加密解密。 这个 Session Key 的机制被称作 对称加密;Symmetric Encryption;;也就是两端使用的相同的 Key 来加密和解密信息。可以看出 SSH 信息的加密解密时并不是用大家自己生成的 Public/ Private Key;而是用双方都一致的 Session Key。
生成 Session Key 的步骤大致如下;
1.客户端和服务端使用沟通时的信息;协商加密算法以及一个双方都知道的数字。
2.双方各自生成只有自己才知道的 private 密码;并使用上一步中的数字进行加密;再次生成密码。
3.双方交换再次加密后的密码。
4.双方在对方发来的密码基础上;加上第二步自己的 private 密码再次加密。本次加密之后得到的结果就是在双方处都相同的 Session Key。
从这个算法中;可以看出客户端和服务端没有直接传输自己在第二步生成的密码;而是通过加密互换再加密的方式来生成 Session Key;从而保障了 Session Key 无法被泄露。
当客户端和服务端之间建立起加密链接后;进入到身份鉴权的步骤。在身份鉴权这一步有两种方式;密码验证登录、密钥验证登录。
密码验证登录过程具体步骤如下;
1.服务端收到客户端的请求后;把自己的公钥发送给客户端;与会话密钥不同;是服务器自身的公钥/私钥对;;
2.客户端使用收到的公钥加密密码;并发送回服务器;
3.服务器使用自己私钥解密信息;若密码正确;则通过验证。
工作中我们在客户端生成的 Public/Private Key;就是指用来身份鉴权的 Authorized Key。客户端拥有 Private 和 Public Key;提前将 Public Key 放到服务端用于登录。登录时的具体步骤如下;
前提条件是手动将客户端的公钥发送给服务器;并填入authorized_keys文件中。
1.客户端把用户验证的密钥对ID发送给服务器;
2.服务器根据密钥对ID在对应用户的authorized_keys文件中进行检索;
3.假设服务器在文件中找到符合密钥对ID的公钥;服务器将生成一个随机数;并用这个公钥进行加密;
4.服务器将加密后的信息发送给客户端;
5.假设客户端拥有对应的私钥;就可以解密出原来的随机数;
6.客户端将得到的随机数与加密会话所用的会话密钥拼接一起后;计算其MD5哈希值;
7.客户端将MD5哈希值发送回服务器;
8.服务器使用相同的会话共享密钥和他生成的随机数计算出MD5哈希值;并与客户端返回的MD5哈希值进行比较。如果两个值相等;证明客户端拥有对应私钥;则通过验证。
也可以通过下图进行理解;
1.客户端用 Private Key 生成签名向服务器发起登录请求。
2.服务端验证签名;检查自己有没有和这个签名匹配的 Public Key;如果有;则进入下一步。
3.服务端生成一串随机字符串;用 Public Key 加密后发送给客户端。
4.客户端用相应的 Private Key 解密这串字符串;再使用 MD5 hash 和 Session Key 加密该字符串;将结果发送给服务端。
5.服务端使用同样的 MD5 hash 和 Session Key 计算这串字符的加密结果;并和客户端发来的结果做比对;如果结果一样;则允许客户端登录。
Public/Private Key 的加密方式被称作 非对称加密;Asymmetry Encryption;;就是说使用不同的 Key 来对信息进行加密解密。客户端使用 Private Key 可以解密服务端使用 Public Key 加密的信息;服务端使用 Public Key 无法解密客户端使用 Private Key 发来的加密信息。登录完成后;Authorized Key 的任务也就完成了。
SSH 完成连接;在接下来的通讯过程中;双方将持续使用 Session Key 进行通讯。
SSH 分为两大步;第一步是客户端和服务端建立连接;最终生成双方都一致的 Session Key。第二步使用 Authorized Key 进行登录;登录过程使用 Public/Private Key 验证身份。连接建立完成后;在通讯过程中使用 Session Key 对信息进行加密解密。
原文链接;
https://zhuanlan.zhihu.com/p/108161141
https://zhuanlan.zhihu.com/p/139285610