FTP 是文件传输协议的缩写,是一种网络协议,曾经广泛用于在客户端和服务器之间移动文件。此后,它已被更快、更安全、更方便的文件传输方式所取代。许多临时互联网用户希望直接从网络浏览器下载https
,并且命令行用户更有可能使用安全协议,例如scp
or sFTP.
FTP 仍然用于支持具有非常特定需求的遗留应用程序和工作流程。如果您可以选择使用哪种协议,请考虑探索更现代的选项。然而,当您确实需要 FTP 时,vsftpd 是一个很好的选择。 vsftpd 针对安全性、性能和稳定性进行了优化,针对其他 FTP 服务器中发现的许多安全问题提供了强大的保护,并且是许多 Linux 发行版的默认设置。
在本教程中,我们将向您展示如何配置 vsftpd 以允许用户使用 FTP 以及受 SSL/TLS 保护的登录凭据将文件上传到他或她的主目录。
要学习本教程,您将需要:
-
具有非 root 用户的 Ubuntu 16.04 服务器
sudo
特权:您可以在我们的中了解有关如何设置具有这些权限的用户的更多信息使用 Ubuntu 16.04 进行初始服务器设置 guide.
一旦你有了 Ubuntu 服务器,你就可以开始了。
我们首先更新软件包列表并安装 vsftpd 守护进程:
-
sudo apt-get update
-
sudo apt-get install vsftpd
安装完成后,我们将复制配置文件,以便我们可以从空白配置开始,将原始配置保存为备份。
-
sudo cp/etc/vsftpd.conf /etc/vsftpd.conf.orig
配置备份到位后,我们就可以配置防火墙了。
我们将检查防火墙状态以查看其是否已启用。如果是这样,我们将确保允许 FTP 流量,这样您在测试时就不会遇到阻止您的防火墙规则。
在这种情况下,仅允许 SSH 通过:
Output
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
您可能有其他规则或根本没有防火墙规则。由于仅ssh
在这种情况下允许流量,我们需要为 FTP 流量添加规则。
我们需要为 FTP 打开端口 20 和 21,稍后启用 TLS 时打开端口 990,并为我们计划在配置文件中设置的被动端口范围打开端口 40000-50000:
-
sudoUFW 允许20/tcp
-
sudoUFW 允许21/tcp
-
sudoUFW 允许990/tcp
-
sudoUFW 允许40000:50000/tcp
-
sudoUFW 状态
现在我们的防火墙规则如下所示:
Output
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)
With vsftpd
安装完毕并打开必要的端口后,我们就可以继续下一步了。
在本教程中,我们将创建一个用户,但您可能已经有一个需要 FTP 访问的用户。在接下来的说明中,我们将注意保留现有用户对其数据的访问权限。即便如此,我们还是建议您从新用户开始,直到您配置并测试了您的设置。
首先,我们将添加一个测试用户:
出现提示时指定密码,然后在其他提示中按“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
我们来验证一下权限:
Output
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
权限检查files
目录应返回以下内容:
Output
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
目录,我们将把注意力转向配置。
我们计划允许具有本地 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
Note:我们预先打开了在此处为被动端口范围设置的端口。如果更改这些值,请务必更新防火墙设置。
由于我们只计划根据具体情况允许 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
Output
sammy
重新启动守护进程以加载配置更改:
-
sudosystemctl 重新启动 vsftpd
现在我们准备好进行测试了。
我们已将服务器配置为仅允许用户sammy
通过 FTP 连接。让我们确保情况确实如此。
匿名用户应该无法连接:我们禁用了匿名访问。在这里,我们将通过尝试匿名连接来测试这一点。如果我们做得正确,应该拒绝匿名用户的权限:
Output
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>
关闭连接:
用户以外的用户sammy
应该无法连接:接下来,我们将尝试连接作为我们的sudo
用户。他们也应该被拒绝访问,并且应该在他们被允许输入密码之前发生。
Output
Connected 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>
关闭连接:
sammy
应该能够连接以及读取和写入文件:在这里,我们将确保我们指定的用户_can_connect:
Output
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
命令将我们之前创建的测试文件传输到本地计算机:
Output
227 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>
我们将立即返回并尝试使用新名称上传文件以测试写入权限:
Output
227 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)
关闭连接:
现在我们已经测试了我们的配置,我们将采取措施进一步保护我们的服务器。
由于 FTP 确实not加密传输中的任何数据(包括用户凭据),我们将启用 TTL/SSL 来提供该加密。第一步是创建用于 vsftpd 的 SSL 证书。
我们将使用openssl
创建一个新证书并使用-days
标志使其有效期为一年。在同一命令中,我们将添加一个 2048 位 RSA 私钥。然后通过设置-keyout
and -out
标志为相同的值,私钥和证书将位于同一个文件中。
我们将使用以下命令来完成此操作:
-
sudoopenssl 请求-x509 -nodes -days 365 -newkeyRSA:2048-keyout/etc/ssl/private/vsftpd.pem-out/etc/ssl/private/vsftpd.pem
系统将提示您提供证书的地址信息。用您自己的信息替换以下问题:
Output
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_IP_address
Email Address []:
有关证书标志的更多详细信息,请参阅OpenSSL 要点:使用 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
to 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
完成后,保存并关闭文件。
现在,我们需要重新启动服务器以使更改生效:
-
sudosystemctl 重新启动 vsftpd
此时,我们将无法再与不安全的命令行客户端连接。如果我们尝试一下,我们会看到类似的内容:
-
ftp -p 203.0.113.0
- 连接到203.0.113.0.
-
220 (vsFTPd 3.0.3)
- Name (203.0.113.0:default): sammy
-
530非匿名会话必须使用加密。
- ftp:登录失败。
-
421服务不可用,远程服务器已关闭连接
- ftp>
接下来,我们将验证是否可以使用支持 TLS 的客户端进行连接。
大多数现代 FTP 客户端都可以配置为使用 TLS 加密。我们将演示如何使用 FileZilla 进行连接,因为它支持跨平台。请参阅其他客户端的文档。
首次打开 FileZilla 时,可以在“文件”一词下方找到“站点管理器”图标,即顶行最左侧的图标。点击它:
将打开一个新窗口。点击右下角的“新建站点”按钮:
Under “My Sites” a new icon with the words “New site” will appear. You can name it now or return later and use the Rename button.
您必须在“主机”字段中填写名称或 IP 地址。在“加密”下拉菜单下,选择“需要基于 TLS 的显式 FTP”。
对于“登录类型”,选择“询问密码”。在“用户”字段中填写您创建的 FTP 用户:
Click “Connect” at the bottom of the interface. You will be asked for the user’s password:
Click “OK” to connect. You should now be connected with your server with TLS/SSL encryption.
When you’ve accepted the certificate, double-click the files
folder and drag upload.txt to the left to confirm that you’re able to download files.
When you’ve done that, right-click on the local copy, rename it to upload-tls.txt` and drag it back to the server to confirm that you can upload files.
You’ve now confirmed that you can securely and successfully transfer files with SSL/TLS enabled.
如果由于客户端要求而无法使用 TLS,您可以通过禁用 FTP 用户以任何其他方式登录的能力来获得一定的安全性。防止这种情况的一种相对简单的方法是创建自定义 shell。这不会提供任何加密,但会限制受感染帐户对可通过 FTP 访问的文件的访问。
首先,打开一个名为ftponly
在bin目录中:
我们将添加一条消息,告诉用户为什么无法登录。粘贴以下内容:
#!/bin/sh
echo "This account is limited to FTP access only."
更改权限以使文件可执行:
-
sudo chmoda+x /bin/ftonly
打开有效 shell 列表:
在底部添加:
/etc/shell
. . .
/bin/ftponly
使用以下命令更新用户的 shell:
-
sudo usermod sammy -s/bin/ftonly
现在尝试以 sammy 身份登录:
您应该看到类似以下内容:
Output
This account is limited to FTP access only.
Connection to 203.0.113.0 closed.
这确认用户不能再ssh
到服务器,并且仅限于 FTP 访问。
在本教程中,我们介绍了为具有本地帐户的用户设置 FTP。如果您需要使用外部身份验证源,您可能需要研究 vsftpd 对虚拟用户的支持。这通过使用 PAM(可插入身份验证模块)提供了一组丰富的选项,如果您在其他系统(例如 LDAP 或 Kerberos)中管理用户,那么这是一个不错的选择。