修改说明:添加了超级用户ftpadmin的需求及权限实现。

1、原始环境分析
新到公司报道,接到了一个新任务:为公司的A客户改造FTP系统,让每个区县的用户只能看到自己的报表,只有下载功能。用公司使用的vsftpd版本号为2.3.3。
 
2、任务分析
在看到需要隔离用户的需求后,首先就考虑到了使用实用户或者虚拟用户方式进行vsftpd搭建,各有优势。使用实用户模式的话,配置比较简单,功能更容易实现。如果用虚拟用户方式的话,不用在系统中创建如此多的用户,相对来说安全性更高一些,而且处理起来更方便些。这里选用vsftpd的虚拟用户功能,并为每个用户指定权限,指定用户有权限读取的目录,并且用户不可以切换目录。
在做操作之前,做了细致的测试工作,不过百密一疏,因为公司的系统是RHEL5u3 x86_64的,64位操作系统跟32位系统在很多地方有区别。我在文中会体现出来。最终还是重新编译了最新版的vsftpd才解决了问题。看来要上生产系统之前,还是一定要有一套完全一样的测试系统才行啊,得赶紧找公司提需求了。
 
附加需求,在创建只读用户的同时,创建一个超级用户ftpadmin,并使其有访问所有目录的权限,同时上传的文件权限为644。
 
3、vsftpd的配置
(1)、修改主配置文件/etc/vsftpd.conf,进行下述操作:
 
  1. # vim /etc/vsftpd.conf  
  2. listen=YES  
  3. anonymous_enable=NO 
  4. local_enable=YES  
  5. write_enable=NO 
  6. anon_upload_enable=NO 
  7. anon_mkdir_write_enable=NO 
  8. anon_other_write_enable=NO 
  9. one_process_model=NO 
  10. chroot_local_user=YES  
  11. guest_enable=YES  
  12. guest_username=ftp  
  13. pam_service_name=vsftpd  
  14. user_config_dir=/etc/vsftpd_user_conf 
开启listen,选用stand alone模式开启vsftpd,这也是vsftpd推荐的登陆模式
关闭匿名用户登陆功能。所有用户都得有账号登陆
允许本地用户登录,因为咱们要开启虚拟用户的录,而虚拟用户登陆的时候需要指定一个真实用户的名字作为他们登陆系统的伪装账户,所以能,这个local_enable必须为YES,不然的话,会提示说:“系统同时拒绝匿名用户登录和本地用户登陆,登录失败……”等等这样的句子。打开local_enable的时候就ok了。因为你也可以观察到其实后边也要指定一个账户用来登陆的。这里我指定的就是ftp用户,匿名用户登陆的时候,就会伪装为这个用户在以实用户模式登陆vsftpd。
下边就要设置初始权限了,这里因为要在后边为每个用户单独设置权限,所以这里先全都设置成NO。也就是默认什么权限都没有,而靠后边的每个用户的单独的权限来限定每个用户的权限。
 chroot_local_user=YES这里指不允许用户切换目录,也就是不允许用户切换出来。安全性会高一些
 guest_enable=YES、guest_username=ftp这里指定允许匿名用户登陆,指定ftp为匿名用户的登陆用户
 pam_service_name=vsftpd、指定pam对虚拟用户登陆进行验证,后期要设置vsftpd那个验证文件
 user_config_dir=/etc/vsftpd_user_conf、这里指定单个用户的配置文件是什么,首先是每个人先赋予系统的默认权限,然后再根据你在自己单独的配置里的设置来更改最最后的权限。
(2)、创建用户配置文件目录
[root@localhost ~]# mkdir /etc/vsftpd_user_conf
(3)、为每个用户创建相应的配置文件,在文件中指定权限与登陆目录,粗体标注的username为需要开通ftp的用户名,此用户名需要与账户初始化文件中记录的用户名一一对应,账户初始化文件为/etc/vsftpd_user_conf/login.txt
  1. # touch /etc/vsftpd_user_conf/username  
  2. # vim /etc/vsftpd_user_conf/username  
  3. anon_world_readable_only=NO 
  4. write_enable=NO 
  5. anon_upload_enable=NO 
  6. local_root=/var/ftproot/report/dirname/ 
 
为ftpadmin手动创建配置文件,指定其相应的权限。注意那个anon_umask的设置,在普通用户的配置里没有写,是因为他们没有上传权限,而单独指定ftpadmin用户的权限,这个umask的使用是:创建目录的默认权限是777-umask=777-022=755,文件的默认权限是666-umaks=666-022=644
 
 
  1. # touch /etc/vsftpd_user_conf/ftpadmin  
  2. # vim /etc/vsftpd_user_conf/ftpadmin  
  3. anon_world_readable_only=NO 
  4. write_enable=YES  
  5. anon_umask=022  
  6. anon_upload_enable=YES  
  7. anon_mkdir_write_enable=YES  
  8. anon_other_write_enable=YES  
  9. local_root=/var/ftproot 
 
这里是个举例,真正的用户是来自一个列表,由同事从mysql中导出,每个用户对应的目录都不一样不说,跟用户名的目录也不一样。哎,要是一样就好搞定了,不一样着实给我郁闷了一下子。后来写了个脚本来逐行读取文件中的信息再写到文件中。脚本文件贴出来供大家参考:
我们的文本的样子如name_dir.txt
user1 0001
user2 0023
user3 0055
……
而且那个对应关系还不是这么有规律的,顺序也是不定的,如果顺序是一定的我也不用这么麻烦直接搞循环就行了,这里就不能这样用了。
贴出代码如下:
  1. #!/bin/csh  
  2. set file=name_dir.txt  
  3. set i = 1  
  4. set l = `awk 'END{print NR}' $file`  
  5. while ( $i <= $l )  
  6.       set line=`awk "{ if (NR == $i) print}" $file`  
  7.       echo $line > tempfile.temp 
  8.       set name = `awk '{print $1}' tempfile.temp`  
  9.       set dir = `awk '{print $2}' tempfile.temp`  
  10.       touch /tmp/test/vsftpd_user_conf/$name 
  11.       echo non_world_readable_only=NO > /tmp/test/vsftpd_user_conf/$name 
  12.       echo write_enable=NO >> /tmp/test/vsftpd_user_conf/$name 
  13.       echo anon_upload_enable=NO >> /tmp/test/vsftpd_user_conf/$name 
  14.       echo local_root=/var/ftproot/report/$dir >> /tmp/test/vsftpd_user_conf/$name 
  15.     mkdir /tmp/test/report/$dir  
  16. #    log file  
  17.       echo /tmp/test/vsftpd_user_conf/$name >> install.log  
  18.       echo /tmp/test/report/$dir >> install.log  
  19.       @ i ++  
  20. end 
  21. rm -f tempfile.temp 
 
脚本简介:这个脚本是参照往上的一个脚本来写的。那个脚本就是用cshel编的,我就是改了下,改成了自己需要的脚本。首先会读取文件,计算出文件中有多少行,这样来控制循环。第二就是用awk的格式输出来分离用户名和目录名,因为所有用户名和目录名的对应都是在这个里面是,而且并没有一个固定的顺序,首先就是里面的名称肯定不会是user1user2这样有规律,是不定规律的,所以要实现name_dir.txt中逐行文件输出,每一个循环输出一行重定向到临时文件,经过awk对临时文件进行处理,将$1和$2分别输出到name和dir变量中,这两个变量在后边的创建文件的时候需要用到的。这样就实现了用户名和文件夹名的同时输出。
(4)、编辑账户初始化文件/etc/vsftpd_user_conf/login.txt,定义可登陆的账户名跟密码。奇数行为用户名,偶数行为上一行用户名相对应的密码。例如:第一行的“user1”为ftp用户登录的用户名“user1”,第二行的“user111”为用户“user1”登陆ftp的密码“user111”。login.txt文件不可被删除,除用户申请的更改账户名、更改密码操作外,不可改动其内容。
[root@localhost ~]# touch /etc/vsftpd_user_conf/login.txt
[root@localhost ~]# vim /etc/vsftpd_user_conf/login.txt
user1
8736239823
user2
8234208345
在实现这个文件的时候。我也是用脚本弄得。首先就是改上边的代码,将awk得到的$1赋值给name,输出一行是奇数行,然后在循环中添加一行创建随机数重定向输出到login.txt文件中,这个随机数便是用户密码。这个随机数的获得方法网上有很多的,问google吧。他什么都知道,比百度知道的多。贴出创建密码文件脚本:
  1. #!/bin/csh  
  2. set file=name_dir  
  3. set i = 1  
  4. set l = `awk 'END{print NR}' $file`  
  5. while ( $i <= $l )  
  6. set line=`awk "{ if (NR == $i) print}" $file`  
  7. echo $line > tempfile.temp 
  8. set name = `awk '{print $1}' tempfile.temp`  
  9. echo $name >>login.txt  
  10. echo `head /dev/urandom | cksum | cut -f1 -d" "` >> login.txt  
  11. #log file  
  12. @ i ++  
  13. end 
  14. rm -f tempfile.temp 
(5)、创建用户登录校验文件,此文件对login.txt进行加密,生成不可读的账号密码验证文件。一定程度上保证账号密码安全。
[root@localhost ~]#db_load -T -t hash -f /etc/vsftpd_user_conf/login.txt \
/etc/vsftpd_user_conf/vsftpd_login.db
这里需要db4-4.3.29-9.fc6.x86_64.rpm,db4-devel-4.3.29-9.fc6.x86_64.rpm,db4-utils-4.3.29-9.fc6.x86_64.rpm,这几个包一定要装上,而db_load这个程序是在db4_utils-4.3.29.9.fc6.x86_64.rpm中,而且一定要注意装的是64位的包还是32位的包。等你生成完了密码文件的时候,在pam验证的时候也需要调用64的验证包才行。这个地方切记。因为我做在线系统实施的时候就是,等我密码文件拷贝完了,控制文件都弄完了,在最后一步测试的时候一直测不通,我一开始说什么都没想清楚,还以为是2.3.3在原来装的时候没有打开pam包支持呢,所以后来自己重新编译了一遍vsftpd2.3.4,幸亏编译了一遍,不然永远也不知道问题出在什么地方。
(6)、设置账户初始化文件 与 登陆校验文件 的权限,使除root以外的用户不可对其进行操作,提升一定的安全性,
 
  1. #chmod 600 /etc/vsftpd_user_conf/login.txt  
  2. #chmod 600 /etc/vsftpd_user_conf/vsftpd_login.db 
(7)、设置安全验证文件/etc/pam.d/vsftpd
  1. #vim /etc/pam.d/vsftpd  
  2. auth required /lib64/security/pam_userdb.so b=/etc/vsftpd_user_conf/vsftpd_login  
  3. account required /lib64/security/pam_userdb.so db=/etc/vsftpd_user_conf/vsftpd_login 
 
问题就在这。看到这个/lib64/security/pam_userdb.so了吗,在man手册中不是这个lib64,而是lib,lib64是64位的库,而我安装的db4-utils-4.3.29-9.fc6.x86_64.rpm是64位版本的,而在密码验证的pam这里填写的竟然是32位的验证文件,所以一直报错,而且在,所以第一次并没有想到会是这里有问题,而是直接想到的编译安装最新版的vsftpd,等编译的时候就出错了。提示什么lib…文件损坏什么的。后来从google上搜索到原来有朋友也出现了这种问题,是因为源码安装的时候,vsftpd并没有考虑到64包的问题,所以lib文件都指定的32位文件,这里手动改了软件make的源文件那个vsf_findlibs.sh,替换写的lib的位置,在vim下的快捷命令是:“:%s?lib/?lib64/?”保存后,先make clean,然后再make就不会报错了,编译正常。哈哈
(8)、启动FTP服务
 
  1. [root@localhost ~]#/usr/local/sbin/vsftpd & 
4、关于FTP服务器的维护的补充
(1)、启动与关闭FTP服务
FTP服务的启动
 
  1. [root@localhost ~]#/usr/local/sbin/vsftpd & 
FTP服务的关闭
 
  1. [root@localhost ~]#pkill vsftpd 
(2)、添加或删除用户
root用户编辑/etc/vsftpd_user_conf/login.txt账户初始化文件,在文件最后新建两行或删除该用户的记录,奇数行是用户名,该用户名的下一行是该用户对应的密码,一定要一同删掉。
 
  1. [root@localhost ~]# cp /etc/vsftpd_user_conf/login.txt  
  2. /etc/vsftpd_user_conf/login.txt.bak  
  3. [root@localhost ~]# vim /etc/vsftpd_user_conf/login.txt  
  4. user1  
  5. user111  
  6. …  
  7. newuser  
  8. newuser123  
  9. [root@localhost ~]# db_load -T -t hash -f /etc/vsftpd_user_conf/login.txt /etc/vsftpd_user_conf/vsftpd_login.db 
(3)、修改用户名或密码
 具体步骤同上一步操作类似,只是把login.txt文件中相应的用户名找到后客户按照要求更改用户名或者密码。一定要注意在操作前做过login.txt的备份。
注意修改用户密码后不用重启服务,直接修改完了就能够用了。
 
总结:各位兄弟们在安装的时候一定要区分软件包的版本哦,64位的db包要用/lib64/security/pam_userdb.so才能正确的读取,不然的话你怎么试都会提示密码错误。改过这个地方就ok了。还有就是make的时候出错,一定要改那个lib为lib64。文中的分隔符用?就是为了防止大家啥都不想而直接敲“:%s/lib/lib64/”,这样可能会破坏一些东西的。一定要用“:%s?lib/?lib64/?”。
别的也没有啥要补充的了。兄弟们做的时候也要细心啊。记下来以防止自己以后再出这样的问题。