每天都在用 SSH,你知道 SSH 的原理吗?
以下内容转自:每天都在用 SSH,你知道 SSH 的原理吗?
现在就让我们一起开心地聊一聊 SSH 到底是怎么运作的。先抛开大家经常讲的 Public/Private Key,我们从其他角度来看看 SSH。SSH 的连接分为两步:
-
客户端和服务端建立连接
-
用户身份鉴权
客户端和服务端建立连接
在这一大步中,又分为以下几小步:
- 客户端联系服务端,双方沟通自己支持的 SSH 协议的版本,约定使用某个共同支持的版本。
- 服务端将自己的 Host Key 、加密方法和其他一些参数发给客户端。
- 客户端通过 Host Key 验证服务端身份,双方用服务端发来的参数和 Diffie-Hellman 算法生成 Session Key。
- 加密通道建立完成。
在这几步中,出现了两个 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 的步骤大致如下:
- 客户端和服务端使用沟通时的信息,协商加密算法以及一个双方都知道的数字。
双方各自生成只有自己才知道的 private 密码,并使用上一步中的数字进行加密,再次生成密码。 - 双方交换再次加密后的密码。
- 双方在对方发来的密码基础上,加上第二步自己的 private 密码再次加密。本次加密之后得到的结果就是在双方处都相同的 Session Key。
从这个算法中,可以看出客户端和服务端没有直接传输自己在第二步生成的密码,而是通过加密互换再加密的方式来生成 Session Key,从而保障了 Session Key 无法被泄露。
用户身份鉴权
当客户端和服务端之间建立起加密链接后,进入到身份鉴权的步骤。在身份鉴权这一步除了使用 Key 登录外,还能使用密码登录,这里我们只讲 Key 方式的登录。
工作中我们在客户端生成的 Public/Private Key,就是指用来身份鉴权的 Authorized Key。客户端拥有 Private 和 Public Key,提前将 Public Key 放到服务端用于登录。登录时的具体步骤如下:
- 客户端用 Private Key 生成签名向服务器发起登录请求。
- 服务端验证签名,检查自己有没有和这个签名匹配的 Public Key,如果有,则进入下一步。
- 服务端生成一串随机字符串,用 Public Key 加密后发送给客户端。
- 客户端用相应的 Private Key 解密这串字符串,再使用 MD5 hash 和 Session Key 加密该字符串,将结果发送给服务端。
- 服务端使用同样的 MD5 hash 和 Session Key 计算这串字符的加密结果,并和客户端发来的结果做比对,如果结果一样,则允许客户端登录。
Public/Private Key 的加密方式被称作不对称加密(Asymmetry Encryption),就是说使用不同的 Key 来对信息进行加密解密。客户端使用 Private Key 可以解密服务端使用 Public Key 加密的信息,服务端使用 Public Key 无法解密客户端使用 Private Key 发来的加密信息。登录完成后,Authorized Key 的任务也就完成了。
SSH 完成连接,在接下来的通讯过程中,双方将持续使用 Session Key 进行通讯。
sshd 服务的启动
可以参考sshd_config 中文手册
如果sshd服务启动了,但是客户端ssh连接不上sshd服务,可以按照下述步骤排查:
如果客户端连不上sshd服务的话,首先确认下服务端是否有这些文件,
/etc/ssh/ 路径下参考sshd_config里的HostKey的地方,看看配置了那些HostKeys,如果没配置,可以取消注释符。然后选择对应的HostKey执行下述指令生成xx_key和xx_key.pub文件,这些文件,就是sshd服务的Private Key和Public Key。
ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key
然后重启下sshd服务:service sshd restart
ssh客户端连接也可以使用用户名+密码的方式,这些配置都在sshd_config里可以配置,具体的配置查看sshd_config的手册
如果重启了sshd服务,需要在本地的~/.ssh/known_hosts里删除远端机器的key,保证下次登录的时候能够重新生成。
总结
SSH 分为两大步,第一步是客户端和服务端建立连接,最终生成双方都一致的 Session Key。第二步使用 Authorized Key 进行登录,登录过程使用 Public/Private Key 验证身份。连接建立完成后,在通讯过程中使用 Session Key 对信息进行加密解密。
参考资料
《SSH, The Secure Shell: The Definitive Guide》