Linux网络文件共享服务之FTP

  一、FTP介绍

  ftp(File Transfer Protocol)是早期的三个应用级协议之一,基于C/S结构,双通道协议,数据和命令连接,数据传输格式默认是二进制,当然也支持文本方式传输。默认情况下FTP协议使用TCP端口中的21和20这两个端口,其中20用于数据传输,21用作命令传输,但是20号端口是否作为数据传输的端口,这与FTP使用的传输模式有关,从FTP服务器的角度讲,FTP传输数据的模式分为主动模式和被动模式。主动模式就是服务器主动去连接客户端,被动模式就是客户端去连接服务器。不管FTP服务器工作在那个模式下,它的命令控制端口都监听在ftp服务器的tcp21端口,而主动模式(PORT)中数据传输端口是ftp服务器的20号端口去连接客户端的一个随机端口来传输数据,在被动模式(PASV)是客户端的一个随机端口去连接FTP服务端的一个随机端口,这样一来各位可能会有一个疑问就是在被动模式中,客户端怎么知道去连接那个端口和服务器连接传输数据呢?双方的随机端口怎么确认呢?它的工作流程是这样的,在被动模式中我们知道命令控制端口是连接FTP服务器的21号端口(这是默认情况,不更改其监听的端口),客户端连接服务端的时候就会和服务端协商,到底哪个端口来当做数据传输的端口啊,事实上被动模式或主动模式中数据传输端口是通过命令链路双方协商好的,主动模式的数据传输端口是通过命令连接告诉给服务端的,这样一来当我们需要下载数据时,服务端会以20端口去连接客户端的一个协商好的端口,同理被动模式中,数据端口也是双方协商好了的,在我们下载数据时,客户端会以一个随机端口去连接协商好的那个服务端的端口。

  服务器被动模式数据端口示例

[root@test ~]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,99,43,241).
150 Here comes the directory listing.
drwxr-xr-x    2 0        0               6 Oct 30  2018 pub
226 Directory send OK.
ftp> 

  说明:我们可以看到消息状态为227的告诉我们被动模式(192.168.0.99,43,241)这是什么意思呢,其实它这就是告诉客户端我们连接服务端的那个端口,它的计算方式是这样的,以上为例它会去连接服务端的11249,这个端口就是通过43*256+241得来的,每传输一次数据都会协商好一个数据端口,这就是ftp工作在被动模式的端口确定方式。

227 Entering Passive Mode (192,168,0,99,201,83).
150 Here comes the directory listing.
-rw-r--r--    1 0        0        1073741824 Dec 27 04:25 bigfile
226 Directory send OK.
ftp> ! ss -nt
State      Recv-Q Send-Q              Local Address:Port                             Peer Address:Port              
ESTAB      0      0                    192.168.0.99:51838                            192.168.0.99:21                 
ESTAB      0      0                    192.168.0.99:59860                            192.168.0.99:3306               
ESTAB      0      0                    192.168.0.99:3306                             192.168.0.99:59860              
ESTAB      0      0                    192.168.0.99:41319                           192.168.0.232:1678               
ESTAB      0      216                  192.168.0.99:41319                           192.168.0.232:1616               
ESTAB      0      0             ::ffff:192.168.0.99:21                        ::ffff:192.168.0.99:51838              
ftp> get bigfile
local: bigfile remote: bigfile
227 Entering Passive Mode (192,168,0,99,247,183).
150 Opening BINARY mode data connection for bigfile (1073741824 bytes).

  说明:可看到命令链路上是客户端的一个随机端口连接服务端的21 端口 ,在下载数据时双方协定的端口是256×247+183,接下来我们在来看看服务端上的端口连接情况

[qiuhom@test ~]$ss -nt
State      Recv-Q Send-Q              Local Address:Port                             Peer Address:Port              
ESTAB      0      0                    192.168.0.99:51838                            192.168.0.99:21                 
ESTAB      0      0                    192.168.0.99:59860                            192.168.0.99:3306               
ESTAB      0      0                    192.168.0.99:3306                             192.168.0.99:59860              
ESTAB      204800 0                    192.168.0.99:35409                            192.168.0.99:63415              
ESTAB      0      216                  192.168.0.99:41319                           192.168.0.232:1678               
ESTAB      0      0                    192.168.0.99:41319                           192.168.0.232:1616               
ESTAB      0      0             ::ffff:192.168.0.99:21                        ::ffff:192.168.0.99:51838              
ESTAB      0      0             ::ffff:192.168.0.99:63415                     ::ffff:192.168.0.99:35409              
[qiuhom@test ~]$bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
256*247+183
63415

  说明:可以看到客户端的35409这个端口与服务端的63415连接着。63415就是在下载数据的时候双方协商好的数据传输端口

  二、FTP软件介绍

  FTP服务器软件有Wu-ftpd,Proftpd,Pureftpd,servU,IIS,vsftpd,在centos上默认的FTP服务器软件就是vsftpd,它号称是非常安全的FTPDaemon ,高速,稳定,下载速度是WU-FTP的两倍,官方数据告诉我们单机最多可支持15000个并发。听上去很牛逼的样子,接下来我们来看看它基本介绍

[root@test ~]#yum info vsftpd
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
已安装的软件包
名称    :vsftpd
架构    :x86_64
版本    :3.0.2
发布    :25.el7
大小    :353 k
源    :installed
来自源:base
简介    : Very Secure Ftp Daemon
网址    :https://security.appspot.com/vsftpd.html
协议    : GPLv2 with exceptions
描述    : vsftpd is a Very Secure FTP daemon. It was written completely from
         : scratch.

[root@test ~]#

  说明:你看看它的简介就是说非常安全的FTP Daemon。具体它的并发能够达到多少,有待测试

  在Linux系统上FTP客户端软件有,ftp,lftp,lftpget ,wget curl,其中ftp和lftp最为常用,ftp这个客户端工具一般用于测试,因为它不具备命令补全的功能,在生产环境中用起来不是很方便,还有就是它列出来的文件、目录,只能看文件属性信息里的‘-’,‘d’来区分,所以在字符界面一般我们都很少用ftp这个客户端,相反lftp就弥补了ftp的确定,受到大众的喜爱,它支持命令补全,我们用它就感觉是操作Linux文件系统一样。

  ftp连接FTP服务器的使用方法:

[root@test ~]#ftp -A 192.168.0.99 2121
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-xr-x    2 0        0              21 Dec 27 04:25 pub
226 Directory send OK.
ftp> cd pub
250 Directory successfully changed.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 0        0        1073741824 Dec 27 04:25 bigfile
226 Directory send OK.
ftp> bye
221 Goodbye.
[root@test ~]#ftp -p 192.168.0.99 2121 
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,99,20,204).
150 Here comes the directory listing.
drwxr-xr-x    2 0        0              21 Dec 27 04:25 pub
226 Directory send OK.
ftp> cd pub
250 Directory successfully changed.
ftp> ls
227 Entering Passive Mode (192,168,0,99,205,210).
150 Here comes the directory listing.
-rw-r--r--    1 0        0        1073741824 Dec 27 04:25 bigfile
226 Directory send OK.
ftp> bye
221 Goodbye.
[root@test ~]#

  说明:-A表示主动模式,-p(小写) 表示被动模式,centos系统上默认ftp客户端是使用的被动模式,这也说明了一点不同的客户端,其连接服务器的模式是不一样。

  lftp连接ftp服务器的使用方法:

[root@test ~]#lftp -u ftp 192.168.0.99 -p 2121
口令: 
lftp ftp@192.168.0.99:~> ls            
drwxr-xr-x    2 0        0              21 Dec 27 04:25 pub
lftp ftp@192.168.0.99:/> cd pub/
lftp ftp@192.168.0.99:/pub> ls
-rw-r--r--    1 0        0        1073741824 Dec 27 04:25 bigfile
lftp ftp@192.168.0.99:/pub> bye
[root@test ~]#lftp ftp@192.168.0.99 -p 2121    
口令: 
lftp ftp@192.168.0.99:~> ls            
drwxr-xr-x    2 0        0              21 Dec 27 04:25 pub
lftp ftp@192.168.0.99:/> cd pub/
lftp ftp@192.168.0.99:/pub> ls
-rw-r--r--    1 0        0        1073741824 Dec 27 04:25 bigfile
lftp ftp@192.168.0.99:/pub> bye
[root@test ~]#

  说明:-p是指定端口 -u 指定用户名,如果不用-u指定,可把用户名写在@前

  还有一些别的客户端工具如浏览器,Windows的资源管理器,filezilla等等,这些都不在这里过多演示

  三、FTP服务

  1)状态码说明

    1xx:表示信息类,比如125:表示数据连接打开

    2xx:表示成功类状态,比如200:命令ok 230表示登录成功

    3xx:表示补充类,比如331表示用户名OK

    4xx:表示客户端错误,比如425表示不能打开数据链接

    5xx:表示服务器错误,比如530表示不能登录

  2)用户认证

    支持匿名用户:ftp,anonymous,对应Linux用户ftp

       系统用户:Linux用户,用户/etc/passwd,密码/etc/shadow

    虚拟用户:特定服务端专用用户,独立的用户/密码文件

  四、vsftpd服务介绍

  vsftpd由vsftpd包提供,默认不再由xinetd管理,当然我们是可以配置成非独立服务的,让它由xinetd服务代管。用户认证配置文件:/etc/pam.d/vsftpd,服务脚本:centos7上是/usr/lib/systemd/system/vsftpd.service,centos6上是/etc/rc.d/init.d/vsftpd;服务主配置文件是:/etc/vsftpd/vsftpd.conf

  其中/etc/vsftpd/vsftpd.conf 可以通过man 5 vsftpd.conf 来查看配置文件帮助,它里面的格式是option=value的格式,等号前后不能有多余的空格,否则服务将无法正常启动。匿名用户(映射为系统用户ftp)共享文件位置上:/var/ftp,这个目录就是默认ftp的共享目录;系统用户共享文件位置就是用户的家目录;虚拟用户共享文件位置:为其映射的系统用户家目录

  五、vsftpd服务配置

  命令端口的配置:命令端口的指定由listen_port=xx来指定,不写在配置文件中表示使用默认的命令端口21

  主动模式端口:connet_from_port_20=YES 表示主动模式端口为20;ftp_data_port=xx表示指定主动模式的端口,默认是20

  被动端口范围:Linux客户端默认使用被动模式,Windows客户端默认使用主动模式;pasv_min_port=xxx;pasv_max_port=xxx通过这两条选项来指定ftp最小连接端口和最大的连接端口,这样配置后,数据端口就只能使用在指定这个范围内的端口。其中0表示随机分配端口

  使用当地时间:use_localtime=YES默认的配置上是NO,使用GMT

  关于匿名用户的配置:

    anonymous_enable=YES 支持匿名用户

    no_anon_password=YES(默认NO) 匿名用户略过口令检查

    anon_world_readable_only (默认YES)只能下载全部读的文件

    anon_upload_enable=YES 匿名上传,注意:文件系统权限

    anon_mkdir_write_enable=YES 匿名建目录

    anon_umask=0333 指定匿名上传文件的umask,默认077

    anon_other_write_enable=YES 可删除和修改上传的文件

  指定上传文件的默认的所有者和权限

    chown_uploads=YES(默认NO)

    chown_username=wang

    chown_upload_mode=0644

  关于Linux系统用户的配置

    local_enable=YES 是否允许linux用户登录

    write_enable=YES 允许linux用户上传文件

    local_umask=022 指定系统用户上传文件的默认权限

    guest_enable=YES 所有系统用户都映射成guest用户

    guest_username=ftp 配合上面选项才生效,指定guest用户

    local_root=/ftproot guest用户登录所在目录

  这里需要注意一个点,映射成guest用户后,用户登录所指定的目录,不能有guest所指定的用户有可写的权限,否则用户无法登陆。也就是说ftp的根目录是不能有当前用户的写权限的。

  禁锢所有系统用户在家目录中

    chroot_local_user=YES(默认NO,不禁锢)禁锢系统用户

    chroot_list_enable=YES开启禁锢列表   

    chroot_list_file=/etc/vsftpd/chroot_list禁锢或不禁锢用户的名单文件,当chroot_local_user=YES时,则chroot_list中的用户不禁锢(白名单),当chroot_local_user=NO时,chroot_list中的用户禁锢(黑名单) 

  wu-ftp日志:默认启用

    xferlog_enable=YES (默认) 启用记录上传下载日志

    xferlog_std_format=YES (默认) 使用wu-ftp日志格式

    xferlog_file=/var/log/xferlog (默认)可自动生成

  vsftpd日志:默认不启用

    dual_log_enable=YES 使用vsftpd日志格式,默认不启用

    vsftpd_log_file=/var/log/vsftpd.log(默认)可自动生成

  登录提示信息

    ftpd_banner=“welcome to mage ftp server"

    banner_file=/etc/vsftpd/ftpbanner.txt 优先上面的选项生效

  目录访问提示信息

    dirmessage_enable=YES (默认)

    message_file=.message(默认) 信息存放在指定目录下.message

   使用pam(Pluggable Authentication Modules)完成用户认证

    pam_service_name=vsftpd

      pam配置文件:/etc/pam.d/vsftpd

      /etc/vsftpd/ftpusers 默认文件中用户拒绝登录,当然具体这里面的用户数拒绝还是允许需要看/etc/pam.d/vsftpd 是怎么定义的了

[root@test ~]#cat /etc/pam.d/vsftpd 
#%PAM-1.0
session    optional     pam_keyinit.so    force revoke
auth       required     pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed
auth       required     pam_shells.so
auth       include      password-auth
account    include      password-auth
session    required     pam_loginuid.so
session    include      password-auth
[root@test ~]#

  说明:此文件默认是定义的是/etc/vsftpd/ftpusers这个文件中的用户是拒绝登录ftp系统的,若我们需要/etc/vsftpd/ftpuser里的用户允许登录ftp系统,我们只需要改动/etc/pam.d/vsftpd即可,把sense=deny改成sense=allow即可。

  是否启用控制用户登录的列表文件

    userlist_enable=YES 默认有此设置

    userlist_deny=YES(默认值) 黑名单,不提示口令,NO为白名单

    userlist_file=/etc/vsftpd/users_list 此为默认值

[root@test ~]#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@test ~]#

  说明:此文件注释告诉我们如果userlist_deny=NO 那么ftp系统只允许此文件中的用户登录系统;如果userlist_deny=YES 且此选项默认是yes选项,那么此文件中的用户是不允许登录到ftp系统的,况且不会给输入密码的机会。这也就是为什么root用户登录系统,没有输入密码的机会就提示权限拒绝,不光是root,像bin,daemon这些用户也是一样的,总之放在这个文件中的用户都不会提示输入口令。假如我们想要让root用户登录到ftp系统里,怎么配置呢?首先我们要把此文件的root用户删除或注释掉。删除了此文件中的root用户,我们用root登录就会有输入密码的提示

[root@test ~]#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@test ~]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): root
530 Permission denied.
Login failed.
ftp> bye
221 Goodbye.
[root@test ~]#sed -i 's@root@#root@' /etc/vsftpd/user_list 
[root@test ~]#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@test ~]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): root
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.
ftp> bye
221 Goodbye.
[root@test ~]#

  说明:我们可以看到我们把root从/etc/vsftpd/user_list文件中注释掉,root用户登录FTP系统就可以输入密码了,但是我们输入正确的口令为什么还是不能登录呢?其实/etc/vsftpd/user_list文件中告诉我们了,说默认vsftpd pam会检查配置文件/etc/vsftpd/ftpusers中的用户,也就说系统用户要想登录FTP系统,必须满足/etc/vsftpd/user_list中没有此用户的同时,pam检查/etc/vsftpd/ftpusers文件此用户通过,如果/etc/pam.d/vsftpd配置文件中指定/etc/vsftpd/ftpusers中的用户拒绝登录到ftp系统,那么此用户也必须满足ftpusers中没有此用户。如果/etc/pam.d/vsftpd配置文件中指定/etc/vsftpd/ftpusers中的用户允许登录到ftp系统,则此用户只需要满足不存在/etc/vsftpd/user_list即可,当然默认情况两个配置文件中都没有的用户是可以登录系统的。

[root@test ~]#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@test ~]#sed -i 's@root@#root@' /etc/vsftpd/ftpusers
[root@test ~]#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@test ~]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): root
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,99,66,75).
150 Here comes the directory listing.
drwxr-xr-x    5 0        0             190 Dec 27 04:26 bak
226 Directory send OK.
ftp> bye
221 Goodbye.
[root@test ~]#

  说明:更改了ftpusers文件,root就可以正常登录系统里,这里需要注意一点,在生产环境中我们是不推荐这样做的,因为ftp默认情况是不加密的,都是明文传输,如果用root登录,很有可能泄露root密码,从而威胁到linux系统。这也告诉我们,我们如果用系统帐号作为ftp的登录帐号,必须限制其登录shell类型,否则会有ftp用户登录到Linux系统的危险。/etc/vsftpd/ftpusers和/etc/vsftpd/user_list这两个文件中的用户具体是拒绝还是允许,都取决于两个参数的配置,ftpusers 取决于pam.d/vsftpd中的配置是否允许,user_list中的用户取决于userlist_deny=yes or no,一般我们都取默认值即可。

  vsftpd服务指定用户身份运行

    nopriv_user=nobody (默认值)

  连接数限制

    max_clients=0 最大并发连接数

    max_per_ip=0 每个IP同时发起的最大连接数

  传输速率:字节/秒

    anon_max_rate=0 匿名用户的最大传输速率

    local_max_rate=0 本地用户的最大传输速率

  连接时间:秒为单位

    connect_timeout=60 主动模式数据连接超时时长

    accept_timeout=60 被动模式数据连接超时时长

    data_connection_timeout=300 数据连接无数据输超时时长

    idle_session_timeout=60 无命令操作超时时长

  优先以文本方式传输

    ascii_upload_enable=YES

    ascii_download_enable=YES

  这两个选项不建议大家配置,因为默认的是binary模式传输数据,如果配置了这两条后,进行传输二进制的文件会有问题,我们知道Windows和Linux的纯文本文件的格式是不一样的,windows上文本文件的格式回车加换行表示Linux里的一个换行,这样一来,假如用户下载一个二进制程序,用windows客户端来下载,有可能存在破坏原来二进制文件的内容,导致下载下来的二进制程序不可用。虽然ftp客户端是可以切换传输模式,但还是不建议大家更改默认优先使用binary传输数据。因为我们用binary模式传输数据,没有破坏文件的风险,顶多下载一个文本文件它的格式不一样,但是我们可以用工具去转换呀,如果是二进制文件被破环了,相对文本文件去转换要难得多,所以还是推荐大家使用binary模式去传输数据。

  配置FTP服务以非独立服务方运行

[root@test-node1 ~]#yum install vsftpd xinetd -y
Loaded plugins: fastestmirror, security
Setting up Install Process
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
Package vsftpd-2.2.2-24.el6.x86_64 already installed and latest version
Package 2:xinetd-2.3.14-40.el6.x86_64 already installed and latest version
Nothing to do
[root@test-node1 ~]#grep "listen" /etc/vsftpd/vsftpd.conf 
# When "listen" directive is enabled, vsftpd runs in standalone mode and
# listens on IPv4 sockets. This directive cannot be used in conjunction
# with the listen_ipv6 directive.
listen=YES
# This directive enables listening on IPv6 sockets. To listen on IPv4 and IPv6
# Make sure, that one of the listen options is commented !!
#listen_ipv6=YES
[root@test-node1 ~]#sed -i 's@listen=YES@listen=NO@' /etc/vsftpd/vsftpd.conf 
[root@test-node1 ~]#grep "listen=" /etc/vsftpd/vsftpd.conf
listen=NO
[root@test-node1 ~]#cat >> /etc/xinetd.d/vsftpd << EOF
> service ftp
> {
> flags = REUSE
> socket_type = stream
> wait = no
> user = root
> server = /usr/sbin/vsftpd
> log_on_failure += USERID
> disable = no
> }
> EOF
[root@test-node1 ~]#cat /etc/xinetd.d/vsftpd 
service ftp
{
flags = REUSE
socket_type = stream
wait = no
user = root
server = /usr/sbin/vsftpd
log_on_failure += USERID
disable = no
}
[root@test-node1 ~]#/etc/init.d/xinetd start
Starting xinetd:                                           [  OK  ]
[root@test-node1 ~]#ss -ntlp |grep 21
LISTEN     0      64                       :::21                      :::*      users:(("xinetd",3966,5))
[root@test-node1 ~]#ftp 192.168.0.151
Connected to 192.168.0.151 (192.168.0.151).
220 (vsFTPd 2.2.2)
Name (192.168.0.151:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,151,252,106).
150 Here comes the directory listing.
drwxr-xr-x    2 0        0            4096 Mar 22  2017 pub
226 Directory send OK.
ftp> cd pub
250 Directory successfully changed.
ftp> ls
227 Entering Passive Mode (192,168,0,151,230,82).
150 Here comes the directory listing.
226 Directory send OK.
ftp> bye
221 Goodbye.
[root@test-node1 ~]#

  说明:centos7上用以上方式是可以开启以xinetd来代管vsftpd,但是没法连接去使用,不知道为什么。centos6上用以上方式是可以的。

  六、基于ssl的ftps实现

    1)查看是否支持SSL

[root@test ~]#ldd `which vsftpd`
        linux-vdso.so.1 =>  (0x00007ffe512c9000)
        libssl.so.10 => /lib64/libssl.so.10 (0x00007f3e65c8a000)
        libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f3e65a7f000)
        libnsl.so.1 => /lib64/libnsl.so.1 (0x00007f3e65865000)
        libpam.so.0 => /lib64/libpam.so.0 (0x00007f3e65656000)
        libcap.so.2 => /lib64/libcap.so.2 (0x00007f3e65451000)
        libdl.so.2 => /lib64/libdl.so.2 (0x00007f3e6524d000)
        libcrypto.so.10 => /lib64/libcrypto.so.10 (0x00007f3e64deb000)
        libc.so.6 => /lib64/libc.so.6 (0x00007f3e64a1e000)
        libgssapi_krb5.so.2 => /lib64/libgssapi_krb5.so.2 (0x00007f3e647d1000)
        libkrb5.so.3 => /lib64/libkrb5.so.3 (0x00007f3e644e8000)
        libcom_err.so.2 => /lib64/libcom_err.so.2 (0x00007f3e642e4000)
        libk5crypto.so.3 => /lib64/libk5crypto.so.3 (0x00007f3e640b1000)
        libz.so.1 => /lib64/libz.so.1 (0x00007f3e63e9b000)
        libaudit.so.1 => /lib64/libaudit.so.1 (0x00007f3e63c72000)
        libattr.so.1 => /lib64/libattr.so.1 (0x00007f3e63a6d000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f3e66127000)
        libkrb5support.so.0 => /lib64/libkrb5support.so.0 (0x00007f3e6385d000)
        libkeyutils.so.1 => /lib64/libkeyutils.so.1 (0x00007f3e63659000)
        libresolv.so.2 => /lib64/libresolv.so.2 (0x00007f3e63440000)
        libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3e63224000)
        libcap-ng.so.0 => /lib64/libcap-ng.so.0 (0x00007f3e6301e000)
        libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f3e62df7000)
        libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f3e62b95000)
[root@test ~]#

  说明:我们知道要想某个软件支持ssl,那么这个软件必须调用ssl的库文件,ssl库文件就是libssl.so,用ldd命令可以查看某个应用调用的库文件有哪些

  2)创建自签名证书

[root@test ~]#cd /etc/pki/tls/certs/
[root@test certs]#ls
ca-bundle.crt  ca-bundle.trust.crt  make-dummy-cert  Makefile  renew-dummy-cert
[root@test certs]#make vsftpd.pem
umask 77 ; \
PEM1=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
PEM2=`/bin/mktemp /tmp/openssl.XXXXXX` ; \
/usr/bin/openssl req -utf8 -newkey rsa:2048 -keyout $PEM1 -nodes -x509 -days 365 -out $PEM2  ; \
cat $PEM1 >  vsftpd.pem ; \
echo ""    >> vsftpd.pem ; \
cat $PEM2 >> vsftpd.pem ; \
rm -f $PEM1 $PEM2
Generating a 2048 bit RSA private key
...........................+++
...+++
writing new private key to '/tmp/openssl.uUotmW'
-----
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) [XX]:CN
State or Province Name (full name) []:sichuan
Locality Name (eg, city) [Default City]:guangyuan
Organization Name (eg, company) [Default Company Ltd]:test
Organizational Unit Name (eg, section) []:test
Common Name (eg, your name or your server's hostname) []:ftp.test.com  
Email Address []:
[root@test certs]#ll
总用量 16
lrwxrwxrwx. 1 root root   49 6月  22 2019 ca-bundle.crt -> /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
lrwxrwxrwx. 1 root root   55 6月  22 2019 ca-bundle.trust.crt -> /etc/pki/ca-trust/extracted/openssl/ca-bundle.trust.crt
-rwxr-xr-x. 1 root root  610 3月  12 2019 make-dummy-cert
-rw-r--r--. 1 root root 2516 3月  12 2019 Makefile
-rwxr-xr-x. 1 root root  829 3月  12 2019 renew-dummy-cert
-rw-------  1 root root 3027 12月 27 22:54 vsftpd.pem
[root@test certs]#cat vsftpd.pem 
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDWYYttWUinc+z9
uzcaEJ38qC3WEp/SNgijGj1Kn8dovJSvxgUHYuZlzgnBe3UfTrkHsQTj/f1y8OUd
4/8UCw1YRjPdZJAhZ4cnCwj6mgSxXM/ru0k232m7IeSZ5RcV/LlEZ+6wxmsv+Vow
2iaGDLlxaXczSgpHb4n0zigswCVzegmXQpQxBZvAuEEzyg204+Qf7J0qJPfc8j0H
F4Gx806C+FAlMxD79pAGxzlyb8w3gosG1H4eIlHJKtXUsZIo5cvPZxlVVqrg6SD4
o1U6FfIVGtOA0Ud4DtQnasrfQOWUOTuQrfJiykShVM8iCp5xGdZMWwD6cP0DbDdB
OUa4hB8PAgMBAAECggEAfckMGuPZKk9tjU6svQFlAVrYUhPpbFjB5pk9vyxSv1Ru
1VeVmcjgsHkc5kZ+6Riynh2yZeegLzHC7S/aebMmaFYAlnUr0D3DYhgqc4etGzf+
0yy3f5fEnMT9MYLmccMwHT/yIAy71ZEz5xgIpHyQzkd4ZkKaF2INivLvRZqUHtU4
IrzkGyF26DJNgw8+s5C+VtpF9Ii8oLQfvBvIkud4tw47rHpU5jp3Osply//s2Q8C
fHWcjqzHPWH6qSW9xppatXkJJmTiqYt9kiFJyEd5gf4ELkSEmv02Q9OHnCt6W4wo
/4EtlsfLcCPvkVjgI66PNCxObCkh13WoBOe/MJNuyQKBgQDrp3ZFPeWGMqCUTYHf
mHLlJcTtgCsqu3fxRYvG/gc5cy2Th8ECXJE4X08X6stCqBrlaLqnc2YgXjl0fNGL
YqjlXX/KymsmRWIUfBCLux6JqTfU9klQyzbZgbSIfZE0ATplT6J8MdpmzhnQJX2O
xm80KI9Vv4GmqtctjGiw4h0XcwKBgQDo4+Ty4h//VatA7sxpnDjY88y58cPyp/J1
4g0DUx2R4RVbCBkp+XgX7VXXT0TghuQSUwzvrVse9JrRxh7JegdkVshdiE2pg4NT
k+OJRi7fbWoX5cfPRCSJ1FXsNY2kz8gMhXuDWLualcQg83sHjdyUGdpCEn5i8dc1
xmsw98ka9QKBgHFNROopxm9tbBOh6G2vCJ7wN+zREPAszpBslbYJcUPIAwPJ45zV
EOV/vbGMLEpSNQxT/FqCe3nYk9tUIBPaTcZp3AWOqVHvTib3N6VXRGl/uN5lw/5a
lnahjEGLzgKpDICld0QrXAzNz09qlyHMeq8jSTc7KoUN4wN9XOCe9snNAoGBAIzv
POHvDcYLJfPJj1JqA8zm3QG52QbDs+q6vX1Bkydwuue34uKP4ak5KzV89wWZG/Qq
5i01D2uQQxCngIIUotyJ1/8iOT1YJOUzHgM4wazcHdQQbfZ0Glh+cvDbB7ixNTK+
pJw72mwWLfZy4gUUSGQnsPlDD9D44W/df4jGqqDxAoGAM107eZVXENYYbVNae0M3
K1o/kg+hVgkTtKJj1t3eMTZSOEIOlwHH48KkIdF5T37t5BQ2cmLaoBqAY2rJMP8U
YhQ65LrpC/m9IyewjE5lD5Zkz51WToMHSA9K+++1VY7+x5aJk4KJobBGl5BHMPDU
hxdjIeQujOoWlRLLWMCn/CE=
-----END PRIVATE KEY-----

-----BEGIN CERTIFICATE-----
MIIDozCCAougAwIBAgIJAIBmy3n1yB5dMA0GCSqGSIb3DQEBCwUAMGgxCzAJBgNV
BAYTAkNOMRAwDgYDVQQIDAdzaWNodWFuMRIwEAYDVQQHDAlndWFuZ3l1YW4xDTAL
BgNVBAoMBHRlc3QxDTALBgNVBAsMBHRlc3QxFTATBgNVBAMMDGZ0cC50ZXN0LmNv
bTAeFw0xOTEyMjcxNDU0MDFaFw0yMDEyMjYxNDU0MDFaMGgxCzAJBgNVBAYTAkNO
MRAwDgYDVQQIDAdzaWNodWFuMRIwEAYDVQQHDAlndWFuZ3l1YW4xDTALBgNVBAoM
BHRlc3QxDTALBgNVBAsMBHRlc3QxFTATBgNVBAMMDGZ0cC50ZXN0LmNvbTCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANZhi21ZSKdz7P27NxoQnfyoLdYS
n9I2CKMaPUqfx2i8lK/GBQdi5mXOCcF7dR9OuQexBOP9/XLw5R3j/xQLDVhGM91k
kCFnhycLCPqaBLFcz+u7STbfabsh5JnlFxX8uURn7rDGay/5WjDaJoYMuXFpdzNK
CkdvifTOKCzAJXN6CZdClDEFm8C4QTPKDbTj5B/snSok99zyPQcXgbHzToL4UCUz
EPv2kAbHOXJvzDeCiwbUfh4iUckq1dSxkijly89nGVVWquDpIPijVToV8hUa04DR
R3gO1Cdqyt9A5ZQ5O5Ct8mLKRKFUzyIKnnEZ1kxbAPpw/QNsN0E5RriEHw8CAwEA
AaNQME4wHQYDVR0OBBYEFBIAwA/ZbgW55Ljm/5Q/55wuGDd+MB8GA1UdIwQYMBaA
FBIAwA/ZbgW55Ljm/5Q/55wuGDd+MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEL
BQADggEBAIXXG0y8PiEkBFCbnusCOK7llJkzMhmogJjWFcLn9UfKzHvgpC1bhCRw
P8TKbviL616grY40NKHvGfy1kpO6vxykSnUnjATloTGyySnVQpmGOwVVT29t3Gtp
Opay0nrhKoyIZIMV44pHhPIbRAkofex3lNOXaL2lWCV8Es/1IXniyuq8XML3JSMZ
d+Lbu0P+e8sUQNQc1NCnbAUN6qFmG+LSjr+hRS25IlKQTATjMPNLcucGsF+2jwIQ
ScsSr4vVvYAj3JeW/2gV71hr4rZI8wLCZLszKKuhyyCGL2cpkS5Hwa3dahprEVkm
RB9ehsAnYgfTOMVPnzS1pgEem8cqDLg=
-----END CERTIFICATE-----
[root@test certs]#

  说明:ftp的证书有一个要求,它需要把私钥信息和证书信息放在同一个文件中。我们也可以先各自创建私钥文件和证书文件,最后把它们合并在一起也行;以上方式就一条命令将私钥文件和证书文件一并放入一个文件中

  3) 配置vsftpd服务支持SSL:/etc/vsftpd/vsftpd.conf

[root@test certs]#grep "ssl" /etc/vsftpd/vsftpd.conf
[root@test certs]#cat >> /etc/vsftpd/vsftpd.conf << EOF
> 
> ssl_enable=YES
> allow_anon_ssl=NO
> force_local_logins_ssl=YES
> force_local_data_ssl=YES
> rsa_cert_file=/etc/pki/tls/certs/vsftpd.pem
> EOF
[root@test certs]#grep "ssl" /etc/vsftpd/vsftpd.conf    
ssl_enable=YES
allow_anon_ssl=NO
force_local_logins_ssl=YES
force_local_data_ssl=YES
[root@test certs]#tail -6 /etc/vsftpd/vsftpd.conf

ssl_enable=YES
allow_anon_ssl=NO
force_local_logins_ssl=YES
force_local_data_ssl=YES
rsa_cert_file=/etc/pki/tls/certs/vsftpd.pem
[root@test certs]#

  说明:ssl_enable=YES表示启用ssl,allow_anon_ssl=NO表示匿名用户不支持ssl,force_local_logins_ssl=YES表示本地用户登录加密,force_local_data_ssl=YES表示本地用户数据传输加密,rsa_cert_file=/etc/pki/tls/certs/vsftpd.pem表示指定自签名证书的位置,这个位置可以任意选择,不一定是在这个目录,也可以将证书放入/etc/vsftpd/ssl中也可以,看自己的习惯怎么放就可以。

  4)重启vsftpd服务,测试

[root@test certs]#systemctl restart vsftpd

  说明:之前添加到选项和对应的值前后都不能有空格,否则重启服务会起不来的,且日志也不会提示明显的错误点在哪里。

测试1,用tcpdump抓包,把vsftpd配置成不启用ssl来抓21端口的报文,然后记录到一个文件中

[root@test certs]#tcpdump -i enp2s0 -nn -x port 21 &> xx.txt
[root@test certs]#cat xx.txt |grep -i user
23:29:44.168817 IP 192.168.0.151.42304 > 192.168.0.99.21: Flags [P.], seq 1:14, ack 21, win 115, options [nop,nop,TS val 5044219 ecr 185815506], length 13: FTP: USER qiuhom
[root@test certs]#cat xx.txt |grep -i pass
23:29:44.169050 IP 192.168.0.99.21 > 192.168.0.151.42304: Flags [P.], seq 21:55, ack 14, win 227, options [nop,nop,TS val 185819003 ecr 5044219], length 34: FTP: 331 Please specify the password.
23:29:45.560826 IP 192.168.0.151.42304 > 192.168.0.99.21: Flags [P.], seq 14:26, ack 55, win 115, options [nop,nop,TS val 5045611 ecr 185819003], length 12: FTP: PASS admin
[root@test certs]#

  说明:可以看到在不启用加密的情况下,用户名和密码就很容易的被别人抓包获取,从而泄漏用户名和密码。

测试2,把vsftpd配置成启用ssl,然后再来抓21端口的报文,然后记录到一个文件中

[root@test certs]#tcpdump -i enp2s0 -nn -x port 21 &> yy.txt
^C[root@test certs]#grep -i "user" yy.txt 
[root@test certs]#grep -i "pass" yy.txt     
[root@test certs]#

  说明:可以看到加密后的报文我们是抓不到user和pass的字样

用filezilla等工具测试

  配置好vsftpd支持ssl加密后重启vsftpd后用filezilla工具连接它就会弹出一个证书信息,让你确认如下所示

 说明:从证书上看,可看到我们刚才在自签证书上填写的内容,我们必须要信任了证书才可登录到服务器,也可以选择以后始终信任,这样以后再连接服务器就不会提示这个证书了内容让我们确认

  七、vsftpd虚拟用户

  虚拟用户:

    所有的虚拟用户会统一映射为一个指定的系统帐号:访问共享位置,即为此系统帐号的家目录,各个虚拟账号可以被赋予不同的访问权限,通过匿名用户的权限控制参数进行指定

  实现虚拟用户帐号的储存方式:文件

  1)编辑文本文件,此文件需要被编码为hash格式,并且奇数行为用户名,偶数行为密码。

[root@test vsftpd]#getent passwd tom
[root@test vsftpd]#getent passwd jerry
[root@test vsftpd]#cat >> vuser.txt << EOF
> tom
> admin
> jerry
> admin123
> EOF
[root@test vsftpd]#cat vuser.txt
tom
admin
jerry
admin123
[root@test vsftpd]#

  2)准备用户数据库文件

[root@test vsftpd]#db_load -T -t hash -f vuser.txt vuser.db
[root@test vsftpd]#ll vuser*
-rw-r--r-- 1 root root    25 12月 27 23:51 vuser.txt
-rw-r--r-- 1 root root 12288 12月 27 23:52 vuser.db
[root@test vsftpd]#

  说明:为了安全,建议将存放用户用户名和密码的数据库文件权限修改成600

  3)创建被映射到用户和访问FTP目录

root@test vsftpd]#useradd -d /var/ftpboot/ -s /sbin/nologin vuser
[root@test vsftpd]#getent passwd vuser
vuser:x:1005:1005::/var/ftpboot/:/sbin/nologin
[root@test vsftpd]#chmod +rx /var/ftpboot/
[root@test vsftpd]#ll /var/ftpboot/ -d
dr-xr-xr-x 4 vuser vuser 127 12月 28 00:40 /var/ftpboot/
[root@test vsftpd]#chmod -w /var/ftpboot/
[root@test vsftpd]#mkdir /var/ftpboot/upload
[root@test vsftpd]#setfacl -m u:vuser:rwx /var/ftpboot/upload
[root@test vsftpd]#

  说明:此帐号只用作虚拟账户映射成登录ftp系统的本地账号,所以应该把shell类型给设置成/sbin/nologin类型,况且家目录要把写的权限给去掉,因为ftp服务器不允许在根目录下对用户有写的权限。在其用户的家目录建立一个可读写的目录是方便用户上传数据

  4)创建pam配置文件

[root@test vsftpd]#cat >> /etc/pam.d/vsftpd.db << EOF
> auth required pam_userdb.so db=/etc/vsftpd/vuser
> account required pam_userdb.so db=/etc/vsftpd/vuser
> EOF
[root@test vsftpd]#cat /etc/pam.d/vsftpd.db 
auth required pam_userdb.so db=/etc/vsftpd/vuser
account required pam_userdb.so db=/etc/vsftpd/vuser
[root@test vsftpd]#

  说明:配置文件中的模块使用方法可以通过man pam_userdb 来查看pam_userdb这个模块的用法

  5)在/etc/vsftpd/vsftpd.conf中指定pam的配置文件,以及开启guest用户,并指定其映射成vuser

[root@test vsftpd]#grep "guest" /etc/vsftpd/vsftpd.conf
[root@test vsftpd]#grep "pam" /etc/vsftpd/vsftpd.conf
pam_service_name=vsftpd
[root@test vsftpd]#sed -i 's@pam_service_name=vsftpd@pam_service_name=vsftpd.db@' /etc/vsftpd/vsftpd.conf
[root@test vsftpd]#sed ^C
[root@test vsftpd]#grep "pam" /etc/vsftpd/vsftpd.conf
pam_service_name=vsftpd.db
[root@test vsftpd]#cat >> /etc/vsftpd/vsftpd.conf << EOF
> guest_enable=YES
> guest_username=vuser
> EOF
[root@test vsftpd]#grep "guest" /etc/vsftpd/vsftpd.conf
guest_enable=YES
guest_username=vuser
[root@test vsftpd]#

  说明:在做以上实验先禁用selinux,若没有禁用selinux ,还需要执行setsebool -P ftpd_full_access 1 

  6)创建虚拟用户独立的配置文件

[root@test vsftpd]#mkdir /etc/vsftpd/vusers.d/
[root@test vsftpd]#grep "user_config_dir" /etc/vsftpd/vsftpd.conf
[root@test vsftpd]#cat >> /etc/vsftpd/vsftpd.conf << EOF
> user_config_dir=/etc/vsftpd/vusers.d/
> EOF
[root@test vsftpd]#grep "user_config_dir" /etc/vsftpd/vsftpd.conf
user_config_dir=/etc/vsftpd/vusers.d/
[root@test vsftpd]#cat >> /etc/vsftpd/vusers.d/tom << EOF
> anon_upload_enable=YES
> anon_mkdir_write_enable=YES
> anon_other_write_enable=YES
> EOF
[root@test vsftpd]#cat >> /etc/vsftpd/vusers.d/jerry << EOF
> local_root=/var/ftp
> EOF
[root@test vsftpd]#cat /etc/vsftpd/vusers.d/tom 
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
[root@test vsftpd]#cat /etc/vsftpd/vusers.d/jerry 
local_root=/var/ftp
[root@test vsftpd]#

  说明:以上分别给tom可以自由下载上传的权限,给jerry赋予登录ftp改变其指定的目录的权限。这里需要注意一点就是用户的授权文件必须同虚拟用户的名称相同。至此基于文件存放验证vsftpd的虚拟用户的实现就到此结束了,接下来就是测试我们新建的两个虚拟用户是否可登录系统,以及登录系统后的权限

测试:

  重启服务,并在/var/ftp/目录下建立一个varftp_dir文件,在/var/ftpboot/下创建一个名为vuser_home,以示区分两个不同的目录,并在var/ftpboot目录下存放一个测试的下载文件

[root@test vsftpd]#systemctl restart vsftpd
[root@test vsftpd]#touch /var/ftp/varftp_dir 
[root@test vsftpd]#touch /var/ftpboot/vuser_home 
[root@test vsftpd]#cp /etc/fstab /var/ftpboot/test_file
[root@test vsftpd]#ll /var/ftp/
总用量 0
drwxr-xr-x 2 root root 21 10月 31 2018 pub
-rw-r--r-- 1 root root  0 12月 28 00:39 varftp_dir
[root@test vsftpd]#ll /var/ftpboot/
总用量 4
-rw-r--r--  1 root root 552 12月 28 00:40 test_file
drwxrwxr-x+ 2 root root   6 12月 28 00:04 upload
-rw-r--r--  1 root root   0 12月 28 00:39 vuser_home
[root@test vsftpd]#

  测试tom用户是否可以正常登录,登录后是否可以正常上传和下载文件

[root@test vsftpd]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): tom
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,99,220,156).
150 Here comes the directory listing.
-rw-r--r--    1 0        0             552 Dec 27 16:40 test_file
drwxrwxr-x    2 0        0               6 Dec 27 16:04 upload
-rw-r--r--    1 0        0               0 Dec 27 16:39 vuser_home
226 Directory send OK.
ftp> pwd
257 "/"
ftp> !ls
ftpusers  user_list  vsftpd.conf  vsftpd.conf.bak  vsftpd_conf_migrate.sh  vuser.db  vusers.d  vuser.txt
ftp> lcd /root
Local directory now /root
ftp> !ls
bak  fstab
ftp> get test_file
local: test_file remote: test_file
227 Entering Passive Mode (192,168,0,99,99,53).
150 Opening BINARY mode data connection for test_file (552 bytes).
226 Transfer complete.
552 bytes received in 9.6e-05 secs (5750.00 Kbytes/sec)
ftp> cd upload
250 Directory successfully changed.
ftp> put fstab 
local: fstab remote: fstab
227 Entering Passive Mode (192,168,0,99,254,231).
150 Ok to send data.
226 Transfer complete.
552 bytes sent in 0.000136 secs (4058.82 Kbytes/sec)
ftp> bye
221 Goodbye.
[root@test vsftpd]#

  说明:用tom用户登录ftp系统可正常的上传下载文件

  测试jerry登录是否在/var/ftp目录下

[root@test vsftpd]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): jerry
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,99,100,79).
150 Here comes the directory listing.
drwxr-xr-x    2 0        0              21 Oct 30  2018 pub
-rw-r--r--    1 0        0               0 Dec 27 16:39 varftp_dir
226 Directory send OK.
ftp> bye
221 Goodbye.
[root@test vsftpd]#ll /var/ftp
总用量 0
drwxr-xr-x 2 root root 21 10月 31 2018 pub
-rw-r--r-- 1 root root  0 12月 28 00:39 varftp_dir
[root@test vsftpd]#

  说明:可看到jerry和tom登录到系统不是同一个目录。

  实现虚拟用户帐号的储存方式:mysql

  1)实验环境

  centos6:ip 192.168.0.218 mysql数据库服务器

  centos7:ip 192.168.0.99 vsftpd服务器

  2)安装所需要的包和包组

  centos6上安装mysql-server 并启动mysql数据库

[root@ansible_centos6 ~]# yum install -y mysql-server
Loaded plugins: fastestmirror, refresh-packagekit, security
Setting up Install Process
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.163.com
 * updates: mirrors.cn99.com
base                                                                       | 3.7 kB     00:00     
epel                                                                       | 5.3 kB     00:00     
epel/primary_db                                                            | 6.1 MB     00:01     
extras                                                                     | 3.4 kB     00:00     
updates                                                                    | 3.4 kB     00:00     
updates/primary_db                                                         | 8.0 MB     00:02     
Resolving Dependencies
--> Running transaction check
---> Package mysql-server.x86_64 0:5.1.73-8.el6_8 will be installed
--> Processing Dependency: mysql = 5.1.73-8.el6_8 for package: mysql-server-5.1.73-8.el6_8.x86_64
--> Processing Dependency: perl-DBI for package: mysql-server-5.1.73-8.el6_8.x86_64
--> Processing Dependency: perl-DBD-MySQL for package: mysql-server-5.1.73-8.el6_8.x86_64
--> Processing Dependency: perl(DBI) for package: mysql-server-5.1.73-8.el6_8.x86_64
--> Running transaction check
---> Package mysql.x86_64 0:5.1.73-8.el6_8 will be installed
---> Package perl-DBD-MySQL.x86_64 0:4.013-3.el6 will be installed
---> Package perl-DBI.x86_64 0:1.609-4.el6 will be installed
--> Finished Dependency Resolution

Dependencies Resolved

==================================================================================================
 Package                    Arch               Version                     Repository        Size
==================================================================================================
Installing:
 mysql-server               x86_64             5.1.73-8.el6_8              base             8.6 M
Installing for dependencies:
 mysql                      x86_64             5.1.73-8.el6_8              base             895 k
 perl-DBD-MySQL             x86_64             4.013-3.el6                 base             134 k
 perl-DBI                   x86_64             1.609-4.el6                 base             705 k

Transaction Summary
==================================================================================================
Install       4 Package(s)

Total download size: 10 M
Installed size: 29 M
Downloading Packages:
(1/4): mysql-5.1.73-8.el6_8.x86_64.rpm                                     | 895 kB     00:00     
(2/4): mysql-server-5.1.73-8.el6_8.x86_64.rpm                              | 8.6 MB     00:01     
(3/4): perl-DBD-MySQL-4.013-3.el6.x86_64.rpm                               | 134 kB     00:00     
(4/4): perl-DBI-1.609-4.el6.x86_64.rpm                                     | 705 kB     00:00     
--------------------------------------------------------------------------------------------------
Total                                                             5.5 MB/s |  10 MB     00:01     
Running rpm_check_debug
Running Transaction Test
Transaction Test Succeeded
Running Transaction
  Installing : perl-DBI-1.609-4.el6.x86_64                                                    1/4 
  Installing : perl-DBD-MySQL-4.013-3.el6.x86_64                                              2/4 
  Installing : mysql-5.1.73-8.el6_8.x86_64                                                    3/4 
  Installing : mysql-server-5.1.73-8.el6_8.x86_64                                             4/4 
  Verifying  : perl-DBD-MySQL-4.013-3.el6.x86_64                                              1/4 
  Verifying  : mysql-server-5.1.73-8.el6_8.x86_64                                             2/4 
  Verifying  : mysql-5.1.73-8.el6_8.x86_64                                                    3/4 
  Verifying  : perl-DBI-1.609-4.el6.x86_64                                                    4/4 

Installed:
  mysql-server.x86_64 0:5.1.73-8.el6_8                                                            

Dependency Installed:
  mysql.x86_64 0:5.1.73-8.el6_8 perl-DBD-MySQL.x86_64 0:4.013-3.el6 perl-DBI.x86_64 0:1.609-4.el6

Complete!
[root@ansible_centos6 ~]# /etc/init.d/mysqld start
Initializing MySQL database:  WARNING: The host 'ansible_centos6' could not be looked up with resolveip.
This probably means that your libc libraries are not 100 % compatible
with this binary MySQL version. The MySQL daemon, mysqld, should work
normally with the exception that host name resolving will not work.
This means that you should use IP addresses instead of hostnames
when specifying MySQL privileges !
Installing MySQL system tables...
OK
Filling help tables...
OK

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

PLEASE REMEMBER TO SET A PASSWORD FOR THE MySQL root USER !
To do so, start the server, then issue the following commands:

/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h ansible_centos6 password 'new-password'

Alternatively you can run:
/usr/bin/mysql_secure_installation

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:
cd /usr ; /usr/bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl
cd /usr/mysql-test ; perl mysql-test-run.pl

Please report any problems with the /usr/bin/mysqlbug script!

                                                           [  OK  ]
Starting mysqld:                                           [  OK  ]
[root@ansible_centos6 ~]# ss -ntl |grep 3306
LISTEN     0      50                        *:3306                     *:*     
[root@ansible_centos6 ~]# 

  在数据库里建立存储虚拟用户数据库和连接的数据库用户

[root@ansible_centos6 ~]# mysql
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.1.73 Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
+--------------------+
3 rows in set (0.00 sec)

mysql> create database vsftpd;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| test               |
| vsftpd             |
+--------------------+
4 rows in set (0.01 sec)

mysql> grant select on vsftpd.* to vsftpd@'%' identified by 'admin123.com';
Query OK, 0 rows affected (0.00 sec)

mysql> 

  在vsftpd库里创建存储虚拟用户用户名和密码的表

mysql> use vsftpd                                 
Database changed
mysql> show tables;                               
Empty set (0.00 sec)

mysql> create table users(
    -> id int auto_increment not null primary key,
    -> name char(50) binary not null,
    -> password char(48) binary not null);
Query OK, 0 rows affected (0.02 sec)

mysql> desc users;
+----------+----------+------+-----+---------+----------------+
| Field    | Type     | Null | Key | Default | Extra          |
+----------+----------+------+-----+---------+----------------+
| id       | int(11)  | NO   | PRI | NULL    | auto_increment |
| name     | char(50) | NO   |     | NULL    |                |
| password | char(48) | NO   |     | NULL    |                |
+----------+----------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

mysql> 

  说明:name和password两个字段分别用binary修饰,表示此字段存储的内容区分大小写,若不用binary 则不区分大小写

  在vsftpd服务器上测试创建的连接数据库的用户是否可以正常连接

[root@test vsftpd]#mysql -uvsftpd -h192.168.0.218 -p
Enter password: 
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 5
Server version: 5.1.73 Source distribution

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| test               |
| vsftpd             |
+--------------------+
3 rows in set (0.00 sec)

MySQL [(none)]> use vsftpd
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
MySQL [vsftpd]> show tables;
+------------------+
| Tables_in_vsftpd |
+------------------+
| users            |
+------------------+
1 row in set (0.00 sec)

MySQL [vsftpd]> desc users;
+----------+----------+------+-----+---------+----------------+
| Field    | Type     | Null | Key | Default | Extra          |
+----------+----------+------+-----+---------+----------------+
| id       | int(11)  | NO   | PRI | NULL    | auto_increment |
| name     | char(50) | NO   |     | NULL    |                |
| password | char(48) | NO   |     | NULL    |                |
+----------+----------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

MySQL [vsftpd]>

  说明:到此数据库服务器上的配置就基本完成

  centos7 vsftpd服务器上安装pam_mysql

[root@test ~]#yum info pam_mysql
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
错误:没有匹配的软件包可以列出

  说明:centos7上没有找到pam_mysql,这个就需要我们去网上找源码包编译安装了

  编译pam_mysql-0.7RC1.tar.gz,说到Linux里的编译安装我们不难就想起来三大步骤,configure,make,make install,在编译前我们还需要注意我们的编译环境是否准备好了,基础的编译开发包是否都安装了

  安装编译环境说依赖的包组和包

yum -y groupinstall "Development Tools"
yum -y install mariadb-devel pam-devel

  上传源码包,解压,进行编译

[root@test ~]#rz
rz waiting to receive.
 zmodem trl+C ȡ

  100%     327 KB  327 KB/s 00:00:01       0 Errorsz...

[root@test ~]#ls
bak  fstab  pam_mysql-0.7RC1.tar.gz  test_file
[root@test ~]#tar xf pam_mysql-0.7RC1.tar.gz 
[root@test ~]#cd pam_mysql-0.7RC1/
[root@test pam_mysql-0.7RC1]#./configure --with-pam-mods-dir=/lib64/security 

  说明:编译选项 就只需要指定模块的存放位置即可,pam相关的模块存放路径都是lib64/security目录下

  ./configure 没有任何错误提示后,就可以make && make install 

[root@test pam_mysql-0.7RC1]#make && make install
/bin/sh ./libtool --mode=compile gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/security -I/usr/include  -g -O2  -g -O2 -I/usr/include/mysql    -c pam_mysql.c
mkdir .libs
 gcc -DHAVE_CONFIG_H -I. -I. -I. -I/usr/include/security -I/usr/include -g -O2 -g -O2 -I/usr/include/mysql -c pam_mysql.c  -fPIC -DPIC -o .libs/pam_mysql.o
pam_mysql.c: In function 'pam_mysql_converse':
pam_mysql.c:3192:4: warning: passing argument 2 of 'conv->conv' from incompatible pointer type [enabled by default]
    conv->appdata_ptr))) {
    ^
pam_mysql.c:3192:4: note: expected 'const struct pam_message **' but argument is of type 'struct pam_message **'
/bin/sh ./libtool --mode=link gcc  -g -O2 -I/usr/include/mysql     -o pam_mysql.la -rpath /lib64/security -module -avoid-version pam_mysql.lo  -L/usr/lib64/mysql -lmysqlclient -lpthread -lz -lm -ldl -lssl -lcrypto    -lcrypt
gcc -shared  .libs/pam_mysql.o  -L/usr/lib64/mysql -lmysqlclient -lpthread -lz -lm -ldl -lssl -lcrypto -lcrypt  -Wl,-soname -Wl,pam_mysql.so -o .libs/pam_mysql.so
creating pam_mysql.la
(cd .libs && rm -f pam_mysql.la && ln -s ../pam_mysql.la pam_mysql.la)
make[1]: 进入目录“/root/pam_mysql-0.7RC1”
/bin/sh ./mkinstalldirs /lib64/security
/bin/sh ./libtool  --mode=install /bin/install -c pam_mysql.la /lib64/security/pam_mysql.la
/bin/install -c .libs/pam_mysql.so /lib64/security/pam_mysql.so
/bin/install -c .libs/pam_mysql.lai /lib64/security/pam_mysql.la
PATH="$PATH:/sbin" ldconfig -n /lib64/security
----------------------------------------------------------------------
Libraries have been installed in:
   /lib64/security

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,--rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
make[1]: 对“install-data-am”无需做任何事。
make[1]: 离开目录“/root/pam_mysql-0.7RC1”
[root@test pam_mysql-0.7RC1]#

  说明:到此pam_mysql就编译安装好了,接下来就需要看,源码包里的README文件,看看模块的用法

[root@test pam_mysql-0.7RC1]#less README 
pam_mysql - A PAM authentication module against MySQL database.
$Id: README,v 1.8.2.9 2006/01/09 10:35:59 moriyoshi Exp $

Introduction
------------
This is a successor of the "old" pam_mysql module, which comes with
a more stable, secure and robust implementation.

Prerequisites
-------------
To try this module, you need the following stuff:
 - A *NIX (or similar) system, in which PAM facility is set up and working
   either system-wide or in a chroot jail.
 - A MySQL server, up and running.

Installation instruction
------------------------
See INSTALL file for detail.

An example of the configuration file:
---------------------------------------------------------------
auth       optional     pam_mysql.so user=root passwd=password
account    required     pam_mysql.so user=root passwd=password
---------------------------------------------------------------

Available options
-----------------
The module options are listed below with default in ()s:

verbose (0)

    If set to 1, produces logs with detailed messages that describes what
    PAM-MySQL is doing. May be useful for debugging.

debug

    An alias for the verbose option. This is added in 0.7pre2.

user

    The user name used to open the specified MySQL database.

passwd

    The password used to open the specified MySQL database.

host

    The host name or the absolute path to the unix socket where the
        MySQL server is listening.  The following formats are accepted:

    1. absolute path to the unix socket (e.g. "/tmp/mysql.sock")
        2. host name (e.g. "somewhere.example.com")
        3. host name + port number (e.g. "somewhere.example.com:3306")

db

    The name of the database that contains a user-password table.

table

    The name of table that maps unique login names to the passwords.
    This can be a combination of tables with full JOIN syntax if you
    need more control.  For example:

        [table=Host LEFT JOIN HostUser ON HostUser.host_id=Host.id \
                    LEFT JOIN User ON HostUser.user_id=User.id]

update_table

    The name of the table used for password alteration.
    If not defined, the value of the "table" option will be used instead.
    This is handy if you have a complex JOIN instead of a simple table in
    the "table" option above.

usercolumn

    The name of the column that contains a unix login name.
    Should be in a fully qualified form.

passwdcolumn

    The name of the column that contains a (encrypted) password string.
    Should be in a fully qualified form.

statcolumn

    The name of the column or an SQL expression that indicates the status of
    the user. The status is expressed by the combination of two bitfields
    shown below:

    bit 0 (0x01): if flagged, pam_mysql deems the account to be expired and
                  returns PAM_ACCT_EXPIRED. That is, the account is supposed
                  to no longer be available. Note this doesn't mean that
                  pam_mysql rejects further authentication operations.

    bit 1 (0x02): if flagged, pam_mysql deems the authentication token
                  (password) to be expired and returns PAM_NEW_AUTHTOK_REQD.
                  This ends up requiring that the user enter a new password.

    This option is available since 0.6.

crypt (plain)

    The method to encrypt the user's password:

       0 (or "plain") = No encryption.  Passwords stored in plaintext.
                        HIGHLY DISCOURAGED.

       1 (or "Y")     = Use crypt(3) function.

       2 (or "mysql") = Use MySQL PASSWORD() function. It is possible
                        that the encryption function used by PAM-MySQL
                        is different from that of the MySQL server, as
                        PAM-MySQL uses the function defined in MySQL's
                        C-client API instead of using PASSWORD() SQL function
                        in the query.
                        
       3 (or "md5")   = Use plain hex MD5.

       4 (or "sha1")  = Use plain hex SHA1.

  说明:从上面的信息我们可以了解到pam_mysql.so的用法就是传给模块几个参数,其中user指定其连接数据库服务器的用户名,passwd指定连接数据库用户名的密码,host是指定mysql服务器地址,db指定数据库名,table指定存放虚拟用户的表名,usercolumn指定存放虚拟用户名单字段名称,passwdcolumn指定存放虚拟用户密码字段名称 ,crypt指定加密类型,其中crypt=2表示存放使用mysql password()函数加密后的密码。接下来编写vsftpd基于mysql验证的配置文件

  创建vsftpd调用pam_mysql的配置文件

[root@test pam_mysql-0.7RC1]#cat /etc/pam.d/vsftpd.mysql
auth required pam_mysql.so user=vsftpd passwd=admin123.com host=192.168.0.218 db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=2
account required pam_mysql.so user=vsftpd passwd=admin123.com host=192.168.0.218 db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=2
[root@test pam_mysql-0.7RC1]#

  说明:pam的配置文件格式大致有4个部分,第一部分是工作类别,比如auth表示认证,account表示验证账号密码正常使用;第二部分是控制模式,用于模块在给出各种结果时pam的行为,required表示认证通过;第三部分是模块名称或路径 ;第四部分是模块的参数;综合这四部分它表达的综合意思是,如果本条目验证通过则验证下面的条目,若不通过则验证最终结果是失败的,但是它还会验证下面的条目,这就是刚才说的第二部分控制模式required,也就说要想验证通过,必须满足此条目。它有一片否决权,但不会打断向下继续验证的流程。

  修改vsftpd配置文件,指定pam的配置文件为vsftpd.mysql

[root@test pam_mysql-0.7RC1]#grep "pam" /etc/vsftpd/vsftpd.conf
pam_service_name=vsftpd.db
[root@test pam_mysql-0.7RC1]#sed -i 's@pam_service_name=vsftpd.db@pam_service_name=vsftpd.mysql@' /etc/vsftpd/vsftpd.conf
[root@test pam_mysql-0.7RC1]#grep "pam" /etc/vsftpd/vsftpd.conf
pam_service_name=vsftpd.mysql
[root@test pam_mysql-0.7RC1]#

  说明:此实验是接着上面的基于文件存放虚拟用户的基础上修改配置来完成对,若不是,还需要创建一个映射到系统用户账号,还要在配置文件中配置启动guest ,guest账号映射成创建的那个账号, 还要更改创建用户的家目录不能有写的权限,在其目录下创建一个目录,让其映射到系统用户有写权限。这些步骤都需要去做。

  重启vsftpd服务,查看服务是否启动起来

[root@test pam_mysql-0.7RC1]#systemctl restart vsftpd
[root@test pam_mysql-0.7RC1]#ss -ntl
State      Recv-Q Send-Q                         Local Address:Port                                        Peer Address:Port              
LISTEN     0      100                                127.0.0.1:25                                                     *:*                  
LISTEN     0      25                                         *:514                                                    *:*                  
LISTEN     0      128                                        *:41319                                                  *:*                  
LISTEN     0      50                                         *:3306                                                   *:*                  
LISTEN     0      100                                      ::1:25                                                    :::*                  
LISTEN     0      25                                        :::514                                                   :::*                  
LISTEN     0      128                                       :::41319                                                 :::*                  
LISTEN     0      128                                       :::80                                                    :::*                  
LISTEN     0      32                                        :::21                                                    :::*                  
[root@test pam_mysql-0.7RC1]#

  说明:可以看到21号端口已经起来了,说明vsftpd的配置文件没有问题。

  在数据库服务器上添加虚拟账号

mysql> desc users;
+----------+----------+------+-----+---------+----------------+
| Field    | Type     | Null | Key | Default | Extra          |
+----------+----------+------+-----+---------+----------------+
| id       | int(11)  | NO   | PRI | NULL    | auto_increment |
| name     | char(50) | NO   |     | NULL    |                |
| password | char(48) | NO   |     | NULL    |                |
+----------+----------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> insert users(name,password) values('user1',password('admin1')),('user2',password('admin2'));
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from users;
+----+-------+-------------------------------------------+
| id | name  | password                                  |
+----+-------+-------------------------------------------+
|  1 | user1 | *6D45FD76D5E9C6A404E39C25106A7F032659ACB8 |
|  2 | user2 | *0E6FD44C7B722784DAE6E67EF8C06FB1ACB3E0A6 |
+----+-------+-------------------------------------------+
2 rows in set (0.00 sec)

mysql> 

  说明:因为我们zai/etc/pam.d/vsftpd.mysql配置文件中写的加密方式是用mysql的password()函数加密密码,所以我们在插入密码口令是一定要调用password()函数来加密我们的口令,否则比对口令时不会通过

  到此vsftpd的虚拟用户已经实现存放到mysql里,接下来我们就可以用我们创建的user1和user2用户登录ftp服务器

[root@test ~]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): user1
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,99,251,38).
150 Here comes the directory listing.
-rw-r--r--    1 0        0             552 Dec 27 16:40 test_file
drwxrwxr-x    2 0        0              19 Dec 27 16:58 upload
-rw-r--r--    1 0        0               0 Dec 27 16:39 vuser_home
226 Directory send OK.
ftp> bye
221 Goodbye.
[root@test ~]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): user2
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,99,163,148).
150 Here comes the directory listing.
-rw-r--r--    1 0        0             552 Dec 27 16:40 test_file
drwxrwxr-x    2 0        0              19 Dec 27 16:58 upload
-rw-r--r--    1 0        0               0 Dec 27 16:39 vuser_home
226 Directory send OK.
ftp> bye
221 Goodbye.
[root@test ~]#

  说明:可看到我们新建两个虚拟账号是可以正常登录到ftp系统,但是它俩的权限似乎都是一致的,登录都是同一目录下。

  修改user1 user2的权限

[root@test ~]#ll /etc/vsftpd/vusers.d/
总用量 8
-rw-r--r-- 1 root root 20 12月 28 00:27 jerry
-rw-r--r-- 1 root root 79 12月 28 00:26 tom
[root@test ~]#cat >> /etc/vsftpd/vusers.d/user1 << EOF
> anon_upload_enable=YES
> anon_mkdir_write_enable=YES
> anon_other_write_enable=YES
> EOF
[root@test ~]#cat /etc/vsftpd/vusers.d/user1 
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
[root@test ~]#cat >> /etc/vsftpd/vusers.d/user2 << EOF
> local_root=/var/ftp
> EOF
[root@test ~]#cat /etc/vsftpd/vusers.d/user2 
local_root=/var/ftp

  测试:

  用user1登录ftp服务器,上传和下载文件

[root@test ~]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): user1
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,99,209,0).
150 Here comes the directory listing.
-rw-r--r--    1 0        0             552 Dec 27 16:40 test_file
drwxrwxr-x    2 0        0              29 Dec 27 19:06 upload
-rw-r--r--    1 0        0               0 Dec 27 16:39 vuser_home
226 Directory send OK.
ftp> get test_file
local: test_file remote: test_file
227 Entering Passive Mode (192,168,0,99,33,135).
150 Opening BINARY mode data connection for test_file (552 bytes).
226 Transfer complete.
552 bytes received in 0.000111 secs (4972.97 Kbytes/sec)
ftp> !ls
bak  pam_mysql-0.7RC1  pam_mysql-0.7RC1.tar.gz  test_file
ftp> cd upload
250 Directory successfully changed.
ftp> ls
227 Entering Passive Mode (192,168,0,99,33,221).
150 Here comes the directory listing.
-rw-------    1 1005     1005          552 Dec 27 16:58 fstab
-rw-------    1 1005     1005       117680 Dec 27 19:06 ls
226 Directory send OK.
ftp> put pam_mysql-0.7RC1.tar.gz 
local: pam_mysql-0.7RC1.tar.gz remote: pam_mysql-0.7RC1.tar.gz
227 Entering Passive Mode (192,168,0,99,189,142).
150 Ok to send data.
226 Transfer complete.
335240 bytes sent in 0.00172 secs (194342.03 Kbytes/sec)
ftp> ls
227 Entering Passive Mode (192,168,0,99,196,23).
150 Here comes the directory listing.
-rw-------    1 1005     1005          552 Dec 27 16:58 fstab
-rw-------    1 1005     1005       117680 Dec 27 19:06 ls
-rw-------    1 1005     1005       335240 Dec 27 19:12 pam_mysql-0.7RC1.tar.gz
226 Directory send OK.
ftp> 

  说明:可看到user1可以正常的上传和下载,当然上传下载还关系到对应的文件系统是否有读写权限,这个还要结合到其他选项的配置。

  用user2登录ftp服务器,查看所在的目录和user1是否相同

[root@test ~]#ftp 192.168.0.99
Connected to 192.168.0.99 (192.168.0.99).
220 (vsFTPd 3.0.2)
Name (192.168.0.99:root): user2
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (192,168,0,99,214,69).
150 Here comes the directory listing.
drwxr-xr-x    2 0        0              21 Oct 30  2018 pub
-rw-r--r--    1 0        0               0 Dec 27 16:39 varftp_dir
226 Directory send OK.
ftp> bye
221 Goodbye.
[root@test ~]#ll /var/ftp/
总用量 0
drwxr-xr-x 2 root root 21 10月 31 2018 pub
-rw-r--r-- 1 root root  0 12月 28 00:39 varftp_dir
[root@test ~]#

  说明:和上面user1登录的目录里的文件可以判断user1和user2登录到ftp服务器后,不是在同一个目录里,user1登录的是vuser的家目录/var/ftpboot/,而user2登录到ftp系统的目录是/var/ftp

posted @ 2019-12-28 03:20  Linux-1874  阅读(4752)  评论(0编辑  收藏  举报