在上一篇博文 Linux 之四 Ubuntu 20.04 WiFi 无法使用、设置无法显示、远程桌面、SSH、Git、PPA 等各问题记录 中,曾试图使用远程桌面功能来连接使用我的 Ubuntu 20.04,但实际情况是远程桌面卡的是惨不忍睹,无奈还是得用 SSH 远程登录。

在网上找了很多 SSH 相关的文章,好记性不如烂笔头,这里整理一下,做个备忘录!

SSH 为 Secure Shell 的缩写(虽然名字中有个 Shell,但他实际并不是 Shell),由互联网工程任务组(Internet Engineering Task Force,IETF)的网络小组(Network Working Group)所制定一个网络协议。SSH 是一种建立在应用层基础上的加密的网络协议。但是,就和 SSL 类似,它有不是仅仅工作在应用层(映射到 TCP/IP 模型)!如下图是 OSI 参考模型与 TCP/IP 模型对比:
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图1

SSH 的经典用途是登录到远程电脑中执行命令。除此之外,SSH 也支持隧道协议、端口映射和 X11 连接。借助 SFTP 或 SCP 协议,SSH 还可以传输文件。

SSH 协议有两个主要版本,分别是 SSH-1 和 SSH-2,两者不兼容。2006 年,SSH-2 协议成为了新的标准,而且目前我们使用的 SSH 大多数都是 SSH-2 版本的 SSH,其标准主要有 :

关于 RFC:

  1. 征求意见稿(Request For Comments,RFC)是由互联网工程任务组(Internet Engineering Task Force,IETF)发布的一系列备忘录。所有关于 Internet 的正式标准都是以 RFC 文档出版。
  2. RFC 由互联网协会(Internet Society,简称 ISOC)赞助发行,会交到互联网工程工作小组(IETF)和互联网结构委员会(IAB)。文档可由网站 https://www.ietf.org/ 下载。
  3. RFC 始于 1969 年,由当时就读加州大学洛杉矶分校(UCLA)的斯蒂芬 · 克罗克(Stephen D. Crocker)用来记录有关 ARPANET 开发的非正式文档,他是第一份 RFC 文档的撰写者。最终演变为用来记录互联网规范、协议、过程等的标准文件。
  4. RFC 文件是由 Internet Society 审核后给定编号并发行。RFC1000 这份文件就是 RFC 的指南。
  5. 还有大量的 RFC 文档都不是正式的标准,出版目的都是为了提供信息。

此外,关于 SSH 的几个专有名词也需要区分一下:

  • SSH: 通用术语,指 SSH 协议 或 基于 SSH 协议的软件产品
  • SSH-1: SSH 协议版本 1。SSH 协议有多个修订版,其中最为大家熟知的是 1.3 和 1.5
  • SSH-2: SSH 协议版本 2。这是由 IETF 的 SECSH 工作组的若干标准文件中定义名称
  • SSH1: 通常代指 Tatu Ylönen 实现的 SSH 协议版本 1 的软件名字
  • SSH2: SSH Communications Security, Inc. (http://www.ssh.com) 实现的 SSH 协议版本 2 的软件名字,这是一个 SSH 协议版本 2 的商业版软件实现
  • ssh: 全部小写的 ssh 是 OpenSSH 中实现的 SSH 客户端的软件名字,这也是如今我们使用最多的 SSH 软件。

历史

  1. 芬兰赫尔辛基理工大学的 Tatu Ylönen 发现自己学校存在嗅探密码的网络攻击,便于 1995 年编写了一套保护信息传输的程序,并称其为 “secure shell”,简称 SSH,设计目标是取代先前的 rlogin、Telnet、FTP 和 rsh 等安全性不足的协议。
  2. 1995 年 7 月,Tatu Ylönen 以免费软件的形式将其发布。程序很快流行起来。
  3. 1995 年 12 月,Tatu Ylönen 创立了 SSH 通信安全公司来继续开发和销售 SSH。由 SSH 公司发布的版本逐渐变成了专有软件。
  4. 1999 年,开发者们希望使用自由版本的 SSH,于是重新使用较旧的 1.2.12 版本,这也是最后一个采用开放源代码许可的版本。随后瑞典程序员 Björn Grönvall 基于这个版本开发了 OSSH。不久之后,OpenBSD 的开发者又在 Grönvall 版本的基础上进行了大量修改,形成了 OpenSSH。
  5. 2006 年,SSH-2 协议成为了新的标准。与 SSH-1 相比,SSH-2 进行了一系列功能改进并增强了安全性,SSH-2 协议与 SSH-1 不兼容,且目前已经逐渐替代了 SSH-1。许多软件也只支持 SSH-2 协议了。

架构

SSH 的软件架构采用了服务器 - 客户端模式(Server - Client),默认的端口为 22。SSH 通过在网络中创建安全隧道来实现 SSH 客户端与服务器之间的连接。整体架构如下图所示:
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图2

SSH 协议有两个主要版本,分别是 SSH-1 和 SSH-2,这两个版本的协议是不兼容的!与 SSH-1 相比,SSH-2 进行了一系列功能改进并增强了安全性,还支持通过单个 SSH 连接任意数量的 shell 会话。两者架构对比如下所示:
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图3

SSH-1 被设计为一个整体,在这个单个协议中定义了多个不同的功能,而 SSH-2 则被设计为分成不同的模块层,共由三种协议组成:
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图4

  • Transport Layer Protocol: 该协议兼容服务器身份验证、私密性和完整性,具有完美的前向私密性。这一层可以提供可选的压缩,并通过 TCP/IP 连接运行,但也可以在任何其他可靠的数据流之上使用。
  • User Authentication Protocol: 该协议向服务器验证客户端,并在传输层上运行。
  • Connection Protocol: 该协议通过用户认证协议将加密通道多路复用到多个逻辑通道。

SSH 只是一种协议,存在多种实现,既有商业实现,也有开源实现。目前,OpenSSH 是最流行的 SSH 实现,而且成为了大量操作系统的默认组件。OpenSSH 仍在积极维护中,而且已经支持 SSH-2 协议。从 7.6 版开始,OpenSSH 不再支持 SSH-1 协议。官网:https://www.openssh.com/ 。OpenSSH 主要包含以下工具:

  • 客户端工具 ssh、scp、sftp
    • ssh:ssh 客户端,是一个用于登录到远程计算机并在远程计算机上执行命令的程序。
    • scp:用于在网络上的主机之间复制文件
    • sftp:一个文件传输程序,类似于 ftp,它通过加密的 ssh 传输执行所有操作。
  • 密钥管理工具 ssh-add、ssh-keysign、ssh-keyscan、ssh-keygen
    • ssh-add:用于将私钥标识添加到身份验证代理(ssh-agent)。在没有参数的情况下运行时,它会添加文件 〜/.ssh/id_rsa〜/.ssh/id_dsa〜/ .ssh/id_ecdsa〜/.ssh/id_ecdsa_sk〜/.ssh/id_ed25519〜/.ssh /id_ed25519_sk。加载私钥后,ssh-add 将尝试从以 - cert.pub 结尾的文件中加载相应的证书信息。
    • ssh-keysign:ssh 使用 ssh-keysign 访问本地主机密钥并生成基于主机身份验证所需的数字签名。默认情况下,该功能是被禁用的,且该程序一般不需要用户调用,而是由 ssh 程序自动调用。
    • ssh-keyscan:用于收集其他主机的公共 SSH 主机键的实用程序。它旨在帮助构建和验证 SSH_KNOKN_HOSTS 文件。
    • ssh-keygen:OpenSSH 身份验证密钥实用程序
  • 服务端工具 sshd、sftp-server、ssh-agent
    • sshd:即 OpenSSH Daemon,是 ssh 的守护程序,也即 SSH 的服务端程序。它通过不安全的网络在两个不受信任的主机之间提供安全的加密通信。
    • ssh-agent:用来保存用于公钥身份验证的私钥。通过使用环境变量,它可以在使用 ssh 登陆其他计算机时,定位并自动处理身份验证。
    • sftp-server:sftp 服务端程序,用来接收并处理来自 sftp 的连接。改程序通常也不需要由用户调用,而是由 ssh 来调用

详细的介绍及使用方法,可以参考 OpenSSH 官方文档:https://www.openssh.com/manual.html。

在这个架构中,SSH 软件分成两个部分:向服务器发出请求的部分,称为客户端(client),OpenSSH 的实现为 ssh;接收客户端发出的请求的部分,称为服务器(server),OpenSSH 的实现为 sshd。

目前,SSH 已经成为了类 Unix 系统的标配组件,直接在 Ubuntu 终端中输入 ssh -V 就可以查看 Ubuntu 自带了 ssh 客户端的版本,我这里的版本号是 OpenSSH_8.2p1。
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图5

然而 Ubuntu 默认并没有安装 ssh server,因此需要自己安装:sudo apt-get install openssh-server,安装之后,查看一下:
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图6

第一个查看安装了 ssh 相关的包,第二个查看 ssh 服务器有没有运行(ssh-agent 表示 ssh-client 启动,sshd 表示 ssh-server 启动)!
  注意,第一次安装之后,SSH 服务端会被默认启动,但是重启电脑之后,SSH 服务端默认不会自动启动。手动启动的命令为:sudo service ssh start。当然,我们可以选择将 SSH 服务端配置为开机自启动。
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图7

在早期的 Linux 中,rc.local 是在系统初始化级别脚本运行之后再执行的,可以安全地在里面添加想在系统启动之后执行的脚本。然而,在比较新的 Linux 发行版已经没有 rc.local 文件了,因为已经将其服务化了。直接使用命令:sudo systemctl enable ssh 表示开机自启动 SSH 服务端。下面是一些常用命令:

  1. 安装 SSH 服务端:sudo apt-get install openssh-server
  2. 开机自动启动 SSH 命令:sudo systemctl enable ssh
    Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图8
  3. 关闭 SSH 开机自动启动命令:sudo systemctl disable ssh
  4. 单次开启 SSH:sudo systemctl start sshsudo service ssh start
    Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图9
  5. 单次关闭 SSH:sudo systemctl stop sshsudo service ssh stop
  6. 查看 SSH 是否启动:sudo systemctl status ssh 看到 Active: active (running) 即表示成功 或者 ps -e | grep ssh 看到有 sshd 即表示成功。

根据网友介绍,目前也可以手动添加 rc.local,在 exit 0 语句前加入:/etc/init.d/ssh start ,这样使 SSH 服务端开启自动启动。具体方法参考:https://cloud.tencent.com/developer/article/1721972

同样,从 Windows 10 1803 版本开始,微软也提供 OpenSSH 工具。直接在 Windows Terminal 中(CMD)输入 ssh 就可以查看当前系统中的 SSH 版本,与 Ubuntu 不同的是,Windows 同时提供了 SSH 客户端和服务端:
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图10

Windows 下如果要使用服务端需要进行一些配置。

配置

SSH 的运行需要各种配置文件。SSH 客户端的全局配置文件是 ssh_config,服务端的配置文件是 sshd_config,他们都位于 /etc/ssh 目录下。这里需要注意,在 Windows 系统中,稍微有些不同。
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图11

Windows 系统中的 OpenSSH 默认没有这两个配置文件。例如,默认没有服务端的配置文件 sshd_config,如果要运行服务端,会提示如下错误(Windows 上正确启用 SSH 服务端需要从 设置 → 应用 →可选功能 中添加服务端,然后使用命令:net start sshd):
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图12

如果我们正常添加了 SSH 服务端,那么在 C:\ProgramData\ssh 下就会找到各种配置文件,如下图所示:
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图13

此外,在 Windows 下,在用户个人的配置文件在 用户名 /.ssh/config,优先级高于全局配置文件。

基本用法

SSH 最常见的用途就是登录服务器,这要求服务器安装并正在运行 SSH 服务器软件。以上面介绍的 OpenSSH 工具,来简单介绍一下使用方法,从 Windows 远程登录 Ubuntu。首先,Ubuntu 必须要先启动 SSH 服务器,方法如上面说的。否则将收到如下错误:
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图14

最简单的 SSH 登录服务器的命令是:ssh hostnamehostname 可以是 IP 地址,也可以是域名。同时,我们还可以指定登录远程服务器的用户名,命令为:ssh username@hostname。用户名也可以使用 SSH 的 -l 参数指定,这样的话,用户名和主机名就不用写在一起了:ssh -l username hostname。此外,SSH 默认的端口为 22,如果不使用默认的端口,则需要 -p 参数可以指定其他端口:ssh -p 6666 hostname
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图15

如果是第一次连接某一台服务器,命令行会显示一段文字(如上图),表示不认识这台机器,提醒用户确认是否需要连接。其中的 ECDSA key fingerprint is SHA256:NhIe5F7qTvYgV7INlL5k0WYj4vc+P22d9d5yyPuSlDM. 就是服务器的公钥的哈希值。一旦用户确认连接之后,ssh 会将本机连接过的所有服务器公钥的指纹,都储存在本机的 ~/.ssh/known_hosts 文件中。每次连接服务器时,通过该文件判断是否为陌生主机(陌生公钥)。

安全套接字层(Secure Socket Layer ,SSL)协议是一种认证和加密技术,通过伯克利套接字样式 API 向 TCP 客户提供安全服务。 最初是由 Netscape Communications Corporation(网景)公司开发,用于给客户端和服务器通信的 HTTP 协议加密,以保证安全。

虽然 SSH 在网络通信安全中很流行,但是它并不是唯一的保证网络通信安全的方案。身份验证、加密和网络安全早在 SSH 之前就已经出现了,SSL/TLS 就是其中的一个非常流行安全解决方案。

1999 年,互联网标准化组织 ISOC 接替 NetScape 公司,发布了 SSL 的升级版 Transport Layer Security(TLS)1.0 版的标准文档 RFC2246,并在后续修订了多个版本。如下表是 SSL/TLS 不同版本的发布情况:

协议 发布日期 状态
SSL1.0 1994 网景公司制定,但并未对外发布
SSL2.0 1995 很快发现有严重漏洞,网景公司开始设计 3.0。 2011 在 RFC6176 中被标记为废弃
SSL3.0 1996 2015 在 RFC7568 中被标记为废弃
TLS1.0 1999 2020 在 RFC8996 中被标记为废弃
TLS1.1 2006 2020 在 RFC8996 中被标记为废弃
TLS1.2 2008
TLS1.3 2018

TLS 和 SSL 就是一个东西,TLS 是 SSL 的改进升级。当前使用最多的是 TLS1.2 和 TLS1.3。在实际使用中,仍然有很多文献使用 SSL 这个名字,或者使用 SSL/TLS。实际情况是,SSL3.0 发布至今没有更新过,且被发现了很多漏洞,现在还少使用 SSL3.0 了。

架构

SSL/TLS 协议采用主从式架构模型,基本思路是采用公钥加密法,即:客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。主要由 SSL record protocol、Handshake protocol、Change-cipher spec protocol、Alert protocol 组成。
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图16

关于 SSL/TLS 协议 每部分中详细的定义,可以参见 https://en.wikipedia.org/wiki/Transport_Layer_Security#Protocol_details。

SSL/TLS 协议的具体实现,在不同的操作系统中有多种存在。OpenSSL 就是 SSL/TLS 协议的一个开源实现。下图是维基百科整理的各种 SSL/TLS 协议 实现对于 SSL/TLS 协议 版本的支持情况:
Linux 之七 SSH、SSL、OpenSSH、OpenSSL、LibreSSL - 图17

从上上一节的图中可以看到,Ubuntu 中的 OpenSSH 使用是 OpenSSL 1.1.1f 提供的加密算法库。 微软在 Win10 中集成的 OpenSSH 使用的就是 LibreSSL 加密算法库。OpenSSL 开源加密库之前发现的漏洞影响遍及整个互联网。OpenBSD 的开发者为此而创建了 OpenSSL 的 分支 LibreSSL,用户编译时可选择链接到 LibreSSL 库。许多大型公司出于安全,效率等考虑,会将 OpenSSH 集成到自己系统之后,用自己实现的算法替换这个算法库。

Heartbleed 漏洞的披露让人们意识到 OpenSSL 就是这样一个组件。这促使 Linux 基金会发起了 Core Infrastructure Initiative 倡议,资助关键基础组件的开发和维护。就目前来看,OpenSSL 的维护要比 LibreSSL 要积极一些。而且 Linux 对于 LibreSSL 的支持明显不如 OpenSSL。具体见 Github:

  1. https://www.cnblogs.com/qishui/p/5428938.html
  2. https://segmentfault.com/a/1190000011395818
  3. https://wangdoc.com/ssh/index.html
  4. https://linuxtect.com/how-to-enable-ssh-on-ubuntu-all-versions/
  5. https://cloud.tencent.com/developer/article/1721972
  6. https://docstore.mik.ua/orelly/networking_2ndEd/ssh/index.htm
  7. https://searchsecurity.techtarget.com/definition/Secure-Shell
  8. https://developer.ibm.com/articles/au-sshsecurity/
  9. https://www.ruanyifeng.com/blog/2014/02/ssl_tls.html
    10.https://en.wikipedia.org/wiki/Transport_Layer_Security
    https://itexp.blog.csdn.net/article/details/121332611