本教程将介绍您在使用 SSH 时可能遇到的最常见错误:连接被拒绝。请继续阅读,详细了解这个问题及其各种解决方案。
Secure Shell (SSH) 是系统管理员最常用的工具之一。它对于管理所有服务器和执行日常任务至关重要。
SSH 服务不工作
您可以执行的最基本的故障排除是首先验证系统上是否安装了 SSH。 SSH 有客户端版本(用于远程连接到其他系统)和服务器版本(用于接受系统的传入连接)。
要查看您的 SSH 客户端是否已正确安装,只需在终端中输入“ssh”即可。
$ ssh
如果您的系统上安装了 SSH 客户端,您将看到一些输出,如上面的屏幕截图。
要检查您的系统是否安装了 SSH 服务器,请尝试启动到系统本身的远程连接:
$ ssh localhost
尝试通过 SSH 连接到本地主机是查看系统当前是否接受连接的好方法。
在这里,我们收到了可怕的“连接被拒绝”错误消息。这要么意味着系统上未安装 SSH 服务器软件包,要么仅意味着该服务当前未运行。
让我们尝试检查 SSH 服务的状态:
$ systemctl status sshd
当检查 SSH 守护进程的状态时,系统通知我们找不到该服务。这意味着我们需要安装它。
我们在本例中使用 Ubuntu,因此我们将使用 apt-get 来安装 openssh-server 软件包。您可能需要使用稍微不同的命令,具体取决于您使用的发行版。
$ sudo apt-get install openssh-server
安装完成后,SSH服务可能会自动启动。要检查它是否正在运行,请再次检查状态:
Systemctl 向我们显示 SSH 服务正在运行(按“q”退出此屏幕并返回终端)。
如果 SSH 守护进程尚未在您的系统上运行,您可以使用以下命令启动它:
$ systemctl start sshd
忘记在启动时打开它&解决方案
每次需要时都启动 SSH 服务显然有点烦人,因此如果您想确保系统在启动时自动接收 SSH 连接,您可以以 root 身份或使用 sudo 使用以下命令:
$ sudo systemctl enable ssh
运行此命令会告诉您的系统在每次计算机启动时启动 SSH 服务。如果您稍后需要恢复此设置,只需键入相同的命令,但使用“禁用”而不是“启用”。
SSH 端口未开放
如果在验证 SSH 服务已启动并运行后仍然遇到连接问题,则可能是 SSH 连接在有机会到达系统之前就被阻止了(就像在路由器上一样)。
路由器阻止端口 22 上的传入 SSH 连接是很常见的。您可以使用任何端口转发测试器来查看该端口是否对 Internet 可见。如果不是,则连接可能被您的路由器或系统上的防火墙阻止,我们将在接下来讨论。
要将路由器配置为允许传入 SSH 连接,您需要查阅制造商有关特定路由器型号上的端口转发的说明。
防火墙阻止 SSH 端口
另一件要检查的事情是操作系统的防火墙。 Ubuntu 和许多其他发行版默认安装了 ufw(简单防火墙),它通常是向系统快速发出防火墙相关命令的最常见方法之一。
要允许 SSH 通过 ufw 通过防火墙,请使用以下命令:
$ sudo ufw allow ssh
Ufw 只是一个前端iptables防火墙,因此,如果您更喜欢使用 iptables 命令(或者可能您甚至没有安装 ufw),这里是允许传入 SSH 连接的 iptables 命令:
$ sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
如果您正在运行firewalld并且需要允许SSH连接,请使用以下命令:
$ firewall-cmd --zone=public --add-service=ssh
SELinux 阻止 SSH
一些发行版,例如 Red Hat 和基于它的发行版,运行 SELinux(安全增强型 Linux)。 SELinux 应自动配置为在端口 22 上侦听 SSH,您可以使用以下命令进行验证:
$ semanage port -l | grep ssh
在上面的屏幕截图中,semanage 命令向我们显示它正在端口 22(SSH 的默认端口)上侦听传入的 SSH 连接。除非您尝试更改系统运行 SSH 服务的端口,否则您不需要对此进行任何额外的配置。
如果需要配置 SELinux 在不同端口上侦听 SSH,可以使用以下命令:
$ semanage port -a -t ssh_port_t -p tcp 1234
将“1234”替换为您已配置 SSH 运行的新端口。
进行这些更改后,请务必重新启动 SSH 服务:
$ systemctl restart sshd
IP地址冲突问题
如果您的系统在网络上有重复的 IP 地址,则 SSH(以及依赖于您的网络的其他服务)可能无法正常运行。检查这一点总是一件好事,并且使用主机命令执行起来非常简单。
$ host x.x.x.x
The 主机命令返回有关我们刚刚传递给它的 IP 地址的信息。使用主机名来确定您确实正在尝试访问正确的系统。
在 Windows 上,您可以在命令提示符中使用 ping -a 来获得类似的结果:
重新安装后公钥发生变化
SSH 服务为每个系统生成唯一的公钥。这样做是为了让连接到系统的客户端能够确保它们连接到目标服务器。
例如,如果你经常连接的服务器更换了IP地址怎么办?您不想将您的登录信息输入到使用以前的 IP 地址的错误系统中。
如果发生这种情况,您的 SSH 客户端应该警告您公钥已更改。 $HOME/.ssh 路径包含系统之前连接到的主机的所有密钥。您可以像这样查看known_hosts 文件:
$ cat ~/.ssh/known_hosts
我们的文件中只有一台主机,但即使如此,对我们来说也只是胡言乱语。与其自己编辑此文件,不如使用 ssh-keygen 命令从文件中删除特定的主机密钥。
$ ssh-keygen -r x.x.x.x
Or
$ ssh-keygen -r example.com
使用服务器的 IP 地址或主机名。在我们的示例中,文件中的密钥仅来自本地主机,因此我们将其删除,如下所示:
SSH 密钥文件权限
由于 SSH 客户端在连接到不同系统时会读取known_hosts 文件,因此当前用户需要对该文件拥有适当的权限。
如果没有适当的权限,您可能会看到如下错误:
如果使用密钥进行身份验证(而不是密码),您将被完全锁定在系统之外,直到您修复密钥文件的权限为止。运行这些命令应该可以解决问题:
$ chmod 700 ~/.ssh
$ chmod 644 ~/.ssh/authorized_keys
$ chmod 644 ~/.ssh/known_hosts
$ chmod 644 ~/.ssh/config
$ chmod 600 ~/.ssh/id_rsa
$ chmod 644 ~/.ssh/id_rsa.pub
根登录(如果禁用)以及如何启用它
出于安全原因,Linux 默认情况下几乎不希望您以 root 身份执行任何操作。如果可能,您应该使用权限较少的帐户,并且仅在必要时提升为 root。
嗯,在极少数情况下建议这样做,有时您可能只想直接登录 root。 SSH 默认配置为拒绝 root 登录。
如果您尝试以 root 身份登录系统,并且尚未进行任何配置来允许此操作,则您只能使用普通用户帐户登录。
您可以通过编辑 sshd_config 文件将 SSH 服务器配置为允许 root 登录。使用 nano、vi 或您喜欢的其他文本编辑器在此处打开文件:
$ sudo vi /etc/ssh/sshd_config
向下滚动此文件,直到看到 PermitRootLogin。
在我们的 Ubuntu 安装中,PermitRootLogin 默认设置为“禁止密码”。这意味着我们可以通过密钥身份验证以 root 身份登录,但不能通过提供 root 密码来登录。
在某些系统上,您可能会看到它只是说“否”,这意味着不允许任何身份验证方法的 root 登录。
要允许 root 用户通过 SSH 登录,您可以将此行更改为 yes。确保删除开头的#,这样它就不再被注释掉。为了允许 root 登录,它需要看起来像这样:
每当您对此文件进行更改时,都必须重新启动 SSH 服务才能使其生效:
$ sudo systemctl restart ssh
警告:在编辑 SSH 配置文件以允许 root 使用密码登录之前,请确保您设置了非常安全的 root 密码。有些机器人会不断扫描互联网以寻找可以通过 SSH 访问的服务器,并且它们会比其他任何帐户更频繁地尝试登录 root 帐户。
这就是为什么 SSH 默认配置为不允许任何类型的 root 通过密码登录。我们将在下一节中展示如何查看这些连接尝试,并展示如何不断针对我们的实时生产服务器执行攻击的真实示例。
连接请求积压(Flooding)
对您的服务器进行的所有连接尝试都保存在log file。在解决连接或用户帐户问题时,仔细阅读此日志文件会很有帮助,但您也可以使用它来确定您的服务器是否已被连接请求淹没。
使用以下命令检查失败的登录尝试:
$ cat /var/log/auth.log | grep "Failed password"
如果您有一台在端口 22 上向互联网开放的服务器,那么每隔 10 分钟左右至少会进行几次连接尝试,这是很常见的,因为机器人会不断浏览互联网以寻找薄弱的服务器进行黑客攻击。
下面是我的一台公共服务器的 auth.log 文件:
在此屏幕截图中没有什么值得警惕的,因为每次连接尝试都间隔至少几秒。
为了强化您的服务器免受 SSH 暴力攻击,我们建议安装CSF防火墙。默认情况下,它配置为停止来自同一 IP 地址的重复 SSH 尝试。您可以根据自己的喜好微调这些设置,但默认设置应该适合大多数系统:
$ vi /etc/csf/csf.conf
# [*]启用 sshd 连接的登录失败检测
LF_SSHD = "5"
LF_SSHD_PERM = "1"
LF_SSHD 设置为“5”是阻止 IP 地址之前的最大失败连接数。
LF_SSHD_PERM 设置为“1”会使此阻塞永久存在。
限制这些虚假连接尝试的另一种流行方法是将受信任的 IP 列入白名单并阻止所有其他 IP。仅当相同的 IP 始终通过 SSH 连接到您的服务器时,此方法才有效。要使用 iptables 实现此目的,您可以使用以下命令:
$ sudo iptables -A INPUT -p tcp -s 10.1.1.1,10.1.1.2 --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
此命令仅允许来自 10.1.1.1 和 10.1.1.2 的 SSH 连接。您可以在该命令中列出所需数量的 IP,或列出整个子网,例如 10.1.1.0/24。请注意,您的输入的链策略必须设置为 drop。
使用 ssh -vvv 调试 SSH 连接并检查日志
收到“连接被拒绝”之类的简单错误对于找出问题所在并没有多大帮助。如果您想查看有关 SSH 连接尝试期间发生的情况的更多信息,可以使用 ssh -v。
$ ssh -v hostname
Or
$ ssh -vvv hostname
在命令中放入三个 v 会进一步增加冗长程度。
使用 -vvv 开关你会得到很多输出,但下面是其中一些输出的一些示例:
希望它会打印一个错误,为您提供需要修复的线索。如果没有,请尝试在谷歌上搜索您收到的错误,看看是否有在线发布的建议。
我介绍了 SSH 连接被拒绝问题的大多数原因,希望本教程对您有用。
继续回来。