如何在家用电脑上设置 SSH 服务器
大约18个月前,我组装了一台台式电脑,以便在需要时拥有更强大的计算能力。我当时的想法是,这样在参加Kaggle竞赛和其他项目时,就不用支付云计算服务的费用了。很快,我就意识到如果能远程使用这台电脑会很方便,于是我找到了一些关于如何将家用电脑设置成SSH服务器的资料。然而,我始终找不到任何一份资料能够提供足够的背景信息,让我不必只是简单地复制粘贴命令。
虽然搭建自己的 SSH 服务器不需要任何特定领域的专业知识,但确实有很多概念需要理解。我将在下文详细解释,简而言之,SSH 服务器是运行在你电脑上的一个进程,它会等待外部计算机通过特定端口请求访问,验证用户身份,然后允许访问该计算机。如果你对这些术语感到困惑,别担心。我第一次尝试搭建 SSH 服务器时也和你一样。以下是我们将要介绍的概念/术语的简要列表:
- 服务器
- SSH
- 网络地址转换
- 公有/私有 IP 地址
- 港口
- 端口转发
- 公钥/私钥认证
我使用的是 Ubuntu 14.04 LTS 操作系统,不过,这些步骤在任何类 Unix 平台上都类似。为了方便操作,请确保您拥有以下权限:
- 将托管 SSH 服务器的基于 Unix 的计算机
- 使用另一台计算机测试与服务器的远程连接
- 访问与主机所连接网络不同的网络(可选,但推荐)
在本指南中,“主机”指的是运行 SSH 服务器的计算机,“客户端”指的是任何请求访问主机的计算机。在本指南的某些步骤中,您的主机也将作为客户端。
初始设置
SSH 代表“安全套接字外壳协议”,它允许我们在两台计算机之间建立安全连接。我们的最终目标是能够从客户端发出命令,并由宿主机执行。想要更全面地了解 SSH,请参阅Digital Ocean 的这篇优秀指南。
“服务器”一词的使用有时比较宽泛。在这里,我们指的是运行在计算机上的进程,其任务是通过网络管理对计算机资源的访问。我们将安装 openssh-server 应用程序,它允许我们在机器上运行一个 SSH 服务器,该服务器将处理来自其他设备的访问主机的请求。
首先更新系统软件包:
sudo apt-get upgrade
安装 openssh-server 应用程序和客户端。您还应该在将用作客户端的机器上安装 openssh-client。
sudo apt-get install openssh-client
sudo apt-get install openssh-server
现在您的机器上应该有一个 SSH 服务器进程正在运行。请使用以下命令进行检查:
ps -A | grep sshd
你应该会看到类似这样的内容:
[number] ? 00:00:00 sshd
如果你像我一样直接复制粘贴了上面的命令(我以前也这么做过),那么花点时间查阅一下你不认识的命令,你会学到更多。如果你是 shell 命令新手(或者只是想复习一下),可以看看Code Academy 的“学习命令行”课程。
检查你是否可以从主机“登录”到主机,也就是说,你的主机在这种情况下也是客户端。
ssh localhost
在 shell 中稍微移动一下(cd、pwd 等),确保一切正常,然后输入“exit”结束会话。
接下来,我们将使用一台真正的“客户端”计算机进行连接。为了确保连接成功,请确保您的客户端计算机与服务器位于同一网络中。如果您在家或公司使用无线网络,那就一切就绪了。
首先,通过列出计算机上的网络接口信息来确定主机的 IP 地址。
ifconfig
您应该会看到“eth0”和“lo”的条目,如果您在台式机上安装了无线网卡,还会看到其他一些条目。如果您的主机通过以太网线连接到网络,请使用与“eth[number]”条目关联的地址。如果您通过 Wi-Fi 连接,请使用“wlan[number]”条目。如果您只想查看设备的 IP 地址列表,可以使用以下命令:
ifconfig | grep "inet addr"
接下来,尝试使用该 IP 地址从客户端计算机登录:
ssh username@X.X.X.X
系统会提示您输入在 SSH 命令中使用的帐户密码。出于安全考虑,密码字符不会显示在 shell 中。如果成功,您应该会看到“欢迎使用 Ubuntu XXX”或类似的消息,具体取决于您的操作系统。
这比我们之前的测试稍微有用一些,但仍然无法解决我们最初的问题,即如何从同一网络之外访问这台机器。如果您能够将客户端机器连接到与主机不同的网络,不妨尝试一下。
如果你的手机流量套餐还有剩余,一个快捷的方法是开启网络共享,将客户端连接到该网络,而主机则保持在另一个网络上。连接到这个独立的网络后,再次尝试执行 ssh 命令:
ssh username@X.X.X.X
您很可能会注意到命令执行过程中会卡住,最终超时。请断开与该网络的连接,我们将继续完成设置的最后一步。但首先,我们花一点时间介绍一些背景概念,以便您更好地理解下一步。
NAT 和公网/私网 IP 地址
或许令人惊讶,但互联网同时在线的用户数量是有限的。在几乎所有电子设备都能接入互联网的今天,实际用户数量很容易接近理论上限。为了解决这个问题,网络地址转换(NAT)技术应运而生,它允许私有网络上的多个设备共享同一个IP地址。在私有网络中,每个设备都会获得一个独立的私有IP地址。例如,您上面使用“ifconfig”命令找到的IP地址就是您本地网络中计算机的私有IP地址。
当您从家庭网络中的任何设备访问网页时,请求都会通过 NAT 设备(因此称为路由器)进行路由,NAT 设备会将私有 IP 地址转换为使用 ISP 分配给路由器的公网 IP 地址的请求。这就是您最终从本地网络外部连接时需要使用的 IP 地址。您可以访问www.whatsmyip.org来确定您的公网 IP 地址。您应该会看到类似 XX.XX.XXX.XXX 的地址。您或许会尝试使用此地址再次执行 SSH 命令,但很可能仍然无法成功。
虽然NAT解决了设备数量限制的问题,但它也给家用电脑配置SSH连接增加了一层复杂性。当客户端发送连接公网IP地址的请求时,路由器并不知道该请求是发往私有网络中的哪台设备。幸运的是,解决方案通常很简单,只需在路由器上设置“端口转发”即可。接下来,我们将继续深入探讨端口相关的术语。如果您已经熟悉这些概念,可以跳过这部分。
港口和港口货运代理
虽然计算机拥有大多数人熟悉的各种物理端口(例如 USB、HDMI、VGA 等),但我这里指的是网络端口,它们是逻辑端口,而非物理端口。当你启动一个服务器(例如你在前面步骤中设置的 SSH 服务器)时,你会将其绑定到这些逻辑端口中的一个。然后,该进程会“监听”其他程序(无论是内部程序还是外部程序)发送到该端口的消息。每个端口都有一个编号,其中一些编号被特定类型的服务保留使用。例如,处理 HTTP 请求的服务器默认使用 80 端口。当你通过 URL 访问网页时,实际上是在向 80 端口上的 HTTP 服务器发送消息,以获取由该服务管理的特定资源(网页或其他内容)。通常,22 端口用于 SSH 服务。
在这种情况下,端口转发是指告诉路由器将使用特定端口发出的请求转发到私有网络上的特定设备。然后,由该设备负责处理请求。您可能会想:为什么不直接通过私有 IP 地址将请求发送到计算机,从而避免所有这些端口转发的麻烦呢?顾名思义,这些 IP 地址是私有的,因此一旦您连接到其他网络,互联网就无法识别此私有 IP 地址,因此连接请求将会失败。
每个路由器的端口转发设置方法都略有不同。这听起来可能像是在敷衍,但说实话,最好的办法是查找您特定路由器的设置指南。例如,这里有AT&T 路由器和Comcast XFINITY 的设置说明。一般来说,您需要执行以下操作:
- 登录路由器的管理页面
- 导航至添加服务页面(SSH 通常是默认选项之一)。
- 选择或输入要发出请求的端口号(SSH 默认端口为 22)。
- 选择或输入您之前找到的主机私有 IP 地址
- 保存更新后的设置
现在,我们可以使用公网 IP 地址重复执行 SSH 命令,该请求应该会被路由器重定向到我们的主机。重新连接到外部网络并尝试:
ssh username@[public IP address]
系统会再次提示您输入主机密码,然后允许您访问。
更安全的 SSH 服务器配置
在最后一部分,我们将对 SSH 服务器的配置设置进行一些更改。在 Ubuntu 系统中,这些设置位于 `/etc/ssh/sshd_config` 文件中。以下是一些简要说明:
- 要编辑此文件,您需要以超级用户身份打开它。
- 每次更新配置设置后,都需要重启 SSH 服务器才能使更改生效。
sudo restart ssh
当运行中的 SSH 服务器通过 22 端口(或其绑定的任何端口)收到请求时,它必须检查请求用户是否拥有访问计算机的权限。虽然可以使用密码进行验证,但使用公钥认证被认为更加安全。公钥加密的工作原理是让用户生成一个可以提供给任何人的公钥,同时将私钥保密。认证过程使用公钥(由用户提供给认证进程)来验证请求用户(其访问服务的请求使用私钥加密)是否与具有访问权限的用户匹配。一旦建立连接,就会使用更高效的数据加密/解密方法来通过此安全连接传输击键和其他信息。
如果您尚未生成公钥/私钥对,则需要生成该密钥对以用于登录您的计算机。请注意,您需要在所有希望访问 SSH 服务器的设备上执行此操作。网上有很多优秀的指南可以指导您完成此操作,因此为了避免重复造轮子,我建议您按照Ubuntu 的说明进行操作。
现在密钥已准备就绪,我们将在 SSH 服务器上启用公钥认证。接下来,请以超级用户身份打开 sshd_config 文件,并首先进行以下更改:
PasswordAuthentication yes
到
PasswordAuthentication no
这将阻止用户使用密码访问服务器,从而有助于抵御试图猜测密码的暴力破解攻击。另一个建议是更改 SSH 服务使用的端口。在配置文件中,注释掉现有的端口配置,然后选择一个新的端口。
# Port 22
Port [new port number]
请记住,根据之前的步骤,您的路由器仍会尝试向 22 端口发送 SSH 请求,因此您需要返回路由器的配置设置,并更新 SSH 服务的端口号。如果您使用的是具有多个用户帐户的计算机,您还可以限制哪些用户可以通过 SSH 登录。在配置文件末尾添加:
AllowUsers [user1] [user 2] ...
您还可以拒绝特定用户和添加/拒绝组,但是,对于家用电脑来说,您不太可能需要这样做。
接下来,通过修改以下内容禁用 root 用户通过 SSH 登录:
PermitRootLogin without-password
到
PermitRootLogin No
除了禁用密码登录之外,您还可以通过限制与 SSH 服务器的并发连接数来防止暴力破解攻击。对于家用电脑,请通过以下方式降低此连接数:
#MaxStartups 10:30:60
到
MaxStartups 3
通过 SSH 连接,您可以隧道传输图形窗口。如果您不打算使用此功能,请通过更改设置将其关闭。
X11Forwarding yes
到
X11Forwarding no
除了通过 Windows 转发端口外,您还可以通过 SSH 转发端口。例如,如果您的主机上运行着一个使用 80 端口的 Web 服务器,您可以将该端口转发到客户端计算机上的某个端口。这非常方便,但如果您暂时不打算使用此功能,请先将其禁用,直到您需要它时再启用,因为它可能被恶意利用。
AllowTcpForwarding no
ssh_config 文件中还有很多其他设置,但我建议除非有充分的理由,否则不要更改默认设置。虽然建议的更改可以提高服务器的安全性,但还有许多其他方法可以增强安全性。事实上,这些方法可能值得单独写一篇文章,但我会在以后再谈。
感谢您抽出时间阅读本文,如有任何不清楚的地方,请随时告诉我。本文最初发表于我的个人博客。