2 分钟阅读

SSH 是开发人员平时很常用的命令,之前对它的原理不甚了解,导致之前在操作云主机时浪费了不少时间。本文参考了多篇文章,目的是对 ssh 的原理做下最基本的介绍。

简介

SSH 的全称是 Secure Shell,中文翻译为安全外壳协议。它是一种加密的网络传输协议,可在不安全的网络中为网络服务提供安全的传输环境。SSH 通过在网络中创建安全隧道来实现 SSH 客户端与服务器之间的连接。虽然任何网络服务都可以通过 SSH 实现安全传输,但 SSH 最常见的用途还是远程登录系统。

传统的网络服务程序,如 FTP、POP 和 Telnet,本质上都是不安全的,因为它们在网络上用明文传送数据、用户帐号和用户口令,很容易受到中间人攻击方式的攻击,就是存在另一个人或者一台机器冒充真正的服务器接收用户传给服务器的数据,然后再冒充用户把数据传给真正的服务器。

认证技术

我们想拉取公司内部 gitlab 上面的代码,首先需要把自己电脑上的公钥放在 gitlab 上面,私钥在自己的电脑上,然后就可以使用 git clone 命令来拉取 ssh 协议地址的代码仓库文件了。这里面用到了公开密钥加密技术。

公开密钥加密(英语:Public-key cryptography),也称为非对称加密(英语:asymmetric cryptography),是密码学的一种算法,它需要两个密钥,一个是公开密钥,另一个是私有密钥;一个用作加密,另一个则用作解密。使用其中一个密钥把明文加密后所得的密文,只能用相对应的另一个密钥才能解密得到原本的明文;甚至连最初用来加密的密钥也不能用作解密。由于加密和解密需要两个不同的密钥,故被称为非对称加密;不同于加密和解密都使用同一个密钥的对称加密。虽然两个密钥在数学上相关,但如果知道了其中一个,并不能凭此计算出另外一个;因此其中一个可以公开,称为公钥,任意向外发布;不公开的密钥为私钥,必须由用户自行严格秘密保管,绝不透过任何途径向任何人提供,也不会透露给被信任的要通信的另一方。

RSA 是一种常见的公钥加密算法,由 Ron Rivest, Adi Shamir, Leonard Adleman 三人在 1978 年首次提出。RSA 的工作原理依赖于如下事实:破译 RSA 私钥需要对某些极大的整数进行因数分解,而目前尚未找到快速的对极大整数作因数分解的算法。换言之,如果有人找到了这样的算法,那么全世界的 RSA 加密都会失效。

生成密钥

可以使用 ssh-keygen 命令来生成公钥和私钥。按照默认配置,私钥会被保存在 ~/.ssh/id_rsa 中,公钥则在 ~/.ssh/id_rsa.pub 中。

ssh-keygen 命令有一些参数,但该命令生成的公钥和私钥对,和生成它们的计算机无关,和计算机所使用的账号无关。也就是说,如果别人知道了你的私钥,他就可以远程登录那些放了与私钥配对的公钥的服务器。

一般建议在客户端电脑上生成密钥对,并且确保私钥始终只存在客户端电脑上,不会以任何形式传播到其他地方,这样就能在一定的程度上保证私钥的安全。

认证过程

为了说明方便,以下将使用下面这些符号:

符号 说明
Ac 客户端公钥
Bc 客户端私钥
As 服务器公钥
Bs 服务器私钥

在认证之前,客户端需要通过某种方法将公钥 Ac 放到服务器上。

认证过程分为两个步骤:

  • 会话密钥(session key)生成
    • 客户端请求连接服务器,服务器将 As 发送给客户端。
    • 服务器生成会话ID(session id),设为 p,发送给客户端。
    • 客户端生成会话密钥(session key),设为 q,并计算 r = p xor q。
    • 客户端将 r 用 As 进行加密,结果发送给服务器。
    • 服务器用 Bs 进行解密,获得 r。
    • 服务器进行 r xor p 的运算,获得 q。
    • 至此服务器和客户端都知道了会话密钥 q,以后的传输都将被 q 加密。
  • 认证
    • 服务器生成随机数 x,并用 Ac 加密后生成结果 S(x),发送给客户端
    • 客户端使用 Bc 解密 S(x) 得到 x
    • 客户端计算 q + x 的 md5 值 n(q+x),q 为上一步得到的会话密钥
    • 服务器计算 q + x 的 md5 值 m(q+x)
    • 客户端将 n(q+x) 发送给服务器
    • 服务器比较 m(q+x) 和 n(q+x),两者相同则认证成功

之后的数据交互,都通过使用对方的公钥加密,对方收到信息后,用其私钥解密,实现安全加密过程。

SSH 其实还有一种认证方式,叫账号口令验证,认证过程如下:

  1. 客户端向 ssh 服务器发出请求,服务器将自己的公钥返回给客户端
  2. 客户端用服务器的公钥加密自己的登录密码,再将信息发送给服务器
  3. 服务器接收到客户端传送的密码,用自己的私钥解码,如果结果正确,则同意登录,建立起连接

这种方式还是存在漏洞,中间人可以假扮成服务器,骗取客户端的密码。而且在每次登陆的时候都需要输入密码,所以一般不采用该验证方式。

本文并非原创,可以认为是一篇读书笔记,主要参考了以下资料:

  1. Secure Shell(Wikipedia)
  2. SSH连接认证原理概述
  3. ssh 公钥方式认证攻略

留下评论