保护 SSH 服务器的最佳方法

保护你的 Linux 系统 SSH 连接的十个简单方法

保护 Linux 系统的 SSH 连接对于确保系统和数据的安全至关重要。无论是系统管理员还是家庭用户,都需要加强对互联网开放的计算机的保护。SSH 配置可能较为复杂,以下是十个简易方法,可以帮助你快速提升 SSH 服务器的安全性。

SSH 安全基础知识

SSH 代表 安全外壳。 “SSH”这个名称既可以指代 SSH 协议本身,也可以指代用于建立安全连接的软件工具。系统管理员和用户可以使用 SSH 协议与远程计算机建立安全的连接。

SSH 协议是一种加密协议,旨在通过不安全的网络(如互联网)提供安全的通信通道。Linux 中的 SSH 基于 OpenSSH 项目的一个可移植版本。它采用 经典的客户端-服务器模型,其中 SSH 服务器接收来自 SSH 客户端的连接请求。客户端用于连接服务器并显示远程会话,服务器则接受连接并执行会话。

在默认配置中,SSH 服务器监听传输控制协议 (TCP) 的 22 端口。 由于这是一个标准的、 广为人知的端口,它成为了 威胁者恶意机器人 的攻击目标。

威胁行为者会启动机器人,扫描一系列 IP 地址以寻找开放端口,然后探测这些端口是否存在可利用的漏洞。认为自己“很安全,坏人会瞄准更大的目标”是错误的。机器人不会基于价值来选择目标,而是系统性地寻找可以破坏的系统。

如果不保护你的系统,你就会将自己置于受害者的位置。

安全摩擦

安全摩擦指的是用户在实施安全措施时遇到的不便或障碍。我们都记得曾经向新手介绍计算机系统,以及他们惊讶地问每次登录大型机是否真的都需要输入密码。这就是安全摩擦的体现。

(顺便说一句,密码的发明归功于 费尔南多·J·科尔巴托,一位计算机科学界的伟人,他的工作为 Unix 的诞生奠定了基础。)

引入安全措施往往会带来某种程度的摩擦。企业主必须为此付出代价。计算机用户可能需要改变习惯,或者记住额外的身份验证细节,或者添加额外的连接步骤。系统管理员将有额外的工作来实施和维护这些新措施。

强化 Linux 或类 Unix 操作系统可能非常复杂。我们将介绍一系列易于实施的步骤,这些步骤可以提高计算机的安全性,无需使用第三方应用程序,也不需要深入研究防火墙。

这些步骤并非 SSH 安全的最终解决方案,但它们可以让你在默认设置的基础上前进一大步,而不会产生太多摩擦。

使用 SSH 协议版本 2

2006 年,SSH 协议从版本 1 更新到 版本 2。这是一个重大的升级,包含了许多改进,特别是在加密和安全性方面。版本 2 不向后兼容版本 1。为了阻止版本 1 客户端的连接,你可以配置系统只接受来自版本 2 客户端的连接。

为此,请编辑 /etc/ssh/sshd_config 文件。本文中我们会经常编辑此文件。每次编辑此文件时,请使用以下命令:

sudo gedit /etc/ssh/sshd_config

添加以下行:

Protocol 2

保存文件。然后,我们将重启 SSH 守护进程。本文中我们也会经常这样做。这是每次使用的命令:

sudo systemctl restart sshd

让我们检查一下新设置是否生效。我们将从另一台机器尝试通过 SSH 连接到我们的测试机器。我们将使用 -1(协议 1)选项强制 ssh 命令使用协议版本 1。

ssh -1 [email protected]

很好,我们的连接请求被拒绝了。接下来确保我们仍然可以使用协议 2 连接。使用 -2(协议 2)选项来验证。

ssh -2 [email protected]

SSH 服务器要求输入密码表明连接已建立,并且你正在与服务器交互。事实上,由于现代 SSH 客户端默认使用协议 2,只要客户端是最新的,我们就不需要指定协议 2。

ssh [email protected]

我们的连接被接受。所以只有较弱且安全性较低的协议 1 连接被拒绝。

避免使用端口 22

端口 22 是 SSH 连接的标准端口。如果使用不同的端口,会通过模糊性增加一点安全性。虽然这种“安全通过隐蔽性”的方法通常不被认为是真正的安全措施,但使用非标准端口可以帮助减少端口 22 上的噪声和不良流量。在其他文章中,我曾反对这种做法。一些更聪明的攻击机器人会探测所有开放端口并确定它们承载的服务,而不是依赖于简单的端口查找列表,并假设它们提供通常的服务。

要配置非标准端口,请编辑 SSH 配置文件:

sudo gedit /etc/ssh/sshd_config

删除“Port”行开头的 #,并将“22”替换为你选择的端口号。保存配置文件并重启 SSH 守护进程:

sudo systemctl restart sshd

看看有什么影响。在另一台计算机上,我们将使用 ssh 命令连接到我们的服务器。 ssh 命令默认使用端口 22:

ssh [email protected]

我们的连接被拒绝。让我们再次尝试并使用 -p(端口)选项指定端口 479:

ssh -p 479 [email protected]

我们的连接被接受。

使用 TCP Wrappers 过滤连接

TCP Wrappers 可以被看作是一个易于理解的 访问控制列表。 它允许你根据连接请求的特征(例如 IP 地址或主机名)排除和允许连接。TCP Wrappers 应该与正确配置的防火墙一起使用,而不是替代它。在我们的特定场景中,我们可以通过使用 TCP Wrappers 大大收紧连接控制。

TCP Wrappers 已经安装在我们用来研究本文的 Ubuntu 18.04 LTS 机器上。它需要在 Manjaro 18.10 和 Fedora 30 上安装。

要在 Fedora 上安装,请使用以下命令:

sudo yum install tcp_wrappers

要在 Manjaro 上安装,请使用以下命令:

sudo pacman -Syu tcp-wrappers

涉及到两个文件。一个保存允许列表,另一个保存拒绝列表。使用以下命令编辑拒绝列表:

sudo gedit /etc/hosts.deny

这将打开 gedit 编辑器,并加载拒绝文件。

添加以下行:

ALL : ALL

并保存文件。这会阻止所有未经授权的访问。我们现在需要授权允许接受的连接。为此,你需要编辑允许文件:

sudo gedit /etc/hosts.allow

这将打开 gedit 编辑器,并加载允许文件。

我们添加了 SSH 守护进程名称,SSHD,以及允许建立连接的计算机的 IP 地址。保存文件,让我们看看限制和权限是否生效。

首先,我们将尝试从不在 hosts.allow 文件中的计算机进行连接:

连接被拒绝。现在我们尝试从 IP 地址为 192.168.4.23 的机器进行连接:

连接被接受。

我们这里的例子有点极端——只有一台计算机可以连接。TCP Wrappers 非常通用,而且比这更灵活。 它支持 主机名、通配符和子网掩码 来接受来自 IP 地址范围的连接。我们建议你 查阅手册页

拒绝没有密码的连接请求

虽然这是一种不好的做法,但 Linux 系统管理员可以创建没有密码的用户帐户。这意味着来自该帐户的远程连接请求将没有密码可以检查。这些连接将被接受但未经身份验证。

SSH 的默认设置接受没有密码的连接请求。我们可以很容易地改变它,并确保所有连接都经过身份验证。

我们需要编辑你的 SSH 配置文件:

sudo gedit /etc/ssh/sshd_config

滚动文件,直到看到显示为“#PermitEmptyPasswords no”的行。从行的开头删除 # 并保存文件。重启 SSH 守护进程:

sudo systemctl restart sshd

使用 SSH 密钥而不是密码

SSH 密钥提供了一种更安全的登录 SSH 服务器的方法。密码可能被猜测、破解或进行 暴力破解。 SSH 密钥对此类攻击不开放。

生成 SSH 密钥时,会创建一对密钥。一个是公钥,另一个是私钥。公钥安装在你要连接的服务器上。顾名思义,私钥在你的计算机上保持安全。

SSH 密钥允许你在没有密码的情况下建立连接——这违反直觉——比使用密码身份验证的连接更安全。

当发出连接请求时,远程计算机会使用你的公钥副本创建一条加密消息,然后将其发送回你的计算机。因为它使用你的公钥加密,所以你的计算机可以使用你的私钥解密它。

然后,你的计算机从消息中提取一些信息,特别是会话 ID,对其进行加密,然后将其发送回服务器。如果服务器可以使用你的公钥副本对其进行解密,并且消息中的信息与服务器发送给你的信息相匹配,则确认你的连接来自你。

在这里,用户使用 SSH 密钥与位于 192.168.4.11 的服务器建立连接。请注意,系统没有提示他们输入密码。

ssh [email protected]

SSH 密钥值得单独写一篇文章。很方便的是,我们已经为你准备了一篇。以下是创建和安装 SSH 密钥的方法。

完全禁用密码验证

当然,使用 SSH 密钥的逻辑延伸是,如果强制所有远程用户都使用它们,就可以完全禁用密码验证。

我们需要编辑你的 SSH 配置文件:

sudo gedit /etc/ssh/sshd_config

滚动文件,直到看到以“#PasswordAuthentication yes”开头的行。删除行首的 # ,将“yes”更改为“no”,然后保存文件。重启 SSH 守护进程:

sudo systemctl restart sshd

禁用 X11 转发

X11 转发允许远程用户通过 SSH 会话从你的服务器运行图形应用程序。在威胁行为者或恶意用户手中,GUI 界面可以使他们的恶意目的更容易得逞。

网络安全的标准口头禅是,如果你没有正当理由将其打开,请将其关闭。我们将通过编辑你的 SSH 配置文件来做到这一点:

sudo gedit /etc/ssh/sshd_config

滚动文件,直到看到以“#X11Forwarding no”开头的行。从行的开头删除 # 并保存文件。重启 SSH 守护进程:

sudo systemctl restart sshd

设置空闲超时值

如果与你的计算机建立了 SSH 连接,并且在一段时间内没有任何活动,这可能会带来安全风险。用户可能会离开他们的办公桌去做其他事情。任何在他们办公桌附近的人都可以坐下来使用他们的计算机,并通过 SSH 使用你的计算机。

设置超时限制更安全。如果非活动时间与时间限制匹配,则 SSH 连接会被断开。我们再次编辑你的 SSH 配置文件:

sudo gedit /etc/ssh/sshd_config

滚动文件,直到看到以“#ClientAliveInterval 0”开头的行。从行的开头删除 #,将数字 0 更改为所需的值。我们使用了 300 秒,即 5 分钟。保存文件,然后重启 SSH 守护进程:

sudo systemctl restart sshd

设置密码尝试限制

定义身份验证尝试次数的限制有助于阻止密码猜测和暴力攻击。在指定的身份验证请求次数后,用户将与 SSH 服务器断开连接。默认情况下,没有限制。但我们将很快纠正这一点。

同样,我们需要编辑你的 SSH 配置文件:

sudo gedit /etc/ssh/sshd_config

滚动文件,直到看到以“#MaxAuthTries 0”开头的行。从行首删除 #,将数字 0 更改为你想要的值。我们在这里使用了 3 个。进行更改后保存文件并重启 SSH 守护进程:

sudo systemctl restart sshd

我们可以通过尝试连接并故意输入错误的密码来测试这一点。

请注意,MaxAuthTries 数字似乎比允许用户尝试的次数多一。在两次错误的尝试之后,我们的测试用户被断开了。这说明我们将 MaxAuthTries 设置为了 3。

禁用 root 登录

在 Linux 计算机上以 root 身份登录是一种不好的做法。你应该以普通用户身份登录并使用 sudo 执行需要 root 权限的操作。更重要的是,你不应该允许 root 登录到你的 SSH 服务器。应该只允许普通用户连接。如果他们需要执行管理任务,他们应该使用 sudo。如果被迫允许 root 用户登录,至少可以强制他们使用 SSH 密钥。

最后一次,我们需要编辑你的 SSH 配置文件:

sudo gedit /etc/ssh/sshd_config

滚动文件,直到看到以“#PermitRootLogin prohibit-password”开头的行。删除行首的 #。

如果你想完全阻止 root 登录,请将 “prohibit-password” 替换为 “no”。
如果你允许 root 登录但强制他们使用 SSH 密钥,请保留 “prohibit-password”。

保存更改并重启 SSH 守护进程:

sudo systemctl restart sshd

终极步骤

当然,如果你根本不需要在你的计算机上运行 SSH,请确保将其禁用。

sudo systemctl stop sshd
sudo systemctl disable sshd

如果你不开窗,就没有人可以爬进来。