使用ssh方式登录远程服务器的连接过程:

  1. 协议协商阶段:服务端监听端口22,客户端发起TCP连接,双方握手建立连接,服务端向客户端发送第一个报文:包括SSH协议版本号。客户端收到后验证是否支持服务端协议版本(一般选择两者支持的低版本协议版本号)并选择决定使用的协议版本号发给服务端,服务端收到后检查是否能和客户端交互,可以则协商成功,否则失败断开连接。成功后进入下一个阶段。
  2. 服务端认证:协商成功后,服务端明文发送Host Public Key(或者简写为Host Key,SSH安装后Host Private Key在/etc/ssh/ssh_host_rsa_key,Host Public Key在/etc/ssh/ssh_host_rsa_key.pub)、Server Key(是SSH-1版本中使用的临时非对称密钥,每隔一定时间(默认一小时)都会在服务端重新生成,用于对会话密钥Session Key加密,SSH-2对Server Key进行了加强)、一个8Bytes的随机数检测字节(防止IP地址欺诈)和服务端支持的加密算法(应该是对称加密算法吧,因为非对称密钥中就带有加密算法)、压缩方式和认证方式。
    客户端收到后,查询该用户下的known_hosts(~/.ssh/下)是否存在对应服务端IP和机器名的Host Key,若不存在交由用户判断是否信任该服务端(防止攻击者冒充服务端,发送自己的密钥。会将服务端发送的Host Key进行哈希之后生成一个Fingerprint(指纹),也就是Host Key的哈希值,因为其太长,rsa算法生成的公钥有1024位长,哈希之后的指纹一般为128位。这样在客户端也没有存服务端真实Host Key,安全更高,也更好比较)。双方根据协商的加密算法(例如MD5,这里可能就是MD5)将Host Key,Server Key和检测字节生成一个128位(16字节)的(MD5)值作为会话ID(Session ID)(这里也有说服务器生成Session ID发给客户端的,本质一样)。客户端检查自己的known_hosts文件(~/.ssh/known_hosts)中是否有该服务端的Host Key。若没有则提示是否信任该服务端,是则添加到该文件中并继续;若存在则继续。
    接下来客户端将生成Session Key(会话密钥,随机生成的对称密钥),接着客户端使用接收到的服务端Server Key对Session Key(还包含检测字节和所选加密算法(从第1步服务端发送的算法中选出的,这个加密算法应该是Session Key的对称加密算法,例如AES128))加密(有说同时使用Host Key和Server Key双重加密,因为Session Key很重要),服务端收到后用Server Private Key解密得到Session Key。(还有说在客户端Session Key和Session ID异或计算一次作为加密的Session Key,服务端用私钥解密后的Session Key再和Session ID异或一次生成真正的Session Key)。这里服务端可能还会发送使用Session Key加密的确认信息给客户端以进一步验证服务端身份(为避免Session Key泄漏)。至此服务器认证结束。
  3. 客户端验证:有多种验证方式,常用的包括密码验证和密钥验证。服务端配置了密钥验证方式后(默认是开启的吧)优先使用密钥方式登录。
    密码验证:客户端使用Session Key对用户名和密码加密,发给服务端,服务端使用Session Key解密后验证是否合法。有说,客户端使用上一步服务端发送的Server Key/Host Key对用户和密码加密,然后发给服务端,服务端使用私钥解密,这个描述不太正确,感觉更容易被攻击。
    密钥验证:客户端需要事先将自己的公钥(可用ssh-keygen生成,在/.ssh/id_rsa.pub下)存放到服务端(会追加到要登陆用户的家目录中的/.ssh/authorized_keys文件中)。客户端若生成了公钥和私钥,则发送公钥认证(Public Key)请求,发送用Session Key加密的包含公钥的模作为标识符(KeyID)的信息,服务端接收到客户端的连接请求后,用Session Key解密拿到公钥的Key ID从authorized_keys文件中找到匹配的对应该客户端的公钥,若找不到则失败,客户端则可继续采取密码登陆。若找到,服务端生成一个256位(32字节)随机数R,并用该公钥加密,最后使用Session Key加密后发送给客户端。
    客户端收到后先用Session Key和自己的私钥解密,得到随机数R,然后将随机数和Session ID结合(防止攻击者重放攻击,replay attack)生成一个MD5值同时用Session Key加密发给服务端。服务端收到后,也用同样的认证方式(随机数R结合Session ID)生成MD5值,然后用Session Key解密客户端发来的MD5值,对比是否一致完成验证。
  4. 数据传输:验证成功后就是数据传输阶段,该阶段使用Session Key进行加密传输。