
用MFA加固PAM
我第一个云服务器只用了不到一天,准确一些来说四个小时,然后就被人爆了密码。后来用了很多方法,现在比较稳定下来的方法就是2FA,实质上来说就是一次性密码。
今天我们上很多网站,都可以用单次密码来进行登录,比如说短信验证码,或者有各种各样的身份验证器。
一次性密码
传统的静态密码,大部分用户都会设置一个常见的字符串作为密码,这使得骇客可以用彩虹表的方法轻易查到密码明文。即使密码比较长、没有规律,我们也可以用暴力猜解的方式破解出密码。
所以有种思路是,在静态密码上增加一层动态的密码,来提高安全性。一般来说动态密码实时生成、有有效期,大部分是完全随机,破解的可能性很小。
举个例子,我们今天网页登录苹果帐号,我们的Mac上会弹出一个6位的数字,每次都不一样,从而验证网页登录的是本人。登录坚果云时会通过短信或者微信发送验证码。不少网站还提供了验证器,比如说Steam令牌就是其中一种。
TOTP/HOTP
Google给我们提供了一个可以访问的、易于接入的方案:Google Authenticator。
Google Authenticator支持两种一次性密码,TOTP和HOTP。两种都有一个初始的秘密。
HOTP全程是HMAC based One Time Password。是一种基于事件和次数的OTP。每一次验证完成后都会给一个反馈,同时两边都会记录:下次我要用新的了。
而TOTP全称是Time based One Time Password。是基于时间的OTP,定期刷新,中间留够你输入验证码的时间。
相对来说TOTP用的更多一些,因为用户,比如说我们自己,都是不可靠的,
PAM
PAM全称是可拔插式身份验证模块,是Linux的一个核心模块,openssh啊窗口管理器啊,还有cockpit这类,只要涉及到登录的,很多都是利用PAM。
配置文件在/etc/pam.d
中,每个应用有自己的配置文件。比如说我们今天要用到的ssh和cockpit的配置文件分别是/etc/pam.d/sshd
和/etc/pam.d/cockpit
。
How
安装Google Authenticator
Google Authenticator有一个手机App。
同时也有Linux的软件包叫google-authenticator,应该可以从各个发行版的仓库中直接安装。CentOS需要先启用epel-release仓库。
推荐同时安装qrencode,可以直接展示一个二维码,用手机扫描一下就好了。
在服务一侧给每个用户生成自己的密钥
很多web服务可以帮你生成密钥,比如说jumpserver。
不过我们用的cockpit和ssh本身没这功能。但是如果需要生成密钥,也只是需要运行一个命令:
google-authenticator -t -d -f -r 3 -R 30
其中-t表示基于时间,-d表示一个OTP只能用一次、不可重用,-f表示强制覆盖,-r 3 -R 30表示30秒内可以重试3次。
执行以后,会问你手机上的一次性密码是多少。
有qrencode的话,用手机扫一下二维码,就会得出来结果并且把秘密保存在手机里面。如果没有二维码,手动添加一个就好,选择基于时间,填好密钥就行。
把手机上的一次性密码填到终端里面就会把密钥保存到本地。
添加PAM模块
在服务对应的PAM配置中添加一行
auth required pam_google_authenticator.so nullok
上面是说身份验证时需要用Google Authenticator。如果用户没有创建Authenticator的密钥,就会忽略这步。如果所有用户都需要Google Authenticator的话,就需要提前先都生成好,去掉nullok。
ssh
ssh需要多一步,否则无法正常输入一次性密码。
修改/etc/sshd_config
修改或增加一行配置:
ChallengeResponseAuthentication yes
除此之外还有一个权限问题。看后面。
重启服务
sudo systemctl restart sshd
sudo systemctl restart cockpit
然后再去登录cockpit或者ssh就会提示你,需要输入Verification Code,打开App,输入现在的一次性密码,成功登录,大功告成。
可能会遇到的问题
SELinux
可能会遇到sshd无法创建读写文件的问题。
最好在第一次登录前,在服务器上把SELinux设置为Permissive,登录完成以后执行:
sudo ausearch -c 'sshd' --raw | audit2allow -M my-sshd
sudo semodule -X 300 -i my-sshd.pp
应该生成了一个my-sshd.pp和my-sshd.te文件。te是SELinux的策略文件。大致是这样:
module my-sshd 1.0;
require {
type sshd_t;
type user_home_dir_t;
class file { create getattr open read rename setattr unlink write };
}
#============= sshd_t ==============
allow sshd_t user_home_dir_t:file { getattr rename create open read setattr unlink write };
重启一下服务一般就没有大问题了。