虚拟用户:
所有的虚拟用户会映射会一个系统用户,访问时的文件目录是为此系统用户的家目录;
虚拟用户账号密码存储方式:
(1)hash编码的文件:
奇数行为用户名,偶数行为密码    注:当用户数量很多时,手动添加非常麻烦
(2)关系型数据库:
pam-mysql实现认证

一、yum安装vsftpd,mysql

# yum -y install vsftpd mysql-server mysql-devel

# mkdir tools
# cd tools/
# tar xf pam_mysql-0.7RC1.tar.gz
# cd pam_mysql-0.7RC1
# ./configure --with-mysql=/usr --with-openssl
# make && make install

注:也可使用yum安装pam_mysql

备注:

--with-openssl在这里可有可无,若有的话,一定要确保其devel包已经安装了

[root@localhost ~]# rpm -q openssl-devel
openssl-devel-1.0.0-27.el6.x86_64
configure报错:
configure: error: Cannot find pam headers. Please check if your system is ready for pam module development.
解决办法:yum -y install pam-*或yum -y install pam pam-devel
这是一个32位的pam库,不过它可以兼容64位
[root@localhost pam_mysql-0.7RC1]# ll  /lib/security/
total 140
-rwxr-xr-x 1 root root    876 Apr  2 03:38 pam_mysql.la
-rwxr-xr-x 1 root root 138572 Apr  2 03:38 pam_mysql.so
下面我们将为其创建软连接至64位库中,方便使用
[root@localhost pam_mysql-0.7RC1]# ln -sv /lib/security/pam_mysql.so /lib64/security/
`/lib64/security/pam_mysql.so' -> `/lib/security/pam_mysql.so'
[root@localhost pam_mysql-0.7RC1]# cd
二、创建虚拟用户账号
1.准备数据库及相关表
首先请确保mysql服务已经正常启动。而后,按需要建立存储虚拟用户的数据库即可,这里将其创建为vsftpd数据库。
[root@localhost ~]# service mysqld start
[root@localhost ~]# mysql
mysql> create database vsftpd;
mysql> grant all on vsftpd.* to 'vsftpd'@'localhost' identified by 'vsftpd';
mysql> grant all on vsftpd.* to 'vsftpd'@'127.0.0.1' identified by 'vsftpd';
mysql> flush privileges;
mysql> exit
Bye

以vsftpd的身份登录mysql,并创建users表
意义:(1)验证上一步用户的授权是否操作成功;(2)创建表
[root@localhost ~]# mysql -uvsftpd -hlocalhost -p'vsftpd'
mysql> show databases;
mysql> use vsftpd;
mysql> create table users (
   -> id int AUTO_INCREMENT NOT NULL,
   -> name char(20) binary NOT NULL,
   -> password char(48) binary NOT NULL,
   -> primary key(id)
   -> );
mysql> insert into users (name,password) values ('tom','mageedu'),('jerry','mageedu');
mysql> \q
Bye

三、配置vsftpd
1.建立pam认证所需文件
#vi /etc/pam.d/vsftpd.mysql
添加如下两行
auth required /lib64/security/pam_mysql.so user=vsftpd passwd=vsftpd host=localhost db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=0
account required /lib64/security/pam_mysql.so user=vsftpd passwd=vsftpd host=localhost db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=0
注意:由于mysql的安装方式不同,pam_mysql.so基于unix sock连接mysql服务器时可能会出问题,此时,建议授权一个可远程连接的mysql并访问vsftpd数据库的用户。

2.修改vsftpd的配置文件,使其适应mysql认证
建立虚拟用户映射的系统用户及对应的目录
# useradd -s /sbin/nologin -d /var/ftproot vuser
# chmod go+rx /var/ftproot
请确保/etc/vsftpd.conf中已经启用了以下选项
anonymous_enable=YES     #启用匿名用户,因为所有的虚拟用户也都是匿名用户
local_enable=YES#启用本地用户,因为所有的虚拟用户都会被映射成本地用户
write_enable=YES#此项可有可无
anon_upload_enable=NO    #是否启用匿名用户上传的权限,NO表示不启用,此项可有可无
anon_mkdir_write_enable=NO #此项可有可无
chroot_local_user=YES #此项可有可无
而后添加以下选项(关键2点)

guest_enable=YES        #启用虚拟用户
guest_username=vuser#虚拟用户映射的系统用户
并确保pam_service_name选项的值如下所示
pam_service_name=vsftpd.mysql   #vsftpd的pam认证文件名称
编辑/etc/vsftpd/vsftpd.conf,添加如下行
user_config_dir=/etc/vsftpd/vusers
若配置文件中还有如下已启用的权限,需将其注释掉
# cd /etc/vsftpd/
# mkdir vusers
# vim tom
anon_upload_enable=NO
# vim jerry
anon_upload_enable=YES
anon_other_write_enable=YES
# service vsftpd restart  #重启服务是操作生效

关于日志的启用:
/var/log/xferlog      注:wu-ftpd风格的日志文件
该日志文件只有在xferlog_enable=YES,并且xferlog_std_format=YES时才会生效。
/var/log/vsftpd.log   注:vsftpd 风格的日志文件
该日志文件只有在xferlog_enable=YES,并且xferlog_std_format=NO时才会生效;
如果我们启用了sys-log_enable的话,vsftpd程序就不会向vsftpd.log写入日志信息,而是将日志信息记录到系统日志

关于虚拟用户权限的设置及生效问题
约定:我们暂且把配置在vsftpd.conf中的选项称之为全局配置;
把定义users目录中,与虚拟用户对应的文件中设置的选项称之为局部配置;
当vsftpd.conf中的全局配置和users目录中的局部配置发生冲突的时候
若某些具有特别意义的选项在vsftpd.conf和users目录中同时出现,但是作用却是相反的的时候,则局部配置优先生效
若某些具有特别意义的选项仅在vsftpd.conf出现的时候,那么该虚拟用户的权限就是全局配置选项和局部配置选项的合集
以虚拟用户tom为例:
我们在users目录中,对其设置的权限是anon_upload_enable=NO,即tom不能上传文件到FTP的特定目录
与此同时,我们不小心在vsftpd.conf设置了如下三个选项:
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_other_write_enable=YES
然后我们重启vsftpd服务,使用lftp以虚拟用户tom的身份登录到ftp,看是否可以上传本地的文件到ftp,以及是否可以执行创建文件、目录和
删除文件目录的操作。
答案:tom用户此时可以执行的操作:创建文件或目录;删除文件或目录;但是不能执行上传本地文件到FTP(因为users中的设置会优先生效)
若我们仅想让tom有下载的权限,那么上面的三个选项,就不能出现在vsftpd.conf中。


我们在建立pam认证所需文件时,在/etc/pam.d/vsftpd.mysql中使用的都是明文的密码,很不安全,
因此我们可以将其加密,方法如下:
第一步:在上面的基础上,将crypt=0修改为crypt=1,表示使用加密的方法存储密码
auth required /lib64/security/pam_mysql.so user=vsftpd passwd=vsftpd host=localhost db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=1
account required /lib64/security/pam_mysql.so user=vsftpd passwd=vsftpd host=localhost db=vsftpd table=users usercolumn=name passwdcolumn=password crypt=1
验证:
# service vsftpd restart   重启服务
# lftp -u tom,mageedu 172.16.251.69  使用明文的密码已不能登录到FTP服务器
lftp tom@172.16.251.69:~> ls                      
ls: Login failed: 530 Login incorrect.
lftp tom@172.16.251.69:~> exit  
第二步:登录mysql数据库,将现有vsftp虚拟用户的明文密码以加密格式存放
# mysql
mysql> use vsftpd;
mysql> select * from users;
+----+-------+----------+
| id | name  | password |
+----+-------+----------+
|  1 | tom   | mageedu  |
|  2 | jerry | mageedu  |
+----+-------+----------+
2 rows in set (0.00 sec)
mysql> update  users set password=encrypt('mageedu');
mysql> select * from users;
+----+-------+---------------+
| id | name  | password      |
+----+-------+---------------+
|  1 | tom   | 3uR5aJ6nzrPt2 |
|  2 | jerry | 3uR5aJ6nzrPt2 |
+----+-------+---------------+
2 rows in set (0.00 sec)

若crypt指定的加密算法和在数据库中password指定的加密算法不一致的时候,可能会导致虚拟用户登录FTP后,无法正常执行操作
其他的加密方式可参考less README
[root@localhost pam_mysql-0.7RC1]# less README 查看pam加密的详细介绍