Paranoid Penguin - 使用 vsftpd 实现安全匿名 FTP

作者:Mick Bauer

您能相信吗,在 Paranoid Penguin 专栏的近四年时间里,我竟然从未谈论过如何配置 FTP 服务?本月我将弥补这个缺憾,使用我最新的心头好 FTP 服务器,Chris Evans 出色的 vsftpd(Very Secure FTP Dæmon)。由于篇幅有限,且 FTP 的最佳用途是匿名 FTP,因此我们专注于匿名 FTP。FTP 协议使用明文身份验证,这使得它成为除匿名文件传输之外的任何用途的糟糕选择。但是,匿名 FTP 仍然非常有用。

vsftpd 越来越受欢迎,并且包含在最新版本的 Debian、SuSE、Fedora、Red Hat 和其他 Linux 发行版中。这种包含可能是因为 vsftpd 提供了安全性和便利性的独特结合。它可以快速启动并运行,而无需在丑陋的安全性和便利性之间做出权衡。

Chris Evans 在创建 vsftpd 时将安全性作为核心设计目标,到目前为止,它的记录令人印象深刻。截至本文撰写之时,在它可用的近四年中,vsftpd 尚未出现任何重大的安全漏洞。无论当您阅读本文时情况是否仍然如此,这都说明了 vsftpd 出色的设计理念,该理念借鉴了 OpenBSD 的“默认安全、默认禁用额外功能、整体复杂度最小化”的座右铭。

vsftpd 有多精简?它的整个源代码树大小仅为 1MB 多一点,完全解压缩后。vsftpd 可执行文件本身只有 80K。

获取和安装 vsftpd

正如我所提到的,vsftpd 现在是许多 Linux 发行版上的标准软件包。二进制软件包的常用优势适用:方便、易于修补以及对其他系统软件的最小影响。在 Debian、SuSE、Fedora 和 Red Hat 中,您需要的软件包名称可预测地为 vsftpd。它没有特别的外部依赖项。大多数用户可能会对他们发行版的默认 vsftpd 软件包感到非常满意。

如果您的首选发行版没有为 vsftpd 提供二进制软件包,或者如果您需要比您的发行版提供的版本更新的版本,请从其源代码 tarball 编译 vsftpd,该 tarball 可在 vsftpd.beasts.org 找到。构建过程非常老派。如果您还不是 root 用户,请先成为 root 用户。然后,解压缩 tarball 并将您的工作目录更改为其根目录,如下所示

# tar -xf vsftpd-1.2.1.tar.gz; cd vsftpd-1.2.1

接下来,输入命令make不带参数。如果成功,则当前目录中应该有一个 vsftp 可执行文件。确保用户 nobody 存在;如果不存在,则创建它。vsftpd 在此帐户上运行。

如果目录 /usr/share/empty 尚不存在,则创建它。它应该由 root 拥有,并且既不能组写入,也不能世界写入——它将被用作默认的 vsftpd chroot 监狱。

为匿名 FTP 用户创建主目录。SuSE 传统上使用 /srv/ftp,其他发行版使用 /var/ftp,但它可以是您喜欢的任何目录。同样,此目录应由 root 拥有,并且不应由任何其他人写入。

创建一个匿名 FTP 用户帐户,例如 ftp,并确保将其主目录设置为您在上一步中创建的目录。您的系统可能已经有这样的帐户。匿名 ftp 用户应该无法在其主目录中写入,并且永远不应拥有任何文件或目录。

现在您已准备好将 vsftpd 以及 vsftpd(8) 和 vsftpd.conf(5) man 页面复制到更有用的位置,因此输入命令make install。手动将示例 vsftpd.conf 文件复制到 /etc。

如果您想将 vsftpd 作为独立守护程序运行,请在 /etc/init.d 中为 vsftpd 创建一个启动脚本。否则,配置 inetd 或 xinetd 以根据需要启动它(请参阅独立守护程序与 inetd/xinetd 部分)。

如果您正在将 vsftpd 作为独立守护程序运行,请使用以下命令启用启动脚本chkconfig如果您使用基于 RPM 的 Linux 发行版,或者使用update-rc.d如果您运行 Debian GNU/Linux。或者,如果您从 RPM 或 deb 软件包安装 vsftpd,则所有这些步骤都会自动执行,但最后一步可能除外。我有没有提到二进制软件包更方便?某些发行版需要手动干预才能启用新安装的软件包。例如,在我的 SuSE 9.0 系统上,尽管 SuSE vsftpd RPM 自动安装了 /etc/init.d/vsftpd,但我必须发出以下命令chkconfig --add vsftpdchkconfig --level 35 vsftpd on以启用该脚本。

vsftpd 的文档

在我开始讨论 vsftpd 的重点狭隘地放在将其作为独立守护程序运行,仅提供匿名 FTP 之前,我应该指出一些更有价值、更完整的 vsftpd 文档来源。首先,vsftpd 附带一个 EXAMPLE/ 目录,其中包含各种 FTP 场景的示例配置,包括独立运行、与 xinetd 一起运行、仅为匿名用户服务以及为本地用户服务。如果您从源代码安装了 vsftpd,则 EXAMPLE 是您的 vsftpd 源代码 tarball 的子目录。如果您从二进制软件包安装了 vsftpd,则它可能已复制到您系统上的 /user/share/doc 下的某个位置。在 SuSE 系统上,它是 /usr/share/doc/packages/vsftpd/EXAMPLE。

正如我在上一节中提到的,vsftpd 具有 man 页面,vsftpd(8) 和 vsftpd.conf(5)。最后,默认(示例)vsftpd.conf 文件本身也带有很好的注释。它不包含所有 vsftpd 选项,但确实说明了最常用的选项。我只对示例 vsftpd.conf 文件进行了最少的调整,就已成功使 vstpd 工作了多次。

独立守护程序与 inetd/xinetd

在配置 vsftpd 本身之前,您必须决定是将其作为独立守护程序运行,还是通过超级服务器 inetd 或 xinetd 运行。在以前版本的 vsftpd 中,其开发者建议将其与 xinetd 一起使用,因为 xinetd 具有日志记录和访问控制功能。但是,vsftpd 1.2 及更高版本具有对大多数这些功能的本机支持。因此,Evans 现在建议 vsftpd 应作为独立守护程序运行。此外,使用 inetd 或 xinetd 会产生性能成本。如果您的系统将成为专用 FTP 服务器,或者您预计 FTP 将占您系统活动的重要百分比,则此成本是不值得的。

我将擅自使用独立守护程序示例来完成本文的其余部分。vsftpd 附带的文档充分描述了如何将 vsftpd 与 inetd 和 xinetd 一起使用;请参阅 vsftpd EXAMPLE 目录中包含的示例配置。

有趣的是,SuSE 9 附带的 vsftpd 软件包预配置为从 xinetd 运行,而 Debian 3.0 的则从 inetd 运行。在后一种情况下,这尤其合乎逻辑,因为 Debian 3.0 附带了较旧版本的 vsftpd (1.0.0),而 SuSE 9.0 使用了 vsftpd 1.2。Fedora 和 Red Hat 附带的 vsftpd RPM 将 vsftpd 安装为独立守护程序。无论如何,将 vsftpd 从 inet/xinetd 启动转换为独立启动需要两个步骤。

首先,正如我在获取和安装 vsftpd 部分中提到的,您必须确保在 /etc/init.d 中为 vsftpd 准备了一个已启用的启动脚本。Fedora Core 1 和 SuSE 9.0 软件包都提供并安装了一个;在 SuSE 的情况下,它存在但默认情况下处于禁用状态,以支持 xinetd。但是,如果您使用了 Debian 3.0 的 vsftpd 软件包或从源代码安装了 vsftpd,则需要创建自己的启动脚本。您还必须在您希望 vsftpd 运行的运行级别目录中创建相应的链接,例如 rc3.d 和 rc5.d。最后一步很容易使用以下命令自动完成chkconfigupdate-rc.d.

其次,您需要通过在 /etc/xinetd.d/vsftpd 文件中设置disable = yes来禁用 vsftpd 的 xinetd 文件,或者注释掉 /etc/inetd.conf 中 vsftpd 的行。或者,如果 vsftpd 是它启动的唯一重要内容,您可以完全禁用 inetd 或 xinetd。

在我看来,在您微调应用程序的安全性之前,就建议您启用应用程序的启动脚本是不负责任的。在我看来,启用是一回事;只要您坚持到底并在实际启动或重新启动系统之前锁定服务,您就没事了。

第三,您需要确保在 /etc/vsftpd.conf 中,参数 listen 设置为 YES。这使我们进入了 vsftpd 的正确配置。

配置 vsftpd 以进行匿名 FTP

实际上,您可能不需要做更多的事情来配置 vsftpd 以实现安全的匿名 FTP。它的默认配置设置仅允许匿名 FTP。更重要的是,默认情况下未启用任何类型的写入命令,并且在最新版本的 vsftpd 中,守护程序会在尽可能的情况下将自身 chroot 到目录 /usr/share/empty。这是我喜欢 vsftpd 的原因之一。实际上,放宽其安全性比收紧安全性需要做更多的工作。

假设您的发行版没有更改此默认行为,那么您现在需要做的就是使用 FTP 内容填充您的匿名 FTP 用户帐户的主目录,供人们下载。在 Debian 3.0、SuSE 9.0 和 Fedora Core 1 上,匿名 FTP 用户默认为 ftp,Debian 和 SuSE 的主目录为 /srv/ftp,Fedora 的主目录为 /var/ftp。如果您从源代码安装了 vsftpd,则匿名 FTP 目录是您分配给您创建的匿名 FTP 用户帐户的任何主目录。在填充 FTP 目录时,请特别注意所有权和权限。默认值可能合适,也可能不合适,但至少快速执行一下ls -al时不时地亲自查看一下。

即使默认设置对于许多用户来说已经足够了,让我们更仔细地看一下与匿名 FTP 最相关的 vsftpd.conf 参数。默认情况下,此文件位于 /etc 中,但在 Red Hat 和 Fedora 系统上,它位于 /etc/vsftpd/ 中。列表 1 显示了一个示例 vsftpd.conf 文件。

列表 1. 匿名 FTP 的 vsftpd.conf 设置

listen=YES
# listen_address=
anonymous_enable=YES
ftp_username=ftp
# anon_root=[$ftp_username's home directory]
write_enable=NO
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_other_write_enable=NO
anon_world_readable_only=YES
anon_max_rate=0
idle_session_timeout=300
ascii_download_enable=NO
ascii_upload_enable=NO
connect_from_port_20=NO
port_enable=YES
hide_ids=NO
log_ftp_protocol=NO
syslog_enable=NO
max_per_ip=0
# cmds_allowed=
local_root=/usr/share/empty
nopriv_user=nobody
ftpd_banner=(vsFTPd 1.2.0)

实际上,您永远不会使用与列表 1 完全相同的 vsftpd.conf 文件。其中的所有参数实际上都设置为其默认值。相反,此列表旨在作为快速参考。让我们依次讨论其参数。

  • listen:告诉 vsftpd 作为守护程序运行,而不是作为 inetd 或 xinetd 根据需要调用的每个连接进程运行。默认值为 NO。

  • listen_address:指定 vsftpd 应在其上侦听连接的本地 IP 地址。默认值为""(null),表示所有本地 IP 地址。如果您想运行多个虚拟 FTP 服务器,则需要在每个虚拟服务器的配置文件中设置此参数(请参阅下一节,虚拟服务器)。

  • anonymous_enable:此参数的默认值为 YES,它确定 vsftpd 是否接受匿名登录。如果设置为 YES 或根本未设置,则 vsftpd 接受来自用户 anonymous 和 ftp(两者是等效的)的连接,而无需真实密码。

  • ftp_username:用于匿名登录的用户帐户的名称,即作为 anonymous 和 ftp 的 FTP 登录。此帐户必须存在于 /etc/passwd 中,并且应具有有效的、不属于该用户帐户的主目录;默认值为 ftp。

  • anon_root:vsftpd 应 chroot 进入以进行匿名登录的目录。这默认为匿名 ftp 用户帐户的主目录(请参阅 ftp_username),但您可以使用此参数设置不同的匿名 FTP 根目录。无论哪种方式,此目录都不应由匿名 ftp 用户拥有。

  • write_enable:除非此参数设置为 YES,否则任何用户在任何情况下都不得上传任何文件,无论 vsftpd.conf 中的其他设置如何。其默认值为 NO。

  • anon_upload_enable:如果此参数和 write_enable 都设置为 YES,则允许匿名用户将文件上传到匿名用户帐户具有写入权限的目录中。

  • anon_mkdir_write_enable:如果此参数和 write_enable 都设置为 YES,则允许匿名用户在匿名用户帐户具有写入权限的目录中创建新目录。

  • anon_other_write_enable:如果此参数和 write_enable 都设置为 YES,则允许匿名用户删除和重命名匿名用户帐户具有写入权限的目录中的目录。

  • anon_world_readable_only:如果设置为 YES,则此参数禁止匿名用户下载任何非世界可读的文件。如果匿名用户能够上传您不希望其他匿名用户下载的文件,则此参数最有用。

  • anon_max_rate:指定匿名用户可以使用的最大数据传输速率,以字节/秒为单位。默认值为 0,表示无限制。

  • idle_session_timeout:FTP 命令之间允许经过的最大时间(以秒为单位),直到服务器强制关闭会话。默认值为 300,但如果您担心拒绝服务攻击,则可能需要将其设置得更低。

  • ascii_download_enable:如果设置为 YES,则允许用户执行 ASCII 模式下载,而不是二进制模式下载。默认值为 NO,因为 ASCII 模式很少甚至从不需要,而且效率要低得多,以至于可能代表拒绝服务攻击的潜在向量。

  • ascii_upload_enable:另一方面,ASCII 模式上传有时对于脚本等内容是必需的。但是,此参数的默认值仍然为 NO。

  • connect_from_port_20:在主动模式 FTP 会话中,每当用户下载任何内容(包括目录列表)时,服务器都会发起一个返回到客户端的新连接,通常源自服务器的 TCP 端口 20。但是,默认情况下,vsftpd 从更高的非特权端口发起此类连接,以避免必须以 root 身份运行。要更改此默认行为,以防您的 FTP 用户从不期望这种行为的代理或防火墙后面连接,请将此参数设置为 YES。

  • port_enable:将此设置为 NO 以禁用 PORT 命令,这将有效地完全禁用主动模式 FTP。默认值为 YES。

  • hide_ids:如果设置为 YES,则将所有目录列表输出中的所有者和组字段分别替换为 ftp 和 ftp。就我个人而言,我认为当在公共 FTP 服务器上使用时,这可能是一个有用的模糊处理,但默认值为 NO。

  • log_ftp_protocol:如果设置为 YES,则启用按命令记录,即 FTP 协议命令,由 FTP 用户空间命令触发但与之不同。对于故障排除非常宝贵。

  • syslog_enable:通常,vsftpd 将日志消息写入 /var/log/vsftpd.log。将此参数设置为 YES(其默认值为 NO)会将这些消息改为发送到系统的 syslog 服务,使用 FTPD 工具。

  • max_per_ip:指定允许从单个源 IP 地址建立的最大并发连接数。限制此值似乎是一个好主意——默认值为 0,表示无限制——但这样做会对从 NAT/SPAT 防火墙后面连接的用户产生不成比例的影响,这会导致多个用户看起来源自同一个源 IP 地址。

  • cmds_allowed:指定逗号分隔的允许的 FTP 命令列表;默认值为""(null),表示无限制。只能指定 FTP 协议级别的命令,而不能指定 FTP 客户端软件包通常接受的命令。例如,要仅允许客户端列出文件、更改工作目录和下载文件,您可以使用cmds_allowed=USER,LIST,NLST,CWD,RETR,PORT,QUIT。网站 www.nsftools.com/tips/RawFTP.htm 是这些命令的有用参考。

  • local_root:这指定一个空的、root 拥有的目录,vsftpd 在任何时候都不需要访问文件系统的其他部分时,都会 chroot 到该目录。默认值为 /usr/share/empty。

  • nopriv_user:指定 vsftpd 在尽可能的情况下以非特权用户身份运行。vsftpd 在执行诸如绑定到 TCP 端口 21 之类的操作时显然需要成为 root 用户。但是,它会尽快降级自身,以减少缓冲区溢出漏洞或其他进程劫持事件导致 root 权限泄露的可能性。

  • ftpd_banner:FTP 客户端尝试连接时显示的横幅消息。默认消息硬编码到 vsftpd 中;在 v1.2.0 中,它只是 (vsFTPd 1.2.0)。或者,您可以使用参数 banner_file 来指定包含您的横幅消息的文本文件。

vsftpd.conf(5) man 页面解释了您可以使用的这些参数和许多其他参数。信不信由你,我在这里只触及了皮毛。

虚拟服务器

如果您想在同一物理主机上拥有多个虚拟 FTP 服务器,一个具有多个 IP 地址,vsftpd 可以轻松做到这一点。您需要做的就是运行多个 vsftpd 守护程序实例,每个实例都有自己的 vsftpd.conf 文件,指定要侦听的 IP 地址以及要用作其匿名根目录的目录。

例如,假设我的机器分配了两个 IP 地址,1.2.3.4 和 1.2.3.5,在 DNS 中分别注册为名称 knusper 和 rover。在这种情况下,我可以有两个 vsftpd 的配置文件,例如 /etc/vsftpd.knusper 和 /etc/vsftpd.rover。列表 2 和 3 显示了这些文件。

列表 2. 虚拟 FTP 服务器配置文件 /etc/vsftpd.knusper

listen=YES
listen_on=1.2.3.4
connect_from_port_20=YES
anonymous_enable=YES
anon_root=/srv/ftp/knusper
ftpd_banner=Welcome to FTP at knusper.wiremonkeys.org. Behave!

列表 3. 虚拟 FTP 服务器配置文件 /etc/vsftpd.rover

listen=YES
listen_on=1.2.3.5
connect_from_port_20=YES
anonymous_enable=NO
ftpd_banner=Private FTP at rover.wiremonkeys.org. Strangers-B-gone.
# DANGER: don't use the following unless you know what you're doing!
local_enable=YES

请注意我在列表 3 中可能愚蠢地使用了 local_enable 参数。将其设置为 YES 是危险的,因为 FTP 登录凭据以明文形式发送。您永远不希望将真实的系统凭据暴露于窃听,尤其是当您的服务器连接到互联网时。我在这里展示它的真正原因是说明,由于每个虚拟服务器都使用自己的配置文件,因此您可以为每个虚拟服务器指定完全不同的行为。一个虚拟服务器可能有一个公共上传目录,匿名用户可以在其中写入,而另一个虚拟服务器可能是一个严格只读的 FTP 站点。相反,您需要注意,您认为对于维护整体系统安全至关重要的设置在同一台计算机上运行的不同虚拟服务器之间是一致设置的。

除了为您希望 vsftpd 提供的每个虚拟 FTP 服务器创建不同的配置文件之外,您还需要相应地更改您的启动脚本。我的示例服务器(由列表 2 和 3 表示)上的启动脚本将需要类似于以下两行的内容

vsftpd /etc/vsftpd.knusper
vsftpd /etc/vsftpd.rover

如果您运行 Red Hat 或 Fedora,则已经为您处理了此问题。这些发行版的 vsftpd RPM 软件包中包含的 /etc/init.d/vsftpd 脚本会自动解析 /etc/vsftpd 目录中您想要放入的任意数量的配置文件,只要每个文件的文件名以 .conf 结尾即可。在我看来,这是 Red Hat 团队非常有远见的一点。

这就是您需要了解的有关使用 vsftpd 设置简单且安全的匿名 FTP 服务器的全部内容。正如我所提到的,我仅涵盖了 vsftpd 功能的一小部分。尽管其设计理念极简,但这确实是一个功能强大的 FTP 服务器。幸运的是,它也得到了很好的文档记录,因此我将您推荐到 vsftpd.conf(5) man 页面和 EXAMPLE/ 目录以获取有关 vsftpd 许多其他用途的信息,这对我来说真的不是推卸责任。

Mick Bauer,CISSP,是Linux Journal的安全编辑,也是明尼苏达州明尼阿波利斯的 IS 安全顾问。他是 Building Secure Servers With Linux(O'Reilly & Associates,2002 年)的作者。

加载 Disqus 评论