c4rt1y

谷歌Google Authenticator实现双因素认证

0x01.Google Authenticator 介绍

双因素身份认证就是通过你所知道再加上你所能拥有的这二个要素组合到一起才能发挥作用的身份认证系统。双因素认证是一种采用时间同步技术的系统,采用了基于时间、事件和密钥三变量而产生的一次性密码来代替传统的静态密码。每个动态密码卡都有一个唯一的密钥,该密钥同时存放在服务器端,每次认证时动态密码卡与服务器分别根据同样的密钥,同样的随机参数(时间、事件)和同样的算法计算了认证的动态密码,从而确保密码的一致性,从而实现了用户的认证。

0x02.安装

#安装开发者工具
[root@master ~]# yum groupinstall "Development Tools" -y
# 安装pam 开发包
[root@master ~]# yum install pam-devel -y
# 安装png展示
[root@master ~]# yum install libpng libpng-devel
#安装时间同步
[root@master ~]# yum install chrony -y
#配置时间同步地址
[root@master ~]# vim /etc/chrony.conf 
server 2.cn.pool.ntp.org iburst

#重启
[root@master ~]# systemctl restart chronyd && chronyc sources
#使用上海时区
[root@master ~]# cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

#下载google双验证代码
[root@master ~]# git clone https://github.com/google/google-authenticator-libpam.git

# 编译运行
[root@master ~]# cd google-authenticator-libpam && ./bootstrap.sh && ./configure && make && make install

#在pam添加auth认证
[root@master ~]# vim /etc/pam.d/sshd 
auth       required pam_google_authenticator.so no_increment_hotp

# /etc/pam.d/sshd 内容如下
[root@master ~]# cat /etc/pam.d/sshd  | grep -Ev "^$|^#"
auth       required pam_google_authenticator.so no_increment_hotp
auth	   required	pam_sepermit.so
auth       substack     password-auth
auth       include      postlogin
-auth      optional     pam_reauthorize.so prepare
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
session    required     pam_selinux.so close
session    required     pam_loginuid.so
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
-session   optional     pam_reauthorize.so prepare

# ssh配置文件增加内容
[root@master ~]# vim /etc/ssh/sshd_config 
ChallengeResponseAuthentication yes
UsePAM yes
UseDNS no

# /etc/ssh/sshd_config内容如下
[root@master ~]# cat /etc/ssh/sshd_config  | grep -Ev "^$|^#"
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
AuthorizedKeysFile      .ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication yes
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
UseDNS no
X11Forwarding yes
UsePrivilegeSeparation sandbox          # Default for new installations.
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem       sftp    /usr/libexec/openssh/sftp-server

# 可能会出现so文件路径指向不对,只用软连接
ln -s /usr/local/lib/security/pam_google_authenticator.so /usr/lib64/security/pam_google_authenticator.so 

# 重启sshd
systemctl restart sshd

# 二维砝展示
wget -c http://fukuchi.org/works/qrencode/qrencode-3.4.4.tar.gz
# 解压
tar zxvf qrencode-3.4.4.tar.gz 
#编译运行
cd qrencode-3.4.4 && ./configure  && make && make install

0x03.使用

## 3.1 使用方法1
# 启用 Google Authenticator
[root@master ~]# google-authenticator
Do you want authentication tokens to be time-based (y/n) y
https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/shenyu@shenyu.me%3Fsecret%3DKHMH46EWI2RIRZ53KQTNGHXNP4%26issuer%3Dshenyu.me
# 这里是个二维码
Your new secret key is: KHMH46EWI2RIRZ53KQTNGHXNP4
Your verification code is 753579
Your emergency scratch codes are:
  99181037
  68865807
  88385439
  59103432
  81045035
这里会显示一个二维码,如果你的终端终端不支持显示二维码,可以手动打开这个网页链接(墙)来查看二维码或者手动输入后面的密钥(secret key)来代替扫描二维码,之后的操作会用到这个二维码/密钥(secret key)。这里还有一个认证码(verifiction code),暂时不知道有什么用,以及 5 个紧急救助码(emergency scratch code),紧急救助码就是当你无法获取认证码时(比如手机丢了),可以当做认证码来用,每用一个少一个,但其实可以手动添加的,建议如果 root 账户使用 Google Authenticator 的话一定要把紧急救助码另外保存一份。

Do you want me to update your "/home/test/.google_authenticator" file? (y/n) y
是否更新用户的 Google Authenticator 配置文件,选择 y 才能使上面操作对当前用户生效,其实就是在对应用户的 Home 目录下生成了一个 .google_authenticator 文件,如果你想停用这个用户的 Google Authenticator 验证,只需要删除这个用户 Home 目录下的 .google_authenticator 文件就可以了。

Do you want to disallow multiple uses of the same authentication
token? This restricts you to one login about every 30s, but it increases
your chances to notice or even prevent man-in-the-middle attacks (y/n) y
每次生成的认证码是否同时只允许一个人使用?这里选择 y。

By default, tokens are good for 30 seconds. In order to compensate for
possible time-skew between the client and the server, we allow an extra
token before and after the current time. If you experience problems with
poor time synchronization, you can increase the window from its default
size of +-1min (window size of 3) to about +-4min (window size of
17 acceptable tokens).
Do you want to do so? (y/n) n
是否增加时间误差?这里选择 n。

If the computer that you are logging into isn't hardened against brute-force
login attempts, you can enable rate-limiting for the authentication module.
By default, this limits attackers to no more than 3 login attempts every 30s.
Do you want to enable rate-limiting (y/n) y
是否启用次数限制?这里选择 y,默认每 30 秒最多尝试登录 3 次。


# 3.1.2 使用命令行(推荐)
[root@master ~]# google-authenticator -t -f -d -l shenyu@shenyu.me -i SHENYU.ME -r 3 -R 30 -W

google-authenticator [<options>]
 -h, --help               Print this message
 -c, --counter-based      Set up counter-based (HOTP) verification
 -t, --time-based         Set up time-based (TOTP) verification
 -d, --disallow-reuse     Disallow reuse of previously used TOTP tokens
 -D, --allow-reuse        Allow reuse of previously used TOTP tokens
 -f, --force              Write file without first confirming with user
 -l, --label=<label>      Override the default label in "otpauth://" URL
 -i, --issuer=<issuer>    Override the default issuer in "otpauth://" URL
 -q, --quiet              Quiet mode
 -Q, --qr-mode={NONE,ANSI,UTF8}
 -r, --rate-limit=N       Limit logins to N per every M seconds
 -R, --rate-time=M        Limit logins to N per every M seconds
 -u, --no-rate-limit      Disable rate-limiting
 -s, --secret=<file>      Specify a non-standard file location
 -S, --step-size=S        Set interval between token refreshes
 -w, --window-size=W      Set window of concurrently valid codes
 -W, --minimal-window     Disable window of concurrently valid codes

 # 3.2 软件下载
 手机端下载Google Authenticator工具,扫描二维码,或者使用密码登录

auth

 # 3.3 登录测试(双验证=验证码+密码)

auth-with-password

# 3.4 验证码登录
注释/etc/pam.d/sshd 中的#auth       substack     password-auth
# /etc/pam.d/sshd 内容如下
[root@master ~]# cat /etc/pam.d/sshd  | grep -Ev "^$|^#"
auth       required pam_google_authenticator.so no_increment_hotp
auth	   required	pam_sepermit.so
#auth       substack     password-auth
auth       include      postlogin
-auth      optional     pam_reauthorize.so prepare
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
session    required     pam_selinux.so close
session    required     pam_loginuid.so
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
-session   optional     pam_reauthorize.so prepare

auth-with-nopassword

3.5 免密码双验证登录(双验证=秘钥+验证码)

3.5.1 服务器上添加免密码登录sshkey

3.5.2 配置ssh文件
# ssh配置文件增加内容
[root@master ~]# vim /etc/ssh/sshd_config 
ChallengeResponseAuthentication yes
UsePAM yes
AuthenticationMethods  publickey,keyboard-interactive
UseDNS no

# /etc/ssh/sshd_config内容如下
[root@master ~]# cat /etc/ssh/sshd_config  | grep -Ev "^$|^#"
HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
AuthorizedKeysFile      .ssh/authorized_keys
PasswordAuthentication yes
ChallengeResponseAuthentication yes
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
UseDNS no
X11Forwarding yes
UsePrivilegeSeparation sandbox          # Default for new installations.
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem       sftp    /usr/libexec/openssh/sftp-server
AuthenticationMethods  publickey,keyboard-interactive

3.5.3 配置pam文件
必须注释/etc/pam.d/sshd 中的#auth       substack     password-auth

# /etc/pam.d/sshd 内容如下
[root@master ~]# cat /etc/pam.d/sshd  | grep -Ev "^$|^#"
auth       required pam_google_authenticator.so no_increment_hotp
auth	   required	pam_sepermit.so
#auth       substack     password-auth
auth       include      postlogin
-auth      optional     pam_reauthorize.so prepare
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
session    required     pam_selinux.so close
session    required     pam_loginuid.so
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
-session   optional     pam_reauthorize.so prepare

登录成如下图所示:

auth-with-publickey-with-nopassword-3

备注:
1.sshd配置文件加入AuthenticationMethods  publickey,keyboard-interactive
2.如果未添加ssh,则会导致服务器无法登陆,除非服务器本地登陆

auth-with-publickey-with-nopassword-1

3.必须屏蔽pam中的密码验证,否则登录需要输入密码

auth-with-publickey-with-nopassword-2

3.6 登录地址权限限制(pam策略)
# 增加权限设置 /etc/pam.d/sshd 
[root@master ~]# vim /etc/pam.d/sshd 
auth require pam_access.so accessfile=/etc/security/access.conf

# /etc/pam.d/sshd 内容如下
[root@master ~]# cat /etc/pam.d/sshd  | grep -Ev "^$|^#"
auth 		require pam_access.so accessfile=/etc/security/access.conf
auth       required pam_google_authenticator.so no_increment_hotp
auth	   required	pam_sepermit.so
#auth       substack     password-auth
auth       include      postlogin
-auth      optional     pam_reauthorize.so prepare
account    required     pam_nologin.so
account    include      password-auth
password   include      password-auth
session    required     pam_selinux.so close
session    required     pam_loginuid.so
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
-session   optional     pam_reauthorize.so prepare

# 配置/etc/security/access.conf
[root@master ~]# vim /etc/security/access.conf
# 只循序192.168.1.0/24段登录
- : ALL : ALL
+ : ALL : 192.168.1.0/24

0x04.资料来源

https://shenyu.me/2016/09/05/centos-google-authenticator.html
http://www.cnblogs.com/hanyifeng/p/5467521.html
https://www.cnblogs.com/hanyifeng/p/5516053.html
https://github.com/google/google-authenticator-libpam 
GoTop