pam是各种服务登陆验证公共模块,任何程序只要调用对应的模块即可不必重新开发相应的功能。

官方文档:

https://github.com/linux-pam/linux-pam

模块存放目录:/lib64/security/

服务调用模块配置文件目录:/etc/pam.d,各种服务是如何调用模块的都在这里配置

专有配置文件:/etc/security/

日志文件:/var/log/secure

]# 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.
# 验证类型  是否必须、可选 模块名称   参数
# type      control       module-path arguments
auth        required      pam_env.so
auth        required      pam_faildelay.so delay=2000000
auth        sufficient    pam_unix.so nullok try_first_pass
auth        requisite     pam_succeed_if.so uid >= 1000 quiet_success
auth        required      pam_deny.so

account     required      pam_unix.so
account     sufficient    pam_localuser.so
account     sufficient    pam_succeed_if.so uid < 1000 quiet
account     required      pam_permit.so

password    requisite     pam_pwquality.so try_first_pass local_users_only retry=3 authtok_type=
password    sufficient    pam_unix.so sha512 shadow nullok try_first_pass use_authtok
password    required      pam_deny.so

session     optional      pam_keyinit.so revoke
session     required      pam_limits.so
-session     optional      pam_systemd.so # 前面的“-”表示这个模块可选,有就验证没有就不验证
session     [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid
session     required      pam_unix.so

type:指模块类型,即功能。

control :PAM库该如何处理与该服务相关的PAM模块的成功或失败情况,一个关健词实现。

module-path: 用来指明本模块对应的程序文件的路径名。

Arguments: 用来传递给该模块的参数。


模块类型(module-type):

        Auth 账号的认证和授权

        Account 帐户的有效性,与账号管理相关的非认证类的功能,如:用来限制/允许用户对某个服务的访问时间,限制用户的位置(例如:root用户只能从控制台登录)。

        Password 用户修改密码时密码复杂度检查机制等功能。

        Session 用户会话期间的控制,如:最多打开的文件数,最多的进程数等。

        -type 表示因为缺失而不能加载的模块将不记录到系统日志,对于那些不总是安装在系统上的模块有用

Control:

        required :一票否决,表示本模块必须返回成功才能通过认证,但是如果该模块返回失败,失败结果也不会立即通知用户,而是要等到同一type中的所有模块全部执行完毕,再将失败结果返回给应用程序,即为必要条件。

        requisite :一票否决,该模块必须返回成功才能通过认证,但是一旦该模块返回失败,将不再执行同一type内的任何模块,而是直接将控制权返回给应用程序。是一个必要条件。

        sufficient :一票通过,表明本模块返回成功则通过身份认证的要求,不必再执行同一type内的其它模块,但如果本模块返回失败可忽略,即为充分条件,优先于前面的required和requisite。

        optional :表明本模块是可选的,它的成功与否不会对身份认证起关键作用,其返回值一般被忽略。

        include: 调用其他的配置文件中定义的配置信息。

module-path:

        模块文件所在绝对路径:

        模块文件所在相对路径:/lib64/security目录下的模块可使用相对路径,如:pam_shells.so、 pam_limits.so

        有些模块有自已的专有配置文件,在/etc/security/*.conf目 录下

Arguments:

        debug :该模块应当用syslog( )将调试信息写入到系统日志文件中

        no_warn :表明该模块不应把警告信息发送给应用程序

        use_first_pass :该模块不能提示用户输入密码,只能从前一个模块得到输入密码

        try_first_pass :该模块首先用前一个模块从用户得到密码,如果该密码验证不通过,再提示用户输入新密码

        use_mapped_pass 该模块不能提示用户输入密码,而是使用映射过的密码

        expose_account 允许该模块显示用户的帐号名等信息,一般只能在安全的环境下使用,因为泄漏用户名会对安全造成一定程度的威胁。


注意:修改PAM配置文件将马上生效

建议:编辑pam规则时,保持至少打开一个root会话,以防止root身份验证错误


常用模块


pam_shells 模块:

功能:检查有效shell,检查shell是否在 /etc/shells中。

帮助:man pam_shells

案例:不允许使用/bin/csh的用户本地登录

]# yum -y install csh
]# vim /etc/pam.d/login
auth required pam_shells.so 
]# vim /etc/shells
去掉 /bin/csh
]# useradd -s /bin/csh testuser
# testuser将不可登录
]# tail /var/log/secure


pam_securetty.so 模块:

检查登陆的终端是否在 /etc/securetty 中。

功能:只允许root用户在 /etc/securetty 列出的安全终端上登陆。

案例:CentOS 7 允许root在telnet登陆。

vi /etc/pam.d/remote
# 将下面一行加上注释
# auth required pam_securetty.so 
# 或者/etc/securetty文件中加入
pts/0,pts/1…pts/n
# 测试用root telnet登录


pam_nologin.so 模块:

功能:如果/etc/nologin文件存在,将导致非root用户不能登陆,当该用户登陆时,会显示/etc/nologin文

件内容,并拒绝登陆。

范例: 默认此模块可以对ssh等登录有效,但不影响su登录。

pam.d]#grep pam_nologin *
login:account   required     pam_nologin.so
remote:account   required     pam_nologin.so
sshd:account   required     pam_nologin.so


pam_limits.so 模块:

查看当前资源限制:

]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15054
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 60000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15054
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited # unlimited 是一个特殊值,用于表示不限制

查询时,若不加H或S参数,默认显示的是软限制

修改时,若不加H或S参数,两个参数一起改变


ulimit命令:

ulimit是linux shell的内置命令,它具有一套参数集,用于对shell进程及其子进程进行资源限制。

ulimit的设定值是 per-process 的,也就是说,每个进程有自己的limits值。

使用ulimit进行修改,立即生效。

ulimit只影响shell进程及其子进程,用户登出后失效。

可以在profile中加入ulimit的设置,变相的做到永久生效。

-H 设置硬件资源限制.
-S 设置软件资源限制.
-a 显示当前所有的资源限制.
-c size:设置core文件的最大值.单位:blocks
-d size:设置数据段的最大值.单位:kbytes
-f size:设置创建文件的最大值.单位:blocks
-l size:设置在内存中锁定进程的最大值.单位:kbytes
-m size:设置可以使用的常驻内存的最大值.单位:kbytes
-n size:设置内核可以同时打开的文件描述符的最大值.单位:n
-p size:设置管道缓冲区的最大值.单位:kbytes
-s size:设置堆栈的最大值.单位:kbytes
-t size:设置CPU使用时间的最大上限.单位:seconds
-u size:最大用户进程数
-v size:设置虚拟内存的最大值.单位:kbytes

案例:

ulimit -Hs 64	# 限制硬资源,线程栈大小为 64K.
ulimit -Sn 32	# 限制软资源,32 个文件描述符。
ulimit -a	# 显示当前所有的 limit 信息
ulimit -c unlimited	# 对生成的 core 文件的大小不进行限制
ulimit -d unlimited	# 对进程的数据段大小不进行限制。
ulimit -f 2048	# 限制进程可以创建的最大文件大小为 2048blocks.
ulimit -132	# 限制最大可加锁内存大小为 32 Kbytes。
ulimit -m unlimited	#对最大内存不进行限制。
ulimit -n 128	# 限制最大可以使用 128 个文件描述符
ulimit -p 512	# 限制管道缓冲区的大小为 512 Kbytes.
ulimit -s 512	# 限制线程栈的大小为 512 Kbytes.
ulimit -t unlimited	# 对最大的 CPU 占用时间不进行限制
ulimit -u 64		# 限制用户最多可以使用 64 个进程
ulimit -v 200000	# 限制最大可用的虚拟内存为 200000Kbytes.

限制的类型

Soft 软限制,普通用户自己可以修改

Hard 硬限制,由root用户设定,且通过kernel强制生效,“-”二者同时限定

限制的资源

nofile 所能够同时打开的最大文件数量,默认为1024

nproc 所能够同时运行的进程的最大数量,默认为1024


示例:

被请求机器:

yum install httpd -y
systemctl status httpd
]# ulimit -n
1024

发送请求机器:

yum install httpd-tools -y
ab -c1000 -n 2000  http://192.168.1.71/

limit配置文件:配置文件只影响到登陆的用户,不影响系统服务

/etc/security/limits.conf
/etc/security/limits.d/*.conf

格式:

<domain>       <type> <item> <value>

domain:可以是用户名、组名、通配符。

type:硬限制、乱限制,“-”横线代表软限制和硬限制设置为一样。

item:各种资源的限制。

value:限制的值。

#<item> can be one of the following:
#        - core - limits the core file size (KB)
#        - data - max data size (KB)
#        - fsize - maximum filesize (KB)
#        - memlock - max locked-in-memory address space (KB)
#        - nofile - 最大文件数
#        - rss - max resident set size (KB)
#        - stack - max stack size (KB)
#        - cpu - max CPU time (MIN)
#        - nproc - 最大进程数
#        - as - address space limit (KB)
#        - maxlogins - 最大登陆数
#        - maxsyslogins - max number of logins on the system
#        - priority - the priority to run user process with
#        - locks - max number of file locks the user can hold
#        - sigpending - max number of pending signals
#        - msgqueue - max memory used by POSIX message queues (bytes)
#        - nice - max nice priority allowed to raise to values: [-20, 19]
#        - rtprio - max realtime priority

示例:

ops - nproc 5 # ops用户的软硬设置相同,打开的进程数不能超过5
pgrep -u ops # 查看用户打开的进程数

生产配置示例:根据服务器性能来设置,否者如果真的有那么大的量容易把机器搞挂,如果有问题可以查看日志 /var/log/secure。

*    -   core       unlimited
*    -   nproc       1000000
*    -   nofile      1000000
*    -   memlock     32000
*    -   msgqueue    8192000


pam_succeed_if.so 模块:

功能:根据参数中的所有条件都满足才返回成功

案例:ubutun不允许root登陆图形界面,注释掉下面行即可。

vim /etc/pam.d/gdm-passwd
#将下面行注释
#auth requried pam_succeed_if.so user !=root quiet_success


pam_google_authenticator.so 模块:

MFA安装脚本:

]# cat google-authenticator.sh 
#安装epel
#yum install -y epel-release.noarch 
#yum makecache 
#安装google authenticator
yum install -y google-authenticator.x86_64


echo -e "\033[31mDo you want me to update your "/root/.google_authenticator" file? (y/n) y"
echo -e "\033[31m你希望我更新你的“/root/.google_authenticator”文件吗(y/n)?\033[0m"
echo -e "\033[31mDo you want to disallow multiple uses of the same authentication"
echo -e "\033[31mtoken? This restricts you to one login about every 30s, but it increases"
echo -e "\033[31myour chances to notice or even prevent man-in-the-middle attacks (y/n) y"
echo -e "\033[31m你希望禁止多次使用同一个验证令牌吗?这限制你每次登录的时间大约是30秒, 但是这加大了发现或甚至防止中间人攻击的可能性(y/n)?\033[0m"
echo -e "\033[31mBy default, a new token is generated every 30 seconds by the mobile app."
echo -e "\033[31mIn order to compensate for possible time-skew between the client and the server,"
echo -e "\033[31mwe allow an extra token before and after the current time. This allows for a"
echo -e "\033[31mtime skew of up to 30 seconds between authentication server and client. If you"
echo -e "\033[31mexperience problems with poor time synchronization, you can increase the window"
echo -e "\033[31mfrom its default size of 3 permitted codes (one previous code, the current"
echo -e "\033[31mcode, the next code) to 17 permitted codes (the 8 previous codes, the current"
echo -e "\033[31mcode, and the 8 next codes). This will permit for a time skew of up to 4 minutes"
echo -e "\033[31mbetween client and server."
echo -e "\033[31mDo you want to do so? (y/n) y"
echo -e "\033[31m默认情况下,令牌保持30秒有效;为了补偿客户机与服务器之间可能存在的时滞,\033[0m"
echo -e "\033[31m我们允许在当前时间前后有一个额外令牌。如果你在时间同步方面遇到了问题, 可以增加窗口从默认的3个可通过验证码增加到17个可通过验证码,\033[0m"
echo -e "\033[31m这将允许客户机与服务器之间的时差增加到4分钟。你希望这么做吗(y/n)?\033[0m"
echo -e "\033[31mIf the computer that you are logging into isn't hardened against brute-force"
echo -e "\033[31mlogin attempts, you can enable rate-limiting for the authentication module."
echo -e "\033[31mBy default, this limits attackers to no more than 3 login attempts every 30s."
echo -e "\033[31mDo you want to enable rate-limiting? (y/n) y"
echo -e "\033[31m如果你登录的那台计算机没有经过固化,以防范运用蛮力的登录企图,可以对验证模块\033[0m"
echo -e "\033[31m启用尝试次数限制。默认情况下,这限制攻击者每30秒试图登录的次数只有3次。 你希望启用尝试次数限制吗(y/n)?\033[0m"
echo -e "\033[32m 在App Store 搜索Google Authenticator 进行App安装 \033[0m"


google-authenticator


#/etc/pam.d/sshd文件,修改或添加下行保存
#auth required pam_google_authenticator.so
sed -i '1a\auth       required     pam_google_authenticator.so' /etc/pam.d/sshd
#编辑/etc/ssh/sshd_config找到下行
#ChallengeResponseAuthentication no
#更改为
#ChallengeResponseAuthentication yes
sed -i 's/^ChallengeResponseAuthentication.*/ChallengeResponseAuthentication yes/' /etc/ssh/sshd_config

#重载SSH服务
systemctl reload sshd

救急码:安装过程中出现如下救急码,手机丢了可以救急,用一个少一个,这个救急码放在 /root/.google_authenticator 文件中,可以自己任意添加。

Your emergency scratch codes are:
  50665588
  57653681
  10399412
  66592355
  60848305

ssh key如果也需要MFA的话需要在/etc/ssh/sshd_config上添加如下配置:

AuthenticationMethods publickey,keyboard-interactive