前言
什么是双因子认证
双因子认证(英语:Two-factor authentication,缩写为2FA),又译为双重验证、双因子验证、双因素验证、二元认证,是多重要素验证中的一个特例,使用两种不同的元素,合并在一起,来确认用户的身份。
传统的单一密码认证(即知识要素,如用户名和密码)容易受到攻击,因此,为了增强安全性,双因子认证引入了至少还需要第二种形式的认证。这种方式通常结合以下两种或更多种验证要素:
知识要素:用户知道的东西,例如密码、PIN码。
持有的物件:用户拥有的东西,如安全令牌、智能卡、手机(通过短信或认证应用生成的一次性代码)。
固有要素(在双因子认证中通常不同时使用):生物特征,例如指纹、虹膜扫描、面部识别。
HOTP和TOTP
HOTP(HMAC-Based One-Time Password,基于HMAC的一次性密码)和TOTP(Time-Based One-Time Password,基于时间的一次性密码)都是实现一次性密码(OTP)的技术,常用于双因素认证中,以增强账户的安全性。它们的主要区别在于生成密码的方式和同步机制:
生成机制:
- HOTP:基于事件同步。HOTP使用一个计数器(counter,简称ctr)作为移动因子(moving factor),每次认证时,计数器递增,服务器和客户端都需要知道当前的计数器值来生成匹配的密码。密码是通过将计数器值与一个共享密钥一起通过HMAC算法计算得出的。
- TOTP:基于时间同步。TOTP利用当前时间作为移动因子,通常以30秒为一个时间步长(time step),在这个时间间隔内生成的密码是相同的。密码是通过将当前时间戳(通常是自1970年1月1日以来的秒数,经过特定偏移和时间步长调整)与共享密钥一起通过HMAC算法计算得出的。
同步需求:
- HOTP:要求客户端和服务器上的计数器保持同步。如果计数器不同步(例如,客户端错过或重复了一个计数器值),则需要通过额外的机制(如手动调整计数器)来重新同步。
- TOTP:依赖于精确的时间同步。客户端和服务器必须有大致相同的时间,否则会因为时间偏差导致密码不匹配。不过,大多数实现都允许一定的时间偏移以应对时钟漂移。
应用场景:
- HOTP:更适合于网络不稳定或时钟不同步的环境,因为它不依赖于绝对时间,但需要解决计数器同步问题。
- TOTP:在大多数现代系统中更为常见,尤其是那些能够维持时间同步的环境,因为它实现简单且用户体验较好,用户无需手动管理计数器。
安装和配置OATH Toolkit
安装OATH Toolkit中的工具和相关库
dnf install pam_oath oathtool qrencode
生成随机种子(令牌)
方法一
openssl rand -hex 32
方法二
head -10 /dev/urandom | sha512sum | cut -b 1-30
可以用以下命令将随机种子(令牌)导出为图片,以下的secret仅仅作为示例,不要在实际的工作环境中使用,注意这里的secret要根据实际情况调整,这里为了在freeotp平台添加所以使用了Base32格式,默认算法是SHA1
qrencode -o /tmp/user.png 'otpauth://totp/MFAtest?otpauth://totp/MFAtest?issuer=myexample&secret=GWSR5NIPEGJTVGGVCSM3O22F&Algorithm=SHA1&digits=6&period=30'
写入配置文件/etc/users.oath
写入以下内容,表示使用TOTP方式,时间窗口为30s,pin码为6位,用户名是hj,令牌为c7878cdbcf95d729967e7877a7a990
users.oath中需要定义所有使用该服务的用户(可以包含root),如果没有在文件中定义,会直接判定验证结果为失败
HOTP/T30/6 hj - c7878cdbcf95d729967e7877a7a990
配置ssh相关参数并重启服务
按照以下配置来修改/etc/ssh/sshd_config
PasswordAuthentication yes
ChallengeResponseAuthentication yes
UsePAM yes
修改/etc/pam.d/sshd,新增以下内容,指定从/etc/users.oath读取配置,如果加在auth的第一行则表示先验证OTP,再验证用户密码,如果加在auth的最后一行则反之
auth required pam_oath.so usersfile=/etc/users.oath window=30 digits=6
修改后的内容如下
#%PAM-1.0
auth substack password-auth
auth include postlogin
auth required pam_oath.so usersfile=/etc/users.oath window=30 digits=6
account required pam_sepermit.so
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 optional pam_motd.so
session include password-auth
session include postlogin
重启sshd服务
systemctl restart sshd
验证
计算实时pin码
[root@localhost ~]# oathtool -v --totp c7878cdbcf95d729967e7877a7a990 -w 5
Hex secret: c7878cdbcf95d729967e7877a7a990
Base32 secret: Y6DYZW6PSXLSTFT6PB32PKMQ
Digits: 6
Window size: 5
TOTP mode: SHA1
Step size (seconds): 30
Start time: 1970-01-01 00:00:00 UTC (0)
Current time: 2024-05-11 07:51:09 UTC (1715413869)
Counter: 0x368812E (57180462)
135923
459844
361657
706010
728960
160225
在登录时输入正确的pin码即可完成登录
PS C:\Users\12058> ssh hj@192.168.15.171
Authorized users only. All activities may be monitored and reported.
(hj@192.168.15.171) Password:
(hj@192.168.15.171) One-time password (OATH) for `hj':
Authorized users only. All activities may be monitored and reported.
Last login: Sat May 11 11:36:45 2024 from 192.168.105.1
Welcome to 4.19.90-2312.1.0.0255.oe2003sp4.x86_64
System information as of time: Sat May 11 11:37:20 CST 2024
System load: 0.00
Processes: 138
Memory used: 7.8%
Swap used: 0.0%
Usage On: 7%
IP address: 192.168.15.171
Users online: 3
To run a command as administrator(user "root"),use "sudo <command>".
验证失败
解决方案一
需要查看selinux策略
getenforce
如果不为Permissive,则需要设置为Permissive
setenforce 0
解决方案二
查询缺失规则
audit2allow -a /var/log/audit/audit.log*
根据缺失规则生成一个策略模块
audit2allow -a /var/log/audit/audit.log* -M pam_oath
加载策略模块
semodule -i pam_oath.pp
附录
linux-pam
模块类型
Linux-PAM有四种模块类型,分别代表四种不同的任务,它们是:
认证管理(auth),账号管理(account),会话管理(session)和密码(password)管理,一个类型可能有多行,它们按顺序依次由PAM模块调用
-
认证管理(auth) :
- 负责验证用户的身份。
- 检验用户输入的凭证(比如密码、一次性密码、证书等)是否正确。
- 常见的模块有
pam_unix.so
(用于UNIX密码认证)、pam_ldap.so
(用LDAP服务认证)等。
-
账号管理(account) :
- 一旦用户身份验证成功,账号管理用于进一步检查账号状态。
- 它用来确认用户账号的有效性,比如确认账号没有过期、时间段内是否允许登录、用户是否有访问请求资源的权限等。
- 常见模块比如
pam_nologin.so
(检查是否有nologin文件,决定系统是否关闭登录)。
-
会话管理(session) :
- 开始和结束用户的登录会话。
- 负责设置和清除用户登录后的会话环境,如用户环境变量、挂载用户的文件系统、日志记录等。
- 会话管理模块包括
pam_mkhomedir.so
(用于创建用户家目录)或pam_lastlog.so
(更新/显示最后一次登录的时间)。
-
密码(password) :
- 用于更新用户凭证,如密码。
- 当用户需要更改密码时,这一类别的模块会被调用。
- 包括切换密码,确保新密码的复杂度和安全性,关联的模块如
pam_cracklib.so
(用于检查密码的复杂度和安全性)。
控制标记
-
required:
- 这个模块必须执行成功。即使该模块失败了,PAM会继续执行后续的模块来收集更多失败信息,但最终的认证结果将是失败。其他
required
模块仍会执行,以便提供完整的日志记录。
- 这个模块必须执行成功。即使该模块失败了,PAM会继续执行后续的模块来收集更多失败信息,但最终的认证结果将是失败。其他
-
requisite:
- 类似于
required
,但如果此类模块失败,那么整个认证过程会立即终止,并返回一个失败的结果,后续的模块将不会被执行。这对于避免不必要的处理非常有用,比如在明确知道认证会失败时。
- 类似于
-
sufficient:
- 如果此类模块成功,并且在它之前的所有
required
模块也成功了,那么认证过程将成功,后续的模块将不会被执行。如果一个required
模块在sufficient
模块之前失败了,即使sufficient
模块成功了,认证也会失败。如果sufficient
模块本身失败了,那么这并不会导致立即认证失败,而是继续执行后续模块。
- 如果此类模块成功,并且在它之前的所有
-
optional:
- 此类模块不是绝对必需的,对认证过程成功与否没有直接的决定性影响。一般来说,要通过多个
optional
模块的聚合结果或者其他required
模块的结果来决定认证结果。
- 此类模块不是绝对必需的,对认证过程成功与否没有直接的决定性影响。一般来说,要通过多个
-
include:
- 这不是一个控制标志,而是一种引用其他PAM配置文件的方法。你可以在一个PAM服务的配置文件中使用
include
引用另一个通用配置的集合,这样可以复用和共享认证配置模块,避免重复配置同样的模块。
- 这不是一个控制标志,而是一种引用其他PAM配置文件的方法。你可以在一个PAM服务的配置文件中使用
服务端方案
服务器需要配置双因子认证服务,一般有以下方案
客户端方案
客户端录入令牌以及根据令牌获取OTP,一般有以下方案