作者选择Electronic Frontier Foundation Inc接受捐赠,作为Write for DOnations计划的一部分。
介绍
Linux 服务器通常通过连接到OpenSSH服务器使用 SSH 进行远程管理,OpenSSH服务器是 Ubuntu、Debian、CentOS、FreeBSD 和大多数其他基于 Linux/BSD 的系统中使用的默认 SSH 服务器软件。为保护 SSH 的服务器端方面投入了大量精力,因为 SSH 充当进入您的服务器的入口。
但是,考虑客户端(例如 OpenSSH 客户端)的安全性也很重要。
OpenSSH 客户端是 SSH 的“客户端”端,也称为ssh
命令。您可以在SSH Essentials:使用 SSH 服务器、客户端和密钥 中了解有关 SSH 客户端-服务器模型的更多信息。
在服务器端强化 SSH 时,主要目标是让恶意行为者更难访问您的服务器。但是,客户端的强化非常不同,因为您正在努力防御和保护您的 SSH 连接和客户端免受各种不同的威胁,包括:
- 网络上的攻击者,称为“中间人”攻击。
- 受到攻击或恶意的服务器发送格式错误的数据包、恶意控制序列或大量数据以使您的客户端过载。
- 人为错误,例如错误输入服务器地址或配置值。
在本教程中,您将强化 OpenSSH 客户端,以帮助确保传出 SSH 连接尽可能安全。
先决条件
要完成本教程,您需要:
-
您用作 SSH 客户端的设备,例如:
- 您的个人电脑
- SSH “跳转主机”或“堡垒主机”
- 按照 Ubuntu 18.04 的初始服务器设置设置 Ubuntu 18.04 服务器,包括 sudo 非 root 用户
-
您要连接的 SSH 服务器,例如:
准备好这些后,以非 root 用户身份登录到您的 SSH 客户端设备以开始。
第 1 步 – 一般硬化
在第一步中,您将实施一些初始强化配置,以提高 SSH 客户端的整体安全性。
最适合您的客户的确切强化配置在很大程度上取决于您自己的威胁模型和风险阈值。但是,本步骤中描述的配置是通用的、全方位的安全配置,应该适合大多数用户。
OpenSSH 客户端的许多加固配置都是使用全局 OpenSSH 客户端配置文件实现的,该文件位于/etc/ssh/ssh_config
. 除此之外,还可以使用您的用户的本地 SSH 配置文件设置一些配置,该文件位于~/.ssh/config
.
在继续本教程之前,建议对这两个文件进行备份,以便您可以在出现问题时恢复它们。
使用以下命令备份文件:
- sudo cp /etc/ssh/ssh_config /etc/ssh/ssh_config.bak
- cp ~/.ssh/config ~/.ssh/config.bak
这将在其默认位置保存文件的备份副本,但.bak
添加了扩展名。
请注意,~/.ssh/config
如果您过去没有使用过,您的本地 SSH 配置文件 ( ) 可能不存在。如果是这种情况,现在可以安全地忽略它。
您现在可以使用您喜欢的文本编辑器打开全局配置文件以开始实施初始强化措施:
- sudo nano /etc/ssh/ssh_config
注意: OpenSSH 客户端配置文件包括许多默认选项和配置。根据您现有的客户端设置,可能已经设置了一些推荐的强化选项。
编辑配置文件时,默认情况下可能会#
在行的开头使用单个哈希字符 ( )注释掉某些选项。要编辑这些选项,或识别注释选项,您需要通过删除散列来取消注释它们。
首先,您应该通过设置以下选项来禁用通过 SSH 的 X11 显示转发:
ForwardX11 no
ForwardX11Trusted no
X11 转发允许通过 SSH 连接显示远程图形应用程序,但这在实践中很少使用。通过禁用它,您可以防止潜在的恶意或受感染的服务器尝试将 X11 会话转发到您的客户端,这在某些情况下可以允许绕过文件系统权限,或监视本地击键。
接下来,您可以考虑禁用 SSH 隧道。SSH 隧道使用非常广泛,因此您可能需要保持启用它。但是,如果您的特定设置不需要它,您可以安全地禁用它作为进一步的强化措施:
Tunnel no
如果不需要,您还应该考虑禁用 SSH 代理转发,以防止服务器请求使用您的本地 SSH 代理来验证 SSH 连接:
ForwardAgent no
在大多数情况下,您的 SSH 客户端将配置为在连接到服务器时使用密码身份验证或公钥身份验证。但是,OpenSSH 客户端还支持其他身份验证方法,其中一些默认启用。如果不需要这些,可以禁用它们以进一步减少客户端的潜在攻击面:
GSSAPIAuthentication no
HostbasedAuthentication no
如果您想了解更多有关 SSH 中可用的一些其他身份验证方法的信息,您可能希望查看以下资源:
OpenSSH 客户端允许您在连接到服务器时自动传递自定义环境变量,例如,设置语言首选项或配置终端设置。但是,如果您的设置中不需要这样做,您可以通过确保该SendEnv
选项被注释掉或完全删除来防止发送任何变量:
# SendEnv
最后,您应该确保启用了严格的主机密钥检查,以确保在远程服务器的主机密钥/指纹更改或第一次连接到新服务器时收到适当的警告:
StrictHostKeyChecking ask
这将阻止您在已知主机密钥发生更改时连接到服务器,这可能意味着服务器已重建或升级,或者可能表明正在进行中间人攻击。
首次连接到新服务器时,您的 SSH 客户端会询问您是否要接受主机密钥并将其保存在您的~/.ssh/known_hosts
文件中。在接受之前验证主机密钥很重要,这通常涉及询问服务器管理员或浏览服务的文档(在 GitHub/GitLab 和其他类似服务的情况下)。
保存并退出文件。
现在您已经完成了初始配置文件的强化,您应该通过在测试模式下运行 SSH 来验证新配置的语法:
- ssh -G .
您可以.
用任何主机名替换以测试/模拟Match
或Host
块中包含的任何设置。
如果您的配置文件具有有效的语法,则将打印出适用于该特定连接的选项。如果出现语法错误,将会有一个描述问题的输出。
您无需重新启动任何系统服务即可使新配置生效,但如果您希望现有 SSH 会话继承新设置,则需要重新建立它们。
在此步骤中,您完成了 OpenSSH 客户端配置文件的一些常规强化。接下来,您将限制可用于 SSH 连接的密码。
第 2 步 – 限制可用密码
接下来,您将配置 SSH 客户端中可用的密码套件,以禁用对已弃用/旧版密码套件的支持。
首先在文本编辑器中打开全局配置文件:
- sudo nano /etc/ssh/ssh_config
接下来,确保现有的Ciphers
配置行被注释掉,方法是在它前面加上一个哈希 ( #
)前缀。
然后,将以下内容添加到文件顶部:
Ciphers -arcfour*,-*cbc
这将禁用旧版Arcfour 密码,以及所有使用密码块链接 (CBC) 的密码,不再推荐使用。
如果需要连接到仅支持这些旧密码的系统,您可以使用Match
块明确地为特定主机重新启用所需的密码。例如,要3des-cbc
为特定的旧主机启用密码,可以使用以下配置:
Match host legacy-server.your-domain
Ciphers +3des-cbc
保存并退出文件。
最后,正如您在步骤 1 中所做的那样,您可能希望再次测试您的 SSH 客户端配置以检查任何潜在的错误:
- ssh -G .
如果您添加了一个Match
块来为特定主机启用旧密码,您还可以在测试期间通过指定关联的主机地址专门针对该配置:
- ssh -G legacy-server.your-domain
您已经保护了 SSH 客户端可用的密码。接下来,您将查看 SSH 客户端使用的文件的访问权限。
第 3 步 – 保护配置文件和私钥权限
在此步骤中,您将锁定 SSH 客户端配置文件和私钥的权限,以帮助防止意外或恶意更改或私钥泄露。这在多个用户之间使用共享客户端设备时特别有用。
默认情况下,在全新安装的 Ubuntu 上,OpenSSH 客户端配置文件被配置为每个用户只能编辑他们自己的本地配置文件 ( ~/.ssh/config
),并且需要 sudo/administrative 访问权限来编辑系统范围的配置 ( /etc/ssh/ssh_config
) .
但是,在某些情况下,特别是在已经存在很长时间的系统上,这些配置文件的权限可能被意外修改或调整过,因此最好重新设置它们以确保配置是安全的。
您可以首先使用以下stat
命令检查系统范围的 OpenSSH 客户端配置文件的当前权限值,您可以使用该命令显示状态或文件和/或文件系统对象:
- stat -c "%a %A %U:%G" /etc/ssh/ssh_config
您可以使用该-c
参数来指定自定义输出格式。
注意:在某些操作系统(例如 macOS)上,您将需要使用该-f
选项来指定自定义格式而不是-c
.
在这种情况下,该%A %a %U:%G
选项将以八进制和人类可读格式打印文件的权限,以及拥有该文件的用户/组。
这将输出类似于以下内容的内容:
Output644 -rw-r--r-- root:root
在这种情况下,权限是正确的,root完全拥有该文件,并且只有root有权写入/修改它。
注意:如果您想在继续之前更新您对 Linux 权限的了解,您可能希望查看Linux 权限简介。
但是,如果您自己的输出不同,您应该使用以下命令将权限重置回默认值:
- sudo chown root:root /etc/ssh/ssh_config
- sudo chmod 644 /etc/ssh/ssh_config
如果您重复stat
此步骤前面的命令,您现在将收到系统范围配置文件的正确值。
接下来,您可以对自己的本地 SSH 客户端配置文件执行相同的检查,如果您有:
- stat -c "%a %A %U:%G" ~/.ssh/config
这将输出类似于以下内容的内容:
Output644 -rw--r--r-- user:user
如果您自己的客户端配置文件权限的权限有任何不同,您应该使用以下命令重置它们,类似于前面的步骤:
- chown user:user ~/.ssh/config
- chmod 644 ~/.ssh/config
接下来,您可以检查目录中每个 SSH 私钥的权限~/.ssh
,因为这些文件只能由您自己访问,而不能由系统上的任何其他用户访问。
首先打印每个私钥的当前权限和所有权值:
- stat -c "%a %A %U:%G" ~/.ssh/id_rsa
这将输出类似于以下内容的内容:
Output600 -rw------- user:user
正确锁定私钥文件的权限非常重要,否则可能会允许设备的其他用户窃取它们并访问关联的服务器或远程用户帐户。
如果权限配置不正确,请在每个私钥文件上使用以下命令将它们重置为安全默认值:
- chown user:user ~/.ssh/id_rsa
- chmod 600 ~/.ssh/id_rsa
在此步骤中,您评估并锁定了 SSH 客户端配置文件和私钥的文件权限。接下来,您将实施出站许可名单以限制您的客户端能够连接到的服务器。
步骤 4 — 使用主机许可名单限制传出连接
在这最后一步中,您将实施传出许可名单,以限制 SSH 客户端能够连接的主机。这对于共享/多用户系统以及 SSH 跳转主机或堡垒主机特别有用。
此安全控制专门用于帮助防止人为错误/错误,例如输入错误的服务器地址或主机名。用户可以通过编辑其本地配置文件轻松绕过它,因此其设计目的不是防御恶意用户/参与者。
如果您想在网络级别限制出站连接,正确的方法是使用防火墙规则。这超出了本教程的范围,但您可以查看UFW Essentials:通用防火墙规则和命令。
但是,如果您想添加一些额外的故障保险,那么这种安全控制可能对您有益。
它的工作原理是在 SSH 客户端配置文件中使用通配符规则将所有出站连接设为空路由,除了到特定地址或主机名的连接。这意味着,如果您不小心输入错误的服务器地址,或尝试连接到您不应该连接的服务器,请求将立即停止,让您有机会意识到自己的错误并采取纠正措施。
您可以在系统级别 ( /etc/ssh/ssh_config
) 或使用本地用户配置文件 ( ~/.ssh/config
) 应用此功能。在本例中,我们将使用本地用户配置文件。
首先打开文件,如果它不存在则创建它:
- nano ~/.ssh/config
在文件底部,添加以下内容,替换为您自己的允许 IP 地址和主机名列表:
Match host !203.0.113.1,!192.0.2.1,!server1.your-domain,!github.com,*
Hostname localhost
您必须在 IP 地址或主机名前加上感叹号 ( !
),并使用逗号分隔列表中的每个项目。最后一个列表项应该是一个*
没有前缀感叹号的星号 ( )。
如果您也在您的机器上运行 SSH 服务器,您可能希望使用除 之外的主机名值localhost
,因为这会导致将空路由连接发送到您自己的本地 SSH 服务器,这可能会适得其反或令人困惑。任何nullrouted主机名是可接受的,例如null
,do-not-use
,或disallowed-server
。
完成更改后保存并关闭文件。
您现在可以通过尝试使用 SSH 客户端连接到不允许的目标来测试配置是否有效。例如:
- ssh disallowed.your-domain
如果配置工作正常,您将立即收到类似于以下内容的错误:
OutputCannot connect to localhost: connection refused
但是,当您尝试连接到允许的目标时,连接将正常成功。
在这最后一步中,您实现了一些额外的故障保护,以帮助防止在使用 SSH 客户端时出现人为错误和错误。
结论
在本文中,您回顾了 OpenSSH 客户端配置并实施了各种强化措施。
这将提高传出 SSH 连接的安全性,并有助于确保您的本地配置文件不会被其他用户意外或恶意修改。
您可能希望查看 OpenSSH 客户端及其相关配置文件的手册页,以确定您想要进行的任何潜在的进一步调整:
最后,如果您也想在服务器端强化 OpenSSH,请查看如何在 Ubuntu 18.04 上强化 OpenSSH。