如何在Debian10上为用户目录设置vsftpd
介绍
FTP是文件传输协议的缩写,是一种网络协议,曾经被广泛用于在客户端和服务器之间移动文件。 此后,它已被更快、更安全、更方便的文件传递方式所取代。 许多普通的互联网用户希望使用 https
从他们的 Web 浏览器直接下载,而命令行用户更有可能使用安全协议,例如 scp
或 SFTP。
FTP 仍用于支持具有非常特殊需求的遗留应用程序和工作流。 如果您可以选择使用哪种协议,请考虑探索更现代的选项。 但是,当您确实需要 FTP 时,vsftpd 是一个很好的选择。 vsftpd 针对安全性、性能和稳定性进行了优化,针对其他 FTP 服务器中发现的许多安全问题提供了强大的保护,并且是许多 Linux 发行版的默认设置。
在本教程中,您将配置 vsftpd 以允许用户使用 FTP 将文件上传到他们的主目录,并使用 SSL/TLS 保护的登录凭据。
先决条件
要学习本教程,您需要:
- Debian 10 服务器和具有
sudo
权限的非 root 用户。 您可以在我们的 Initial Server Setup with Debian 10 指南中了解有关如何创建具有这些权限的用户的更多信息。
第 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:
OutputStatus: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6)
您可能有其他规则或根本没有防火墙规则。 由于在这种情况下只允许 SSH 流量,我们需要为 FTP 流量添加规则。
让我们打开端口 20
和 21
用于 FTP,端口 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
您的防火墙规则现在应该如下所示:
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
并打开必要的端口后,让我们继续创建一个专用的 FTP 用户。
第 3 步 — 准备用户目录
我们将创建一个专用的 FTP 用户,但您可能已经有一个需要 FTP 访问的用户。 我们将在以下说明中注意保留现有用户对其数据的访问权限。 尽管如此,我们还是建议您在配置和测试设置之前从新用户开始。
首先,添加一个名为 sammy
的测试用户:
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
对 ftp
目录的权限检查应返回以下内容:
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
设置并设置为 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
Outputsammy
重新启动守护程序以加载配置更改:
sudo systemctl restart vsftpd
配置到位后,我们可以继续测试 FTP 访问。
第 5 步 — 测试 FTP 访问
我们已将服务器配置为仅允许用户 sammy 通过 FTP 连接。 让我们确保它按预期工作。
匿名用户应该无法连接:我们已禁用匿名访问。 让我们通过尝试匿名连接来测试它。 如果我们的配置设置正确,匿名用户应该被拒绝权限。 打开另一个终端并运行以下命令。 请务必将 203.0.113.0
替换为 您服务器的公共 IP 地址 ,并使用 anonymous
作为您的用户名:
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): your_sudo_user 530 Permission denied. ftp: Login failed. ftp>
关闭连接:
bye
用户 sammy 应该可以连接、读取和写入文件:让我们确保我们指定的用户可以连接:
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
Output229 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
Output229 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 以提供该加密。 第一步是创建用于 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
系统将提示您提供证书的地址信息。 用您自己的信息替换下面突出显示的值。 对于 Common Name
字段,请务必添加 your_server_ip
:
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_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
此时,我们将无法连接不安全的命令行客户端。 如果我们尝试,我们会看到如下内容:
Outputftp -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 时,在 Host 字样上方找到站点管理器图标,即顶行最左侧的图标。 点击它:
将打开一个新窗口。 点击右下角的【X10X】新建站点【X22X】按钮:
在 My Sites 下将出现一个带有 New Site 字样的新图标。 您可以现在命名或稍后返回并使用 Rename 按钮。
使用您的域名或 IP 地址填写 Host 字段。 在 Encryption 下拉菜单下,选择 Require explicit FTP over TLS。
对于登录类型,选择询问密码。 在 User 字段中填写您的 FTP 用户:
点击界面下方的【X6X】连接【X17X】。 您将被要求输入用户密码:
点击【X6X】确定【X12X】进行连接。 您现在应该使用 TLS/SSL 加密与您的服务器连接。
成功后,您将看到如下所示的服务器证书:
当您接受证书后,双击 files
文件夹并将 upload.txt
拖到左侧以确认您可以下载文件:
完成后,右键单击本地副本,将其重命名为 upload-tls.txt
并将其拖回服务器以确认您可以上传文件:
您现在已确认您可以在启用 SSL/TLS 的情况下安全且成功地传输文件。
第 8 步 — 禁用 Shell 访问(可选)
如果由于客户端要求而无法使用 TLS,则可以通过禁用 FTP 用户以任何其他方式登录的能力来获得一些安全性。 一种相对简单的防止它的方法是创建自定义外壳。 这不会提供任何加密,但会限制受感染帐户对 FTP 可访问的文件的访问。
首先,在bin
目录下打开一个名为ftponly
的文件:
sudo nano /bin/ftponly
添加一条消息,告诉用户他们无法登录的原因:
/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@your_server_ip
您应该会看到如下内容:
OutputThis account is limited to FTP access only. Connection to 203.0.113.0 closed.
这确认用户不能再 ssh
访问服务器,并且仅限于 FTP 访问。
结论
在本教程中,我们介绍了为具有本地帐户的用户设置 FTP。 如果您需要使用外部身份验证源,您可能需要查看 vsftpd
对虚拟用户的支持。 这通过使用 PAM(可插入身份验证模块)提供了一组丰富的选项,如果您在另一个系统(例如 LDAP 或 Kerberos)中管理用户,这是一个不错的选择。