安全服务器 - `sftp`
(附带 SSH 锁定程序)¶
简介¶
当 SSH 协议本身是安全的时,文档专门讨论 `sftp`(openssh-server 包的一部分)的“安全”使用似乎有些奇怪。但大多数系统管理员不希望向所有人开放 SSH 来为所有人实现 `sftp`。本文档描述了为 `sftp` 实现更改根(chroot)监狱,同时限制 SSH 访问。
许多文档都涉及创建 `sftp` chroot 监狱,但大多数文档没有考虑用户可能正在访问具有多个网站的服务器上的 Web 目录的用例。本文档解决了这个问题。如果这不是您的用例,您可以快速将这些概念应用于不同的情况。
作者还认为,在编写 `sftp` 的 chroot 监狱文档时,有必要讨论作为系统管理员所需的其他事项,以最大限度地减少您通过使用 SSH 向世界提供的目标。因此,本文档分为四个部分:
- 第一部分处理您将在整个文档中使用的通用信息。
- 第二部分处理 chroot 设置。如果您到此为止,完全由您决定。
- 第三部分讨论为系统管理员设置公钥/私钥 SSH 访问,并关闭远程基于密码的身份验证。
- 本文档的第四部分也是最后一部分讨论关闭远程 root 登录。
这些步骤为您的客户提供安全的 `sftp` 访问,同时最大限度地减少恶意行为者攻击端口 22(为 SSH 访问保留的端口)的可能性。
面向初学者的 chroot 监狱
chroot 监狱是一种限制进程及其所有子进程在您的计算机上可以执行的操作的方法。它允许您选择计算机上的特定目录或文件夹,并将其设为任何进程或程序的“根”目录。
从那时起,该进程或程序**只能**访问该文件夹及其子文件夹。
第一部分:一般信息¶
假设和约定¶
假设是:
- 您能够舒适地在命令行中执行命令
- 您可以使用命令行编辑器,例如 `vi`(此处使用)、`nano`、`micro` 等
- 您了解用于添加组和用户的基本 Linux 命令,或可以很好地跟随
- 您的多站点网站类似于:Apache 多站点
- 您已在服务器上安装了 `httpd`(Apache)
注意
您可以将这些概念应用于任何服务器设置和任何 Web 守护程序。虽然这里假定是 Apache,但您也可以将其用于 Nginx。
站点、用户、管理员¶
这些是虚构的场景。与真实人物或网站的任何相似之处纯属巧合。
站点
- mybrokenaxel = (site1.com) 用户 = mybroken
- myfixedaxel = (site2.com) 用户 = myfixed
管理员
- Steve Simpson = ssimpson
- Laura Blakely = lblakely
第二部分:SFTP chroot 监狱¶
安装¶
安装并不困难。您只需要安装 `openssh-server`,它可能已经安装好了。输入此命令以确保
dnf install openssh-server
设置¶
目录¶
目录路径结构将是 `/var/www/sub-domains/[ext.domainname]/html`,此路径中的 `html` 目录将是 `sftp` 用户的 chroot 监狱。
创建配置文件目录
mkdir -p /etc/httpd/sites-available
mkdir -p /etc/httpd/sites-enabled
创建 Web 目录
mkdir -p /var/www/sub-domains/com.site1/html
mkdir -p /var/www/sub-domains/com.site2/html
您将在后面的脚本应用中处理这些目录的所有权。
httpd
配置¶
您需要更改内置的 `httpd.conf` 文件,使其加载 `/etc/httpd/sites-enabled` 目录中的配置文件。方法是在 `httpd.conf` 文件底部添加一行。
使用您喜欢的编辑器编辑文件。作者在此处使用 `vi`
vi /etc/httpd/conf/httpd.conf
并在文件底部添加此行
Include /etc/httpd/sites-enabled
保存文件并退出。
网站配置¶
您需要创建两个站点。您将在 `/etc/httpd/sites-available` 中创建配置,并将它们链接到 `../sites-enabled`
vi /etc/httpd/sites-available/com.site1
注意
示例仅使用 HTTP 协议。任何实际网站都需要 HTTPS 协议配置、SSL/TLS 证书以及更多内容。
<VirtualHost *:80>
ServerName www.site1.com
ServerAdmin username@rockylinux.org
DocumentRoot /var/www/sub-domains/com.site1/html
DirectoryIndex index.php index.htm index.html
Alias /icons/ /var/www/icons/
CustomLog "/var/log/httpd/com.site1.www-access_log" combined
ErrorLog "/var/log/httpd/com.site1.www-error_log"
<Directory /var/www/sub-domains/com.site1/html>
Options -ExecCGI -Indexes
AllowOverride None
Order deny,allow
Deny from all
Allow from all
Satisfy all
</Directory>
</VirtualHost>
保存此文件并退出。
vi /etc/httpd/sites-available/com.site2
<VirtualHost *:80>
ServerName www.site2.com
ServerAdmin username@rockylinux.org
DocumentRoot /var/www/sub-domains/com.site2/html
DirectoryIndex index.php index.htm index.html
Alias /icons/ /var/www/icons/
CustomLog "/var/log/httpd/com.site2.www-access_log" combined
ErrorLog "/var/log/httpd/com.site2.www-error_log"
<Directory /var/www/sub-domains/com.site2/html>
Options -ExecCGI -Indexes
AllowOverride None
Order deny,allow
Deny from all
Allow from all
Satisfy all
</Directory>
</VirtualHost>
保存此文件并退出。
创建完两个配置文件后,从 `/etc/httpd/sites-enabled` 中链接它们
ln -s ../sites-available/com.site1
ln -s ../sites-available/com.site2
启用并启动 `httpd` 进程
systemctl enable --now httpd
用户创建¶
对于此示例环境,假设所有用户尚不存在。从您的管理员用户开始。请注意,在您处理此过程的这一点,您仍然可以作为 root 用户登录来添加其他用户并按您想要的方式设置它们。在用户设置并测试完成后,您可以移除 root 登录。
管理员¶
useradd -g wheel ssimpson
useradd -g wheel lblakely
通过将您的用户添加到 "wheel" 组,您授予了他们 `sudo` 访问权限。
您仍然需要一个密码才能获得 `sudo` 访问权限。为两个管理员设置安全的密码
passwd ssimpson
Changing password for user ssimpson.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
passwd lblakely
Changing password for user lblakely.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
使用 `ssh` 从另一台机器测试对服务器的访问,用于您的两个管理员用户。您应该能够
- 使用 `ssh` 登录到服务器的管理员用户之一。(例如:`ssh lblakely@192.168.1.116` 或 `ssh lblakely@mywebserver.com`)
- 您应该能够使用 `sudo -s` 访问 root,并输入管理员用户的密码。
如果这对所有管理员用户都有效,那么您就准备好进行下一步了。
Web 用户 (sftp)¶
您需要添加 Web 用户。该 `../html` 目录结构已存在,因此您在添加用户时不想创建它,但您**确实**想指定它。您还希望除了 `sftp` 之外没有任何其他登录方式,因此您需要使用一个拒绝登录的 shell。
useradd -M -d /var/www/sub-domains/com.site1/html -g apache -s /usr/sbin/nologin mybroken
useradd -M -d /var/www/sub-domains/com.site2/html -g apache -s /usr/sbin/nologin myfixed
稍微分解一下这些命令
- `-M` 选项表示**不要**为用户创建标准的家目录。
- `-d` 指定后面的是**实际**的家目录。
- `-g` 表示该用户所属的组是 `apache`。
- `-s` 表示分配的 shell 是 `/usr/sbin/nologin`
- 最后是用户的实际用户名。
**注意:** 对于 Nginx 服务器,您将使用 `nginx` 作为组。
您的 `sftp` 用户仍然需要密码。现在为每个用户设置一个安全的密码。您之前已经看到过命令输出
passwd mybroken
passwd myfixed
SSH 配置¶
警告
在开始此过程之前,强烈建议您备份您将要修改的系统文件:`/etc/ssh/sshd_config`。损坏此文件并且无法恢复到原始状态可能会给您带来很多麻烦!
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
您需要对 `/etc/ssh/sshd_config` 文件进行一项更改。您将构建一个模板,将 Web 目录更改放在配置文件之外,并脚本化您需要的添加项。
首先,进行手动更改
vi /etc/ssh/sshd_config
在文件底部附近,您会发现
# override default of no subsystems
Subsystem sftp /usr/libexec/openssh/sftp-server
您想将其更改为如下形式:
# override default of no subsystems
# Subsystem sftp /usr/libexec/openssh/sftp-server
Subsystem sftp internal-sftp
保存并退出文件。
`sftp-server` 和 `internal-sftp` 是 OpenSSH 的一部分。`internal-sftp` 虽然与 `sftp-server` 差别不大,但它通过使用 `ChrootDirectory` 来强制客户端使用不同的文件系统根目录,从而简化了配置。这就是为什么您使用 `internal-sftp`。
模板和脚本¶
为什么为接下来的部分创建模板和脚本?原因是尽可能避免人为错误。您还没有完成修改 `/etc/ssh/sshd_config` 文件,但您希望在需要进行这些修改时消除尽可能多的错误。您将在 `/usr/local/sbin` 中创建所有这些。
模板¶
首先,创建您的模板
vi /usr/local/sbin/sshd_template
此模板将包含以下内容:
Match User replaceuser
PasswordAuthentication yes
ChrootDirectory replacedirectory
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
注意
`PasswordAuthentication yes` 通常不需要用于 chroot 监狱。但是,您稍后将为其他所有人关闭 `PasswordAuthentication`,因此在此模板中包含此行至关重要。
您还需要一个用于用户文件的目录,您将从模板中创建它
mkdir /usr/local/sbin/templates
脚本和 `sshd_config` 更改¶
在 Rocky Linux 的近期版本中,`sshd_config` 文件有一个新选项,允许进行下拉式配置。这是一个**很棒**的更改。这意味着您只需要对 `sshd_config` 文件进行一次额外更改,然后您的脚本将在单独的配置文件中构建 `sftp` 更改。这个新更改使事情更加安全。
您的脚本将使用一个新的下拉式配置文件:`/etc/ssh/sftp/sftp_config`。
首先,创建该目录
mkdir /etc/ssh/sftp
创建 `sshd_config` 的备份副本
cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
最后编辑 `sshd_config` 文件,滚动到文件最底部,并添加此行:
Include /etc/ssh/sftp/sftp_config
保存您的更改并退出文件。您需要重启 `sshd`,但您的脚本将在您更新 `sftp_config` 文件后为您完成此操作,因此请创建脚本并运行它。
vi /usr/local/sbin/webuser
将此代码添加到文件中
#!/bin/bash
# script to populate the SSHD configuration for web users.
# Set variables
tempfile="/usr/local/sbin/sshd_template"
dompath="/var/www/sub-domains/"
# Prompt for user and domain in reverse (ext.domainname):
clear
echo -n "Enter the web sftp user: "
read sftpuser
echo -n "Enter the domain in reverse. Example: com.domainname: "
read dom
echo -n "Is all of this correct: sftpuser = $sftpuser and domain = $dom (Y/N)? "
read yn
if [ "$yn" = "n" ] || [ "$yn" = "N" ]
then
exit
fi
if [ "$yn" = "y" ] || [ "$yn" = "Y" ]
then
/usr/bin/cat $tempfile > /usr/local/sbin/templates/$dom.txt
/usr/bin/sed -i "s,replaceuser,$sftpuser,g" /usr/local/sbin/templates/$dom.txt
/usr/bin/sed -i "s,replacedirectory,$dompath$dom,g" /usr/local/sbin/templates/$dom.txt
/usr/bin/chown -R $sftpuser.apache $dompath$dom/html
# Ensure directory permissions are correct
# The root user owns all directories except the chroot, which is owned by the sftpuser
# when connecting, you will end up one directory down, and you must actually change to the html directory
# With a graphical SFTP client, this will be visible to you, you just need to double-click on the html
# directory before attmpting to drop in files.
chmod 755 $dompath
chmod 755 $dompath$dom
chmod 755 $dompath$dom/html
chmod 744 -R $dompath$dom/html/
fi
## Make a backup of /etc/ssh/sftp/sftp_config
/usr/bin/rm -f /etc/ssh/sftp/sftp_config.bak
/usr/bin/cp /etc/ssh/sftp/sftp_config /etc/ssh/sftp/sftp_config.bak
## Now append our new user information to to the file
cat /usr/local/sbin/templates/$dom.txt >> /etc/ssh/sftp/sftp_config
## Restart sshd
/usr/bin/systemctl restart sshd
echo " "
echo "Please check the status of sshd with systemctl status sshd."
echo "You can verify that your information was added by doing a more of the sftp_config"
echo "A backup of the working sftp_config was created when this script was run: sftp_config.bak"
最终更改和脚本说明¶
技巧
如果您查看上面的脚本,您会注意到 `sed` 默认使用的分隔符已从 `/` 更改为 `,`。`sed` 允许您使用任何单字节字符作为分隔符。您在文件中搜索的内容包含许多 "/" 字符,您将不得不转义每个字符(在其前面加上 "\")来搜索和替换这些字符串。更改分隔符使此操作变得更加容易,因为它消除了进行这些转义的需要。
关于脚本以及 `sftp` chroot 的几点值得注意。首先,您会提示所需信息并将其回显给用户进行验证。如果您回答“N”表示确认问题,脚本将退出且什么也不做。脚本会创建 `sftp_config` 文件的备份副本(`/etc/ssh/sftp/sftp_config.bak`)。这样,如果您在输入时出错,您可以恢复相应的备份文件并重启 `sshd` 以恢复正常工作。
`sftp` chroot 要求 `sshd_config` 中提供的路径具有 root 所有权。因此,您不需要在路径末尾添加 `html` 目录。一旦用户通过身份验证,chroot 将把用户的家目录(在这种情况下是 `../html` 目录)切换到您正在输入的任何域。您的脚本已适当地将 `../html` 目录的所有者更改为 `sftpuser` 和 `apache` 组。
使脚本可执行
chmod +x /usr/local/sbin/webuser
运行脚本以用于您的两个测试域。
测试 SSH 拒绝和 `sftp` 访问¶
首先,尝试从另一台机器使用 `ssh` 以其中一个 `sftp` 用户的身份连接到您的主机。在输入密码后,您应该会收到此消息:
This service allows sftp connections only.
图形工具测试¶
如果**确实**收到该消息,接下来就是测试 `sftp` 访问。为了方便测试,您可以使用支持 `sftp` 的图形 FTP 应用程序,例如 Filezilla。在这种情况下,您的字段将类似于:
- **主机:** sftp://主机名_或_服务器IP
- **用户名:** (示例:myfixed)
- **密码:** (sftp 用户的密码)
- **端口:** 如果您使用默认端口 22 的 SSH 和 `sftp`,则输入该端口
填写完毕后,您可以单击“快速连接”(Filezilla)按钮,您将连接到相应站点的 `../html` 目录。双击“html”目录进入其中,然后尝试将文件上传到该目录。如果您成功了,一切正常。
命令行工具测试¶
您可以在安装了 SSH 的机器(大多数 Linux 安装)上从命令行完成所有这些操作。以下是连接的命令行方法的简要概述和一些选项:
- `sftp` 用户名 (示例:myfixed@ 主机名或服务器 IP:sftp myfixed@192.168.1.116)
- 提示时输入密码
- `cd html` (切换到 html 目录)
- `pwd` (应显示您在 html 目录中)
- `lpwd` (应显示您本地的工作目录)
- `lcd` PATH (应将您的本地工作目录更改为您想要使用的目录)
- `put filename` (将文件复制到 `..html` 目录)
有关选项和更多信息的详尽列表,请参阅`sftp` 手册页。
Web 测试文件¶
对于您的测试域,您需要创建几个 `index.html` 文件,您可以用它们来填充 `../html` 目录。创建后,您需要使用该域的 `sftp` 凭据将其放入每个域的目录中。这些文件很简单。您只需要一些东西来验证您的站点是否正常运行以及 `sftp` 是否按预期工作。这是一个文件示例。您可以根据需要进行更改。
<!DOCTYPE html>
<html>
<head>
<title>My Broken Axel</title>
</head>
<body>
<h1>My Broken Axel</h1>
<p>A test page for the site.</p>
</body>
</html>
Web 测试¶
您需要更改工作站上的 *hosts* 文件,以测试这些文件是否按预期显示和加载。对于 Linux,这将是 `sudo vi /etc/hosts`,并添加您正在测试的 IP 和主机名:
127.0.0.1 localhost
192.168.1.116 www.site1.com site1.com
192.168.1.116 www.site2.com site2.com
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
技巧
您会在真实的域名上将上面的主机信息填充到您的 DNS 服务器中。但是,您可以使用此*穷人 DNS* 来测试任何域,即使是尚未在真实 DNS 服务器上上线的域。
打开您的 Web 浏览器,并通过在浏览器地址栏中输入 URL 来确保每个域的 `index.html` 文件均按预期显示。(示例:http://site1.com)如果您的测试索引文件加载成功,则一切正常。
第三部分:使用 SSH 密钥对进行管理员访问¶
请注意,您将在此处使用文档SSH 公钥和私钥中讨论的概念,但也会对其进行改进。如果您不熟悉此过程,请在继续之前阅读该文章。
创建公钥和私钥对¶
从管理员用户之一的工作站命令行(示例:lblakely)执行以下操作:
ssh-keygen -t rsa
这将产生如下输出:
Generating public/private rsa key pair.
Enter file in which to save the key (/home/lblakely/.ssh/id_rsa):
按Enter在显示的位置创建私钥。这将显示以下对话框:
Enter passphrase (empty for no passphrase):
您需要自己决定是否需要此步骤的密码。作者总是直接按Enter。
Enter same passphrase again:
重复您之前输入的任何密码,或者按Enter以不设置密码。
此时,公钥和私钥已存在。为您的其他系统管理员示例用户重复此步骤。
将公钥传输到 `sftp` 服务器¶
下一步是将您的密钥导出到服务器。实际上,负责管理多个服务器的系统管理员会将他们的公钥传输到他们负责的所有服务器。
创建后,用户可以使用 `ssh-id-copy` 安全地将密钥发送到服务器:
ssh-id-copy lblakely@192.168.1.116
服务器将提示一次输入用户密码,并将密钥复制到 *authorized_keys*。您也会收到此消息:
Number of key(s) added: 1
尝试使用“ssh 'lblakely@192.168.1.116'”登录到该机器,并检查以确保只添加了您想要的密钥。
如果您能够使用此帐户登录,请对另一位管理员重复此过程。
仅允许基于密钥的登录¶
如果一切按计划进行,并且您的管理员密钥已放置在 `sftp` 服务器上,您就需要关闭服务器上的密码身份验证。为了安全起见,请确保您有两个到服务器的连接,以便在出现意外后果时可以撤销任何更改。
要完成此步骤,您需要再次更改 `sshd_config`,并且与之前一样,您需要先备份该文件:
cp -f /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
接下来,编辑 `sshd_config` 文件:
vi /etc/ssh/sshd_config
您需要关闭隧道密码。在此配置中找到此行:
PasswordAuthentication yes
将其更改为“no” - 请注意,仅仅注释掉此行将不起作用,因为默认值始终是“yes”。
PasswordAuthentication no
公钥身份验证默认是开启的,但请通过删除此行前面的注释来确保它已开启:
#PubkeyAuthentication yes
使其显示为:
PubkeyAuthentication yes
这在一定程度上使我们的 `sshd_config` 文件具有自我记录性。
保存您的更改。祈祷好运,然后重启 `sshd`:
systemctl restart sshd
尝试使用您的管理员用户通过他们的密钥登录服务器应能按原样工作。如果不行,请恢复您的备份,确保您已遵循所有步骤,然后重试。
第四部分:关闭远程 root 登录¶
您已经实际完成了这一点。如果您尝试使用 root 用户登录服务器,您将收到以下消息:
root@192.168.1.116: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
但是,您需要确保有人无法为 root 用户创建公钥和私钥对并以这种方式访问服务器。要做到这一点,您需要最后一步。您将在 `sshd_config` 文件中进行此更改。
与之前一样,您需要在继续之前创建该文件的备份副本:
cp -f /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
编辑 `sshd_config`:
vi /etc/ssh/sshd_config
找到此行:
PermitRootLogin yes
将其更改为“no”:
PermitRootLogin no
保存,退出文件,然后重启 `sshd`:
systemctl restart sshd
通过 `ssh` 远程登录 root 用户将收到与之前相同的拒绝消息,但即使他们拥有 root 的公钥和私钥对,**仍然**无法访问服务器。
附录:新系统管理员¶
尚未讨论的是添加另一位系统管理员时会发生什么。`ssh-copy-id` 在关闭密码身份验证时将无法工作。以下是作者对此类情况的建议。请注意,存在不止一种解决方案。此外,除了此处提到的方法之外,现有管理员还可以为另一位管理员生成和部署密钥。
解决方案一 - U盘传输¶
此解决方案假设您对服务器有物理访问权限,并且服务器是物理硬件而不是虚拟(容器或 VM)。
- 将用户添加到 `sftp` 服务器上的“wheel”组:
- 让用户生成其 SSH 公钥和私钥:
- 使用 USB 驱动器,将公钥复制到驱动器,然后将其物理带到服务器,并将其手动安装在新系统管理员的 `/home/[username]/.ssh` 目录中。
解决方案二 - 临时编辑 `sshd_config`¶
此解决方案容易出现人为错误,但由于它不经常执行,如果小心操作,应该还可以。
- 将用户添加到 `sftp` 服务器上的“wheel”组:
- 让另一位已拥有基于密钥的身份验证的系统管理员,暂时在 `sshd_config` 文件中启用“PasswordAuthentication yes”,然后重启 `sshd`:
- 让新系统管理员运行 `ssh-copy-id`,使用他们的密码将 SSH 密钥复制到服务器。
解决方案三 - 脚本化过程¶
此过程使用已拥有基于密钥访问的系统管理员和一个必须使用 `bash [script-name]` 运行的脚本来完成与前面“解决方案二”相同的事情。
- 手动编辑 `sshd_config` 文件,并删除看起来像这样的注释掉的行:`#PasswordAuthentication no`。此行是对关闭密码身份验证过程的记录,但它会干扰下面的脚本,因为您的脚本会查找 `PasswordAuthentication no` 的第一个实例,然后查找 `PasswordAuthentication yes` 的第一个实例。如果您删除这一行,脚本将正常工作。
- 在 `sftp` 服务器上创建一个名为“quickswitch”(或您想要的任何名称)的脚本。此脚本的内容如下:
#!/bin/bash
# for use in adding a new system administrator
/usr/bin/cp -f /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
/usr/bin/sed -i '0,/PasswordAuthentication no/ s/PasswordAuthentication no/PasswordAuthentication yes/' /etc/ssh/sshd_config
/usr/bin/systemctl restart sshd
echo "Have the user send his keys, and then hit enter."
read yn
/usr/bin/sed -i '0,/PasswordAuthentication yes/ s/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
/usr/bin/systemctl restart sshd
echo "Changes reversed"
脚本说明:您不使其成为可执行文件。原因是不想让它意外运行。脚本(如上所述)通过以下方式运行:`bash /usr/local/sbin/quickswitch`。此脚本会创建 `sshd_config` 文件的备份副本。然后它会就地编辑 `sshd_config` 文件,搜索 `PasswordAuthentication no` 的**第一个**实例并将其更改为 `PasswordAuthentication yes`,然后重启 `sshd`,并在脚本用户按Enter继续之前等待。运行脚本的系统管理员将与新系统管理员进行通信。当新系统管理员运行 `ssh-copy-id` 将其密钥复制到服务器时,运行脚本的系统管理员会按Enter,这就撤销了更改。
总之,在实施 SSH 锁定程序后,存在多种添加另一位系统管理员的方法。
结论¶
本文档内容广泛。它将使多站点 Web 服务器更安全,并在启用 `sftp` 以供客户访问时,减少通过 SSH 遭受攻击的可能。`sftp` 比 FTP 安全得多,即使您使用一个非常**好的** FTP 服务器,并像本VSFTPD 文档中所述的那样将其尽可能安全地设置。通过实施本文档中的**所有**步骤,您可以放心地将端口 22 (SSH) 对公众开放,并且仍然知道您的环境是安全的。
作者:Steven Spencer
贡献者:Ezequiel Bruni, Ganna Zhyrnova