如何在Ubuntu16.04上为用户目录设置vsftpd

来自菜鸟教程
跳转至:导航、​搜索

介绍

FTP是文件传输协议的缩写,是一种网络协议,曾经被广泛用于在客户端和服务器之间移动文件。 此后,它已被更快、更安全、更方便的文件传递方式所取代。 许多普通的 Internet 用户希望使用 https 从他们的 Web 浏览器直接下载,而命令行用户更有可能使用 scpsFTP 等安全协议。

FTP 仍用于支持具有非常特殊需求的遗留应用程序和工作流。 如果您可以选择使用哪种协议,请考虑探索更现代的选项。 但是,当您确实需要 FTP 时,vsftpd 是一个很好的选择。 vsftpd 针对安全性、性能和稳定性进行了优化,针对其他 FTP 服务器中发现的许多安全问题提供了强大的保护,并且是许多 Linux 发行版的默认设置。

在本教程中,我们将向您展示如何配置 vsftpd 以允许用户使用由 SSL/TLS 保护的登录凭据使用 FTP 将文件上传到他或她的主目录。

先决条件

要学习本教程,您需要:

  • 具有 sudo 权限的非 root 用户的 Ubuntu 16.04 服务器:您可以在我们的 使用 Ubuntu 16.04 的初始服务器设置指南中了解有关如何设置具有这些权限的用户的更多信息。

一旦你有了一个 Ubuntu 服务器,你就可以开始了。

第 1 步 — 安装 vsftpd

我们将首先更新我们的包列表并安装 vsftpd 守护进程:

sudo apt-get update
sudo apt-get install vsftpd

安装完成后,我们将复制配置文件,以便我们可以从空白配置开始,将原始配置保存为备份。

sudo cp /etc/vsftpd.conf /etc/vsftpd.conf.orig

备份配置后,我们就可以配置防火墙了。

第 2 步 — 打开防火墙

我们将检查防火墙状态以查看它是否已启用。 如果是这样,我们将确保允许 FTP 流量,这样您在测试时就不会遇到阻止您的防火墙规则。

sudo ufw status

在这种情况下,只允许通过 SSH:

OutputStatus: active

To Action  From
-- ------  ----
OpenSSH ALLOW   Anywhere
OpenSSH (v6)   ALLOW   Anywhere (v6)

您可能有其他规则或根本没有防火墙规则。 由于在这种情况下只允许 ssh 流量,我们需要为 FTP 流量添加规则。

我们需要为 FTP 打开端口 20 和 21,稍后启用 TLS 时打开端口 990,并为我们计划在配置文件中设置的被动端口范围打开端口 40000-50000:

sudo ufw allow 20/tcp
sudo ufw allow 21/tcp
sudo ufw allow 990/tcp
sudo ufw allow 40000:50000/tcp
sudo ufw status

现在我们的防火墙规则如下所示:

OutputStatus: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
990/tcp                    ALLOW       Anywhere
20/tcp                     ALLOW       Anywhere
21/tcp                     ALLOW       Anywhere
40000:50000/tcp            ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
20/tcp (v6)                ALLOW       Anywhere (v6)
21/tcp (v6)                ALLOW       Anywhere (v6)
990/tcp (v6)               ALLOW       Anywhere (v6)
40000:50000/tcp (v6)       ALLOW       Anywhere (v6)

安装 vsftpd 并打开必要的端口后,我们就可以进行下一步了。

第 3 步 — 准备用户目录

对于本教程,我们将创建一个用户,但您可能已经有一个需要 FTP 访问的用户。 我们将在以下说明中注意保留现有用户对其数据的访问权限。 即便如此,我们还是建议您从新用户开始,直到您配置和测试您的设置。

首先,我们将添加一个测试用户:

sudo adduser sammy

出现提示时分配密码,并在其他提示中随意按“ENTER”。

当用户被限制在特定目录时,FTP 通常更安全。vsftpd 使用 chroot 监狱来实现这一点。 当为本地用户启用 chroot 时,默认情况下他们被限制在他们的主目录中。 但是,由于 vsftpd 保护目录的方式,它不能被用户写入。 这对于只应通过 FTP 连接的新用户来说很好,但如果现有用户也有 shell 访问权限,他们可能需要写入他们的主文件夹。

在此示例中,我们将创建一个 ftp 目录作为 chroot 和一个可写的 files 目录来保存主目录,而不是从主目录中删除写权限实际文件。

创建 ftp 文件夹,设置其所有权,并确保使用以下命令删除写入权限:

sudo mkdir /home/sammy/ftp
sudo chown nobody:nogroup /home/sammy/ftp
sudo chmod a-w /home/sammy/ftp

让我们验证权限:

sudo ls -la /home/sammy/ftp
Outputtotal 8
4 dr-xr-xr-x  2 nobody nogroup 4096 Aug 24 21:29 .
4 drwxr-xr-x 3 sammy  sammy   4096 Aug 24 21:29 ..

接下来,我们将创建可以上传文件的目录并将所有权分配给用户:

sudo mkdir /home/sammy/ftp/files
sudo chown sammy:sammy /home/sammy/ftp/files

files 目录的权限检查应返回以下内容:

sudo ls -la /home/sammy/ftp
Outputtotal 12
dr-xr-xr-x 3 nobody nogroup 4096 Aug 26 14:01 .
drwxr-xr-x 3 sammy  sammy   4096 Aug 26 13:59 ..
drwxr-xr-x 2 sammy  sammy   4096 Aug 26 14:01 files

最后,我们将添加一个 test.txt 文件以供我们稍后测试时使用:

echo "vsftpd test file" | sudo tee /home/sammy/ftp/files/test.txt

现在我们已经保护了 ftp 目录并允许用户访问 files 目录,我们将注意力转向配置。

第 4 步 — 配置 FTP 访问

我们计划允许具有本地 shell 帐户的单个用户连接 FTP。 在 vsftpd.conf 中已经设置了这两个键的设置。 首先打开配置文件以验证配置中的设置是否与以下设置匹配:

sudo nano /etc/vsftpd.conf

/etc/vsftpd.conf

. . .
# Allow anonymous FTP? (Disabled by default).
anonymous_enable=NO
#
# Uncomment this to allow local users to log in.
local_enable=YES
. . .

接下来,我们需要更改文件中的一些值。 为了允许用户上传文件,我们将取消注释 write_enable 设置,以便我们拥有:

/etc/vsftpd.conf

. . .
write_enable=YES
. . .

我们还将取消注释 chroot 以防止 FTP 连接的用户访问目录树之外的任何文件或命令。

/etc/vsftpd.conf

. . .
chroot_local_user=YES
. . .

我们将添加一个 user_sub_token 以便在我们的 local_root directory 路径中插入用户名,这样我们的配置将适用于该用户以及可能添加的任何未来用户。

/etc/vsftpd.conf

user_sub_token=$USER
local_root=/home/$USER/ftp

我们将限制可用于被动 FTP 的端口范围,以确保有足够的连接可用:

/etc/vsftpd.conf

pasv_min_port=40000
pasv_max_port=50000

注意: 我们预先打开了我们在此处为被动端口范围设置的端口。 如果您更改这些值,请务必更新您的防火墙设置。


由于我们只计划在具体情况下允许 FTP 访问,因此我们将设置配置,以便仅当用户显式添加到列表而不是默认情况下才授予用户访问权限:

/etc/vsftpd.conf

userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO

userlist_deny 切换逻辑。 当它设置为“YES”时,列表中的用户将被拒绝 FTP 访问。 当设置为“NO”时,仅允许列表中的用户访问。 完成更改后,保存并退出文件。

最后,我们将创建用户并将其添加到文件中。 我们将使用 -a 标志附加到文件:

echo "sammy" | sudo tee -a /etc/vsftpd.userlist

仔细检查它是否按预期添加:

cat /etc/vsftpd.userlist
Outputsammy

重新启动守护程序以加载配置更改:

sudo systemctl restart vsftpd

现在我们准备好进行测试了。

第 5 步 — 测试 FTP 访问

我们已将服务器配置为仅允许用户 sammy 通过 FTP 连接。 让我们确保情况确实如此。

匿名用户应该无法连接:我们禁用了匿名访问。 在这里,我们将通过尝试匿名连接来测试它。 如果我们做得正确,匿名用户应该被拒绝权限:

ftp -p 203.0.113.0
OutputConnected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): anonymous
530 Permission denied.
ftp: Login failed.
ftp>

关闭连接:

bye

sammy 以外的用户应该无法连接:接下来,我们将尝试以我们的 sudo 用户身份连接。 他们也应该被拒绝访问,并且应该在他们被允许输入密码之前发生。

ftp -p 203.0.113.0
OutputConnected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): sudo_user
530 Permission denied.
ftp: Login failed.
ftp>

关闭连接:

bye

sammy应该可以连接,也可以读写文件:这里,我们要确保我们指定的用户_can_connect:

ftp -p 203.0.113.0
OutputConnected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): sammy
331 Please specify the password.
Password: your_user's_password
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>

我们将切换到 files 目录,然后使用 get 命令将我们之前创建的测试文件传输到本地机器:

cd files
get test.txt
Output227 Entering Passive Mode (203,0,113,0,169,12).
150 Opening BINARY mode data connection for test.txt (16 bytes).
226 Transfer complete.
16 bytes received in 0.0101 seconds (1588 bytes/s)
ftp>

我们将右转并尝试使用新名称上传文件以测试写入权限:

put test.txt upload.txt
Output227 Entering Passive Mode (203,0,113,0,164,71).
150 Ok to send data.
226 Transfer complete.
16 bytes sent in 0.000894 seconds (17897 bytes/s)

关闭连接:

bye

现在我们已经测试了我们的配置,我们将采取措施进一步保护我们的服务器。

第 6 步 — 保护交易

由于 FTP 对传输中的任何数据(包括用户凭据)进行加密,因此我们将启用 TTL/SSL 以提供该加密。 第一步是创建用于 vsftpd 的 SSL 证书。

我们将使用 openssl 创建新证书并使用 -days 标志使其有效期为一年。 在同一命令中,我们将添加一个私有 2048 位 RSA 密钥。 然后通过将 -keyout-out 标志设置为相同的值,私钥和证书将位于同一个文件中。

我们将使用以下命令执行此操作:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/vsftpd.pem -out /etc/ssl/private/vsftpd.pem

系统将提示您提供证书的地址信息。 用您自己的信息代替以下问题:

OutputGenerating a 2048 bit RSA private key
............................................................................+++
...........+++
writing new private key to '/etc/ssl/private/vsftpd.pem'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:US
State or Province Name (full name) [Some-State]:NY
Locality Name (eg, city) []:New York City
Organization Name (eg, company) [Internet Widgits Pty Ltd]:DigitalOcean
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []: your_IP_address
Email Address []:

有关证书标志的更多详细信息,请参阅 OpenSSL Essentials:使用 SSL 证书、私钥和 CSR

创建证书后,再次打开 vsftpd 配置文件:

sudo nano /etc/vsftpd.conf

在文件的底部,您应该有两行以 rsa_ 开头。 将它们注释掉,使它们看起来像:

/etc/vsftpd.conf

# rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
# rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key

在它们下面,添加以下行,指向我们刚刚创建的证书和私钥:

/etc/vsftpd.conf

rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem

之后,我们将强制使用 SSL,这将阻止无法处理 TLS 的客户端连接。 这是必要的,以确保所有流量都被加密,但可能会迫使您的 FTP 用户更改客户端。 将 ssl_enable 更改为 YES

/etc/vsftpd.conf

ssl_enable=YES

之后,添加以下行以明确拒绝通过 SSL 的匿名连接,并要求 SSL 用于数据传输和登录:

/etc/vsftpd.conf

allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES

在此之后,我们将通过添加以下行将服务器配置为使用 TLS,这是 SSL 的首选继任者:

/etc/vsftpd.conf

ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO

最后,我们将添加另外两个选项。 首先,我们不需要 SSL 重用,因为它会破坏许多 FTP 客户端。 我们将需要“高”加密密码套件,这目前意味着密钥长度等于或大于 128 位:

/etc/vsftpd.conf

require_ssl_reuse=NO
ssl_ciphers=HIGH

完成后,保存并关闭文件。

现在,我们需要重新启动服务器以使更改生效:

sudo systemctl restart vsftpd

此时,我们将无法连接不安全的命令行客户端。 如果我们尝试,我们会看到如下内容:

ftp -p 203.0.113.0
Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): sammy
530 Non-anonymous sessions must use encryption.
ftp: Login failed.
421 Service not available, remote server has closed connection
ftp>

接下来,我们将验证是否可以使用支持 TLS 的客户端进行连接。

第 7 步 — 使用 FileZilla 测试 TLS

大多数现代 FTP 客户端都可以配置为使用 TLS 加密。 我们将演示如何使用 FileZilla 进行连接,因为它支持跨平台。 查阅其他客户端的文档。

当您第一次打开 FileZilla 时,在“文件”一词下方找到站点管理器图标,即顶行最左侧的图标。 点击它:

将打开一个新窗口。 点击右下角的“新建站点”按钮:

在“我的站点”下,将出现一个带有“新站点”字样的新图标。 您可以现在命名或稍后返回并使用重命名按钮。

您必须使用名称或 IP 地址填写“主机”字段。 在“加密”下拉菜单下,选择“要求显式 FTP over TLS”。

对于“登录类型”,选择“询问密码”。 在“用户”字段中填写您创建的 FTP 用户:

点击界面底部的“连接”。 您将被要求输入用户密码:

单击“确定”进行连接。 您现在应该使用 TLS/SSL 加密与您的服务器连接。

接受证书后,双击 files 文件夹并将 upload.txt 拖到左侧以确认您可以下载文件。
完成后,在本地复制右键,重命名为upload-tls.txt`拖回服务器,确认可以上传文件。

您现在已确认您可以在启用 SSL/TLS 的情况下安全且成功地传输文件。

第 8 步 — 禁用 Shell 访问(可选)

如果由于客户端要求而无法使用 TLS,则可以通过禁用 FTP 用户以任何其他方式登录的能力来获得一些安全性。 一种相对简单的防止它的方法是创建自定义外壳。 这不会提供任何加密,但会限制受感染帐户对 FTP 可访问的文件的访问。

首先,在 bin 目录下打开一个名为 ftponly 的文件:

sudo nano /bin/ftponly

我们将添加一条消息,告诉用户他们无法登录的原因。 粘贴以下内容:

#!/bin/sh
echo "This account is limited to FTP access only."

更改权限以使文件可执行:

sudo chmod a+x /bin/ftponly

打开有效 shell 列表:

sudo nano /etc/shells

在底部,添加:

/etc/shells

. . .
/bin/ftponly

使用以下命令更新用户的 shell:

sudo usermod sammy -s /bin/ftponly

现在尝试以 sammy 身份登录:

ssh sammy@203.0.113.0

您应该会看到如下内容:

OutputThis account is limited to FTP access only.
Connection to 203.0.113.0 closed.

这确认用户不能再 ssh 访问服务器,并且仅限于 FTP 访问。

结论

在本教程中,我们介绍了为具有本地帐户的用户设置 FTP。 如果您需要使用外部身份验证源,您可能需要查看 vsftpd 对虚拟用户的支持。 这通过使用 PAM(可插入身份验证模块)提供了一组丰富的选项,如果您在另一个系统(例如 LDAP 或 Kerberos)中管理用户,这是一个不错的选择。