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

1、SSH协议简介

咱们常常会使用ssh username@hostIp命令登录咱们的linux服务器,以下图所示:html

咱们也明白这是使用了SSH协议进行登录,但咱们想知道的是,为何可使用SSH协议进行登录,并且为何使用SSH就是安全的,其背后的原理是什么?下面咱们就一块儿来探讨下这几个话题。linux

固然啦!若是如今你手头上有相关公网可访问的云主机,那么请你登录你的云主机,而后执行grep sshd.*Failed /var/log/secure命令看看,或许你会惊讶的发现有不少输出日志,你就会明白到底有多少人想尝试登录你的主机了。git

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

  • 一、传输层协议[SSH-TRANS]:提供服务器验证、完整性和保密性功能,创建在传统的TCP/IP协议之上。
  • 二、验证协议[SSH-USERAUTH]:向服务器验证客户端用户,有基于用户名密码和公钥两种验证方式,创建在传输层协议[SSH-TRANS]之上。
  • 三、链接协议[SSH-CONNECT]:将加密隧道复用为若干逻辑信道。它创建在验证协议之上。

这里不对SSH协议作更加详细的介绍,咱们能够自行百度一下。下面的写做思路将先经过wireshire抓包分析SSH协议上述三个流程,最后将提出整个学习过程当中小编遇到的问题进行探讨。算法

2、SSH协议握手过程分析

在接着下面的内容以前,这里有几个概念很是重要!安全

  • 一、会话密钥 key:key是经过客户端和服务器之间经过诸如D-H算法协商出来的。
  • 二、公钥 pub key:pub key成为服务器主机密钥server_host_key,用于SSH-TRANS传输协议进行服务器验证,说白了就是客户端去验证服务器用的

SSH协议握手过程大体流程以下图所示:服务器

下面是小编经过wireshire工具抓的数据包,让咱们分别一步步进行分析:网络

  • 一、TCP三次握手创建链接

咱们都知道,TCP协议有个叫三次握手的过程,从上面图中能够看出序号(647-649)便是TCP链接创建过程。app

NO. 描述 seq Win ACK 解释
647 第一次握手 0 8192 seq = 0表示客户端当前的TCP包序列号
648 第二次握手 0 14600 1 seq = 0,表示服务器端当前的TCP包序列号
ack = 1(客户端seq + 1),表示对客户端第 seq = 0 的TCP包进行应答
649 第三次握手 1 65536 1 seq = 1,表示客户端端当前的TCP包序列号
ack = 1(服务器seq + 1),表示对服务器端第 seq = 0 的TCP包进行应答
  • 二、SSH版本协议交换

上图序号(647-649)便是SSH版本协议交换过程。ssh

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

这一步其实没什么高大上的内容,就是发送一个格式为SSH-protoversion-softwareversion SP comments CR LF的字节流而已。

  • 三、密钥协商key

上图序号(652-677)便是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_client_to_server MAC算法,主要用于保证数据完整性
5 compression_algorithms_client_to_server 压缩算法
  • 四、认证阶段

上图序号(678-680)便是SSH版本认证阶段。

  • 一、基于帐号和口令的验证方式

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

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

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

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

3、相关问题

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

就个人理解,第一次老是不安全的。为何呢?上面说到协商过程当中,服务器会将本身的公钥server_host_key_algorithms发送给客户端,可是客户端没法保证它拿到的公钥就是目标服务器所发出来的,极可能有个中间人拦截了你的请求,而后中间人发了另一个公钥给到你客户端,这就不安全了!这也很好解释了为何咱们第一次登录的时候,Shell终端老是会出现这个提示的缘由:

这也是将确认权留给客户端本身去判断的一种策略。相反,若是想要更加安全,那么咱们能够采用第二种认证方式进行登录。因为提示的是通过MD5以后的公钥,那么咱们怎么判断这个值是有效的呢?请看下面第3个疑问。

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

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

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

请你告诉小编吧!小编苦于找不到答案!

4、其余

下面是相关资料文档:

咱们可能会问了,既然有了SSH协议文档,那么假如咱们想要照着文档写一个实现出来,那么应该怎么去入手呢?其实SSH中的传输协议[SSH-TARNS]是基于TCP协议的,所以咱们能够从建立一个最基本Java Socket套接字开始,逐步实现SSH的传输协议、认证协议以及链接协议。若是你对实现过程感兴趣,能够研究下ganymed-ssh2-build209.jar中的源码,结合SSH协议RFC文档,你就会发现,其实SSH协议中的协商和认证过程,其实都是经过Socket输入流、输出流的形式实现的。小编本身撸到协商阶段果断放弃,缘由是不懂得算法太多了!

相关文章
相关标签/搜索