理解SSH的加密与连接过程

理解SSH的加密与连接过程

提供:ZStack社区

前言

SSH(secure shell“安全的壳”)是一种安全协议,是管理远程服务器最常用的方式。通过一系列的加密技术,SSH在两个端点之间建立起加密连接,在每个端点上验证另一端,并在两端之间传输命令。

我之前的其他文章中介绍过如何配置SSH密钥如何建立SSH连接,以及一些SSH的使用技巧。今天,我将介绍SSH底层的加密技术,介绍SSH是如何使用这些技术建立安全连接的。本文内容涉及各层的加密方式,建立连接的步骤,以及端与端之间验证的方式。

对称加密、非对称加密与哈希

针对信息传输的保护,SSH采用了多种数据处理办法,包括对称加密、非对称加密、以及哈希的数种方案。

对称加密(Symmetrical Encryption)

用于加密数据的组件和用于解密数据的组件,两者之间的关联性决定了该种加密方式是对称型的还是非对称型的。

对称加密采用同一个密钥加密和解密数据。也就是说,任意两个持有同样密钥的人就可以在相互之间传递加密信息并解密。

该种加密方式常被称为“共同的秘密(shared secret)”式加密或者“秘密的钥匙(secret key)”式加密。通常情况下,所有的操作都使用同一个密钥,或者一对关联度非常高、使得接收方能够很容易的推断出发送方使用的密钥的密钥对。

SSH使用对称密钥为整个连接过程加密。众所周知的公钥/私钥(public/private)是非对称密钥对,然而它们仅仅用于身份验证的过程,而没有用在传输过程。对称加密可以保护密码验证过程不受嗅探(snooping)的威胁。

该对称密钥由客户端与服务器端共同创建,生成的密钥不告知任何第三方。创建密钥的过程涉及一个密钥交换算法(key exchange algorithm),使用该算法时,客户端和服务器端根据共享的部分公共数据加上指定的秘密数据分别独立生成同样一个密钥(下文将详细介绍这个过程)。

该过程创建的对称加密密钥是基于会话(session)的,负责对服务器和客户端之间传输的数据进行加密。创建后,其余的所有数据传输都会经过该密钥的加密。这个过程在认证客户端之前执行。

SSH可以配置不同的对称加密法(symmetrical cipher system),包括AES、Blowfish、3DES、CAST128、以及Arcfour。服务器和客户端都可以选择其使用的加密法,最终使用的加密法一般由机器上加密法列表的排序决定:客户端加密法列表上出现的第一个服务器端也支持的加密算法,将用于双方加密传输的实现。

Ubuntu 14.04的默认列表顺序如下(客户端和服务器端通用):aes128-ctraes192-ctr,aes256-ctrarcfour256arcfour128aes128-gcm@openssh.comaes256-gcm@openssh.comchacha20-poly1305@openssh.comaes128-cbcblowfish-cbccast128-cbcaes192-cbcaes256-cbcarcfour

也就是说,如果是两台Ubuntu 14.04之间进行数据传输,则它们总会使用aes128-ctr加密算法(除非做过另外的配置)。

非对称加密(Asymmetrical Encryption)

非对称加密的发送与接收需要使用两个密钥,这两个密钥是相互关联的,一个叫做私钥(private key),另一个叫做公钥(public key)。

公钥可以共享给其他人,仅仅持有公钥是无法推导出私钥的。从数学的实现上,公钥加密的信息仅仅可以由私钥解密(而不能由公钥自己解密),私钥加密的信息也不能用公钥解密。这是一个单向的过程。

私钥必须要严格保密,不可与其他人共享。私钥的保密是整个加密范式安全性的关键。该范式假设:持有私钥是解密的唯一方式。如果一台主机能够解密由公钥加密过的信息,这只能表示它掌握着对应的密钥。

SSH在以下几个节点采用了非对称加密。首先是一开始建立用于连接的对称加密时的密钥交换过程(key exchange)。在这一阶段,服务器和客户端都各自生成了临时的公钥/私钥对,以计算出同一个用于连接加密的共享密钥。

其次是广为人知的SSH身份验证过程。SSH密钥对用于让服务器验证一个客户端的身份。密钥对在客户端上生成,其中的公钥上传至远程服务器,保存在~/.ssh目录下一个叫做authorized_keys的文件里。

安全连接建立后,服务器就会触发身份验证过程。服务器会用其文件里的公钥加密一条信息发给客户端,如果客户端能够解密出正确的信息,则证明了它持有对应的私钥,然后服务器才会对该客户端开放自己的环境。

哈希(Hashing)

SSH还使用了另一种叫做密码哈希函数(cryptographic hashing / cryptographic hash functions)的数据处理技术。密码哈希函数可以为一组信息创建一个简明的“签名”(也可以说是一段摘要),这个签名是独一无二的,而且理论上没有任何方法可以从这个签名反向推导出原来的信息内容。

同样的信息,同样的哈希函数,应生成同样的哈希结果(hash);对信息稍微做一点更改,就会生成完全不同的哈希结果。从设计上,用户不能通过一个哈希推断出信息原文,但是可以根据信息原文生成的哈希推断出该信息是否与指定的某条信息完全一致。

基于上述特性,哈希常用于数据完整性的检测以及通讯身份验证。SSH中常用的哈希叫做HMAC,即“基于哈希的信息验证代码(hash-based message authentication codes)”,此类代码用于确保接收的信息内容与发送的信息内容完全一致。

在上文提到的对称加密过程中,SSH会选择一个信息验证码(MAC,message authentication code)的算法,具体是何种算法取决于客户端与服务器端上的算法列表次序,即客户端算法列表上出现的第一个服务器端也支持的算法。

加密连接建立后,每一条发送的信息都会包含一个MAC,这样接收方就能够用这个MAC来验证信息完整性。MAC的计算过程使用了共享密钥、信息包的顺序代号、以及信息自身的内容。

在内容发送过程中,MAC是在每一个信息包的最后发送的,位于对称加密区之外。这是因为根据科研人员的建议,最好按照先加密、后计算MAC的顺序进行数据的处理。

SSH的工作过程

你大概已经对SSH的工作过程有过一些简单的了解。SSH协议采用C-S(客户端-服务器端)架构进行双方的身份验证以及数据的加密。

服务器端组件监听指定的端口,负责安全连接的建立、对连接方的身份认证、以及为通过身份认证的用户建立正确的环境。

客户端负责发起最初的TCP握手、安全连接的建立、验证服务器的身份与之前记录中的一致、并将自己的验证信息提供给服务器。

一个SSH会话的建立过程分为两个阶段。第一阶段,双方沟通并同意建立一个加密连接通道以供后续信息传输用。第二阶段,对请求接入的用户进行身份验证以确定服务器端是否要给该用户开放访问权限。

共同建立加密通道

当客户端发起TCP连接时,服务器端返回信息说明自己支持的协议版本,如果客户端上支持的协议与之匹配,则连接继续。服务器会提供自己的公共主机密钥(public host key)以让客户端确认自己访问的是正确的机器。

然后,双方采用一种Diffie-Hellman算法共同为该会话建立密钥。每一方的一部分私有数据,加上来自对方的一部分公共数据,通过这种算法计算,能够得出完全相同的密钥用于本次会话。

整个会话的通讯内容都使用该密钥进行加密。这个阶段使用的公钥/私钥对与用户验证身份用的SSH密钥是完全无关的。

经典Diffie-Hellman算法的计算步骤如下:

  1. 双方共同选择一个大值素数作为种子值(seed value)
  2. 双方共同选择一个加密生成器(通常是AES),用于后续的数值操作
  3. 双方分别各自选择一个素数,该素数的值对对方保密,用于生成本次通讯的私钥(与SSH身份认证私钥无关)
  4. 双方分别用各自的私钥、共同的加密生成器、和共同的素数生成各自的公钥
  5. 双方将各自的公钥共享给对方
  6. 双方用各自的私钥和对方发过来的公钥生成另一个密钥。根据该算法,双方各自计算出来的两个密钥是完全一样的,即“共同的秘密”
  7. 该密钥被用于本次通讯所有内容的加密

这个共享密钥的加密方式被称为二进制数据包协议(binary packet protocol)。该过程能够让双方平等的参与密钥生成的过程,而不是由单方掌握。这种共享密钥生成的过程是安全的,双方没有交换过任何未经加密的信息。

生成的密钥是对称式密钥,一方用于加密信息的密钥等同于另一方用于解密信息的密钥,而任何第三方由于不持有该密钥,是无法解密双方传递的内容的。

会话加密通道建立后,SSH开始进入用户认证阶段。

服务器认证用户以开放访问权限

下一步,服务器验证用户身份以决定是否准许其访问。验证有不同的方式,选择的验证方式取决于服务器的支持。

最简单的验证是密码验证:服务器要求客户端输入密码,客户端输入的密码经过上述的通道加密传输给服务器。

虽然密码是加密过的,然而该方法仍然不被推荐,因为用户经常为了省事而使用过于简单的密码,而这类密码很容易就能够被自动化脚本破解。

最流行的验证方式是SSH密钥对,这也是当前最推荐的方式。SSH密钥对是非对称密钥,私钥和公钥分别用于不同的功能。

公钥用于加密,而私钥用于解密。公钥可以随意上传、共享,因为公钥的流通并不会危及到私钥的保密性。

SSH密钥对的验证过程起始于上一部分加密通道建立之后,其具体执行步骤如下:

  1. 客户端发送自己的密钥ID给服务器端
  2. 服务器在自己的authorized_keys文件中检查是否有此ID的公钥
  3. 如果有,则服务器生成一个随机数,用该公钥加密之
  4. 服务器将加密后的随机数发给客户端
  5. 客户端用私钥解密该随机数,然后在本地为随机数做MD5哈希
  6. 客户端将该MD5哈希发给服务器端
  7. 服务器端为一开始自己生成的随机数也做一个MD5哈希,然后用通讯通道“公共的密钥”将该哈希加密,再跟客户端发来的内容进行对比。如果双方内容一致,则通过验证,开放访问权限给客户端

简单来说,服务器端用公钥加密信息,客户端用私钥解密信息以证明自己持有私钥。该过程同时使用了对称加密和非对称加密,两种方式各有自己的功用。

总结

了解SSH建立连接、进行信息加密的方式,有助于我们理解在登陆远程服务器的过程中都发生了什么。希望在阅读本文之后,你对于其中涉及的组件和算法有了更深入的认识。

本文来源自DigitalOcean Community。英文原文:Understanding the SSH Encryption and Connection Process by Justin Ellingwood

翻译:lazycai

展开阅读全文

没有更多推荐了,返回首页