FTP协议和vsftpd

文件共享服务 – 应用层的FTP, 工作在内核的nfs(难以跨平台), 跨平台的文件服务samba(在Linux上实现SMB).

先来说说我们的存储模型有哪些呢? DAS, NAS, SAN. 我们所使用的磁盘其实就是DAS模型, 而NAS其实就是专门用作存储的设备, 其内核对SAMBA, NFS等有特别的优化. 至于SAN, 他和NAS的区别就在于他是基于块的存储, 而NAS是基于文件共享的.

FTP协议

FTP的全称是(File Transfer Protocol), 也就是文件传输协议. 基于应用层协议来实现. 是一个C/S架构的协议. FTP是使用Socket进行的通信, 所以那也就会有端口的绑定. 但是FTP的连接却不像其他的服务一样(只监听一个端口), 它首先监听了21号端口. 但是FTP是很复杂的协议, 起码和HTTP协议比起来是复杂了很多. 因为它涉及到很多文件的管理功能. 例如创建, 改变权限, 复制, 移动等等. 所以他需要很多很多命令. 这样FTP就需要传输两类命令, 或者说两种数据:

  • 命令连接: 用来进行命令的传输
  • 数据连接: 用来传输用户所请求的上传和下载文件, 按需创建和关闭连接

当客户端想要进行访问FTP服务端的时候, 它先将请求发送到服务器端的21号端口. 鉴于之前说过的FTP需要传输两种数据. 所以他需要在接收到客户端命令之后(例如, 下载一个文件)从磁盘上获取, 接着另起一个连接. 这个连接和之前的session已经不是一样的了. 所以他需要再次通过一个套接字将数据发送. 发送结束之后, 结束这个新的Session.

同HTTP协议一样, FTP在传输非文本数据的时候也有问题, 例如图片, 如果启用字符传输机制, 对方可能看到的是一堆乱码. 而如果使用的是二进制的传输形式, 对方可能无法理解得到的结果. 所以FTP既支持文本传输也支持二进制传输格式, 这个是依靠传输数据的格式来判断的.

另外, FTP有个麻烦的模式: 主动和被动. 之所有会有这个, 是因为客户端请求下载一个文件的时候, 我们说需要一个新的数据连接, 这个连接谁来创建? 如果是服务器端, 这就是主动模式. 但是这个是存在一个问题的, 服务器端主动发送请求, 但是我们都知道一次连接是需要知道对方打开的端口是多少的. 这个时候客户端是随机的端口, 服务端怎么发送请求?

所以, 其实在主动模式下, 客户端选择一个随机端口. 连接服务器端的21号端口. 接着服务器端会将自己的20号端口去和客户端的随机端口+1的那个端口建立连接, 如果被占用就继续加一. 后者的这个连接上就是数据传输通道, 而前者就是命令传输端口. 其实在一开始命令连接的时候 客户端也会告诉服务器端, 自己打开的端口是哪一个.

然而, 这样是有很大的安全隐患的. 因为我们知道客户端主动打开了一个端口等着我, 如果加以构造, 服务端是可以随意向客户端发送数据的. 所以客户端是需要防火墙的, 但是这又出现了问题, 我们怎么知道开启那个端口使得服务端连接过来呢?

这么麻烦, 所以催生了后来的被动模式, 不管是命令还是数据传输都有客户端来负责建立连接. 这样客户端使用一个随机端口连接到服务器端的21端口, 接着再有客户端连接到20端口发起数据传输请求. 接着就可以将服务器端的随机端口托付过来传输数据就行了. 服务端发送过来端口形式是XXX,XX这样的形式 这个是需要进行计算的: XXX * 256 + XX.

可是, 服务器端也有防火墙啊? 他怎么知道服务器端的那个随机端口是哪一个呢? 关于这个, 在随后的iptables中在看. ( 连接追踪 )

简单的说说FTP协议, 接下来看看有那些典型的FTP软件:

  • wu-ftpd
  • proftpd
  • pureftpd
  • vsftpd
  • ServU ( Windows )

以上是服务器端, 而客户端也有很多, 例如:

  • wget
  • lftp
  • ftp
  • curl
  • filezilla
  • gftp ( GUI )

FTP协议的响应码

1XX: 信息类的响应码

2XX: 成功类的响应码

3XX: 需要补充信息的状态码

4XX: 客户端错误

**5XX: ** 服务端错误

这个和HTTP的响应码几乎是一样的.

用户认证

现在想想我们之前说过的MySQL, 和FTP有一点像么? 当然他们组织数据的方式是不一样的, MySQl提供的是结构化的数据. 对于用户认证, MySQL提供的验证机制和系统是不一样的, 用户需要提供账号和密码, 这些信息是保存在一个数据表中的. 这种认证方式 我们把这个叫做虚拟用户 . 这个是为了和操作系统其他的资源隔离起来, 更加安全. 此用户仅仅是为了一个特定服务而存在.

与MySQL应用层服务不同的是, FTP协议存在的非常早, 在互联网混沌初开的时候就已经存在了. 早期, FTP使用的是系统用户进行认证. 其实也是因为FTP提供的是系统文件服务, 所以才选择这样的策略 – 关联系统账号.

现在的FTP已经完全支持虚拟用户了. 尽管默认使用的是系统用户, 但是可以非常方便的进行用户认证管理, 另外, 结合之前说过的MySQL, 我们还可以将用户账号信息丢到数据库中( 当然这里说的和mysql.user表是没有什么关系的 ). 这样更方便管理和组织.

Linux上平台独有的一些验证技术, 比如说之前说过的PAM模块, 如果我们的FTP程序使用这个做为用户认证的依赖, 那么移植到Win平台就比较困难. 所以为了通用和跨平台, 就需要FTP程序自我实现验证.

除了我们上面说的系统用户和虚拟用户, 还有一种匿名用户. 其实, 说到底虚拟用户和匿名用户还是系统用户的一个包装, 最终操作都需要系统用户去进行 这是由Linux系统决定的机制.

vsftpd

现在就来说说这个典型的FTP程序, 按照惯例, 安装完了之后我们先看看安装了哪些文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[root@WWW ~]# rpm -ql vsftpd
/etc/logrotate.d/vsftpd
/etc/pam.d/vsftpd
/etc/vsftpd
/etc/vsftpd/ftpusers
/etc/vsftpd/user_list
/etc/vsftpd/vsftpd.conf
/etc/vsftpd/vsftpd_conf_migrate.sh
/usr/lib/systemd/system-generators/vsftpd-generator
/usr/lib/systemd/system/vsftpd.service
/usr/lib/systemd/system/vsftpd.target
/usr/lib/systemd/system/vsftpd@.service
/usr/sbin/vsftpd
...(omitted)
/var/ftp
/var/ftp/pub

首先就看到了我们的日志滚动配置和PAM用户认证配置文件.

接着就是systemd的服务Unit. 主配置文件: /etc/vsftpd/vsftpd.conf

接着还有用户控制配置文件, 以及主程序. 最后的两个路径, 就像是HTTP服务的共享资源目录一样, 匿名用户的资源位置就是这个目录. 其实这个匿名用户就是ftp用户的映射:

1
2
3
4
5
6
[root@WWW ~]# finger ftp
Login: ftp Name: FTP User
Directory: /var/ftp Shell: /sbin/nologin
Never logged in.
No mail.
No Plan.

其实就是家目录.

而虚拟用户就需要我们进行制定映射系统目录了 ( 系统用户的家目录 )

直接启动试试:

1
2
3
4
5
6
7
8
9
[root@WWW ~]# systemctl start vsftpd.service
[root@WWW ~]# ss -antp
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 10 192.168.56.101:53 *:* users:(("named",pid=1035,fd=22))
LISTEN 0 10 127.0.0.1:53 *:* users:(("named",pid=1035,fd=21))
LISTEN 0 128 192.168.56.101:22 *:* users:(("sshd",pid=1004,fd=3))
LISTEN 0 128 127.0.0.1:953 *:* users:(("named",pid=1035,fd=23))
ESTAB 0 52 192.168.56.101:22 192.168.56.1:6533 users:(("sshd",pid=12137,fd=3))
LISTEN 0 32 :::21 :::* users:(("vsftpd",pid=12421,fd=3))

现在服务已经起来了, 我们进入另外一台主机试试:

1
2
3
4
5
6
7
8
9
10
[root@WWW ~]# ftp 192.168.56.101
Connected to 192.168.56.101 (192.168.56.101).
220 (vsFTPd 3.0.2)
Name (192.168.56.101:root): anonymous
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>

我们使用匿名用户账号登录.(也可以使用ftp用户本身) 接着看到了2XX的成功信息:

1
2
3
4
5
ftp> ls
227 Entering Passive Mode (192,168,56,101,159,15).
150 Here comes the directory listing.
drwxr-xr-x 2 0 0 6 Aug 03 06:10 pub
226 Directory send OK.

看到了pub目录, 还有进入了被动模式. 接下来快速的执行两次命令:

1
2
3
4
5
6
7
8
9
10
ftp> ls
227 Entering Passive Mode (192,168,56,101,25,251).
150 Here comes the directory listing.
drwxr-xr-x 2 0 0 6 Aug 03 06:10 pub
226 Directory send OK.
ftp> ls
227 Entering Passive Mode (192,168,56,101,243,212).
150 Here comes the directory listing.
drwxr-xr-x 2 0 0 6 Aug 03 06:10 pub
226 Directory send OK.

端口是一次传输换一个, 另外这个时候快速的回到服务器端查看一下:

1
2
TIME-WAIT   0      0                                     ::ffff:192.168.56.101:62420                                             ::ffff:192.168.56.103:41501              
TIME-WAIT 0 0 ::ffff:192.168.56.101:6651 ::ffff:192.168.56.103:34982

计算一下, 25 * 256 + 251 = 6651, 果然是吧.

可以使用help来查看所有支持的命令.

接下来我们要看看vsftpd的配置文件了.

vsftpd配置

1
2
3
4
anonymous_enable=YES
local_enable=YES
write_enable=YES
local_umask=022

这几项都很好理解吧

我们在FTP服务器上进行一个用户的创建接下来看看:

1
2
3
4
[root@WWW vsftpd]# useradd test
[root@WWW vsftpd]# echo "test" | passwd test --stdin
Changing password for user test.
passwd: all authentication tokens updated successfully.

接着我们在客户端尝试使用test用户进行连接:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[root@WWW ~]# ftp 192.168.56.101
Connected to 192.168.56.101 (192.168.56.101).
220 (vsFTPd 3.0.2)
Name (192.168.56.101:root): test
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pwd
257 "/home/test"
ftp> cd /etc/
250 Directory successfully changed.
ftp> ls
227 Entering Passive Mode (192,168,56,101,170,58).
150 Here comes the directory listing.
-rw-r--r-- 1 0 0 1240 Sep 28 08:40 passwd
drwxr-xr-x 3 0 0 219 Jun 25 12:39 ppp
lrwxrwxrwx 1 0 0 14 Jun 25 02:20 redhat-release -> centos-release
-rw-r--r-- 1 0 0 30 Sep 28 07:47 resolv.conf
---------- 1 0 0 844 Sep 28 08:41 shadow
drwxr-xr-x 3 0 0 54 Jun 25 12:39 udev
drwxr-xr-x 2 0 0 111 Sep 28 08:38 vsftpd
drwxr-xr-x 3 0 0 38 Jun 26 08:13 yum.repos.d
226 Directory send OK.
ftp>

默认的目录会是自己的家目录, 这个我们之前就说过了, 但是, 在这情况下, 客户端可以随意的移动倒其他的目录, FTP是明文传输, 这样实在是太危险了. 所以我们必须把系统用户像匿名用户那样锁在一个目录中, 或者说根切换.

接下来我们按照用户类型看一下配置项:

匿名用户

anonymous_enable=YES
anon_upload_enable=YES 匿名用户能不能进行文件上传
anon_mkdir_write_enable=YES 匿名用户能否创建新目录
anon_other_write_enable=YES 匿名用户能否进行其他写操作

我们打开文件上传选项, 做个试验:

1
2
3
4
ftp> put anaconda-ks.cfg 
local: anaconda-ks.cfg remote: anaconda-ks.cfg
227 Entering Passive Mode (192,168,56,101,30,146).
553 Could not create file.

尽管开启了选项但是似乎没有起到作用?? 其实不是, 如果这个选项没有开启, 收到的信息应该是Permission Denied. 但现在的这个消息说明了什么信息呢?

1
drwxr-xr-x   3 root root    17 Sep 28 02:27 ftp

没错, 是目录权限问题, 那怎么办? 直接修改权限? 肯定不行, 这样的话安全机制就荡然无存了呀, 所以这个时候我们可以这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
[root@WWW ftp]# ls
pub
[root@WWW ftp]# mkdir upload
[root@WWW ftp]# setfacl -m u:ftp:rwx upload/
[root@WWW ftp]# getfacl upload/
# file: upload/
# owner: root
# group: root
user::rwx
user:ftp:rwx
group::r-x
mask::rwx
other::r-x

现在就可以了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@WWW ~]# ftp 192.168.56.101
Connected to 192.168.56.101 (192.168.56.101).
220 (vsFTPd 3.0.2)
Name (192.168.56.101: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,56,101,189,51).
150 Here comes the directory listing.
drwxr-xr-x 2 0 0 6 Aug 03 06:10 pub
drwxrwxr-x 2 0 0 6 Sep 28 08:54 upload
226 Directory send OK.
ftp> cd upload
250 Directory successfully changed.
ftp> put anaconda-ks.cfg
local: anaconda-ks.cfg remote: anaconda-ks.cfg
227 Entering Passive Mode (192,168,56,101,91,5).
150 Ok to send data.
226 Transfer complete.
1249 bytes sent in 0.00625 secs (199.87 Kbytes/sec)

但是:

1
2
ftp> mkdir test
550 Permission denied.

无法创建目录, 这个时候就需要第三个选项了, 允许新建目录.

可是刚把目录创建好, 又遇到了新的问题. 这个上传的文件和目录怎么删除不掉啊!!

这就是第四个选项的功能, 启动之后再试:

1
2
3
4
ftp> rmdir test
250 Remove directory operation successful.
ftp> delete anaconda-ks.cfg
250 Delete operation successful.

就可以了.

以上的这些属性都是比较危险的选项, 开启时候要注意的.

本地用户的配置

local_enable=YES
write_enable=YES
local_umask=022
chroot_local_user=YES
allow_writeable_chroot=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list

关于这些属性的意味我们在实验中展示: [ 前三个就省略了, 看看都明白了 ]

1
2
3
4
5
6
7
8
9
10
11
[root@WWW ~]# ftp 192.168.56.101
Connected to 192.168.56.101 (192.168.56.101).
220 (vsFTPd 3.0.2)
Name (192.168.56.101:root): test
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pwd
257 "/"

原先我们使用系统用户进行登录的时候, 会显示对方的家目录, 但是开启了第四个选项之后就可以看到被禁锢到根下了. 注意: 要和第五个选项同时开启,否则服务器会直接报错 拒绝连接

复原第四个选项, 我们开启第六和第七个选项, 先来创建一个新用户: ( 同样需要第五个选项 )

1
2
3
4
[root@WWW ftp]# useradd test2
[root@WWW ftp]# echo "test" | passwd test2 --stdin
Changing password for user test2.
passwd: all authentication tokens updated successfully.

接着创建需要的那个列表文件:

1
[root@WWW vsftpd]# echo "test2" > chroot_list

好了, 现在进行验证:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[root@WWW ~]# ftp 192.168.56.101
Connected to 192.168.56.101 (192.168.56.101).
220 (vsFTPd 3.0.2)
Name (192.168.56.101:root): test
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pwd
257 "/home/test"
ftp> bye
221 Goodbye.
[root@WWW ~]# ftp 192.168.56.101
Connected to 192.168.56.101 (192.168.56.101).
220 (vsFTPd 3.0.2)
Name (192.168.56.101:root): test2
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> pwd
257 "/"
ftp>

这就是指定chroot的用户.

接下来我们继续看几个配置:

dirmessage_enable=YES

这个选项允许你改变进入目录的提示信息, 在目录下新建一个.message文件就可以了, 有点像motd的感觉. 也有类似banner的选项就是: ftpd_banner=Welcome to blah FTP service.

xferlog_enable=YES 这个看名字也知道是什么了吧, 即使开启记录日志, 和这个配置相互配合的还有几个选项:

xferlog_file=/var/log/xferlog

xferlog_std_format=YES

其实就是日志保存位置和是否使用标准格式.

chown_uploads=YES
chown_username=whoever

是否修改上传文件的属主, 如果启用, 指定系统上存在的一个用户就行. 下面两个和连接相关:

idle_session_timeout=600
data_connection_timeout=120

都是关于超时的设定.

最后还有关于pam的设定, 我们看看

1
2
[root@WWW ~]# ls /etc/pam.d/vsftpd  -l
-rw-r--r-- 1 root root 335 Aug 3 02:10 /etc/pam.d/vsftpd

后面还有一个userlist和一个tcp_wrapper. 先来说说这个userlist, 这个其实可以和pam归在一起. 可以使用这些选项来建立访问用户控制(白名单, 黑名单)

例如:
在userlist文件中加上test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Users that are not allowed to login via ftp
root
bin
daemon
adm
lp
sync
shutdown
halt
mail
news
uucp
operator
games
nobody
test

接着在另一台主机测试:

1
2
3
4
5
6
7
8
[root@WWW ~]# ftp 192.168.56.101
Connected to 192.168.56.101 (192.168.56.101).
220 Welcome to blah FTP service.
Name (192.168.56.101:root): test
331 Please specify the password.
Password:
530 Login incorrect.
Login failed.

我确定我的密码输入的是正确的, 但是会被deny.

这是一份黑名单, vsftpd借助pam模块实现. 但是其实他自己也有用户控制, 就是另外一个user_list文件. 这个更加灵活, 可以作为黑名单, 也可以作为白名单. 通过选项: userlist_deny=YES|NO

接着还有连接参数, 一些限制参数:

max_clients: 最大并发连接数
max_per_ip: 每个IP可同时发起的并发请求.

还有速率上的限制:

anno_max_rate: 匿名用户的最大传输限制, 字节/s
local_max_rate: 本地用户的最大传输限制, 字节/s

虚拟用户的配置

虚拟用户需要映射到一个指定的系统账号. 所以每一个虚拟用户访问到的就是这个系统账号的家目录. 但是我们却可以赋予这些虚拟用户不同的权限, 这是依靠匿名用户进行的设定.

关于账号的存储, 我们说过可以存储在文件中, 奇数偶数分别为用户名/密码. 这个文件为了安全会被Hash, 但是我的每一次修改都要进行Hash计算, 所以很不方便.

因此更好的方法是存储在数据库中. 而且这样还是即时的. 但是我们知道vsftpd是依靠于PAM的验证机制的, 如果想要访问数据库, 就需要PAM能够访问数据库. 这样就需要一个模块: pam-mysql, 这个模块是第三方的, 默认不会有, 所以就需要安装.

这个模块在epel源中, 如果搜索不到需要建立yum源, 如果实在搜索不到就使用二进制的rpm包吧.

安装完成之后会看到:

1
2
3
4
5
6
[root@WWW ~]# yum list pam_mysql
Installed Packages
pam_mysql.x86_64 1:0.8.1-0.22.el7.lux installed
[root@WWW ~]# rpm -ql pam_mysql
/lib64/security/pam_mysql.so
...(omitted)

只要出现了so对象就可以了. 接着就可以继续了.

在pam_mysql的文档中, 我们可以看到官方给的一个示例:

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

后面还有更多的配置项. 接下来就直接来实现:

准备2台主机, 一台作为ftp服务器, 另外一台mysql服务器.

mysql准备好了之后进行用户添加和权限管理:

1
2
3
4
5
6
7
8
MariaDB [mysql]> create database vsftpd;
Query OK, 1 row affected (0.00 sec)
MariaDB [mysql]> use vsftpd;
Database changed
MariaDB [vsftpd]> grant select on vsftpd.* to vsftpd@192.168.56.101 identified by '???';
Query OK, 0 rows affected (0.00 sec)
MariaDB [vsftpd]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

接着在vsftpd的主机上进行连接测试:

1
2
3
4
5
6
7
8
9
10
11
[root@WWW ~]# mysql -u vsftpd -p -h 192.168.56.103
Enter password:
Welcome to the MariaDB monitor. Commands end with ; or \g.
Your MariaDB connection id is 14
Server version: 5.5.56-MariaDB MariaDB Server

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

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

MariaDB [(none)]>

成功 ! 那我们继续. 接下来创建表和插入用户信息:

1
2
3
4
5
6
7
8
9
10
11
12
MariaDB [vsftpd]> desc users;
+----------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | char(20) | NO | | NULL | |
| password | char(48) | NO | | NULL | |
+----------+----------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

MariaDB [vsftpd]> insert users values(default, 'justin', password("????"));
Query OK, 1 row affected (0.01 sec)

这一步也完成之后, 我们就可以建立pam认证所需的文件了.

关于文件的写法, 可以参考pam_mysql的说明文件.

完成后的pam文件应该是这样:

1
2
auth required /lib64/security/pam_mysql.so user=vsftpd passwd=???? host=192.168.56.103 db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=mysql
account required /lib64/security/pam_mysql.so user=vsftpd passwd=???? host=192.168.56.103 db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=mysql

接着在vsftpd的配置文件中指定:

1
2
3
pam_service_name=vsftpd.mysql
guest_enable=YES
guest_username=vuser

接着重启服务就完成了, 如果中间存在报错, 检查vsftpd的配置文件, 如果还不行, 查看secure日志吧.

以上就是连接mysql虚拟用户的配置. 接下来我继续谈这个, 我们在数据库中插入一个新的用户:

1
2
3
4
5
6
+----+--------+-------------------------------------------+
| id | name | password |
+----+--------+-------------------------------------------+
| 1 | justin | *29B43F519A224212716DDB7493DBE966B405D061 |
| 2 | bieber | *29B43F519A224212716DDB7493DBE966B405D061 |
+----+--------+-------------------------------------------+

现在的问题是, 我希望这些用户拥有不同的权限, 这怎么办呢?

对于这个问题, vsftpd的解决方法是在一个单独的user_config目录下, 一个用户一个配置文件来实现管理, 我们实际操作一下就行了:
比方说我们把这个单独的目录放在和主配置文件一样的位置, 就在配置文件中加上这个:

1
user_config_dir=/etc/vsftpd/vusers

接着创建之, 并且在里面写上对应的用户控制:

1
2
[root@WWW vusers]# ls
bieber justin

我是这样写的:

1
2
3
4
5
6
7
8
[root@WWW vusers]# cat justin 
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
[root@WWW vusers]# cat bieber
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_other_write_enable=NO

这样, justin用户可以进行写操作, 而bieber用户 不可以进行任何上传和写操作了.

实验效果略.

再插一句, 我们之前说过ftps是明文的, 而另外一个现在更加常用的文件传输 – sftp. 它是基于SSH协议的, 所以是加密传输的, 更加安全.