在上一篇博文 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 模型对比:
SSH 的经典用途是登录到远程电脑中执行命令。除此之外,SSH 也支持隧道协议、端口映射和 X11 连接。借助 SFTP 或 SCP 协议,SSH 还可以传输文件。
SSH 协议有两个主要版本,分别是 SSH-1 和 SSH-2,两者不兼容。2006 年,SSH-2 协议成为了新的标准,而且目前我们使用的 SSH 大多数都是 SSH-2 版本的 SSH,其标准主要有 :
关于 RFC:
此外,关于 SSH 的几个专有名词也需要区分一下:
SSH 的软件架构采用了服务器-客户端模式(Server - Client),默认的端口为 22。SSH 通过在网络中创建安全隧道来实现 SSH 客户端与服务器之间的连接。整体架构如下图所示:
SSH 协议有两个主要版本,分别是 SSH-1 和 SSH-2,这两个版本的协议是不兼容的!与 SSH-1 相比,SSH-2 进行了一系列功能改进并增强了安全性,还支持通过单个SSH 连接任意数量的 shell 会话。两者架构对比如下所示:
SSH-1 被设计为一个整体,在这个单个协议中定义了多个不同的功能,而 SSH-2 则被设计为分成不同的模块层,共由三种协议组成:
SSH 只是一种协议,存在多种实现,既有商业实现,也有开源实现。目前,OpenSSH 是最流行的 SSH 实现,而且成为了大量操作系统的默认组件。OpenSSH 仍在积极维护中,而且已经支持 SSH-2 协议。从 7.6 版开始,OpenSSH 不再支持 SSH-1 协议。官网:https://www.openssh.com/ 。OpenSSH 主要包含以下工具:
ssh
:ssh 客户端,是一个用于登录到远程计算机并在远程计算机上执行命令的程序。scp
:用于在网络上的主机之间复制文件sftp
:一个文件传输程序,类似于 ftp,它通过加密的 ssh 传输执行所有操作。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
:即 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。
然而 Ubuntu 默认并没有安装 ssh server,因此需要自己安装:sudo apt-get install openssh-server
,安装之后,查看一下:
第一个查看安装了 ssh 相关的包,第二个查看 ssh 服务器有没有运行(ssh-agent 表示 ssh-client 启动,sshd 表示 ssh-server 启动)!
注意,第一次安装之后,SSH 服务端会被默认启动,但是重启之后,SSH 服务端不会自动启动。手动启动的命令为:sudo service ssh start
,也可以打开 /etc/rc.local
文件,在 exit 0
语句前加入:/etc/init.d/ssh start
,这样使 SSH 服务端开启自动启动。
- 在早期的 Linux 中,rc.local 是在系统初始化级别脚本运行之后再执行的,可以安全地在里面添加想在系统启动之后执行的脚本。然而,在比较新的 Linux 发行版已经没有 rc.local 文件了,因为已经将其服务化了。直接使用命令:
sudo systemctl enable ssh
- 也可以手动添加 rc.local,具体方法参考:https://cloud.tencent.com/developer/article/1721972
同样,从 Windows 10 1803 版本开始,微软也提供 OpenSSH 工具。直接在 Windows Terminal 中(CMD)输入 ssh
就可以查看当前系统中的 SSH 版本,与 Ubuntu 不同的是,Windows 同时提供了 SSH 客户端和服务端:
SSH 的运行需要各种配置文件。SSH 客户端的全局配置文件是 ssh_config
,服务端的配置文件是 sshd_config
,他们都位于 /etc/ssh
目录下。这里需要注意,在 Windows 系统中,稍微有些不同。
Windows 系统中的 OpenSSH 默认没有这两个配置文件。例如,默认没有服务端的配置文件 sshd_config
,如果要运行服务端,会提示如下错误(Windows 上正确启用 SSH 服务端需要从 设置 → 应用 →可选功能
中添加服务端,然后使用命令:net start sshd
):
如果我们正常添加了 SSH 服务端,那么在 C:\ProgramData\ssh
下就会找到各种配置文件,如下图所示:
此外,在 Windows 下,在用户个人的配置文件在 用户名/.ssh/config
,优先级高于全局配置文件。
SSH 最常见的用途就是登录服务器,这要求服务器安装并正在运行 SSH 服务器软件。以上面介绍的 OpenSSH 工具,来简单介绍一下使用方法,从 Windows 远程登录 Ubuntu。首先,Ubuntu 必须要先启动 SSH 服务器,方法如上面说的。否则将收到如下错误:
最简单的 SSH 登录服务器的命令是:ssh hostname
,hostname
可以是 IP 地址,也可以是域名。同时,我们还可以指定登录远程服务器的用户名,命令为:ssh username@hostname
。用户名也可以使用 SSH 的 -l
参数指定,这样的话,用户名和主机名就不用写在一起了:ssh -l username hostname
。此外,SSH 默认的端口为 22,如果不使用默认的端口,则需要 -p
参数可以指定其他端口:ssh -p 6666 hostname
。
如果是第一次连接某一台服务器,命令行会显示一段文字(如上图),表示不认识这台机器,提醒用户确认是否需要连接。其中的 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 组成。
关于 SSL/TLS 协议 每部分中详细的定义,可以参见 https://en.wikipedia.org/wiki/Transport_Layer_Security#Protocol_details。
SSL/TLS 协议的具体实现,在不同的操作系统中有多种存在。OpenSSL 就是 SSL/TLS 协议的一个开源实现。下图是维基百科整理的各种 SSL/TLS 协议 实现对于 SSL/TLS 协议 版本的支持情况:
从上上一节的图中可以看到,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: