什么是FTP?

FTP是文件传输协议的缩写,是一种广泛用于在客户端和服务器之间移动文件的网络协议。FTP被广泛运维人员用户对服务器程序、文件下载/上传中使用,相比较于http/https传输多了一道门槛。

FTP仍然用于支持具有特定需求的遗留问题。如果可以选择使用其它协议,请谨慎考虑。但是当你需要FTP时,vsftpd是一个很好的选择。
vsftpd针对安全性,性能和稳定性进行了优化,可以很好地防范其他FTP服务器中存在的许多安全问题,并且是许多Linux发行版的默认设置。

在本教程中,您将配置vsftpd以允许用户使用FTP将文件上载到其主目录,并使用SSL / TLS保护登录凭据。

先决条件

要学习本教程,您需要:

  • Debian 10服务器和具有sudo权限的非root用户。

第1步 – 安装vsftpd

让我们从更新包列表并安装vsftpd守护进程开始:

sudo apt update
 sudo apt install vsftpd

安装完成后,复制配置文件,以便可以从空白配置开始,并将原始文件另存为备份:

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

通过备份配置,我们已准备好配置防火墙。

第2步 – 打开防火墙

让我们检查防火墙状态以查看它是否已启用。如果是,我们将确保允许FTP流量,因此防火墙规则不会阻止我们的测试。本指南假定您已按照初始服务器设置指南中的步骤4安装了UFW 。

检查防火墙状态:

sudo ufw status

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

Status: active

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

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

让我们打开端口20和21FTP,990我们启用TLS时的端口,以及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

您的防火墙规则现在应如下所示:

输出
Status: 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已安装和必要的端口打开,让我们继续创建一个专用的FTP用户。

第3步 – 准备用户目录

我们将创建一个专用的FTP用户,但您可能已经有一个需要FTP访问的用户。我们将注意保留现有用户在后续说明中对其数据的访问权限。即便如此,我们建议您在配置和测试设置之前先与新用户合作。

首先,添加一个名为的测试用户sammy


sudo adduser sammy

出现提示时分配密码。随意按下ENTER其他提示。

当用户被限制在特定目录时,FTP通常更安全。vsftpd用chrootjails 完成这个。当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
输出
total 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

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


sudo ls -la /home/sammy/ftp
输出
total 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取消注释该设置并将其设置为YES:来允许用户上传文件:

/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

注意:在步骤2中,我们打开了我们在此处为被动端口范围设置的端口。如果更改值,请务必更新防火墙设置。

要根据具体情况允许FTP访问,让我们设置配置,以便用户只有在明确添加到列表时才能访问,而不是默认情况下:

/etc/vsftpd.conf文件
. . .
userlist_enable=YES
userlist_file=/etc/vsftpd.userlist
userlist_deny=NO

userlist_deny切换逻辑:当设置为时YES,列表中的用户被拒绝FTP访问。设置为时NO,只允许列表中的用户访问。

完成更改后,保存文件并退出编辑器。

最后,让我们将用户添加到/etc/vsftpd.userlist。使用该-a标志附加到文件:


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

检查它是否按预期添加:


cat /etc/vsftpd.userlist
输出
sammy

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


sudo systemctl restart vsftpd

配置到位后,我们可以继续测试FTP访问。

第5步 – 测试FTP访问

我们已将服务器配置为仅允许用户sammy通过FTP连接。让我们确保它按预期工作。

匿名用户应该无法连接:我们已禁用匿名访问。让我们通过尝试匿名连接来测试它。如果我们的配置设置正确,则应拒绝匿名用户的权限。打开另一个终端并运行以下命令。请务必203.0.113.0使用服务器的公共IP地址替换,并将其用作用anonymous户名:

ftp -p 203.0.113.0
输出
Connected 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
输出
Connected to 203.0.113.0.
220 (vsFTPd 3.0.3)
Name (203.0.113.0:default): your_sudo_user
530 Permission denied.
ftp: Login failed.
ftp>

关闭连接:

bye

用户sammy应该能够连接,读取和写入文件:让我们确保我们的指定用户可以连接:


ftp -p 203.0.113.0
输出
Connected 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
输出
229 Entering Extended Passive Mode (|||47398|)
150 Opening BINARY mode data connection for test.txt (17 bytes).
100% |**********************************|    17      146.91 KiB/s    00:00 ETA
226 Transfer complete.
17 bytes received in 00:00 (0.17 KiB/s)
ftp>

接下来,让我们使用新名称上传文件以测试写入权限:

put test.txt upload.txt
输出
229 Entering Extended Passive Mode (|||46598|)
150 Ok to send data.
100% |**********************************|    17        8.93 KiB/s    00:00 ETA
226 Transfer complete.
17 bytes sent in 00:00 (0.08 KiB/s)

关闭连接:

bye

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

第6步 – 保护交易

因为FTP并没有加密在传输过程中的任何数据,包括用户的凭据,我们将启用TLS / SSL来提供加密。第一步是创建用于的SSL证书vsftpd。

让我们使用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

系统将提示您提供证书的地址信息。将您自己的信息替换为下面突出显示的值。对于该Common Name字段,请务必添加your_server_ip

输出
Generating 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_server_ip
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
. . .

完成的文件部分应如下所示:

/etc/vsftpd.conf文件
# This option specifies the location of the RSA certificate to use for SSL
# encrypted connections.
#rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
#rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
rsa_cert_file=/etc/ssl/private/vsftpd.pem
rsa_private_key_file=/etc/ssl/private/vsftpd.pem
ssl_enable=YES
allow_anon_ssl=NO
force_local_data_ssl=YES
force_local_logins_ssl=YES
ssl_tlsv1=YES
ssl_sslv2=NO
ssl_sslv3=NO
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.
ftp>

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

第7步 – 使用FileZilla测试TLS

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

当你第一次打开FileZilla中,找到刚才上面的字站点管理器图标主机,顶行最左侧的图标。点击它:

现场经理Screent Shot

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

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

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

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