SSH连接的那一刻究竟发生了什么?

菜鸡实验项目,如有不当之处烦请指出
学习笔记,内容多为摘抄自dalao博文

1.什么是SSH

SSH 为 Secure Shell 的缩写,由 IETF 的网络小组(Network Working Group)所制定;SSH 为建立在应用层基础上的安全协议。SSH 是较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用 SSH 协议可以有效防止远程管理过程中的信息泄露问题。SSH最初是UNIX系统上的一个程序,后来又迅速扩展到其他操作平台。SSH在正确使用时可弥补网络中的漏洞。SSH客户端适用于多种平台。几乎所有UNIX平台—包括HP-UX、Linux、AIX、Solaris、Digital UNIX、Irix,以及其他平台,都可运行SSH。

2.了解SSH协议

SSH 主要由三部分组成:

传输层协议 [SSH-TRANS]

提供了服务器认证,保密性及完整性。此外它有时还提供压缩功能。 SSH-TRANS 通常运行在TCP/IP连接上,也可能用于其它可靠数据流上。 SSH-TRANS 提供了强力的加密技术、密码主机认证及完整性保护。该协议中的认证基于主机,并且该协议不执行用户认证。更高层的用户认证协议可以设计为在此协议之上。

用户认证协议 [SSH-USERAUTH]

用于向服务器提供客户端用户鉴别功能。它运行在传输层协议 SSH-TRANS 上面。当SSH-USERAUTH 开始后,它从低层协议那里接收会话标识符(从第一次密钥交换中的交换哈希H )。会话标识符唯一标识此会话并且适用于标记以证明私钥的所有权。 SSH-USERAUTH 也需要知道低层协议是否提供保密性保护。

连接协议 [SSH-CONNECT]

将多个加密隧道分成逻辑通道。它运行在用户认证协议上。它提供了交互式登录话路、远程命令执行、转发 TCP/IP 连接和转发 X11 连接。

3.当SSH连接的那一刻究竟发生了什么

TCP三次握手

连接ssh仅仅是一个短暂的过程,但是他到底以何种形式进行了哪些数据转换呢?
本次实验环境:windows10 ssh版本为:OpenSSH_7.4p1, OpenSSL 1.0.2k-fips
抓包后发现,发现TCP三次握手

ssh
关于TCP三次握手:
tcp握手
即客户端从53629端口发起向服务端22端口的请求,tcp建立完成

SSH协议协商

随后即进入第一个阶段,双方协议版本交换
协议交换

协议格式如下:
SSH-protoversion-softwareversion SP comments CR LF
protoversion: 协议版本-softwareversion: 软件版本 SP: 空格
comments: 可选字符串 CR: 回车 LF: 换行

协商时,如客户端版本高于服务端,客户端如果有特定代码能兼容较低版本,则会发送低版本的版本号,如没有则会发送当前版本。

版本号协商阶段,SSH目前包括 SSH1和SSH2两个版本, 双方通过版本协商确定使用的版本
v1: 基于CRC-32做MAC,不安全;可能会被MITM攻击(Man-in-the-MiddleAttack)
v2:双方主机协议选择安全的MAC方式

发送算法协商

完成ssh版本协商后,服务器端和客户端分别发送算法协商报文给对端,报文中包含自己支持的公钥算法列表、加密算法列表、MAC(Message Authentication Code,消息验证码)算法列表、压缩算法列表等;

SSH主要由下列类型的算法作为基础:

1.压缩算法
none (必须支持)
zlib
2.加密算法
3des-cbc (必须支持)
aes128-cbc (rfc4253推荐)
aes128-ctr (rfc4344推荐)
aes192-ctr (rfc4344推荐)
aes256-ctr (rfc4344推荐)
3des-ctr (rfc4344推荐)
其他许多可选的加密算法
3.数据校验算法
hmac-sha1 (必须支持)
hmac-sha1-96 (推荐)
hmac-md5
hmac-md5-96
4.密钥交换算法
diffie-hellman-group1-sha1 (必须支持)
diffie-hellman-group14-sha1 (必须支持)
5.公钥认证算法
ssh-dss (必须支持)
ssh-rsa (必须支持)

在这里插入图片描述
双端获取到报文后开始进行算法协商,首先由客户端发送Key exchange
key exchange
内容如下:在这里插入图片描述

类型名称解释
byteSSH_MSG_KEXINIT
byte[16]cookie (random bytes)必须是一个由发送方生成的随机值。它的作用是使任何一方都不可能对密钥和会话标识符拥有完全决定权。
name-listkex_algorithms秘钥交换算法
name-listserver_host_key_algorithms服务器主机秘钥
name-listencryption_algorithms_client_to_server客户端到服务端的加密算法
name-listencryption_algorithms_server_to_client服务端到客户端的加密算法
name-listmac_algorithms_client_to_server客户端到服务端的数据校验用hash算法
name-listmac_algorithms_server_to_client服务端到客户端的数据校验用hash算法
name-listcompression_algorithms_client_to_server客户端到服务端的压缩算法
name-listcompression_algorithms_server_to_client服务端到客户端的压缩算法
name-listlanguages_client_to_server客户端到服务端语言
name-listlanguages_server_to_client服务端到客户端语言
booleanfirst_kex_packet_follows
uint320 (为将来扩展预留)预留

每个算法类型列表的第一个算法必须是首选的算法,服务器应以客户端的算法优先级作为考虑,就拿交换算法举例:
现在服务器有三个算法dh1,dh2,dh3
客户端有两个算法dh3,dh2
那么服务器的首选算法是dh1,而客户端是dh3,客户端此时知道服务器有dh3算法,因此客户端就确认使用dh3算法。服务器发现自己的首选算法与客户端不同,而自己拥有客户端的首选算法,因此服务器也确认使用dh3算法。
再看另一个情况
服务器:dh1,dh2,dh3
客户端:dh4,dh3,dh1
这时服务器没有客户端的首选算法,客户端会使用第二个算法dh3,此时服务器也支持第二个算法,双方将确定使用dh3算法。如果服务器和客户端双方没有共同的算法,这次会话将会终止。

Diffie-Hellman 密钥交换

交换流程
算法选择后,客户端发送SSH_MSG_KEXDH_INIT数据包,发送Diffie-Hellman参数e。服务端响应SSH_MSG_KEXDH_REPLY回复参数K_S、f、hash(H)。客户端验证回复参数后响应SSH_MSG_NEWKEYS,之后服务端也响应SSH_MSG_NEWKEYS,之后客户端与服务端使用新的密钥进行加密和校验数据。
按照Diffie-Hellman算法,客户端和服务端分别使用参数e和f计算出Shared Secret,然后计算出Exchange Hash,再进一步计算出客户端和服务端加密密钥、初始向量、消息签名密钥。第一次计算出的Exchange Hash作为当次会话的Session Id,作为会话的永久识别标识。
其中K_S是服务端公钥,rsa和dss的序列化格式稍有差异。第一个字段是算法当前算法名称,接下来若干个mpint表示当前算法的公钥参数。

在这里插入图片描述
由客户端发送

byte SSH_MSG_KEXDH_INIT
mpint e

服务端响应

byte SSH_MSG_KEXDH_REPLY
string K_S,服务器公钥和证书 (
mpint f
string s,对 H 的签名

密钥更新

SSH允许每个一段时间或传输一定量数据后,由任意一方再次发起密钥交换。再次密钥交换的过程与上述过程一致。无论是客户端还是服务端发起再次交换密钥的请求,原客户端和服务端的角色不改变。密钥更新过程中除了密钥交换的数据包,别的数据包都禁止发送。再次密钥交换是以SSH_MSG_KEXINIT开始,SSH_MSG_NEWKEYS结束。密钥更新继续沿用旧的向量(加密密钥、初始向量、消息签名密钥),密钥交换后更新所有的向量。密钥更新过程可以改变服务端密钥、算法等,唯独Session Id不会更新。

到此,传输层协议的作用已经发挥完毕。随后将是用户认证相关内容。

身份验证流程

客户端请求需要的服务前,需要向服务端表明身份。首先客户端发送SSH_MSG_USERAUTH_REQUEST,表明需要请求的服务和打算使用的身份认证方式(publickey、password、hostbased、keyboard-interactive等)。若服务端接受就直接返回SSH_MSG_USERAUTH_SUCCESS,这样客户端就不用发送任何身份认证数据证明我是我了。如果服务器觉得还需要进一步验明真身,会返回SSH_MSG_USERAUTH_FAILURE,并告知服务端支持的身份认证方式。接下来客户端与服务端大战100回合以证明“我就是我!”。

基于密码的安全验证

客户端先发送请求,随后会从服务端收到公钥

第一次连接ssh时都会遇到是否接受公钥

在这里插入图片描述
随后客户端将用此公钥对密码进行加密,服务端接收加密后的密码通过私钥进行解密来判断于密码是否合法。如合法则有客户端生成sess_key,使用 ser_rsa.pub 加密后传输给服务器(会话密钥)服务器获取到后使用 ser_rsa 解密,得到sess_key完成本次身份认证。
注:此方法无法规避MITM攻击的风险。

基于密钥的安全验证

文章引用:
1.教你纯手工用C#实现SSH协议作为GIT服务端
2.ssh两种认证方式的原理介绍
3.ssh 协议:SSH 传输层协议
4.SSH协议介绍
5.ssh两种认证方式的原理介绍

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值