纯干货 常用的Linux可插拔认证模块(PAM)应用举例:pam_limits.so、pam_rootok.so和pam_userdb.so模块
pam_limits.so模块:
pam_limits.so模块的主要功能是限制用户会话过程中对各种系统资源的使用情况。缺省情况下该模块的配置文件是/etc/security/limits.conf。而该配置文件的基本格式实际上是由4个字段组成的表,其中具体限制的内容包括:
Domain type item value
用户名/组名 软/硬限制 具体值
core——core文件大小 (KB)
data——最大数据大小(KB)
fsize——最大文件大小(KB)
memlock——最大可用内存空间(KB)
nofile——最大可以打开的文件数量
rss——最大可驻留空间(KB)
stack——最大堆栈空间(KB)
cpu——最大CPU使用时间(MIN)
nproc——最大运行进程数
as——地址空间限制
maxlogins——用户可以登录到系统最多次数
locks——最大锁定文件数目
需要注意的是,如果没有任何限制可以使用”-”号,并且针对用户限制的优先级一般要比针对组限制的优先级更高。
使用pam_limits.so模块的最常见的场景是在运行Oracle数据库的RHEL服务器中,因为一般Oracle数据库在安装之前,按照其官方文档的说明需要先对某些用户(Oracle)使用系统资源的情况进行限制。
所以我们总是能够在Oracle数据库服务器的/etc/security/limits.conf文件中看到类似这样的配置:
oracle soft nproc 2047
oracle hard nproc 16384
oracle soft nofile 1024
oracle hard nofile 65536
结合上面的配置文件说明,可知Oracle数据库需要对Oracle用户使用资源的情况进行一些限制,包括: oracle用户最大能开启的进程数不超过16384,最大能打开的文件数不超过65536。
至于soft和hard的区别,不同于磁盘配额中的软限制和硬限制。普通用户可以调整自己的soft limit但最高不能超过hard limit,而且除了root以外的普通用户也不能够随意更改hard limit。该调整完成之后一般可以使用ulimit命令查看。
顺便提一下,针对nofile,这个只是基于用户层面的限制和调整方法。基于系统层面的限制和调整方法是修改/etc/sysctl.conf文件,直接改fs.file-max参数,调整之后sysctl –p生效。
另外一个例子,pam_limits.so模块也可以使用在对一般应用程序使用的资源限制方面。举例来说,如果需要在SSH服务器上对来自不同用户的ssh访问进行限制,就可以调用该模块来实现相关功能。例如,当需要限制用户admin登录到SSH服务器时的最大连接数(防止同一个用户开启过多的登录进程),就可以在/etc/pam.d/sshd文件中增加一行对pam_limits.so模块的调用:
session required pam_limit.so
然后在/etc/security/limits.conf文件中增加一行对admin用户产生的连接数进行限定:
admin hard maxlogins 2
完成之后重启服务器端的sshd服务。
之后我们可以看到,从客户端以admin身份登录SSH服务器时,在客户端上可以打开两个控制台登录。但当客户端开启第三个登录窗口的时候会被服务器拒绝,但其它用户不会受到限制。
pam_rootok.so模块
一般情况下,pam_rootok.so模块的主要作用是使uid为0的用户,即root用户能够直接通过认证而不用输入密码。
pam_rootok.so模块的一个典型应用是插入到一些应用程序的认证配置文件中,当root用户执行这些命令的时候可以不用输入口令而直接通过认证。
比如说“su”命令,为什么当以root用户执行“su”切换到普通用户身份的时候是不需要输入任何口令而可以直接切换过去?
当我们查看一下/etc/pam.d/su文件的内容就不会奇怪了。因为该文件的第一行就是:
auth sufficient pam_rootok.so
而如果将该行配置注释掉的情况下,就会发现即便以root用户切换普通用户的时候仍然要求输入口令。
另外一种方法,只需要将上述的“sufficient”改成“required”即可。因为这样,pam_rootok.so模块的验证通过就成为了必要条件之一。
pam_rootok.so模块的另外一个应用是在chfn命令中。Chfn命令用于改变/etc/passwd中的用户的说明字段。当以root身份执行chfn命令修改用户信息的时候是不用输入密码的。但是以普通用户身份执行chfn则需要输入密码之后才能改变自己的用户说明。这实际上也是因为在/etc/pam.d/chfn配置文件中的第一行调用了pam_rootok.so的结果。
不过这里即便将该配置中的第一行注释掉,root用户通过chfn修改自己信息的时候仍然不需要使用密码。所以恐怕效果不是很明显。究其原因主要是很多PAM模块对root用户是不会产生限制的。
pam_userdb.so模块
pam_userdb.so模块的主要作用是通过一个轻量级的Berkeley数据库来保存用户和口令信息。这样用户认证将通过该数据库进行,而不是传统的/etc/passwd和/etc/shadow或者其它的一些基于LDAP或者NIS等类型的网络认证。所以存在于Berkeley数据库中的用户也称为虚拟用户。
pam_userdb.so模块的一个典型用途就是结合vsftpd配置基于虚拟用户访问的FTP服务器。
相对于本地用户以及匿名用户来说,虚拟用户只是相对于FTP服务器而言才有用的用户,这些用户被严格地限定在pam_userdb数据库当中。所以虚拟用户只能访问FTP服务器所提供的资源,因而可以大大提高系统安全性。另外相对于匿名用户而言,虚拟用户必须通过用户名和密码才能够访问FTP的资源。这样也提高了对FTP用户下载的可管理性。
基于虚拟用户实现的vsftpd的原理基本上是这样一个过程:
先定义一些专门针对FTP的虚拟用户,然后将用户信息加入到系统自带的数据库中(但不是passwd)从而生成一个访问FTP的虚拟用户列表,这里使用的数据库是db4也就是Berkeley DB。然后可以通过使用pam_userdb.so模块来调用该数据库存储用户信息以及实现FTP用户认证。当然同时也可以在系统中通过对配置文件的定义和划分来实现对不同虚拟用户不同类型的访问控制。
下面我将详细介绍一下基于虚拟用户的FTP服务器配置方法,其中也包含了对pam_userdb.so模块的使用。
我的实验环境很简单:
FTP服务器的IP地址是:10.66.0.136,使用的操作系统是RHEL 5.4,FTP服务是vsftpd。
操作步骤:
1.备份配置文件:
[root@dhcp-0-136 ~]# cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.bak
2.建立虚拟用户数据库文件login.txt:
[root@dhcp-0-136 vsftpd]# pwd
/etc/vsftpd
[root@dhcp-0-136 vsftpd]# cat login.txt
ftpuser1
123
ftpuser2
123
ftpuser3
123
该文件单数行为用户名称,双数行为用户访问FTP服务器时的口令。
完成之后根据该文件内容创建登录用户数据库文件:
[root@dhcp-0-136 vsftpd]# db_load -T -t hash -f /etc/vsftpd/login.txt /etc/vsftpd/vsftpd_login.db
之后需要确认系统上已经安装Berkeley DB,即db4软件包。
完成之后,在/etc/vsftpd/vsftpd.conf目录下会产生vsftpd_login.db文件。
设置该文件的访问权限为仅root可读写:
[root@dhcp-0-136 vsftpd]# chmod 600 vsftpd_login.db
3.使用PAM来实现对登录FTP用户的限制:
现在需要创建一个使用数据库的pam配置文件,在这里该文件命名为vsftpd.pam,在/etc/pam.d目录下。
[root@dhcp-0-136 ~]# touch /etc/pam.d/vsftpd.pam
[root@dhcp-0-136 ~]# vi /etc/pam.d/vsftpd.pam
在该文件中写入下面的两行:
[root@dhcp-0-136 ~]# cat /etc/pam.d/vsftpd.pam
auth required /lib/security/pam_userdb.so db=/etc/vsftpd/vsftpd_login
account required /lib/security/pam_userdb.so db=/etc/vsftpd/vsftpd_login
假如说以后添加了新的用户,那么修改login.txt,然后再次执行命令:
db_load -T -t hash -f /etc/vsftpd/login.txt /etc/vsftpd/vsftpd_login.db
生成新的数据库即可。
4.建立一个本地用户,其主目录作为虚拟用户对FTP服务器的访问时的服务目录:
[root@dhcp-0-136 ~]# useradd –d /home/ftpsite virtual
通过上面的步骤建立一个名为virtual的本地用户,并且该用户的主目录是/home/virtual
5.现在通过对/etc/vsftpd/vsftpd.conf主配置文件的定义来使虚拟用户可以访问FTP服务:
[root@dhcp-0-136 ~]# vi /etc/vsftpd/vsftpd.conf
既然该服务器要求使用虚拟用户访问,那么需要先关闭匿名用户访问功能:
anonymous_enable=NO
local_enable=YES
另外出于安全考虑,此处添加的所有用户都只赋予对FTP服务器只读权限:
write_enable=NO
anon_upload_enable=NO
anon_mkdir_write_enable=NO
anon_other_write_enable=NO
确保用户在登录的时候使用刚才定义的PAM配置文件来进行身份验证,因此更改此行为:
pam_service_name=/etc/pam.d/vsftpd.pam
6.激活虚拟用户功能,并将所有虚拟用户对FTP服务器的访问映射为刚才所添加的virtual用户对FTP服务器的访问。
guest_enable=YES
guest_username=virtual
这个 guest_enable非常重要,该选项用来激活虚拟用户! 而guest_username 是将所有虚拟用户映射成先前所建立的真实用户”virtual”。这也决定了虚拟用户在整个文件系统中的位置,也就是”virtual”的主目录 /home/ftpsite。
如果系统中还有本地用户需要访问FTP服务器,可以再次对本地用户访问FTP服务时的根目录进行指定:
local_root=/home/ftpsite
当然在这里将local_root改为其它用户也没有任何问题。 再增加一行:
listen=YES
表示FTP服务器将会以standalone的模式启动。即不通过xinetd以及/etc/init.d下的脚本启动,而可以直接执行vsftpd的启动。最后启动FTP服务:
[root@dhcp-0-136 ~]# service vsftpd restart
在服务启动之后可在客户端上进行测试: 我们可以使用刚才在自定义数据库中建立的用户ftpuser1、ftpuser2、ftpuser3分别登录FTP服务器进行访问测试,如果都能够在ftp的命令行中正常登录则证明整个实验成功! 但是如果访问失败,比如说如果出现 “failed to open directory”,则有可能是因为目录/home/ftpsite不是全局只读属性(如果想更改,可以通过设置 anon_world_readable_only=NO来实现,这个默认是YES,它是用来设置匿名用户只能下载全局可读的文件)。
7.在FTP服务器的虚拟用户建立之后,可以考虑针对不同的虚拟用户设置不同的访问权限:
整个功能只有在使用虚拟帐号的情况下才能借助虚拟帐号的per-user功能来实现。 为了测试需要,现在添加另外三个新的用户,分别是ftpuser4,ftpuser5和ftpuser6:
[root@dhcp-0-136 vsftpd]# cat login.txt
ftpuser1
123
ftpuser2
123
ftpuser3
123
ftpuser4
123
ftpuser5
123
ftpuser6
123
然后将该文件所有信息再次导入数据库中:
[root@dhcp-0-136 vsftpd]# db_load -T -t hash -f /etc/vsftpd/login.txt /etc/vsftpd/vsftpd_login.db
假如在该场景中需要设置ftpuser4和ftpuser5用户具有对主目录的读取权限,而ftpuser6具有对主目录的写入权限。 那么可以针对这三个用户分别建立配置文件来进行限制。
首先创建并且定义一个容纳每个用户配置文件的目录:
[root@dhcp-0-136 vsftpd]# mkdir /etc/vsftpd_user_conf
然后在主配置文件中进行定义,定义的是不同用户配置文件所存储的路径,就在刚才建立的目录下:
user_config_dir=/etc/vsftpd_user_conf
进入该目录创建不同用户的配置文件:
[root@dhcp-0-136 vsftpd]# cd /etc/vsftpd_user_conf
创建的ftpuser4配置文件的内容如下:
[root@dhcp-0-136 vsftpd]# ls /etc/vsftpd_user_conf
ftpuser4
[root@dhcp-0-136 vsftpd]# cat /etc/vsftpd_user_conf/ftpuser4
anon_world_readalbe_only=NO
通过上面的定义,ftpuser4用户可以读取的同时也能够下载文件。但是如果写成YES则意味着无法列出文件和目录。 然后赋予ftpuser5用户相同的权限,由于权限与ftpuser4一致,所以只需要拷贝配置文件即可:
[root@dhcp-0-136 vsftpd]#cp /etc/vsftpd_user_conf/ftpuser4 /etc/vsftpd_user_conf/ftpuser5
最后是定义ftpuser6的权限,该用户可以向服务器目录写入和上传,那么配置文件内容为:
[root@dhcp-0-136 vsftpd]# vi /etc/vsftpd_user_conf/ftpuser6
anon_world_readable_only=NO 不仅仅是只读,还可以下载
write_enable=YES 可以写入
anon_upload_enable=YES 可以上传
anon_mkdir_write_enable=YES 可以建立目录
如果ftpuser5已经提升为管理员,现在需要针对管理员定义一个更高的权限,可以将ftpuser5的配置文件增加一行:
anon_other_write_enable=YES 增加管理员用户的删除/重命名的权限
完成之后保存退出,并重启服务:
分别测试ftpuser4、ftpuser5以及ftpuser6的权限会发现:
ftpuser4只有登录浏览权限; ftpuser5除了登录浏览之外还可以删除文件以及重命名文件 ftpuser6可以登录浏览并上传和下载,但是对于已有的文件没有写入权限。
实验到此基本成功!
在实际操作中,这种方法能够更好解决对服务器访问用户细化地设置权限的问题。而且pam_userdb.so模块也不仅仅只是用于在FTP服务中创建和使用虚拟用户,类似的服务,例如postfix,web服务等,都可以使用该模块实现类似功能。