概述
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服务器。
安装
环境准备
基础环境准备,我在centos7服务器上做简单测试。为方便起见,禁用了selinux和防火墙(firewalld)
[root@VM-4-6-centos ~]# setenforce 0
setenforce: SELinux is disabled
[root@VM-4-6-centos ~]# systemctl stop firewalld
ftp的安装很简单,同时将ftp的客户端一起安装好,后面方便测试。centos7 下直接使用yum安装。
#服务端
[root@VM-4-6-centos ~]# yum install vsftpd -y
#客服端
[root@VM-4-6-centos ~]# yum install ftp -y
vsftpd服务程序的主配置文件是/etc/vsftpd/vsftpd.conf,其内容总长度有127行之多,但大多都是注释信息(#开头),看起来复杂。我们可以使用以下方式稍作处理。然后进行查看修改,当然不明白的地方也可以查看初始文件中的注释信息进行理解。
[root@VM-4-6-centos vsftpd]# mv /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.init
[root@VM-4-6-centos vsftpd]# grep -v "#" /etc/vsftpd/vsftpd.conf.init > /etc/vsftpd/vsftpd.conf
#默认使用参数
[root@VM-4-6-centos vsftpd]# cat /etc/vsftpd/vsftpd.conf
anonymous_enable=YES
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
tcp_wrappers=YES
[root@VM-4-6-centos vsftpd]#
以上是默认的使用参数,有很多重要的参数默认没有启用,但是却是很重要的。下面总结了一些常用的重要参数,如下表。大家需要大致了解其含义。
vsftpd服务程序常用的参数以及说明
参数 | 说明 |
---|---|
listen=[YES|NO] | 是否以独立运行的方式监听服务 |
listen_address=IP地址 | 设置要监听的IP地址 |
listen_port=21 | 设置FTP服务的监听端口 |
download_enable=[YES|NO] 是 | 否允许下载文件 |
userlist_enable=[YES|NO] | 设置用户允许列表 |
userlist_deny=[YES|NO] | 设置用户禁止列表 |
max_clients=0 | 最大客户端连接数,0为不限制 |
max_per_ip=0 | 同一IP地址的最大连接数,0为不限制 |
anonymous_enable=[YES|NO] | 是否允许匿名用户访问 |
anon_upload_enable=[YES|NO] | 是否允许匿名用户上传文件 |
anon_umask=022 | 匿名用户上传文件的umask值 |
anon_root=/var/ftp | 匿名用户的FTP根目录 |
anon_mkdir_write_enable=[YES|NO] | 是否允许匿名用户创建目录 |
anon_other_write_enable=[YES|NO] | 是否开放匿名用户的其他写入权限(包括重命名、删除等操作权限) |
anon_max_rate=0 | 匿名用户的最大传输速率(字节/秒),0为不限制 |
local_enable=[YES|NO] | 是否允许本地用户登录FTP |
local_umask=022 | 本地用户上传文件的umask值 |
local_root=/var/ftp | 本地用户的FTP根目录 |
chroot_local_user=[YES|NO] | 是否将用户权限禁锢在FTP目录,以确保安全 |
local_max_rate=0 | 本地用户最大传输速率(字节/秒),0为不限制 |
模式选择
匿名模式
在vsftpd服务程序中,匿名开放模式是最不安全的一种认证模式。任何人都可以无须密码验证而直接登录FTP服务器。这种模式一般用来访问不重要的公开文件(在生产环境中尽量不要存放重要文件)。当然,如果采用第8章中介绍的防火墙管理工具(如TCP Wrapper服务程序)将vsftpd服务程序允许访问的主机范围设置为企业内网,也可以提供基本的安全性。
vsftpd服务程序默认关闭了匿名开放模式,我们需要做的就是开放匿名用户的上传、下载文件的权限,以及让匿名用户创建、删除、更名文件的权限。需要注意的是,针对匿名用户放开这些权限会带来潜在危险,我们只是为了在Linux系统中练习配置vsftpd服务程序而放开了这些权限,不建议在生产环境中如此行事。下表为匿名模式时可以向匿名用户开放的权限参数以及作用:
参数 | 说明 |
---|---|
anonymous_enable=YES | 允许匿名访问模式 |
anon_umask=022 | 匿名用户上传文件的umask值 |
anon_upload_enable=YES | 允许匿名用户上传文件 |
anon_mkdir_write_enable=YES | 允许匿名用户创建目录 |
anon_other_write_enable=YES | 允许匿名用户修改目录名称或删除目录 |
[root@VM-4-6-centos pub]# cat /etc/vsftpd/vsftpd.conf
anonymous_enable=YES
anon_umask=022
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
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
tcp_wrappers=YES
[root@VM-4-6-centos pub]# systemctl restart vsftpd
[root@VM-4-6-centos pub]# systemctl status vsftpd
现在就可以在客户端执行ftp命令连接到远程的FTP服务器了。在vsftpd服务程序的匿名开放认证模式下,其账户统一为anonymous,密码为空。而且在连接FTP服务器后,默认访问的是/var/ftp目录。可以切换到该目录下的pub目录中,然后尝试创建一个新的目录文件,以检验是否拥有写入权限。
[root@VM-4-6-centos ~]# ftp 10.0.4.6
Connected to 10.0.4.6 (10.0.4.6).
220 (vsFTPd 3.0.2)
Name (10.0.4.6:root): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pwd
257 "/"
ftp> ls
227 Entering Passive Mode (10,0,4,6,175,224).
150 Here comes the directory listing.
drwxr-xr-x 3 14 0 4096 Aug 23 08:33 pub
226 Directory send OK.
ftp> cd pub
250 Directory successfully changed.
ftp> mkdir test
257 "/pub/test" created
ftp> ls
227 Entering Passive Mode (10,0,4,6,181,166).
150 Here comes the directory listing.
drwxr-xr-x 2 14 50 4096 Aug 23 08:38 test
226 Directory send OK.
#注意上传文件时要指定名字
ftp> put /etc/vsftpd/vsftpd.conf /pub/vsftpd.conf
local: /etc/vsftpd/vsftpd.conf remote: /pub/vsftpd.conf
227 Entering Passive Mode (10,0,4,6,96,157).
150 Ok to send data.
226 Transfer complete.
342 bytes sent in 1.5e-05 secs (22800.00 Kbytes/sec)
#更多支持的命令可以通过`?`进行查看
ftp> ?
Commands may be abbreviated. Commands are:
! debug mdir sendport site
$ dir mget put size
account disconnect mkdir pwd status
append exit mls quit struct
ascii form mode quote system
bell get modtime recv sunique
binary glob mput reget tenex
bye hash newer rstatus tick
case help nmap rhelp trace
cd idle nlist rename type
cdup image ntrans reset user
chmod lcd open restart umask
close ls prompt rmdir verbose
cr macdef passive runique ?
delete mdelete proxy send
#删除文件
ftp> delete /pub/1.txt
250 Delete operation successful.
#删除文件夹
ftp> rmdir test
250 Remove directory operation successful.
ftp> exit
221 Goodbye.
注意:如果出现550 Permission denied.
需要关闭selinux。或者不关闭的话需要设置相应的权限。使用匿名用户登录后,vsftpd服务程序登陆后所在目录为/var/ftp
本地用户模式
相较于匿名开放模式,本地用户模式要更安全,而且配置起来也比较简单。如果之前启用了匿名模式,建议先关闭后再开启本地用户模式。本地用户模式的权限参数以及作用如下所示。
本地用户模式使用的权限参数以及作用
参数 | 说明 |
---|---|
anonymous_enable=NO | 禁止匿名访问模式 |
local_enable=YES | 允许本地用户模式 |
write_enable=YES | 设置可写权限 |
local_umask=022 | 本地用户模式创建文件的umask值 |
userlist_deny=YES | 启用“禁止用户名单”,名单文件为ftpusers和user_list |
userlist_enable=YES | 开启用户作用名单文件功能 |
默认情况下本地用户所需的参数都已经存在,不需要修改。其中关于umask一般被称为“权限掩码”或“权限补码”,能够直接影响到新建文件的权限值。例如在Linux系统中,新建的普通文件的权限是644,新建的目录的权限是755。虽然大家对此都习以为常,但是有考虑过权限为什么是这些数字么?
其实,普通文件的默认权限是666,目录的默认权限是777,这都是写在系统配置文件中的。但默认值不等于最终权限值。umask参数的默认值是022,根据公式“默认权限−umask=实际权限”,所以普通文件的默认权限到手后就剩下644,而目录文件就剩下755了。
最终配置如下:
[root@VM-4-6-centos ~]# 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_deny=YES
userlist_enable=YES
tcp_wrappers=YES
#然后重启
[root@VM-4-6-centos ~]# systemctl restart vsftpd
默认情况下,不能使用root用户进行登录,会报530 Permission denied.
错误。这是因为vsftpd服务程序所在的目录中默认存放着两个名为“用户名单”的文件(ftpusers和user_list),而在上面的配置中userlist_enable和user_list_deny我们设置的参数为YES。可以查看这两个文件,分别为not allow和denied里面的用户,这其中就有root用户。所以我们需要先将root用户注释后才能使用root登录。当然为了安全起见,我们建议选择其他用户进行登录。
测试
[root@VM-4-6-centos ~]# ftp 10.0.4.6
Connected to 10.0.4.6 (10.0.4.6).
220 (vsFTPd 3.0.2)
Name (10.0.4.6:root): root
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
#其他操作如上面的匿名模式
注意:使用本地用户登录后,vsftpd服务程序登陆后所在目录为该登录用户的家目录。
虚拟用户模式
虚拟用户模式是这3种模式中最安全的一种认证模式,所谓的虚拟用户是专门创建出一个账号来登录FTP传输服务的,这个账号在系统中默认不存在,更不能用于以SSH方式登录服务器。当然,因为它的安全性较之于前面两种模式有了提升,所以配置流程也会稍微复杂一些。
创建用户登录信息
创建用于进行FTP认证的用户数据库文件,其中奇数行为账户名,偶数行为密码。例如,分别创建test1和test2两个用户,密码均为margu:
[root@VM-4-6-centos ~]# cd /etc/vsftpd/
[root@VM-4-6-centos vsftpd]# cat vuser.list
test1
margu
test2
margu
加密用户信息
由于明文信息既不安全,也不符合让vsftpd服务程序直接加载的格式,因此需要使用db_load命令用哈希(hash)算法将原始的明文信息文件转换成数据库文件,并且降低数据库文件的权限,删除原始的明文信息文件,防止他人查看到数据库的文件内容。
[root@VM-4-6-centos vsftpd]# db_load -T -t hash -f vuser.list vuser.db
[root@VM-4-6-centos vsftpd]# chmod 600 vuser.db
[root@VM-4-6-centos vsftpd]# rm -rf vuser.list
创建映射的系统本地用户
由于Linux系统中的每一个文件都有所有者、所属组属性,例如使用虚拟账户“test1”新建了一个文件,但是系统中找不到账户“张三”,就会导致这个文件的权限出现错误。为此,需要再创建一个可以映射到虚拟用户的系统本地用户。简单来说,就是让虚拟用户默认登录到与之有映射关系的这个系统本地用户的家目录中。虚拟用户创建的文件的属性也都归属于这个系统本地用户,从而避免Linux系统无法处理虚拟用户所创建文件的属性权限。
为了方便管理FTP服务器上的数据,可以把这个系统本地用户的家目录设置为/var目录(该目录用来存放经常发生改变的数据)。并且为了安全起见,将这个系统本地用户设置为不允许登录FTP服务器,这不会影响虚拟用户登录,而且还能够避免黑客通过这个系统本地用户进行登录。
[root@VM-4-6-centos vsftpd]# useradd -d /var/ftproot -s /sbin/nologin virtualuser
[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
为不同虚拟用户设置权限
对于不同的虚拟用户,我们可以设置不通的使用权限。比如,只允许test1用户查看文件,而允许test2用户上传、创建、修改、查看、删除文件。这可以通过vsftpd服务程序来实现。只需新建一个目录,在里面分别创建两个以test1和test2命名的文件,其中在名为test2的文件中写入允许的相关权限(使用匿名用户的参数):
[root@linuxprobe ~]# mkdir /etc/vsftpd/vusers_dir/
[root@linuxprobe ~]# cd /etc/vsftpd/vusers_dir/
[root@linuxprobe vusers_dir]# touch test1
[root@linuxprobe vusers_dir]# vim test2
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
anon_world_readable_only=NO #可查看文件列表
更多权限参数请自行测试使用。
配置文件修改
在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文件即可。该操作中用到的参数以及作用如下表所示。
利用PAM文件进行认证时使用的参数以及作用
参数 | 说明 |
---|---|
参数 作用 | |
anonymous_enable=NO | 禁止匿名开放模式 |
local_enable=YES | 允许本地用户模式 |
guest_enable=YES | 开启虚拟用户模式 |
guest_username=virtualuser | 指定虚拟用户账户 |
pam_service_name=vsftpd.vu | 指定PAM文件 |
allow_writeable_chroot=YES | 允许对禁锢的FTP根目录执行写入操作,而且不拒绝用户的登录请求 |
最终配置
[root@VM-4-6-centos vsftpd]# cat /etc/vsftpd/vsftpd.conf
anonymous_enable=NO
local_enable=YES
write_enable=YES
guest_enable=YES
guest_username=virtualuser
allow_writeable_chroot=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.vu
userlist_enable=YES
user_config_dir=/etc/vsftpd/vusers_dir
#重启
[root@VM-4-6-centos vsftpd]# systemctl restart vsftpd
测试
#以test1用户登录,不能创建文件夹
[root@VM-4-6-centos tmp]# ftp 10.0.4.6
Connected to 10.0.4.6 (10.0.4.6).
220 (vsFTPd 3.0.2)
Name (10.0.4.6:root): test1
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> mkdir test
550 Permission denied.
ftp> 221 Goodbye.
#切换用户以test2用户登录,能创建文件夹
[root@VM-4-6-centos tmp]# ftp 10.0.4.6
Connected to 10.0.4.6 (10.0.4.6).
220 (vsFTPd 3.0.2)
Name (10.0.4.6:root): test2
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> mkdir test2
257 "/test2" created
ftp> pwd
257 "/"
ftp> ls
227 Entering Passive Mode (10,0,4,6,199,233).
150 Here comes the directory listing.
drwx------ 2 1002 1002 4096 Aug 24 03:05 test2
226 Directory send OK.
#不能切换到root目录,一定程度上保证了安全性
ftp> cd /root
550 Failed to change directory.
ftp> cd test2
250 Directory successfully changed.
ftp> pwd
257 "/test2
ftp> ls
227 Entering Passive Mode (10,0,4,6,173,15).
150 Here comes the directory listing.
-rw------- 1 1002 1002 369 Aug 24 06:32 test.txt
226 Directory send OK.
ftp>
注意:虚拟模式下,vsftpd服务程序登陆后所在目录为对应映射用户的家目录,如上面为virtualuser的家目录/var/ftproot/
更多关于Linux的知识请前往博客主页查看,编写过程中可能由于能力有限难免出现问题,敬请指出,谢谢。