【SSH】SSH流程与wireshark抓包分析

Razors_ 2024-07-13 17:37:02 阅读 84

一、SSH需求的产生与SSH运行流程

0.为什么要有SSH?

传统的互联网通信使用明文传输数据,内容一旦被截获就会完全暴露,存在很多安全隐患。SSH协议通过对网络数据进行加密和验证,建立SSH客户端和SSH服务器之间的安全隧道,在不安全的网络环境中为网络服务提供了安全的传输通道。

SSH最常用的场景是远程登录和文件传输。在SSH协议出现之前,Telnet广泛应用于远程登录场景,为远程管理网络设备提供了极大便利,而FTP作为常用的文件传输协议,兼具操作简单和传输效率高的优点,但它们都存在相同的问题,即明文传输数据带来的安全隐患。SSH采用加密传输数据、提升认证强度等手段,克服了Telnet和FTP应用中的安全性问题,实现了安全的远程登录和文件传输业务。

SSH常用场景

1.什么SSH?

SSH(Secure Shell,安全外壳)是一种网络安全协议,通过加密认证机制实现安全的访问和文件传输等业务。传统远程登录和文件传输方式,例如Telnet、FTP,使用明文传输数据,存在很多的安全隐患。随着人们对网络安全的重视,这些方式已经慢慢不被接受。SSH协议通过对网络数据进行加密和验证,在不安全的网络环境中提供了安全的网络服务。作为Telnet和其他不安全远程shell协议的安全替代方案,目前SSH协议已经被全世界广泛使用,大多数设备都支持SSH功能。

2. SSH是如何工作的?(SSH的工作流程)

SSH由服务器和客户端组成,为建立安全的SSH通道,双方需要先建立TCP连接,然后协商使用的版本号和各类算法,并生成相同的会话密钥用于后续的对称加密。在完成用户认证后,双方即可建立会话进行数据交互。SSH的工作流程包括如下几个阶段。

SSH工作流程

连接建立

SSH依赖端口进行通信。在未建立SSH连接时,SSH服务器会在指定端口侦听连接请求,SSH客户端向SSH服务器该指定端口发起连接请求后,双方建立一个TCP连接,后续会通过该端口通信。

默认情况下,SSH服务器使用端口号22。当SSH应用于NETCONF时,可以指定默认端口号是22或者830。SSH使用的端口号可以被更改为设备其他可用端口,更改后当前所有的连接都会断开,SSH服务器开始侦听新的端口。由于SSH默认端口号22为知名端口,在进行关键安全传输时,建议修改SSH端口号。

版本协商

SSH协议目前存在SSH1.X(SSH2.0之前的版本)和SSH2.0版本。SSH2.0协议相比SSH1.X协议来说,在结构上做了扩展,可以支持更多的认证方法和密钥交换方法,同时提高了服务能力。SSH服务器和客户端通过协商确定最终使用的SSH版本号,过程如下:

SSH服务器通过建立好的连接向SSH客户端发送支持的SSH版本信息。

SSH客户端收到版本信息后,根据自身支持的SSH版本决定使用的版本号,并将决定使用的版本号发送给SSH服务器。

SSH服务器判断自己是否支持客户端决定使用的版本号,从而确定版本协商是否成功。

算法协商

SSH工作过程中需要使用多种类型的算法,包括用于产生会话密钥的密钥交换算法、用于数据信息加密的对称加密算法、用于进行数字签名和认证的公钥算法和用于数据完整性保护的HMAC算法。SSH服务器和客户端对每种类型中具体算法的支持情况不同,因此双方需要协商确定每种类型中最终使用的算法,过程如下:

SSH服务器和客户端分别向对方发送自己支持的算法。

SSH服务器和客户端依次协商每种类型中具体使用的算法。在每类算法的协商过程中,SSH服务器和客户端都会匹配出双方均支持的算法作为最终使用的算法。每类算法均匹配成功后,算法协商完成。如果某类算法全部匹配失败,则该类型的算法协商失败,这会导致SSH服务器和客户端之间算法协商失败并断开连接。

密钥交换

SSH服务器和客户端通过密钥交换算法,动态生成共享的会话密钥和会话ID,建立加密通道。会话密钥主要用于后续数据传输的加密,会话ID用于在认证过程中标识该SSH连接。

由于SSH服务器和客户端需要持有相同的会话密钥用于后续的对称加密,为保证密钥交换的安全性,SSH使用一种安全的方式生成会话密钥,由SSH服务器和客户端共同生成会话密钥,利用数学理论巧妙地实现不直接传递密钥的密钥交换,无需通过不安全通道传送该密钥,具体过程如下图所示。

SSH密钥交换

SSH服务器生成素数G、P、服务器私钥b,并计算得到服务器公钥y=(Gb)%P。

SSH服务器将素数G、P、服务器公钥y发送给SSH客户端。

SSH客户端生成客户端私钥a,计算得到客户端公钥x=(Ga)%P。

SSH客户端将客户端公钥x发送给SSH服务器。

SSH服务器计算得到对称密钥K=(xb )%P,SSH客户端计算得到对称密钥K=(ya )%P,数学定律可以保证SSH服务器和SSH客户端生成的对称密钥相同。

用户认证

SSH客户端向SSH服务器发起认证请求,SSH服务器对SSH客户端进行认证。SSH支持以下几种认证方式:

密码(password)认证:客户端通过用户名和密码的方式进行认证,将加密后的用户名和密码发送给服务器,服务器解密后与本地保存的用户名和密码进行对比,并向客户端返回认证成功或失败的消息。

密钥(publickey)认证:客户端通过用户名,公钥以及公钥算法等信息来与服务器进行认证。

password-publickey认证:指用户需要同时满足密码认证和密钥认证才能登录。

all认证:只要满足密码认证和密钥认证其中一种即可。

SSH用户认证最基本的两种方式是密码认证和密钥认证。密码认证方式比较简单,且每次登录都需要输入用户名和密码。而密钥认证可以实现安全性更高的免密登录,是一种广泛使用且推荐的登录方式。

密码认证

密码认证的基本原理是SSH客户端使用服务器公钥对密码进行加密,SSH服务器使用服务器私钥解密后验证密码的合法性,具体过程如下图所示。

SSH密码认证登录流程

SSH客户端向SSH服务器发送登录请求。

SSH服务器将服务器公钥发送给SSH客户端。

SSH客户端输入密码,使用服务器公钥加密密码后发送给SSH服务器。

SSH服务器收到密文,使用服务器私钥解密得到密码。验证密码是否正确,如果正确则认证通过。

但是,这种认证方式存在中间人攻击的风险,如果有人截获了SSH客户端的登录请求后,冒充SSH服务器将伪造的公钥发送给SSH客户端,就可以获取到用户的登录密码。所以,在首次登录SSH服务器时,SSH客户端上会提示公钥指纹,并询问用户是否确认登录。用户确认后公钥将被保存并信任,下次访问时,SSH客户端将会核对SSH服务器发来的公钥和本地保存的是否相同。这种方式适用于公布了公钥指纹的SSH服务器以及已登录过正确SSH服务器的SSH客户端。

密钥认证

为避免中间人攻击,可以使用安全性更高的密钥认证。密钥认证的基本原理是SSH服务器使用客户端的公钥对随机内容加密,SSH客户端使用自己的私钥解密并发送给服务器以证实自己的身份,具体的过程如下图所示。

SSH密钥认证登录流程

在进行SSH连接之前,SSH客户端需要先生成自己的公钥私钥对,并将自己的公钥存放在SSH服务器上。

SSH客户端向SSH服务器发送登录请求。

SSH服务器根据请求中的用户名等信息在本地搜索客户端的公钥,并用这个公钥加密一个随机数发送给客户端。

SSH客户端使用自己的私钥对返回信息进行解密,并发送给SSH服务器。

SSH服务器验证SSH客户端解密的信息是否正确,如果正确则认证通过。

会话请求

认证通过后,SSH客户端向服务器发送会话请求,请求服务器提供某种类型的服务,即请求与服务器建立相应的会话。服务器根据客户端请求进行回应。

会话交互

会话建立后,SSH服务器端和客户端在该会话上进行数据信息的交互,双方发送的数据均使用会话密钥进行加解密。

3. SSH和TLS/SSL的区别

SSH和TLS(SSL是TLS的前身)都是网络安全协议,通过加密和认证提升两台设备间传输数据的安全性。但SSH和SSL的生效方式和服务目标存在差异。

SSH在两台设备间创建安全隧道,使这两台设备间可以安全地发送命令、传输数据等。例如,客户端通过SSH远程登录到一台服务器上,就可以安全地远程管理这台服务器,在服务器上执行想要的命令。

SSL则是使用SSL证书保证两台设备间安全地传输数据,而不是像SSH那样可以执行命令。例如,用户通过浏览器访问某安装了SSL证书且启用了HTTPS的服务器,浏览器和服务器之间可以安全地传输数据。

TLS (Transport Layer Security)用于在计算机网络上保障通信安全的协议。主要用于在Web浏览器和服务器之间、电子邮件系统中等进行安全通信。提供端到端的通信安全,确保数据在传输过程中不被窃听或篡改。

SSH (Secure Shell):用于在计算机网络上安全地执行命令和传输文件的协议。主要用于远程登录到计算机系统并执行命令,以及通过SCP(Secure Copy Protocol)或SFTP(SSH File Transfer Protocol)安全地传输文件。提供身份验证和加密,以保护远程访问和文件传输的安全性。

SSH就像一辆汽车,我们看不到这辆封闭的汽车里装载的是什么。而SSL就像一个封闭的集装箱,我们可以用不同的交通工具运输它,但看不到集装箱里装的是什么。

二、截包分析SSH建立流程

简单地说,SSH协议是建立在不安全的网络之上的进行远程安全登陆的协议。它是一个协议族,其中有三个子协议,分别是:

1、传输层协议[SSH-TRANS]:提供服务器验证、完整性和保密性功能,建立在传统的TCP/IP协议之上。

2、验证协议[SSH-USERAUTH]:向服务器验证客户端用户,有基于用户名密码和公钥两种验证方式,建立在传输层协议[SSH-TRANS]之上。

3、连接协议[SSH-CONNECT]:将加密隧道复用为若干逻辑信道。它建立在验证协议之上。

在这里插入图片描述

下面先通过wireshire抓包分析SSH协议上述三个流程.

1. SSH协议握手过程分析

在接着下面的内容之前,这里有几个概念非常重要!

1、会话密钥 key:key是通过客户端和服务器之间通过诸如D-H算法协商出来的。

2、公钥 pub key:pub key成为服务器主机密钥server_host_key,用于SSH-TRANS传输协议进行服务器验证,说白了就是客户端去验证服务器用的

SSH协议握手过程大致流程如下图所示:

在这里插入图片描述

下图是我在一次SSH链接构建过程中的截包,200.153主机为server,200.1主机为client。本次截包使用的是VScode连接宿主机中ubuntu虚拟机上的ssh服务

在这里插入图片描述

1.TCP三次握手建立连接

描述 seq Win ACK 解释
第一次握手 0 64240 seq = 0表示客户端当前的TCP包序列号
第二次握手 0 64240 1 seq = 0,表示服务器端当前的TCP包序列号;ack = 1(客户端seq + 1),表示对客户端第 seq = 0 的TCP包进行应答
第三次握手 1 131328 1 seq = 1,表示客户端端当前的TCP包序列号;ack = 1(服务器seq + 1),表示对服务器端第 seq = 0 的TCP包进行应答

2、SSH版本协议交换

上图序号(36和38)即是SSH版本协议交换过程。

在这里插入图片描述

此处的包顺序与第一部分中讲解到的版本协商顺序不一样。

NO. 描述 解释
36 协议版本协商 客户端将自己的SSH协议版本发送到服务器,格式为:SSH-protoversion(版本号)-softwareversion(自定义) SP(空格一个,可选) comments(注释,可选) CR(回车符) LF(换行符)
38 协议版本协商 服务器将自己的SSH协议版本发送到客户端,格式为:SSH-protoversion(版本号)-softwareversion(自定义) SP(空格一个,可选) comments(注释,可选) CR(回车) LF(换行))

这一步本质上就是发送一个格式为SSH-protoversion-softwareversion SP comments CR LF的字节流而已。

3、密钥协商key

上图序号(39-45)即是SSH版本协议交换过程。

在这里插入图片描述

密钥协商过程从客户端和服务器相互发出Key Exchange Init请求开始,主要是告诉对方自己支持的相关加密算法列表、MAC算法列表等。

在这里插入图片描述

最后协商成功之后,将会生成一个对称加密会话密钥key以及一个会话ID,在这里要特别强调,这个是对称加密密钥key,不要和公钥相混淆了,公钥和密钥在上面开头已经着重强调两者的区别了,公钥是给客户端去验证服务器用的。

在这一步中,公钥会从服务器传送到客户端:

在这里插入图片描述

而会话密钥是通过D-H算法计算出来的,不会在网络上传输,其破解的难度取决于离散对数的破解难度,一般不会被破解的,有兴趣的可以自行了解该算法原理。

下面我将贴出Key Exchange Init发送的请求包数据分析

在这里插入图片描述

NO. 描述 解释
1 kex_algorithms 密钥交换算法,里边即包含我们使用的D-H算法,用于生成会话密钥
2 server_host_key_algorithms 服务器主机密钥算法,可以采用 ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,有公钥和私钥的说法,公钥即我们上面讲到的pub key,对于公钥私钥的概念,可以参见understanding public key private key concepts
3 encryption_algorithms_client_to_server 对称加密算法,常用的有aes128-cbc,3des-cbc
4 mac_algorithms_clien_to_server MAC算法,主要用于保证数据完整性
5 compression_algorithms_client_to_server 压缩算法

4、认证阶段

在这里插入图片描述

从第46个包之后就已经是加密包了。因此我们看不到SSH的认证阶段、会话请求、会画交互阶段。

SSH认证的方法通常有以下几种形式:

1、基于账号和口令的验证方式

客户端将自己的用户名 + 密码用上面生成的会话密钥key进行加密之后传送到服务器端进行验证,服务器端验证通过,则响应成功,否则在进行有限次(推荐是20次)重新认证。至于服务器是怎么验证的,是否结合了会话ID小编也不清楚,网上众说纷纭。注意,用户名和密码是采用上面密钥协商阶段生成的会话密钥key进行加密的,包括后面的连接会话阶段所传送的数据都是,不要认为是采用服务器的pub key加密的

2、基于公钥和私钥的验证方式

这种方式也称为免密登陆。简单地说,就是客户端自己生成公钥私钥(通常采用ssh-keygen程序生成),然后将公钥以某种方式(通常是手动添加)保存到服务器~/.ssh/authorized_keys文件中,以后服务器都会接受客户端传过来的经过会话密钥加密过的公钥,然后解密得到公钥之后和本地authorized_keys配置的公钥是否相等,如果是,则允许登陆。

如果你配过github或者gitlab的公钥,其实第二种方式认证方式很好理解,因为github它们也是采用SSH协议进行代码克隆的,没有配置公钥好像是不允许克隆的。

3. SSH 存在的中间人攻击风险问题

1、密钥协商阶段安全吗?有没有中间人攻击的情况!

就我的理解,第一次总是不安全的。为什么呢?上面说到协商过程中,服务器会将自己的公钥server_host_key_algorithms发送给客户端,但是客户端无法保证它拿到的公钥就是目标服务器所发出来的,很可能有个中间人拦截了你的请求,然后中间人发了另外一个公钥给到你客户端,这就不安全了!这也很好解释了为什么我们第一次登陆的时候,Shell终端总是会出现这个提示的原因:

在这里插入图片描述

这也是将确认权留给客户端自己去判断的一种策略。相反,如果想要更加安全,那么我们可以采用第二种认证方式进行登陆。由于提示的是经过MD5之后的公钥,那么我们怎么判断这个值是有效的呢?请看下面第3个疑问。

2、传输协议协商出来的会话密钥和会话ID到底有什么作用?

会话密钥:对称加密算法的密钥,用于对通信数据进行加解密,会话ID有点像WEB中的Session,就是用来表示每一个会话的,同时在认证阶段也起判断是否同一会话有效的作用。

3、既然密码验证登陆,那么客户端第一次登陆的时候如何验证服务器公钥的正确性?

在SSH的安全连接中,用户首先需要知道要连接的服务器的公钥的哈希值(指纹),并在第一次连接时进行对比,以确保没有受到中间人攻击。

参考资料

什么是SSH?SSH是如何工作的?

SSH 协议基本原理及 wireshark 抓包分析



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。