1. 文件传输协议
一般来讲,人们将计算机联网的首要目的就是获取资料,而文件传输是一种非常重要的获取资料的方式。今天的互联网是由几千万台个人计算机、工作站、服务器、小型机、大型机、巨型机等具有不同型号、不同架构的物理设备共同组成的,而且即便是个人计算机,也可能会装有 Windows、Linux、UNIX、macOS 等不同的操作系统。为了能够在如此复杂多样的设备之间解决文件传输的问题,文件传输协议(FTP)应运而生。
FTP 是一种在互联网中进行文件传输的协议,基于客户端/服务器模式,默认使用 20、21 号端口,其中端口 20 用于进行数据传输,端口 21 用于接受客户端发出的相关 FTP 命令与参数。FTP 服务器普遍部署于内网中,具有容易搭建、方便管理的特点。而且有些 FTP 客户端工具还可以支持文件的多点下载以及断点续传技术,因此得到了广大用户的青睐。FTP 的传输拓扑如图所示。
FTP 服务器是按照 FTP 协议在互联网上提供文件存储和访问服务的主机,FTP 客户端则是向服务器发送连接请求,以建立数据传输链路的主机。FTP 协议有下面两种工作模式。
➢ 主动模式 :FTP 服务器主动向客户端发起连接请求。
➢ 被动模式 :FTP 服务器等待客户端发起连接请求(默认工作模式)。
在学习防火墙服务配置时我们知道,防火墙一般是用于过滤从外网进入内网的流量,因此有些时候需要将 FTP 的工作模式设置为主动模式,才可以传输数据。
由于 FTP、HTTP、Telnet 等协议的数据都是使用明文进行传输的,因此从设计上就是不可靠的。人们为了满足以密文方式传输文件的需求,发明了 vsftpd 服务程序。vsftpd(very secure ftp daemon,非常安全的 FTP 守护进程)是一款运行在 Linux 操作系统上的 FTP 服务程序,不仅完全开源而且免费。此外,它还具有很高的安全性、传输速度,以及支持虚拟用户验证等其他 FTP 服务程序不具备的特点。在不影响使用的前提下,管理者可以自行决定客户端是采用匿名开放、本地用户还是虚拟用户的验证方式来登录 vsftpd 服务器。这样即便黑客拿到了虚拟用户的账号密码,也不见得能成功登录 vsftpd 服务器。
在配置妥当软件仓库之后,就可以安装 vsftpd 服务程序了。无论是使用 yum 还是 dnf 命令都可以安装,这里优先选择使用 dnf 命令。
[root@linuxprobe~]# dnf install vsftpd
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use
subscription-manager to register.
AppStream 3.1 MB/s | 3.2 kB 00:00
BaseOS 2.7 MB/s | 2.7 kB 00:00
Dependencies resolved.
===============================================================================
Package Arch Version Repository Size
===============================================================================
Installing:
vsftpd x86_64 3.0.3-28.el8 AppStream 180 k
Transaction Summary
===============================================================================
Install 1 Package
Total size: 180 k
Installed size: 356 k
Is this ok [y/N]: y
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : vsftpd-3.0.3-28.el8.x86_64 1/1
Running scriptlet: vsftpd-3.0.3-28.el8.x86_64 1/1
Verifying : vsftpd-3.0.3-28.el8.x86_64 1/1
Installed products updated.
Installed:
vsftpd-3.0.3-28.el8.x86_64
Complete!
iptables 防火墙管理工具默认禁止了 FTP 协议的端口号,因此在正式配置 vsftpd 服务程序之前,为了避免这些默认的防火墙策略“捣乱”,还需要清空 iptables 防火墙的默认策略,并把当前已经被清理的防火墙策略状态保存下来:
[root@linuxprobe~]# iptables -F
[root@linuxprobe~]# iptables-save
然后再把 FTP 协议添加到 firewalld 服务的允许列表中(前期准备工作一定要做充足):
[root@linuxprobe~]# firewall-cmd --permanent --zone=public --add-service=ftp
success
[root@linuxprobe~]# firewall-cmd --reload
success
vsftpd 服务程序的主配置文件(/etc/vsftpd/vsftpd.conf)内容总长度有 127 行之多,但其中大多数参数在开头都添加了井号(#),从而成为注释信息,大家没有必要在注释信息上花费太多的时间。我们可以在 grep 命令后面添加-v 参数,过滤并反选出没有包含井号(#)的参数行(即过滤掉所有的注释信息),然后将过滤后的参数行通过输出重定向符写回原始的主配置文件中。这样操作之后,就只剩下 12 行有效参数了,马上就不紧张了:
[root@linuxprobe~]# mv /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf_bak
[root@linuxprobe~]# grep -v "#" /etc/vsftpd/vsftpd.conf_bak > /etc/vsftpd/vsftpd.conf
[root@linuxprobe~]# cat /etc/vsftpd/vsftpd.conf
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
listen=NO
listen_ipv6=YES
pam_service_name=vsftpd
userlist_enable=YES
表中罗列了 vsftpd 服务程序主配置文件中常用的参数以及作用。当前大家只需要简单了解即可,在后续的实验中将演示这些参数的用法,以帮助大家熟悉并掌握。
2. vsftpd 服务程序
vsftpd 作为更加安全的文件传输协议服务程序,允许用户以 3 种认证模式登录 FTP 服务器。
➢ 匿名开放模式 :是最不安全的一种认证模式,任何人都可以无须密码验证而直接登录到 FTP 服务器。
➢ 本地用户模式 :是通过 Linux 系统本地的账户密码信息进行认证的模式,相较于匿名开放模式更安全,而且配置起来也很简单。但是如果黑客破解了账户的信息,就可以畅通无阻地登录 FTP 服务器,从而完全控制整台服务器。
➢ 虚拟用户模式 :更安全的一种认证模式,它需要为 FTP 服务单独建立用户数据库文件,虚拟出用来进行密码验证的账户信息,而这些账户信息在服务器系统中实际上是不存在的,仅供 FTP 服务程序进行认证使用。这样,即使黑客破解了账户信息也无法登录服务器,从而有效降低了破坏范围和影响。
ftp 是 Linux 系统中以命令行界面的方式来管理 FTP 传输服务的客户端工具。我们首先手动安装这个 ftp 客户端工具,以便在后续实验中查看结果。
[root@linuxprobe~]# dnf install ftp
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use
subscription-manager to register.
Last metadata expiration check: 0:00:30 ago on Tue 02 Mar 2021 09:38:50 PM CST.
Dependencies resolved.
===============================================================================
Package Arch Version Repository Size
===============================================================================
Installing:
ftp x86_64 0.17-78.el8 AppStream 70 k
Transaction Summary
===============================================================================
Install 1 Package
Total size: 70 k
Installed size: 112 k
Is this ok [y/N]: y
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : ftp-0.17-78.el8.x86_64 1/1
Running scriptlet: ftp-0.17-78.el8.x86_64 1/1
Verifying : ftp-0.17-78.el8.x86_64 1/1
Installed products updated.
Installed:
ftp-0.17-78.el8.x86_64
Complete!
如果大家想用 Windows 主机测试实验的效果,则可以从 FileZilla、FireFTP、SmartFTP、WinSCP 和 Cyberduck 中挑一个喜欢的工具并从网上下载。它们的功能会比 ftp 命令更加强大。
2.1 匿名访问模式
vsftpd 服务程序默认关闭了匿名开放模式,我们需要做的就是开放匿名用户的上传、下载文件的权限,以及让匿名用户创建、删除、更名文件的权限。需要注意的是,针对匿名用户放开这些权限会带来潜在危险,我们只是为了在 Linux 系统中练习配置 vsftpd 服务程序而放开了这些权限,不建议在生产环境中如此行事。表中罗列了可以向匿名用户开放的权限参数以及作用。
[root@linuxprobe~]# vim /etc/vsftpd/vsftpd.conf
1 anonymous_enable=YES
2 anon_umask=022
3 anon_upload_enable=YES
4 anon_mkdir_write_enable=YES
5 anon_other_write_enable=YES
6 local_enable=YES
7 write_enable=YES
8 local_umask=022
9 dirmessage_enable=YES
10 xferlog_enable=YES
11 connect_from_port_20=YES
12 xferlog_std_format=YES
13 listen=NO
14 listen_ipv6=YES
15 pam_service_name=vsftpd
16 userlist_enable=YES
在 vsftpd 服务程序的主配置文件中正确填写参数,然后保存并退出。还需要重启 vsftpd服务程序,让新的配置参数生效。在此需要提醒各位读者,在生产环境中或者在 RHCSA、RHCE、RHCA 认证考试中一定要把配置过的服务程序加入到开机启动项中,以保证服务器在重启后依然能够正常提供传输服务:
[root@linuxprobe~]# systemctl restart vsftpd
[root@linuxprobe~]# systemctl enable vsftpd
Created symlink /etc/systemd/system/multi-user.target.wants/vsftpd.service→ /
usr/lib/systemd/system/vsftpd.service.
现在就可以在客户端执行 ftp 命令连接到远程的 FTP 服务器了。在 vsftpd 服务程序的匿名开放认证模式下,其账户统一为 anonymous,密码为空。而且在连接 FTP 服务器后,默认访问的是/var/ftp 目录。可以切换到该目录下的 pub 目录中,然后尝试创建一个新的目录文件,以检验是否拥有写入权限:
[root@linuxprobe~]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 (vsFTPd 3.0.3)
Name (192.168.10.10:root): anonymous
331 Please specify the password.
Password: (此处敲击回车即可)
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd pub
250 Directory successfully changed.
ftp> mkdir files
550 Permission denied.
系统显示拒绝创建目录!我们明明在前面清空了 iptables 防火墙策略,而且也在 vsftpd服务程序的主配置文件中添加了允许匿名用户创建目录和写入文件的权限。 那么问题出在哪里?
前文提到,在 vsftpd 服务程序的匿名开放认证模式下,默认访问的是/var/ftp 目录。查看该目录的权限得知,只有 root 管理员才有写入权限。下面将目录的所有者身份改成系统账户 ftp。
[root@linuxprobe~]# ls -ld /var/ftp/pub
drwxr-xr-x. 2 root root 6 Aug 13 2021 /var/ftp/pub
[root@linuxprobe~]# chown -R ftp /var/ftp/pub
[root@linuxprobe~]# ls -ld /var/ftp/pub
drwxr-xr-x. 2 ftp root 6 Aug 13 2021 /var/ftp/pub
[root@linuxprobe~]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 (vsFTPd 3.0.3)
Name (192.168.10.10:root): anonymous
331 Please specify the password.
Password: (此处敲击回车即可)
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd pub
250 Directory successfully changed.
ftp> mkdir files
550 Create directory operation failed.
系统再次报错!尽管在使用 ftp 命令登入 FTP 服务器后,在创建目录时系统依然提示操作失败,但是报错信息却发生了变化。在没有写入权限时,系统提示“权限拒绝”(Permission denied),但现在系统提示“创建目录的操作失败”(Create directory operation failed),应该意识到是 SELinux 服务在“捣乱”了。
下面使用 getsebool 命令查看与 FTP 相关的 SELinux 域策略都有哪些:
[root@linuxprobe~]# getsebool -a | grep ftp
ftpd_anon_write --> off
ftpd_connect_all_unreserved --> off
ftpd_connect_db --> off
ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_fusefs --> off
ftpd_use_nfs --> off
ftpd_use_passive_mode --> off
httpd_can_connect_ftp --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off
tftp_home_dir --> off
我们可以根据经验和策略的名称判断出是 ftpd_full_access--> off 策略规则导致了操作失败。接下来修改该策略规则,并且在设置时使用-P 参数让修改过的策略永久生效,确保在服务器重启后依然能够顺利写入文件。
[root@linuxprobe~]# setsebool -P ftpd_full_access=on
等 SELinux 域策略修改完毕后,就能够顺利执行文件的创建、修改及删除等操作了:
[root@linuxprobe~]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 (vsFTPd 3.0.3)
Name (192.168.10.10:root): anonymous
331 Please specify the password.
Password: (此处敲击回车即可)
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> cd pub
250 Directory successfully changed.
ftp> mkdir files
257 "/pub/files" created
ftp> rename files database
350 Ready for RNTO.
250 Rename successful.
ftp> rmdir database
250 Remove directory operation successful.
ftp> exit
221 Goodbye.
在上面的操作中,由于权限不足,所以我们将/var/ftp/pub 目录的所有者设置成 ftp 用户本身。除了这种方法,也可以通过设置权限的方法让其他用户获取到写入权限(例如 777 这样的权限)。但是,由于 vsftpd 服务自身带有安全保护机制,因此不要直接修改/var/ftp 的权限,这有可能导致服务被“安全锁定”而不能登录。一定要记得是对里面的 pub 目录修改权限:
[root@linuxprobe~]# chmod -R 777 /var/ftp
[root@linuxprobe~]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 (vsFTPd 3.0.3)
Name (192.168.10.10:root): anonymous
331 Please specify the password.
Password: (此处敲击回车即可)
500 OOPS: vsftpd: refusing to run with writable root inside chroot()
Login failed.
421 Service not available, remote server has closed connection
注:在进行下一次实验之前,一定记得将虚拟机还原到最初始的状态,以免多个实验相互产生冲突。
2.2 本地用户模式
针对本地用户模式的权限参数以及作用如表所示:
默认情况下本地用户所需的参数都已经存在,不需要修改。而 umask 这个参数一起来看一下。unmask 一般被称为“权限掩码”或“权限补码”,能够直接影响到新建文件的权限值。例如在 Linux 系统中,新建的普通文件的权限是 644,新建的目录的权限是 755。虽然大家对此都习以为常,但是有考虑过权限为什么是这些数字么?
其实,普通文件的默认权限是 666,目录的默认权限是 777,这都是写在系统配置文件中的。但默认值不等于最终权限值。umask 参数的默认值是 022,根据公式“默认权限−umask=实际权限”,所以普通文件的默认权限到手后就剩下 644,而目录文件就剩下 755 了。
如果大家还不明白,我们再来看一个例子。我们每个人的收入都要纳税,税就相当于umask 值。如果政府想让每个人到手的收入多一些,那么就减少税(umask);如果想让每个人到手的收入少一些,那么就多加税(umask)。也就是说,umask 实际是权限的反掩码,通过它可以调整文件最终的权限大小。
接下来配置本地用户的参数:
[root@linuxprobe~]# vim /etc/vsftpd/vsftpd.conf
1 anonymous_enable=NO
2 local_enable=YES
3 write_enable=YES
4 local_umask=022
5 dirmessage_enable=YES
6 xferlog_enable=YES
7 connect_from_port_20=YES
8 xferlog_std_format=YES
9 listen=NO
10 listen_ipv6=YES
11 pam_service_name=vsftpd
12 userlist_enable=YES
在 vsftpd 服务程序的主配置文件中正确填写参数,然后保存并退出。还需要重启 vsftpd服务程序,让新的配置参数生效。在执行完上一个实验并还原虚拟机之后,还需要将配置好的服务添加到开机启动项中,以便在系统重启自后依然可以正常使用 vsftpd 服务。
[root@linuxprobe~]# systemctl restart vsftpd
[root@linuxprobe~]# systemctl enable vsftpd
Created symlink /etc/systemd/system/multi-user.target.wants/vsftpd.service→ /u
sr/lib/systemd/system/vsftpd.service.
按理来讲,现在已经完全可以用本地用户的身份登录 FTP 服务器了。但是在使用 root 管理员的身份登录后,系统提示如下的错误信息:
[root@linuxprobe~]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 (vsFTPd 3.0.3)
Name (192.168.10.10:root): root
530 Permission denied.
Login failed.
ftp>
可见,在我们输入 root 管理员的密码之前,就已经被系统拒绝访问了。这是因为 vsftpd服务程序所在的目录中默认存放着两个名为“用户名单”的文件(ftpusers 和 user_list)。不知道大家是否已看过一部日本电影“死亡笔记”,里面就提到有一个黑色封皮的小本子,只要将别人的名字写进去,这人就会挂掉。vsftpd 服务程序目录中的这两个文件也有类似的功能----只要里面写有某位用户的名字,就不再允许这位用户登录到 FTP 服务器上。
[root@linuxprobe~]# cat /etc/vsftpd/user_list
# vsftpd userlist
# If userlist_deny=NO, only allow users in this file
# If userlist_deny=YES (default), never allow users in this file, and
# do not even prompt for a password.
# Note that the default vsftpd pam config also checks /etc/vsftpd/ftpusers
# for users that are denied.
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
news
uucp
operator
games
nobody
root@linuxprobe~]# cat /etc/vsftpd/ftpusers
# Users that are not allowed to login via ftp
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
news
uucp
operator
games
nobody
将上述两个文件中的root用户名去掉,使root可以访问ftp。
[root@linuxprobe~]# vim /etc/vsftpd/user_list
# vsftpd userlist
# If userlist_deny=NO, only allow users in this file
# If userlist_deny=YES (default), never allow users in this file, and
# do not even prompt for a password.
# Note that the default vsftpd pam config also checks /etc/vsftpd/ftpusers
# for users that are denied.
bin
daemon
adm
lp
sync
shutdown
halt
mail
news
uucp
operator
games
nobody
root@linuxprobe~]# vim /etc/vsftpd/ftpusers
# Users that are not allowed to login via ftp
bin
daemon
adm
lp
sync
shutdown
halt
mail
news
uucp
operator
games
nobody
vsftpd 服务程序为了保证服务器的安全性而默认禁止了 root 管理员和大多数系统用户的登录行为,这样可以有效地避免黑客通过 FTP 服务对 root 管理员密码进行暴力破解。如果您确认在生产环境中使用 root 管理员不会对系统安全产生影响,只需按照上面的提示删除掉 root 用户名即可。也可以选择 ftpusers 和 user_list 文件中不存在的一个普通用户尝试登录 FTP 服务器:
[root@linuxprobe~]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 (vsFTPd 3.0.3)
Name (192.168.10.10:root): root
331 Please specify the password.
Password: (此处输入该用户的密码)
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
在继续后面的实验之前,有这样一个问题:为什么同样是禁止用户登录的功能,却要制作两个一模一样的文件呢?
这个小玄机其实就在 user_list 文件上面。如果把上面主配置文件中 userlist_deny 的参数值改成 NO,那么 user_list 列表就变成了强制白名单。它的功能与之前完全相反,只允许列表内的用户访问,拒绝其他人的访问。
另外,在采用本地用户模式登录 FTP 服务器后,默认访问的是该用户的家目录,而且该目录的默认所有者、所属组都是该用户自己,因此不存在写入权限不足的情况。但是当前的操作仍然被拒绝,这是因为我们刚才将虚拟机系统还原到最初的状态了。为此,需要再次开启 SELinux 域中对 FTP 服务的允许策略:
[root@linuxprobe~]# getsebool -a | grep ftp
ftpd_anon_write --> off
ftpd_connect_all_unreserved --> off
ftpd_connect_db --> off
ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_fusefs --> off
ftpd_use_nfs --> off
ftpd_use_passive_mode --> off
httpd_can_connect_ftp --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off
tftp_home_dir --> off
[root@linuxprobe~]# setsebool -P ftpd_full_access=on
在实验课程和生产环境中设置 SELinux 域策略时,一定记得添加-P参数,否则服务器在重启后就会按照原有的策略进行控制,从而导致配置过的服务无法使用。
在配置妥当后再使用本地用户尝试登录 FTP 服务器,分别执行文件的创建、重命名及删除等命令。操作均成功!
[root@linuxprobe vsftpd]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 (vsFTPd 3.0.3)
Name (192.168.10.10:root): root
331 Please specify the password.
Password: (此处输入该用户的密码)
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> mkdir files
257 "/root/files" created
ftp> rename files database
350 Ready for RNTO.
250 Rename successful.
ftp> rmdir database
250 Remove directory operation successful.
ftp> exit
221 Goodbye.
注:在完成本实验后请先还原设置在进行下一个实验,否则可能导致配置文件冲突而报错。
2.3 虚拟用户模式
最后讲解的虚拟用户模式是这 3 种模式中最安全的一种认证模式,是专门创建出一个账号来登录 FTP 传输服务的,而且这个账号不能用于以 SSH 方式登录服务器。当然,因为它的安全性较之于前面两种模式有了提升,所以配置流程也会稍微复杂一些。
第一步:重新安装 vsftpd 服务。创建用于进行 FTP 认证的用户数据库文件,其中奇数行为账户名,偶数行为密码。例如,分别创建 zhangsan 和 lisi 两个用户,密码均为 redhat:
[root@linuxprobe~]# cd /etc/vsftpd/
[root@linuxprobe vsftpd]# vim vuser.list
zhangsan
redhat
lisi
redhat
由于明文信息既不安全,也不符合让 vsftpd 服务程序直接加载的格式,因此需要使用db_load 命令用哈希(hash)算法将原始的明文信息文件转换成数据库文件,并且降低数据库文件的权限(避免其他人看到数据库文件的内容),然后再把原始的明文信息文件删除。
第二步:创建 vsftpd 服务程序用于存储文件的根目录以及用于虚拟用户映射的系统本地用户。vsftpd 服务用于存储文件的根目录指的是,当虚拟用户登录后所访问的默认位置。
由于 Linux 系统中的每一个文件都有所有者、所属组属性,例如使用虚拟账户“张三”新建了一个文件,但是系统中找不到账户“张三”,就会导致这个文件的权限出现错误。为此,需要再创建一个可以映射到虚拟用户的系统本地用户。简单来说,就是让虚拟用户默认登录到与之有映射关系的这个系统本地用户的家目录中。虚拟用户创建的文件的属性也都归属于这个系统本地用户,从而避免 Linux 系统无法处理虚拟用户所创建文件的属性权限。
为了方便管理 FTP 服务器上的数据,可以把这个系统本地用户的家目录设置为/var 目录(该目录用来存放经常发生改变的数据)。并且为了安全起见,将这个系统本地用户设置为不允许登录 FTP 服务器,这不会影响虚拟用户登录,而且还能够避免黑客通过这个系统本地用户进行登录。
[root@linuxprobe~]# useradd -d /var/ftproot -s /sbin/nologin virtual
[root@linuxprobe~]# ls -ld /var/ftproot/
drwx------. 3 virtual virtual 74 Jul 14 17:50 /var/ftproot/
[root@linuxprobe~]# chmod -Rf 755 /var/ftproot/
第三步:建立用于支持虚拟用户的 PAM 文件。
PAM(可插拔认证模块)是一种认证机制,通过一些动态链接库和统一的 API 把系统提供的服务与认证方式分开,使得系统管理员可以根据需求灵活调整服务程序的不同认证方式。
通俗来讲,PAM 是一组安全机制的模块,系统管理员可以用来轻易地调整服务程序的认证方式,而不必对应用程序进行任何修改。PAM 采取了分层设计(应用程序层、应用接口层、鉴别模块层)的思想,其结构如图所示。
新建一个用于虚拟用户认证的 PAM 文件 vsftpd.vu,其中 PAM 文件内的“db=”参数为使用db_load 命令生成的账户密码数据库文件的路径,但不用写数据库文件的后缀:
[root@linuxprobe~]# vim /etc/pam.d/vsftpd.vu
auth required pam_userdb.so db=/etc/vsftpd/vuser
account required pam_userdb.so db=/etc/vsftpd/vuser
第四步:在 vsftpd 服务程序的主配置文件中通过 pam_service_name 参数将 PAM 认证文件的名称修改为 vsftpd.vu。PAM 作为应用程序层与鉴别模块层的连接纽带,可以让应用程序根据需求灵活地在自身插入所需的鉴别功能模块。当应用程序需要 PAM 认证时,则需要在应用程序中定义负责认证的 PAM 配置文件,实现所需的认证功能。
例如,在 vsftpd 服务程序的主配置文件中默认就带有参数 pam_service_name=vsftpd,表示登录 FTP 服务器时是根据/etc/pam.d/vsftpd 文件进行安全认证的。现在我们要做的就是把vsftpd 主配置文件中原有的 PAM 认证文件 vsftpd 修改为新建的 vsftpd.vu 文件即可。该操作中用到的参数以及作用如表所示。
[root@linuxprobe~]# vim /etc/vsftpd/vsftpd.conf
1 anonymous_enable=NO
2 local_enable=YES
3 write_enable=YES
4 guest_enable=YES
5 guest_username=virtual
6 allow_writeable_chroot=YES
7 local_umask=022
8 dirmessage_enable=YES
9 xferlog_enable=YES
10 connect_from_port_20=YES
11 xferlog_std_format=YES
12 listen=NO
13 listen_ipv6=YES
14 pam_service_name=vsftpd.vu
15 userlist_enable=YES
第五步:为虚拟用户设置不同的权限。虽然账户 zhangsan 和 lisi 都是用于 vsftpd 服务程序认证的虚拟账户,但是我们依然想对这两人进行区别对待。比如,允许张三上传、创建、修改、查看、删除文件,只允许李四查看文件。这可以通过 vsftpd 服务程序来实现。只需新建一个目录,在里面分别创建两个以 zhangsan 和 lisi 命名的文件,其中在名为 zhangsan 的文件中写入允许的相关权限(使用匿名用户的参数):
[root@linuxprobe~]# mkdir /etc/vsftpd/vusers_dir/
[root@linuxprobe~]# cd /etc/vsftpd/vusers_dir/
[root@linuxprobe vusers_dir]# touch lisi
[root@linuxprobe vusers_dir]# vim zhangsan
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
然后再次修改 vsftpd 主配置文件,通过添加 user_config_dir 参数来定义这两个虚拟用户不同权限的配置文件所存放的路径。为了让修改后的参数立即生效,需要重启 vsftpd 服务程序并将该服务添加到开机启动项中:
[root@linuxprobe~]# vim /etc/vsftpd/vsftpd.conf
1 anonymous_enable=NO
2 local_enable=YES
3 write_enable=YES
4 guest_enable=YES
5 guest_username=virtual
6 allow_writeable_chroot=YES
7 local_umask=022
8 dirmessage_enable=YES
9 xferlog_enable=YES
10 connect_from_port_20=YES
11 xferlog_std_format=YES
12 listen=NO
13 listen_ipv6=YES
14 pam_service_name=vsftpd.vu
15 userlist_enable=YES
16 user_config_dir=/etc/vsftpd/vusers_dir
[root@linuxprobe~]# systemctl restart vsftpd
[root@linuxprobe~]# systemctl enable vsftpd
Created symlink /etc/systemd/system/multi-user.target.wants/vsftpd.service→ /
usr/lib/systemd/system/vsftpd.service.
第六步:设置 SELinux 域允许策略,然后使用虚拟用户模式登录 FTP 服务器。先按照前面实验中的步骤开启 SELinux 域的允许策略,以免再次出现操作失败的情况:
[root@linuxprobe~]# getsebool -a | grep ftp
ftpd_anon_write --> off
ftpd_connect_all_unreserved --> off
ftpd_connect_db --> off
ftpd_full_access --> off
ftpd_use_cifs --> off
ftpd_use_fusefs --> off
ftpd_use_nfs --> off
ftpd_use_passive_mode --> off
httpd_can_connect_ftp --> off
httpd_enable_ftp_server --> off
tftp_anon_write --> off
tftp_home_dir --> off
[root@linuxprobe~]# setsebool -P ftpd_full_access=on
此时,不但可以使用虚拟用户模式成功登录到 FTP 服务器,还可以分别使用账户 zhangsan和 lisi 来检验他们的权限。李四只能登录,没有其他权限:
[root@linuxprobe~]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 (vsFTPd 3.0.3)
Name (192.168.10.10:root): lisi
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> mkdir files
550 Permission denied.
ftp> exit
221 Goodbye.
而张三不仅可以登录,还可以创建、改名和删除文件,因此张三的权限是满的。大家在生产环境中一定要根据真实需求来灵活配置参数。
[root@linuxprobe vusers_dir]# ftp 192.168.10.10
Connected to 192.168.10.10 (192.168.10.10).
220 (vsFTPd 3.0.3)
Name (192.168.10.10:root): zhangsan
331 Please specify the password.
Password: (此处输入虚拟用户的密码)
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> mkdir files
257 "/files" created
ftp> rename files database
350 Ready for RNTO.
250 Rename successful.
ftp> rmdir database
250 Remove directory operation successful.
最后总结一下在使用不同的方式登录文件传输服务器后,默认所在的位置,如表所示。这样,大家在登录后就可以心里有底,不用担心把文件传错了目录。
3. TFTP(简单文件传输协议)
简单文件传输协议(Trivial File Transfer Protocol,TFTP)是一种基于 UDP 协议在客户端和服务器之间进行简单文件传输的协议。顾名思义,它提供不复杂、开销不大的文件传输服务,可将其当作 FTP 协议的简化版本。
TFTP 的命令功能不如 FTP 服务强大,甚至不能遍历目录,在安全性方面也弱于 FTP 服务。而且,由于 TFTP 在传输文件时采用的是 UDP 协议,占用的端口号为 69,因此文件的传输过程也不像 FTP 协议那样可靠。但是,因为 TFTP 不需要客户端的权限认证,也就减少了无谓的系统和网络带宽消耗,因此在传输琐碎(trivial)不大的文件时,效率更高。
接下来在系统上安装相关的软件包,进行体验。其中,tftp-server 是服务程序,tftp 是用于连接测试的客户端工具,xinetd 是管理服务(后面会讲到):
[root@linuxprobe~]# dnf install tftp-server tftp xinetd
Updating Subscription Management repositories.
Unable to read consumer identity
This system is not registered to Red Hat Subscription Management. You can use
subscription-manager to register.
AppStream 3.1 MB/s | 3.2 kB 00:00
BaseOS 2.7 MB/s | 2.7 kB 00:00
Dependencies resolved.
===============================================================================
Package Arch Version Repository Size
===============================================================================
Installing:
tftp x86_64 5.2-24.el8 AppStream 42 k
tftp-server x86_64 5.2-24.el8 AppStream 50 k
xinetd x86_64 2:2.3.15-23.el8 AppStream 135 k
Transaction Summary
===============================================================================
Install 3 Packages
Total size: 227 k
Installed size: 397 k
Is this ok [y/N]: y
Downloading Packages:
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
Preparing : 1/1
Installing : xinetd-2:2.3.15-23.el8.x86_64 1/3
Running scriptlet: xinetd-2:2.3.15-23.el8.x86_64 1/3
Installing : tftp-server-5.2-24.el8.x86_64 2/3
Running scriptlet: tftp-server-5.2-24.el8.x86_64 2/3
Installing : tftp-5.2-24.el8.x86_64 3/3
Running scriptlet: tftp-5.2-24.el8.x86_64 3/3
Verifying : tftp-5.2-24.el8.x86_64 1/3
Verifying : tftp-server-5.2-24.el8.x86_64 2/3
Verifying : xinetd-2:2.3.15-23.el8.x86_64 3/3
Installed products updated.
Installed:
tftp-5.2-24.el8.x86_64 tftp-server-5.2-24.el8.x86_64 xinetd-2:2.3.15-23.
el8.x86_64
Complete!
在 Linux 系统中,TFTP 服务是使用 xinetd 服务程序来管理的。xinetd 服务可以用来管理多种轻量级的网络服务,而且具有强大的日志功能。它专门用于控制那些比较小的应用程序的开启与关闭,有点类似于带有独立开关的插线板,想开启那个服务,就编辑对应的 xinetd 配置文件的开关数。
简单来说,在安装 TFTP 软件包后,还需要在 xinetd 服务程序中将其开启。在 RHEL 8 系统中,tftp 所对应的配置文件默认不存在,需要用户根据示例文件(/usr/share/doc/xinetd/sample.conf)自行创建。大家可以直接将下面的内容复制到文件中,就可以使用了:
[root@linuxprobe~]# vim /etc/xinetd.d/tftp
service tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /var/lib/tftpboot
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
然后,重启 xinetd 服务并将它添加到系统的开机启动项中,以确保 TFTP 服务在系统重启后依然处于运行状态。考虑到有些系统的防火墙默认没有允许 UDP 协议的 69 端口,因此需要手动将该端口号加入到防火墙的允许策略中:
[root@linuxprobe~]# systemctl restart tftp
[root@linuxprobe~]# systemctl enable tftp
[root@linuxprobe~]# systemctl restart xinetd
[root@linuxprobe~]# systemctl enable xinetd
[root@linuxprobe~]# firewall-cmd --zone=public --permanent --add-port=69/udp
success
[root@linuxprobe~]# firewall-cmd --reload
success
TFTP 的根目录为/var/lib/tftpboot。可以使用刚才安装好的 tftp 命令尝试访问其中的文件,亲身体验 TFTP 服务的文件传输过程。在使用 tftp 命令访问文件时,可能会用到表中的参数。
[root@linuxprobe ~]# echo "i love linux" > /var/lib/tftpboot/readme.txt
[root@linuxprobe ~]# tftp 192.168.10.10
tftp> get readme.txt
tftp> quit
[root@linuxprobe~]# ls
anaconda-ks.cfg Documents initial-setup-ks.cfg Pictures readme.txt Videos
Desktop Downloads Music Public Templates
[root@linuxprobe ~]# cat readme.txt
i love linux
TFTP 服务的玩法还不止于此,后面会将 TFTP 服务与其他软件相搭配,组合出一套完整的自动化部署系统方案。