*******技术宅男********

常用的Linux可插拔认证模块(PAM)应用举例(一)

pam_access.so模块

pam_access.so模块主要的功能和作用是根据主机名(包括普通主机名或者FQDN)、IP地址和用户实现全面的访问控制。pam_access.so模块的具体工作行为根据配置文件/etc/security/access.conf来决定。该配置文件的主体包含了三个字段——权限、用户和访问发起方。格式上是一个用“:”隔开的表。 第一个字段:权限(permission),使用“+”表示授予权限,用“-”表示禁止权限。 第二个字段:用户(user),定义了用户、组以及用“@”表示的在不同主机上的同名用户和同一主机上不同名用户。 第三个字段:访问发起方(origins),定义了发起访问的主机名称、域名称、终端名称。

而且该文件提供了很多范例供修改时参考,并且都给出了具体的说明,例如:

#禁止非root用户通过tty1访问相关服务
#-:ALL EXCEPT root:tty1

#禁止除了wheel、shutdown以及sync之外的所有用户访问相关服务
#-:ALL EXCEPT wheel shutdown sync:LOCAL

#禁止wheel用户通过.win.tue.nl之外的其它它终端访问相关服务
#-:wheel:ALL EXCEPT LOCAL .win.tue.nl

# 禁止下面的用户从任何主机登录。其它用户可以从任意地方访问相关服务
#-:wsbscaro wsbsecr wsbspac wsbsym wscosor wstaiwde:ALL

# root用户允许通过cron来使用tty1到tty6终端访问相关服务
#+ : root : cron crond :0 tty1 tty2 tty3 tty4 tty5 tty6

# 用户root允许从下面的地址访问相关服务
#+ : root : 192.168.200.1 192.168.200.4 192.168.200.9
#+ : root : 127.0.0.1

# 用户root可以从192.168.201.网段访问相关服务
#+ : root : 192.168.201.

# 用户root可以从.foo.bar.org中任何主机访问相关服务
#+ : root : .foo.bar.org

# 用户root不允许从任何主机访问相关服务
#- : root : ALL

# 用户@nis_group和foo可以从任何主机访问相关服务
#+ : @nis_group foo : ALL

# 用户john只能从127.0.0.0/24来对本机相关服务进行访问
#+ : john : 127.0.0.0/24

# 用户john可以通过ipv4和ipv6的地址对本机相关服务进行访问
#+ : john : ::ffff:127.0.0.0/127

# 用户john可以通过ipv6的地址访问本机相关服务
#+ : john : 2001:4ca0:0:101::1

# 用户john可以通过ipv6的主机IP地址来访问本机
#+ : john : 2001:4ca0:0:101:0:0:0:1

# 用户john可以通过ipv6的IP地址和掩码来访问相关服务
#+ : john : 2001:4ca0:0:101::/64

# 开放所有用户对本机所有相关服务的访问
#- : ALL : ALL

那么具体如何应用到实际环境中呢?我们来设计这样一个例子:

如果要在网络内架设一个FTP服务器,而且在该FTP服务器上需要强制地指定某个用户只能通过某个IP地址登录。这个时候pam_access.so模块就派上用场了。

假设我的FTP服务器是使用vsftp来构建的,那么具体方法是:

首先修改FTP服务器的/etc/pam.d/vsftpd文件,在调用account接口处插入:

“account    required     pam_access.so”

到第一行,那么整个文件的内容如下:

[root@localhost ~]# 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      system-auth
account    required     pam_access.so
account    include      system-auth
session    include      system-auth
session    required     pam_loginuid.so

上述配置表示当针对FTP访问执行用户类接口的时候会增加pam_access.so的认证。保存退出之后修改/etc/security/access.conf配置文件,添加下面的两行:

- : admin1 : ALL EXCEPT 192.168.10.251
- : admin2 : ALL EXCEPT 192.168.10.252

前提是我在系统上事先已经建立了admin1和admin2两个用户。所以上面的配置表示:admin1用户不能从192.168.10.251之外的任何客户端访问FTP服务器;而admin2用户不能从192.168.10.252之外的任何客户端访问FTP服务器。

最后再修改/etc/vsftpd/vsftpd.conf文件,禁用匿名登录:

Anonymous_enable = NO

这样当重启vsftpd服务之后,用户admin1将只能从192.168.10.251访问ftp服务,而admin2将只能从192.168.10.252访问ftp服务。

所以当针对这种需求而且不想使用防火墙以及应用程序自带的认证机制的时候,通过pam_access.so可以实现所需的效果。

pam_listfile.so模块

pam_listfile.so模块的功能和pam_access.so模块类似,目标也是实现基于用户/组,主机名/IP,终端的访问控制。不过它实现的方式和pam_access.so会稍微有些不同,因为它没有专门的默认配置文件。访问控制是靠pam配置文件中的控制选项和一个自定义的配置文件来实现的。而且除了针对上述访问源的控制之外,还能够控制到ruser,rhost,所属用户组和登录shell。所以有些用户认为它的功能似乎比pam_access.so更加灵活和强大一些。

对于pam_listfile.so的配置方法,我们可以参考vsftpd文件中对pam的调用方式。

熟悉vsftpd的人都知道,在vsftpd默认配置中,root用户是不允许通过ftp方式直接访问FTP服务器的。这个功能实际上是由/etc/vsftpd/vsftpd.conf,/etc/vsftpd/ftpusers和/etc/pam.d/vsftpd共同控制的。 因为在/etc/pam.d/vsftpd中有这样的一行配置:

auth       required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed

表示当用户试图登录FTP服务器的时候,会调用pam_listfile.so模块来验证用户是否可以登录,这里item=user表示访问控制是基于user即用户实现的。那么哪些用户可以登录呢?就是除了file选项所定义的/etc/vsftpd/ftpusers文件之外的用户,这是由另外一个选项sense=deny所决定的。

而在/etc/vsftpd/vsftpd.conf中明确指定了对用户的认证需要通过/etc/pam.d/vsftpd中的配置调用pam模块:

pam_service_name=vsftpd

而恰好root用户又在/etc/vsftpd/ftpusers文件中,所以这成为了制约root登录FTP服务器的一个必要条件(但不是唯一条件)。

所以针对这种情况,我们要开放和允许root用户登录FTP的权限,至少有三种改法:

  1. 修改/etc/pam.d/vsftpd文件,将sense=deny改成sense=allow。这样会正好将情况反转过来,FTP服务器只允许/etc/vsftpd/ftpusers文件内的用户登录;
  2. 修改/etc/pam.d/vsftpd文件,注释掉调用pam_listfile.so那行。这样FTP服务器在认证用户的时候将不再考虑pam_listfile.so模块的任何限制;
  3. 将root从/etc/vsftpd/ftpuser文件中注释掉;

不过需要注意的是,root用户比较特殊,因为它在vsftpd配置中的限制不仅仅来自于pam,vsftpd本身的配置中也对其做了限制。当我们看/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.

表示当vsftpd.conf中userlist_deny=NO的时候,系统将只允许user_list中的用户登录FTP服务器;如果userlist_deny=YES,情况将截然相反——此时user_list变成了黑名单,里面的用户将一概不允许登录FTP服务器。所以要彻底开放root登录FTP的权限,我们还要在/etc/vsftpd/vsftpd.conf中增加userlist_deny=YES或者注释掉user_list中的root。

不过不管怎么说,vsftpd中禁用root用户的直接登录是在绝大多数FTP服务器上默认的安全措施,所以开放root权限时应该慎重。

另外除了通过pam_listfile.so实现基于用户的访问控制之外,还可以实现基于其它条件的访问控制。我们具体看看pam_listfile.so模块的选项就会比较清楚:

使用pam_listfile.so模块配置的格式分为五个部分:分别是item、sense、file、onerr以及apply。 其中:

item=[tty|user|rhost|ruser|group|shell]:定义了对哪些列出的目标或者条件采用规则,显然,这里可以指定多种不同的条件。

onerr=succeed|fail:定义了当出现错误(比如无法打开配置文件)时的缺省返回值。

sense=allow|deny:定义了当在配置文件中找到符合条件的项目时的控制方式。如果没有找到符合条件的项目,则一般验证都会通过。

file=filename:用于指定配置文件的全路径名称。

apply=user|@group:定义规则适用的用户类型(用户或者组)。

而至于file文件的写法就简单了,每行一个用户或者组名称即可。

所以,当我们需要对其它服务进行类似的访问控制的时候,就可以照葫芦画瓢。例如现在需要在SSH服务器上对ssh客户端实现基于用户的访问控制,目的是不允许admin从通过ssh登录。

针对这种需求只需要更改/etc/pam.d/sshd文件,并在该文件中添加一行(添加到第一行):

auth required pam_listfile.so  item=user sense=deny file=/etc/pam.d/denyusers onerr=succeed

然后建立文件/etc/pam.d/denyusers,并在文件中写入用户信息——>就写admin即可。

表示用户以ssh登录必须要通过pam_listfile.so模块进行认证,认证的对象类型是用户,采用的动作是禁止,禁止的目标是/etc/pam.d/denyuser文件中所定义的用户。

这样在该条目添加到该文件之后,使用admin从其它主机远程ssh访问服务器会出现密码错误的提示。但是使用root或者其它用户则访问能够成功。

再次强调,要注意pam模块使用的顺序,刚才的规则一定要添加到auth的第一行之前,否则不会生效。

pam_listfile.so的另外一个案例是应用于诸如xinetd超级进程上的的非独立服务的应用。例如笔者曾接触过一个用户在对系统进行安全加固的时候需要禁止gssftp的匿名用户登录功能。这里需要说明的是gssftp是RHEL系统上基于kerberos协议进行认证的一款轻量级的FTP服务器。默认情况下,当修改了/etc/xinetd/gssftp配置文件并通过重启xinetd启动服务就可以开启该服务。当开启gssftp服务之后,该ftp服务器也是允许匿名用户登录的。而且除了/etc/xinetd.d/gssftp之外没有其它的配置文件可以对该服务进行过多的定制。这个时候实际上也可以借用pam_listfile.so模块来对其进行一些简单的控制。

参考如下的例子,如果要禁用匿名登录,则可以修改/etc/xinetd.d/gssftp文件如下:

[root@localhost ~]# cat /etc/xinetd.d/gssftp 
# default: off
# description: The kerberized FTP server accepts FTP connections \
#              that can be authenticated with Kerberos 5.
service ftp
{
        flags           = REUSE
        socket_type     = stream        
        wait            = no
        user            = root
        server          = /usr/kerberos/sbin/ftpd
#        server_args     = -l -a    
        log_on_failure  += USERID
        disable         = no
}

然后在/etc/pam.d/gssftp文件中增加对pam_listfile.so模块的调用:

auth    required pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed

并根据PAM配置文件内容建立相应配置文件/etc/ftpusers,内容为:

anonymous
ftp

这样修改之后的效果是,当没有改server_args时,那么启用/etc/ftpusers之后,所有用户都无法登录服务器;而如果保存了server_args之后,只有pam_listfile.so指定在/etc/ftpusers文件中的用户不能登录FTP服务器,而且在输入用户名之后会被直接拒绝掉。但root或者其它自建立的用户可以访问FTP服务器。

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服务等,都可以使用该模块实现类似功能。

pam_securetty.so模块

pam_securetty.so模块用于控制用户登录系统的时候所使用的终端。为说明该模块的用法,我们可以例举一个简单的例子:  在RHEL操作系统上一旦开启telnet服务之后,默认情况下root用户是无法通过telnet登录的。如果要开启该功能的话,只需要修改/etc/pam.d/remote文件,将该文件中的:

auth       required     pam_securetty.so

这一行注释掉即可。

当通过这种方式telnet成功之后,再执行who命令查看用户登录情况的时候不难发现,刚才root用户telnet上来使用的终端是pts/0,即网络终端。那么为什么root用户无法使用pts/0登录系统呢?实际上这是pam_securetty.so模块的配置文件/etc/securetty所定义的。默认情况下该文件中只定义了本地终端,所以另外一种改法是将pts/0,pts/1这类网络终端以及所需要添加的其它类型终端加入到该文件中去。这样修改之后root用户一样可以登录。

不过当我们使用非root用户通过telnet登录的时候会发现登录成功的时候通过who显示出来用的也是pts/0终端,那么为什么非root用户不用修改securetty文件而root用户就需要?其实答案很简单,只要访问/usr/share/doc/pam-/txt/README.pam_securetty文件(该目录下也有其它PAM模块的帮助文档)就可以获知,实际上pam_securetty.so和其它的pam模块不同,它只针对root用户起作用。

所以pam_securetty模块和pam_limit.so模块在某种程度上是差不多的,即都可以针对系统资源使用做出明确的限制。

pam_cracklib.so模块

pam_cracklib.so是一个常用并且非常重要的PAM模块。该模块主要的作用是对用户密码的强健性进行检测。即检查和限制用户自定义密码的长度、复杂度和历史等。如不满足上述强度的密码将拒绝用户使用。

pam_cracklib.so比较重要和难于理解的是它的一些参数和计数方法,其常用参数包括:

debug:将调试信息写入日志;

type=xxx:当添加/修改密码时,系统给出的缺省提示符是“New UNIX password:”以及“Retype UNIX

password:”,而使用该参数可以自定义输入密码的提示符,比如指定type=your own word;

retry=N:定义登录/修改密码失败时,可以重试的次数;

Difok=N:定义新密码中必须有几个字符要与旧密码不同。但是如果新密码中有1/2以上的字符与旧密码不同时,该新密码将被接受;

minlen=N:定义用户密码的最小长度;

dcredit=N:定义用户密码中必须包含多少个数字;

ucredit=N:定义用户密码中必须包含多少个大写字母;

lcredit=N:定义用户密码中必须包含多少个小些字母;

ocredit=N:定义用户密码中必须包含多少个特殊字符(除数字、字母之外);

下面是关于pam_cracklib.so的一个应用实例——在/etc/pam.d/system-auth中使用pam_cracklib.so来限制用户修改自己密码时必须满足一定的强健性要求。

 [root@localhost ~]# cat /etc/pam.d/system-auth 
#%PAM-1.0
# This file is auto-generated.
# User changes will be destroyed the next time authconfig is run.
auth        required      /lib/security/$ISA/pam_env.so
auth        sufficient    /lib/security/$ISA/pam_unix.so likeauth nullok
auth        required      /lib/security/$ISA/pam_deny.so
account     required      /lib/security/$ISA/pam_unix.so
account     sufficient    /lib/security/$ISA/pam_succeed_if.so uid < 100 quiet
account     required      /lib/security/$ISA/pam_permit.so
password    required      /lib/security/$ISA/pam_cracklib.so retry=3 minlen=9 dcredit=-1 ucredit=-1 lcredit=-1 ocredit=-1
password    sufficient    /lib/security/$ISA/pam_unix.so nullok use_authtok md5 shadow
password    required      /lib/security/$ISA/pam_deny.so
session     required      /lib/security/$ISA/pam_limits.so
session     required      /lib/security/$ISA/pam_unix.so

从上面使用pam_cracklib.so的策略看,要求用户修改密码时必须要满足9位,并且密码中至少要包含一个大写字母、小写字母、数字和特殊符号。

但是实际上像minlen和所有credit所对应的数值可以是非0之外的正负整数,那么这些数值到底表示什么意思呢?很多人将其简单地理解为某一类字符的位数,其实远远没有那么简单。

下面我们对这些数值和关系做一个简短的说明:

首先要明确整个环境中密码的长度要满足下面的计算公式:

计算公式:最小密码长度(minlen)应该小于或者等于 dcredit+ucredit+lcredit+ocredit+其它分值 (同时满足 * credit的条件),关于分值我们随后会讲解。 (参考file:///usr/share/doc/pam-0.99.6.2/html/sag-pam_cracklib.html理解)

(注)*credit=-1表示至少有一个的意思,*credit=N(N表示当满足条件的时候加N分,例如dcredit=2表示一个数字加2分,两个数字加4分),所以这里minlen其实更准确的表述应该是mincredit。

所以在下面的例子中,当pam_cracklib.so的参数按如下方式指定:

password    requisite     pam_cracklib.so try_first_pass retry=3 minlen=12 dcredit=2 ucredit=0 lcredit=0 ocredit=0

那么当用户执行命令修改密码的时候:

[test@dhcp-0-185 ~]$ passwd 
Changing password for user test.
Changing password for test
(current) UNIX password: 
New UNIX password:                   输入密码: 1\=poiuyt   不成功      1个数字再加2分

此时密码有一个数字,2分,其它的字符每个1分,总共10分,不满足minlen的位数需求,所以该密码不能通过。

BAD PASSWORD: is too simple
New UNIX password:                   输入密码: 12\=poiuyt   成功     2个数字再加2分
Retype new UNIX password:

此时密码有两个数字,4分,其它的字符每个1分,总共12分,满足minlen的位数需求,所以密码可以通过。

New UNIX password:                   输入密码: 1\=poiuytre   成功     1个数字再加2分
Retype new UNIX password:

此时密码有1个数字,2分,其它的字符每个1分,总共12分,满足minlen的位数需求,所以密码可以通过。

因此通过上述的配置基本可以得出这样的结论:

当某类credit为正数N的时候,表示密码中该类字符一个可以加N分;当某类credit为负数N的时候,表示密码中某类字符必须具备N个。时间关系我将不会一一演示。

所以当输入的密码所有的字符总分大于或者等于minlen,并且满足所有credit的要求,该密码通过; 即:输入的密码长度(每个输入值都算数)+*credit(加分)>=minlen

所以pam_cracklib.so模块在系统安全管理策略和管理中的用途是非常重要和广泛的。

pam_pwhistroy.so模块

pam_pwhistory.so模块也是一个常用模块,一般辅助pam_cracklib.so,pam_tally.so以及pam_unix.so等模块来加强用户使用密码的安全度。不过pam_pwhistory.so模块起的是另一类的作用,即专门为用户建立一个密码历史档案,防止用户在一定时间内使用已经用过的密码。

例如,当需要限定用户在90天之内不能重复使用以前曾经使用过的10个密码,那么具体操作方法是去修改/etc/pam.d/system-auth文件,在password接口处增加:

……
    password     required       pam_cracklib.so    retry=3
    password     required       pam_pwhistory.so   enforce_for_root remember=10
……

此时用户使用过的密码将会记录到/etc/security/opasswd文件中。但是pam_pwhistory.so并没有什么选项可以限定密码在多少天之内无法被重复使用,所以上述的90天是无法配置的。一个简单的解决方法就是当90天左右的时候,手动清空一次opasswd文件即可。

当然,如果要实现同样的功能除了pam_pwhistory.so模块之外还有其它的办法。比较常用的是pam_unix.so模块。具体方法是修改/etc/pam.d/system-auth文件,给pam_unix.so模块里加上remember=10这个选项,修改之后的配置文件为:

password required pam_unix.so md5 remember=10 use_authtok

这样系统将同样记住10个已经使用的密码。

具体情况请参考: http://www.deer-run.com/~hal/sysadmin/pam_unix.html

不过此时/etc/security/opasswd文件因为记录了N个使用过的密码,所以安全性就十分关键了,所以要确保该文件只能被root用户读取和编辑:

 
# touch /etc/security/opasswd
# chown root:root /etc/security/opasswd
# chmod 600 /etc/security/opasswd

Posted in linux技术

Comments are currently closed.