一、背景
通过绿盟等安扫软件扫描到服务器OpenSSH存在漏洞,需要升级修复,通过编译最新OpenSSH完成升级后,出现如下问题:
问题1:控制台服务和其他服务器之间的免秘钥登陆失效
问题2:在服务器通过ulimit -a查看普通用户(非root)能打开文件数被重置为1024,不是之前调优过的65535
二、 解决方法
控制台服务和其他服务器之间的免秘钥登陆失效
针对问题1,执行 sudo cat /var/log/secure 查看系统的安全日志
检查各服务器SSH 升级后相关秘钥证书、目录属主和权限
$ ls -l /etc/ssh/*key*
$ ls -l ~/.ssh
$ ls -ld ~/.ssh
私钥 400
公钥 644
相关证书存放目录 700
确保相关证书存放目录属主正确
如果是基于JAVA应用,使用JSCH连接SSH报错:Invalid privatekey,那么需要看一下 生产密钥对的类型。
SSH版本太高,默认生成密钥格式不同了,会导致解析失败!
一个是RSA,一个是OPENSSH的密钥了,那么解析不了就很正常了。
重新生产秘钥对,ssh-keygen -m PEM -t rsa,加上参数-m PEM,生成的密钥对,就是RSA的了。
$ ssh-keygen -m PEM -t rsa -b 4096
在服务器通过ulimit -a查看普通用户(非root)能打开文件数被重置为1024
针对问题2,在服务器通过ulimit -a查看普通用户(非root)能打开文件数被重置为1024,不是之前调优过的65535
这会导致一些问题:
使用普通业务用户启动组件,如果某些组件启动时对打开句柄数有要求,那么会启动失败;
就算启动成功,在高并发的情况下,会报错 too many open files
并且观察到一个现象,如果你以root用户切到普通业务用户,句柄数是调优数,再启动业务进程,没问题。
If this problem occurs in SSH sessions, it may be that SSH servers are not configured to use PAM yes.
/etc/security/limits.conf is a configuration file for the pam_limits module (refer to man limits.conf).
For SSH sessions, to make limits. conf effective, you must ensure that the UsePAM option in the SSH server configuration is valid.
By the way, two points are not directly related to the solution of this problem:
- For limits.conf changes to take effect, no system reboot is required. Just log in again.
- A clumsy way to avoid this is to add ulimit-n 65535 to the current user’s .bashrc file.
根据OpenSSH的安装说明,如果有启用PAM,那么就需要手工安装一个给sshd程序使用的PAM配置文件,否则安装好OpenSSH后你可能会无法使用密码登录系统。
在编译时,我使用 --with-pam 选项启用了对PAM的支持,但是,编译OpenSSH时并没有编译选项让你指定PAM配置文件的位置,那么我们要怎么提供这个配置文件呢?
事实上,OpenSSH有另外一个编译选项--with-pam-service=name可以指定PAM服务名,它的默认值是sshd,操作系统自带的PAM软件默认将所有PAM配置文件都放置在/etc/pam.d目录下。
结合这两个信息,就可确定OpenSSH的PAM配置文件应为/etc/pam.d/sshd文件。
这个文件原来就有了,所以我们不用额外手工创建一个。
注意,UsePAM一定要启用,OpenSSH的安装说明里有提到,如果编译时启用了PAM支持,那么就必须在sshd_config文件中启用它。
- 编译时OpenSSH,需要加编译参数 --with-pam
./configure --prefix=/usr/ --sysconfdir=/etc/ssh --with-pam XXX (其他编译参数)
- OpenSSH配置文件sshd_config中启动 PAM
cat /etc/pam.d/sshd
%PAM-1.0
auth required pam_sepermit.so
auth substack password-auth
auth include postlogin
# Used with polkit to reauthorize users in remote sessions
-auth optional pam_reauthorize.so prepare
account required pam_nologin.so
account include password-auth
password include password-auth
# pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session required pam_loginuid.so
# pam_selinux.so open should only be followed by sessions to be executed in the user context
session required pam_selinux.so open env_params
session required pam_namespace.so
session optional pam_keyinit.so force revoke
session include password-auth
session include postlogin
# Used with polkit to reauthorize users in remote sessions
-session optional pam_reauthorize.so prepare
# cat /etc/ssh/sshd/sshd_config
use PAM yes
# systemctl restart sshd
三、关于SSH的PAM验证机制
RPM包安装OpenSSH自带PAM模块;如果是编译安装,必须--with-pam。
登录时的PAM验证机制流程:
第一阶段:验证阶段
1)经过pam_securetty.so判断,看用户是什么,如果是root,读取/etc/securetty的配置
2)经过pam_env.so配置额外的环境变量
3)透过pam_unix.so验证口令
4)3验证不通过则pam_deny.so判断UID是不是大于500.小于500则返回失败
5)由pam_deny.so拒绝连接
第二阶段:授权阶段
1)先以pam_nologin.so判断/etc/nologin是否存在,若存在则不许一般使用者登陆;
2)以pam_unix进行账号管理,
3)pam_succeed_if.so判断UID是否小于500,若小于500则不记录登录信息。
4)最后以pam_permit.so允许该账号登陆。
第三阶段:口令阶段
1)先以pam_cracklib.so配置口令仅能尝试错误3次;
2)接下来以pam_unix.so透过md5,shadow等功能进行口令检验,若通过则回报login程,若不通过则以pam_deny.so拒绝登陆。
第四阶段:会议阶段
1)先以pam_selinux.so暂时关闭SELinux;
2)使用pam_limits.so配置好用户能够操作的系统资源;
3)登陆成功后开始记录相关信息在登录文件中;
4)以 pam_loginuid.so规范不同的 UID 权限;
5)开启pam_selinux.so的功能。
如何确定ssh是否编译了PAM模块?
在SSH主配置文件/etc/ssh/sshd_config开启PAM机制「UsePAM yes」查看log中没有PAM的报错,有报错是这样的「Starting sshd:/etc/ssh/sshd_config line 82: Unsupported option UsePAM」,说明没有编译PAM模块。
为什么root无法以telnet直接登陆系统,但是却能够使用ssh直接登陆?
一般来说,telnet会引用login的PAM模块,而login的验证阶段会有/etc/securetty的限制。
由于远程联机属于pts/n (n 为数字)的动态终端机接口装置名称,并没有写入到/etc/securetty ,因此root无法以telnet登陆远程主机。
至于ssh使用的是/etc/pam.d/sshd这个模块,你可以查阅一下该模块,由于该模块的验证阶段并没有加入pam_securetty,因此就没有/etc/securetty的限制,故可以从远程直接联机到服务器端。
为什么编译OpenSSH没有启动PAM 模块,root用户能打开的句柄数ok,其他普通业务用户却被重置为默认的1024了呢?
一般创建通业务用户,用户uid都大于500,如果不启用PAM模块,无法读取全局级的 /etc/security/limits.conf 下关于用户打开句柄数的配置。
四、 参考
在登录时使用pam管理limit
https://www.linuxprobe.com/ulimit.html
JSCH连接SSH报错:Invalid privatekey
https://www.jianshu.com/p/dc90771761a7
Why can't you modify ulimit's value?
https://developpaper.com/question/why-cant-you-modify-ulimits-value
"open files" ulimit: controlling via limits.conf
https://serverfault.com/questions/387884/open-files-ulimit-controlling-via-limits-conf
升级操作系统OpenSSH及其OpenSSL的正确姿势
https://blog.51cto.com/techsnail/2138927