浅谈SSH加密与连接过程(译)
简介
SSH,即Secure Shell,它是一种安全协议,并且是安全而又最常见的用于管理远程服务器的方式。SSH提供了一种机制,用于为双方(客户端和服务器)建立带密码保护的连接,同时验证另一方的合法性,以及传输命令和返回输出。
在另外的几篇文章中,我们谈到了如何配置基于key的SSH连接,如何使用SSH连接服务器,以及一些SSH的贴士与技巧。
而在这篇文章中,我们将探讨SSH使用的底层加密技术以及它是如何实现安全连接的。这有利于理解SSH在双方建立连接和进行验证时做的不同层次的加密和步骤。
对称加密,非对称加密和哈希
为了确保信息能安全传输,SSH在连接的不同步骤中使用了不同的数据处理技术,包括对称加密,非对称加密和哈希。
对称加密
加密是对称加密还是非对称加密取决于加密和解密的工具间的关系。
在对称加密中,一个密钥能用于加密发送到另一方的信息,同时也能用于解密从另一方接收的信息。这意味着,只要知道密钥,就可以用来加密和解密其他有相同密钥的人的信息。
这种加密设计也常被称作“共享密钥加密”,或“密钥加密”。这种加密通常只用一个密钥来完成所有操作,或者是用一对密钥,而它们之间的关系很容易就可以推导出来,生成派生钥并没有什么作用。
对称密钥在SSH中用来加密整个连接过程。但不像某些人认为,对称加密只用于连接加密,而没有用于使用公钥/私钥的验证加密。对称加密甚至可以防止用户密码在验证过程中被窃取。
SSH中的对称密钥是由客户端和服务器双方参与生成的,因此第三方并不能窃取到相关信息。对称密钥使用一种密钥交换算法生成,通过这个算法,服务器和客户端交换部分公开数据并对其用私有数据进行处理,就可以获得相同的密钥。这个算法在后面的部分会详细描述。
由上述方式生成的对称密钥是基于会话的,将会用于加密客户端和服务器之间的信息。密钥生成后,客户端和服务器传输的数据都必须使用这个密钥来加密/解密。这个步骤是在进行验证前就完成的。
SSH可以通过配置实现多种不同的对称密钥系统,包括AES、Blowfish、3DES、CAST1238和Arcfour。客户端和服务器都可以配置一个密钥系统列表,按优先级排序。使用SSH连接时,采用客户端的密钥列表中第一种出现在服务器列表中的加密算法。
在Ubuntu 14.04中,客户端和服务器的默认列表如下:aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,aes128-gcm@openssh.com,aes256-gcm@openssh.com,chacha20-poly1305@openssh.com,aes128-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,arcfour。
因此当两个Ubuntu 14.04的机器按默认配置相互用SSH连接时,他们都会使用aes128-ctr加密算法来加密连接。
非对称加密
非对称加密与对称加密的不同点在于,非对称加密在数据单向传输的过程中使用到了两个相互间有关联的密钥。其中一个密钥被称作公钥,另一个被称作私钥。
公钥可以向任何人公开,它跟私钥是有关联的,但是私钥无法从公钥推导出来。公钥和私钥间存在着某种数学关联,使得用公钥加密的信息只能被私钥解密。上述过程是单向的,即公钥无法解密由它自身加密的信息,也无法解密由私钥加密的信息。
私钥则需要做好保护,不能向任何人公开,这是公钥能正常工作的关键。私钥只能用于解密经由公钥加密的信息。基于这样的条件,只有知道私钥的人才可以解密这些信息。
SSH在几个不同的地方都使用了非对称加密。在加密会话时进行的对称加密过程中,客户端和服务器双方交换密钥时就使用了非对称加密。在这个过程中,客户端和服务器双方都生成了一个临时的公钥/私钥对,并互相交换了公钥用来加密对称加密过程中所需的信息。
不过在SSH的非对称加密这方面,讨论得最多的还是SSH的密钥认证。SSH进行客户端至服务器的用户验证时使用的是密钥对(公钥/私钥)。用户在客户端生成一对密钥,并将公钥上传到他想要访问的服务器上。即用户要将公钥写到远程服务器中对应账户的~/.ssh文件夹下的authorized_keys文件中
通过对称加密建立了客户端与服务器间的连接后,就需要验证客户端的身份。服务器使用authorized_keys中的公钥加密一条验证信息并发送给客户端,如果客户端可以正确解密这段信息,则可以证明客户端拥有对应的私钥,然后服务器就会允许客户端访问。
哈希
SSH使用的最后一种数据处理技术为加密哈希,加密哈希是用于生成简单签名或简易数据集的方法。加密哈希与另外两种数据处理技术最主要的不同点在于加密哈希生成的结果是无法复原的,加密哈希生成的结果几乎不会被干扰,也几乎不会重复。
使用同一种哈希算法对信息加密总是能得出相同结果,但随意修改信息的某处将产生完全不同的哈希值。尽管我们无法从一个哈希值解析出原来的信息,但是我们可以知道这个哈希值是不是某条信息产生的。
由此可见,哈希算法主要用于验证数据完整性和验证通讯的真实性。哈希在SSH中的主要应用是HMAC,和基于哈希的信息验证编码,他们用于保证接收到的信息是完整且没有被修改过的。
信息验证编码算法,即message authentication code(MAC)算法,应用在我们前面说的对称加密上。MAC算法也是从客户端MAC算法列表中选取,采用第一个被服务器支持的算法。
客户端和服务器双方都必须在发送的加密信息中加入MAC,用于验证数据包的完整性,这个MAC是通过共享密钥、信息的数据包序列号以及信息内容计算出来的。
MAC本身并不会放在对称加密区域内,而是放在数据包的末尾。一般来说推荐采用这种先加密数据,然后再计算MAC的做法。
SSH是如何工作的?
通过前面的介绍,你可能已经对SSH是怎样工作的有个大体的想法。SSH协议实现了一个通讯模型,使客户端和服务器之间能相互认证并加密他们之间交换的数据。
服务器端会监听一个用于连接的特定端口。服务器端负责的工作是协商安全连接,认证连接的客户端,以及为符合访问资格的客户端提供访问环境。
客户端则负责初始化与服务器的TCP握手,协商安全连接,验证服务器的身份与是否符合以往访问的相同服务器的身份,以及为身份验证提供凭证。
SSH会话的建立分为两个阶段,第一个阶段为协商并做好加密以保护之后的通信。第二个阶段是验证用户身份并判断用户是否有访问服务器的权限。
协商会话所使用的加密
当客户端发起TCP连接后,服务器会返回其支持的协议版本,若客户端兼容该版本的协议,将进入下一步。同时服务器还会提供他的公共主机密钥,客户端可以通过它判断服务器是否为预期的主机。
此时,双方会通过Diffie-Hellman算法交换一个会话密钥。Diffie-Hellman算法(或其变式)的功能是,令客户端和服务器双方通过自身的私有数据和从对方处获得的数据进行处理,而得到相同的会话密钥。
这个会话密钥将会用于加密整个会话过程。我们下面所说的私钥和公钥跟SSH用来进行身份验证的公钥、私钥是完全不同的,请区分清楚。
一般Diffie-Hellman算法的基本步骤为:
- 双方商定一个较大的素数作为种子值。
- 双方商定一种加密方式(一般为AES),用于处理数据。
- 双方独自生成另外一个素数,且不能让另一方知道。这个素数就是交互过程中的私钥(这跟SSH用于验证用户身份的私钥是不同的)。
- 双方使用各自的私有素数(私钥)、以及共享的素数(种子值),通过商定的加密方式产生公钥,此公钥是可以公开给另一方的。
- 双方交换他们生成的公钥。
- 收到公钥后,使用自己的私钥,对方的公钥以及共享的素数(种子值)计算出共享密钥,尽管这个共享密钥是通过对方的私钥和公钥计算出来的,但双方最后都会获得相同的共享密钥。
在接下来的连接中用到的共享密钥加密被称作二进制包协议。上述密钥交换的算法令双方都可以平等的参与到密钥生成的过程中,而不只让某一方负责密钥生成。同时它在产生共享密钥的过程中,并没有把共享密钥暴露在不安全的连接路径上。
这个产生的共享密钥就是对称密钥,即可以同时用于加密和解密信息的密钥。这一步的目的是使得往后的通信都在一个经过加密的通道进行,外界无法进行解密。
在会话加密建立后,就进入用户验证阶段。
验证用户对服务器的访问权限
下一个阶段涉及到验证用户身份和访问权限,假设服务器允许,有几种方法都可以进行验证。
最简单的方法大概就是密码认证。服务器将会向客户端请求要登录账号的密码。这个密码是经加密之后再发送的,所以外界用户(即除通信双方外的用户)无法窃取。
但是尽管密码会被加密,这种方法一般是不推荐的,因为密码的复杂性是有限的。对比起其他验证方法,使用自动化脚本就可以轻松破解出密码。
接下来这一段参考自SSH基本原理和免密码登录,是译者自己添加的,为了使内容更加完整:
SSH密码认证的步骤如下:
- 服务器收到客户端请求后,把自己的公钥发送给客户端(这跟SSH密钥对不同,是服务器自身的公钥/私钥对)。
- 客户端使用收到的公钥加密密码,并发送回服务器。
- 服务器使用自己私钥解密信息,若密码正确,则通过验证。
SSH密码认证还有一个弊端,就是如果服务器是其他服务器冒充的,这样别人就能拿到正确的密码了。
使用最广泛且最推荐使用的是SSH密钥对。SSH密钥对是非对称密钥,这两个互相关联的密钥负责不同的工作。
公钥用于加密信息,加密结果只能由私钥进行解密。公钥可以随意公开,因为从公钥是无法推导出私钥的。
在前面说过的连接加密建立完成后,使用SSH密钥对的验证就会开始。过程如下:
- 客户端把他用于验证的SSH密钥对的ID发送给服务器
- 服务器根据密钥对ID在对应用户的`authorized_keys`文件中进行检索
- 假设服务器在文件找到了符合密钥对ID的公钥,服务器将生成一个随机数,并用这个公钥进行加密。
- 服务器将加密后的信息发送给客户端
- 假设客户端拥有对应的私钥,那他就可以从加密信息中解密出原来的随机数。
- 客户端将得到的随机数与加密会话所使用的会话密钥间拼接在一起后,计算出其MD5哈希值。
- 客户端把MD5哈希值发送回服务器。
- 服务器自己使用相同的会话共享密钥和他生成的随机数计算出MD5值,把它和客户端返回的MD5值进行比较。如果两个值相等,则证明客户端拥有对应私钥,将通过验证。
服务器自己使用相同的会话共享密钥和他生成的随机数计算出MD5值,把它和客户端返回的MD5值进行比较。如果两个值相等,则证明客户端拥有对应私钥,将通过验证。
你可以看出,密钥的非对称性使得服务器可以用公钥加密信息并发送给客户端,而客户端可以通过他能正确解密信息来证明他拥有对应私钥。这两种加密方式(对称加密、非对称加密)各自都能在这个模型中发挥他们的特点。
总结
理解SSH的加密层次以及连接建立的顺序,能帮助你更好地理解SSH登录的过程中发生了什么。希望你现在可以更好的了解到不同组件与算法的关系,且他们之间是如何配合工作的。