在使用git的远程推送功能时,常用ssh协议连接远程服务器, ssh协议的使用免去了每次连接都要输入用户名,密码的麻烦,通过实现存放在远程主机的公钥与存放在本地的私钥的配对确定请求者的身份。
Ssh认证的流程:
-------------------------------协商阶段---------------------------------
客户端向服务端发送连接请求,服务端监听22端口,收到请求后返回自己支持的ssh版本号,
客户端收到ssh版本号回复后,将自己支持的ssh版本号发送到服务端,服务端根据自己是否支持,选择建立连接或者关闭连接
(这个阶段可能发生降级中间人攻击,强制通信以低版本较容易被攻击的ssh版本进行通信)
---------------------------------服务端认证阶段-----------------------------------
服务端向客户端发送hostKey(服务器的指纹),serverKey,一个随机数,服务器支持的认证方式等信息
HostKey标识自己的身份,防止中间人攻击,随机数防止ip欺骗
客户端收到信息后,先比对hostKey是否在本地Known_host库中,若在库中,则认为服务端是可信的,使用hostKey,ServerKey,8字节的随机数生成sessionId,
接下来,客户端向服务端发送sessionKey,用作正常传输过程中的密钥,这个sessionKey是对称加密的。由于hostKey与ServerKey的使用提供了一个安全壳,所以sessionKey的传输过程被认为是安全的。
----------------------------客户端认证阶段---------------------------------------
客户端向服务器发起一个认证请求
服务端收到请求检查服务端是否有该请求账号的公钥(这个公钥是通过一个安全的方式事先存放在服务端的,比如我们在电脑使用rsa-gen命令创建了一对密钥后将.pub结尾的文件内容复制到github的ssh栏),如果找到了该公钥,随机生成一串256位字符串,并使用这个公钥加密,发送给客户端。
客户端收到后,使用本地的私钥进行解密,将拿到的字符串与session_id结合生成一个字符串发送给服务端,使用session_id的目的是防止重放攻击,由于session_id与攻击者的session_id相同的概率微乎其微,由此使用其他session_id生成的字符串是肯定不同的,这是以提问-应答方式来防范重放攻击。
服务端使用原始字符串与session_id结合用同样的方式生成一个md5,与客户端发送过来的md5进行比较,如果相同,则认证成功。
--------------------------------------数据传输阶段---------------------------
两边都已获得认证,为了提高传输效率,这个阶段只是用sessionKey来进行加密。