一、介绍:什么是双因素认证

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


二、安装Google Authenticator


2.1 基本环境:

  OS:Centos 7

  IP :192.168.150.125

2.2 所需软件:
chrony
pam-devel
qrencode-3.4.4
libpng、libpng-devel


2.3 部署

2.3.1 安装gcc等编译器,以及需要用到的库

[root@kbsonlong ~]# yum install gcc-c++ git -y


2.3.2 安装pam 开发包

[root@kbsonlong ~]# yum install pam-devel -y

2.3.3 安装chrony 软件,因为动态口令再验证时用到了时间,所以要保持时间上的一致性。简单说下chrony:chrony 是网络时间协议的(NTP)的另一种实现,与网络时间协议后台程序(ntpd)不同,它可以更快地更准确地同步系统始终。如果要使用ntp 需要单独安装。

[root@kbsonlong ~]# yum install chrony -y
[root@kbsonlong ~]# vim /etc/chrony.conf 
…
server 2.cn.pool.ntp.org iburst


重启服务并使用命令查看同步(注:202.118.1.130就是我们上一步添加的那个ntp server)

[root@kbsonlong ~]# systemctl restart chronyd
[root@kbsonlong ~]# chronyc sources
210 Number of sources = 3
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* 202.118.1.130                 2   6    17    54    -58us[ +132us] +/-   85ms
^+ news.neu.edu.cn               2   6    17    54   +542us[ +732us] +/-   89ms
^- dns1.synet.edu.cn             2   6   251    46    +25ms[  +25ms] +/-   60ms

如果时区不对的话,可以拷贝你当前地区所在地的时区到系统运行的时区,如下:

cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

2.3.4 下载Google Authenticator源码

git clone https://github.com/google/google-authenticator-libpam.git


2.3.5 编译安装Google Authentication

[root@kbsonlong google-authenticator-libpam]# pwd
/data/google-authenticator/google-authenticator-libpam
[root@kbsonlong google-authenticator-libpam]# ll
total 80
-rwxr-xr-x 1 root root   605 May  7 16:31 bootstrap.sh
drwxr-xr-x 2 root root  4096 May  7 16:31 build
-rw-r--r-- 1 root root  2081 May  7 16:31 configure.ac
drwxr-xr-x 2 root root  4096 May  7 16:31 contrib
-rw-r--r-- 1 root root  1452 May  7 16:31 CONTRIBUTING.md
drwxr-xr-x 2 root root  4096 May  7 16:31 examples
-rw-r--r-- 1 root root  2622 May  7 16:31 FILEFORMAT
-rw-r--r-- 1 root root 11358 May  7 16:31 LICENSE
-rw-r--r-- 1 root root  2340 May  7 16:31 Makefile.am
drwxr-xr-x 2 root root  4096 May  7 16:31 man
-rw-r--r-- 1 root root  7155 May  7 16:31 README.md
drwxr-xr-x 2 root root  4096 May  7 16:31 src
drwxr-xr-x 2 root root  4096 May  7 16:31 tests
-rw-r--r-- 1 root root  9423 May  7 16:31 totp.html
drwxr-xr-x 2 root root  4096 May  7 16:31 utc-time
[root@kbsonlong google-authenticator-libpam]# ./bootstrap.sh 
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, `build'.
libtoolize: copying file `build/ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIR, `build'.
libtoolize: copying file `build/libtool.m4'
libtoolize: copying file `build/ltoptions.m4'
libtoolize: copying file `build/ltsugar.m4'
libtoolize: copying file `build/ltversion.m4'
libtoolize: copying file `build/lt~obsolete.m4'
configure.ac:16: installing 'build/config.guess'
configure.ac:16: installing 'build/config.sub'
configure.ac:13: installing 'build/install-sh'
configure.ac:13: installing 'build/missing'
Makefile.am: installing 'build/depcomp'
parallel-tests: installing 'build/test-driver'
[root@kbsonlong google-authenticator-libpam]# ./configure
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /usr/bin/grep
checking for egrep... /usr/bin/grep -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking minix/config.h usability... no
checking minix/config.h presence... no
checking for minix/config.h... no
checking whether it is safe to define __EXTENSIONS__... yes
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking for style of include used by make... GNU
checking dependency style of gcc... gcc3
checking whether to enable maintainer-specific portions of Makefiles... yes
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking how to print strings... printf
checking for a sed that does not truncate output... /usr/bin/sed
checking for fgrep... /usr/bin/grep -F
checking for ld used by gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 1572864
checking whether the shell understands some XSI constructs... yes
checking whether the shell understands "+="... yes
checking how to convert x86_64-unknown-linux-gnu file names to x86_64-unknown-linux-gnu format... func_convert_file_noop
checking how to convert x86_64-unknown-linux-gnu file names to toolchain format... func_convert_file_noop
checking for /usr/bin/ld option to reload object files... -r
checking for objdump... objdump
checking how to recognize dependent libraries... pass_all
checking for dlltool... no
checking how to associate runtime and link libraries... printf %s\n
checking for ar... ar
checking for archiver @FILE support... @
checking for strip... strip
checking for ranlib... ranlib
checking command to parse /usr/bin/nm -B output from gcc object... ok
checking for sysroot... no
checking for mt... no
checking if : is a manifest tool... no
checking for dlfcn.h... yes
checking for objdir... .libs
checking if gcc supports -fno-rtti -fno-exceptions... no
checking for gcc option to produce PIC... -fPIC -DPIC
checking if gcc PIC flag -fPIC -DPIC works... yes
checking if gcc static flag -static works... no
checking if gcc supports -c -o file.o... yes
checking if gcc supports -c -o file.o... (cached) yes
checking whether the gcc linker (/usr/bin/ld -m elf_x86_64) supports shared libraries... yes
checking whether -lc should be explicitly linked in... no
checking dynamic linker characteristics... GNU/Linux ld.so
checking how to hardcode library paths into programs... immediate
checking whether stripping libraries is possible... yes
checking if libtool supports shared libraries... yes
checking whether to build shared libraries... yes
checking whether to build static libraries... yes
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking for gcc option to accept ISO C99... -std=gnu99
checking for gcc -std=gnu99 option to accept ISO Standard C... (cached) -std=gnu99
checking sys/fsuid.h usability... yes
checking sys/fsuid.h presence... yes
checking for sys/fsuid.h... yes
checking for explicit_bzero... no
checking for setfsuid... yes
checking for security/pam_appl.h... yes
checking for security/pam_modules.h... yes
checking for pam_get_user in -lpam... yes
checking whether certain PAM functions require const arguments... yes
checking for library containing dlopen... -ldl
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating contrib/rpm.spec
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands

  google-authenticator version 1.05
  Prefix.........: /usr/local
  Debug Build....: 
  C Compiler.....: gcc -std=gnu99 -g -O2 
  Linker.........: /usr/bin/ld -m elf_x86_64  -ldl 

[root@kbsonlong google-authenticator-libpam]# make && make install
make  all-am
make[1]: Entering directory `/data/google-authenticator/google-authenticator-libpam'
  CC       src/pam_google_authenticator_la-pam_google_authenticator.lo
  CC       src/pam_google_authenticator_la-util.lo
  CC       src/pam_google_authenticator_la-base32.lo
  CC       src/pam_google_authenticator_la-hmac.lo
  CC       src/pam_google_authenticator_la-sha1.lo
  CCLD     pam_google_authenticator.la
  CC       src/google-authenticator.o
  CC       src/util.o
  CC       src/base32.o
  CC       src/hmac.o
  CC       src/sha1.o
  CCLD     google-authenticator
make[1]: Leaving directory `/data/google-authenticator/google-authenticator-libpam'
make[1]: Entering directory `/data/google-authenticator/google-authenticator-libpam'
 /usr/bin/mkdir -p '/usr/local/bin'
  /bin/sh ./libtool   --mode=install /usr/bin/install -c google-authenticator '/usr/local/bin'
libtool: install: /usr/bin/install -c google-authenticator /usr/local/bin/google-authenticator
 /usr/bin/mkdir -p '/usr/local/share/doc/google-authenticator'
 /usr/bin/install -c -m 644 FILEFORMAT README.md '/usr/local/share/doc/google-authenticator'
 /usr/bin/mkdir -p '/usr/local/share/doc/google-authenticator'
 /usr/bin/install -c -m 644 totp.html '/usr/local/share/doc/google-authenticator'
 /usr/bin/mkdir -p '/usr/local/share/man/man1'
 /usr/bin/install -c -m 644 man/google-authenticator.1 '/usr/local/share/man/man1'
 /usr/bin/mkdir -p '/usr/local/share/man/man8'
 /usr/bin/install -c -m 644 man/pam_google_authenticator.8 '/usr/local/share/man/man8'
 /usr/bin/mkdir -p '/usr/local/lib/security'
 /bin/sh ./libtool   --mode=install /usr/bin/install -c   pam_google_authenticator.la '/usr/local/lib/security'
libtool: install: /usr/bin/install -c .libs/pam_google_authenticator.so /usr/local/lib/security/pam_google_authenticator.so
libtool: install: /usr/bin/install -c .libs/pam_google_authenticator.lai /usr/local/lib/security/pam_google_authenticator.la
libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/go/bin:/usr/local/go/bin:/root/bin:/sbin" ldconfig -n /usr/local/lib/security
----------------------------------------------------------------------
Libraries have been installed in:
   /usr/local/lib/security

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
make[1]: Leaving directory `/data/google-authenticator/google-authenticator-libpam'


2.3.6 安装二维码生成工具。这步✌也可以省略,如果不装的话,因为下一步生成的二维码就会成一个链接,到时将链接复制到你的浏览器中,也是可以出现二维码的,到时利用智能手机打开google author 进行扫描。


[root@kbsonlong google-authenticator]# wget -c http://fukuchi.org/works/qrencode/qrencode-3.4.4.tar.gz
--2018-05-07 16:35:22--  http://fukuchi.org/works/qrencode/qrencode-3.4.4.tar.gz
Resolving fukuchi.org (fukuchi.org)... 173.230.148.37
Connecting to fukuchi.org (fukuchi.org)|173.230.148.37|:80... connected.
HTTP request sent, awaiting response... 301 Moved Permanently
Location: https://fukuchi.org/works/qrencode/qrencode-3.4.4.tar.gz [following]
--2018-05-07 16:35:23--  https://fukuchi.org/works/qrencode/qrencode-3.4.4.tar.gz
Connecting to fukuchi.org (fukuchi.org)|173.230.148.37|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 468788 (458K) [application/x-gzip]
Saving to: ‘qrencode-3.4.4.tar.gz’

100%[=========================================================================================================================================>] 468,788     --.-K/s   in 0.05s   

2018-05-07 16:35:23 (8.95 MB/s) - ‘qrencode-3.4.4.tar.gz’ saved [468788/468788]

[root@kbsonlong google-authenticator]# tar zxvf qrencode-3.4.4.tar.gz 
qrencode-3.4.4/
qrencode-3.4.4/tests/
qrencode-3.4.4/tests/Makefile.am
qrencode-3.4.4/tests/test_all.sh
qrencode-3.4.4/tests/Makefile.in
qrencode-3.4.4/tests/common.h
qrencode-3.4.4/tests/decoder.c
qrencode-3.4.4/tests/decoder.h
qrencode-3.4.4/tests/create_frame_pattern.c
qrencode-3.4.4/tests/create_mqr_frame_pattern.c
qrencode-3.4.4/tests/prof_qrencode.c
qrencode-3.4.4/tests/pthread_qrencode.c
qrencode-3.4.4/tests/test_bitstream.c
qrencode-3.4.4/tests/test_estimatebit.c
qrencode-3.4.4/tests/test_mask.c
qrencode-3.4.4/tests/test_mmask.c
qrencode-3.4.4/tests/test_monkey.c
qrencode-3.4.4/tests/test_mqrspec.c
qrencode-3.4.4/tests/test_qrencode.c
qrencode-3.4.4/tests/test_qrinput.c
qrencode-3.4.4/tests/test_qrspec.c
qrencode-3.4.4/tests/test_rs.c
qrencode-3.4.4/tests/test_split.c
qrencode-3.4.4/tests/view_qrcode.c
qrencode-3.4.4/tests/frame
qrencode-3.4.4/use/
qrencode-3.4.4/use/depcomp
qrencode-3.4.4/use/compile
qrencode-3.4.4/use/config.guess
qrencode-3.4.4/use/config.rpath
qrencode-3.4.4/use/config.sub
qrencode-3.4.4/use/install-sh
qrencode-3.4.4/use/missing
qrencode-3.4.4/use/ltmain.sh
qrencode-3.4.4/Makefile.in
qrencode-3.4.4/Makefile.am
qrencode-3.4.4/configure
qrencode-3.4.4/acinclude.m4
qrencode-3.4.4/configure.ac
qrencode-3.4.4/aclocal.m4
qrencode-3.4.4/config.h.in
qrencode-3.4.4/libqrencode.pc.in
qrencode-3.4.4/qrencode.spec.in
qrencode-3.4.4/qrencode.1.in
qrencode-3.4.4/qrencode.h
qrencode-3.4.4/COPYING
qrencode-3.4.4/ChangeLog
qrencode-3.4.4/NEWS
qrencode-3.4.4/README
qrencode-3.4.4/TODO
qrencode-3.4.4/qrencode.c
qrencode-3.4.4/qrencode_inner.h
qrencode-3.4.4/qrinput.c
qrencode-3.4.4/qrinput.h
qrencode-3.4.4/bitstream.c
qrencode-3.4.4/bitstream.h
qrencode-3.4.4/qrspec.c
qrencode-3.4.4/qrspec.h
qrencode-3.4.4/rscode.c
qrencode-3.4.4/rscode.h
qrencode-3.4.4/split.c
qrencode-3.4.4/split.h
qrencode-3.4.4/mask.c
qrencode-3.4.4/mask.h
qrencode-3.4.4/mqrspec.c
qrencode-3.4.4/mqrspec.h
qrencode-3.4.4/mmask.c
qrencode-3.4.4/mmask.h
qrencode-3.4.4/qrenc.c
qrencode-3.4.4/autogen.sh
qrencode-3.4.4/qrencode.spec
qrencode-3.4.4/Doxyfile
[root@kbsonlong google-authenticator]# yum install libpng libpng-devel
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirror.scalabledns.com
 * elrepo-kernel: repos.lax-noc.com
 * extras: mirror.linuxfix.com
 * remi-safe: mirrors.mediatemple.net
 * updates: mirror.steadfast.net
Package 2:libpng-1.5.13-7.el7_2.x86_64 already installed and latest version
Package 2:libpng-devel-1.5.13-7.el7_2.x86_64 already installed and latest version
Nothing to do
[root@kbsonlong google-authenticator]# cd qrencode-3.4.4
[root@kbsonlong qrencode-3.4.4]# ./configure 
checking build system type... x86_64-unknown-linux-gnu
checking host system type... x86_64-unknown-linux-gnu
checking target system type... x86_64-unknown-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for style of include used by make... GNU
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking dependency style of gcc... gcc3
checking for an ANSI C-conforming const... yes
checking for inline... inline
checking how to run the C preprocessor... gcc -E
checking for grep that handles long lines and -e... /usr/bin/grep
checking for egrep... /usr/bin/grep -E
checking for ANSI C header files... yes
checking for gcc... (cached) gcc
checking whether we are using the GNU C compiler... (cached) yes
checking whether gcc accepts -g... (cached) yes
checking for gcc option to accept ISO C89... (cached) none needed
checking whether gcc understands -c and -o together... (cached) yes
checking dependency style of gcc... (cached) gcc3
checking how to print strings... printf
checking for a sed that does not truncate output... /usr/bin/sed
checking for fgrep... /usr/bin/grep -F
checking for ld used by gcc... /usr/bin/ld
checking if the linker (/usr/bin/ld) is GNU ld... yes
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 1572864
checking whether the shell understands some XSI constructs... yes
checking whether the shell understands "+="... yes
checking how to convert x86_64-unknown-linux-gnu file names to x86_64-unknown-linux-gnu format... func_convert_file_noop
checking how to convert x86_64-unknown-linux-gnu file names to toolchain format... func_convert_file_noop
checking for /usr/bin/ld option to reload object files... -r
checking for objdump... objdump
checking how to recognize dependent libraries... pass_all
checking for dlltool... no
checking how to associate runtime and link libraries... printf %s\n
checking for ar... ar
checking for archiver @FILE support... @
checking for strip... strip
checking for ranlib... ranlib
checking command to parse /usr/bin/nm -B output from gcc object... ok
checking for sysroot... no
checking for mt... no
checking if : is a manifest tool... no
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking for dlfcn.h... yes
checking for objdir... .libs
checking if gcc supports -fno-rtti -fno-exceptions... no
checking for gcc option to produce PIC... -fPIC -DPIC
checking if gcc PIC flag -fPIC -DPIC works... yes
checking if gcc static flag -static works... no
checking if gcc supports -c -o file.o... yes
checking if gcc supports -c -o file.o... (cached) yes
checking whether the gcc linker (/usr/bin/ld -m elf_x86_64) supports shared libraries... yes
checking whether -lc should be explicitly linked in... no
checking dynamic linker characteristics... GNU/Linux ld.so
checking how to hardcode library paths into programs... immediate
checking whether stripping libraries is possible... yes
checking if libtool supports shared libraries... yes
checking whether to build shared libraries... yes
checking whether to build static libraries... no
checking for ranlib... (cached) ranlib
checking for pkg-config... /usr/bin/pkg-config
checking pkg-config is at least version 0.9.0... yes
checking for strdup... yes
checking for pthread_mutex_init in -lpthread... yes
checking for png... yes
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating libqrencode.pc
config.status: creating tests/Makefile
config.status: creating qrencode.spec
config.status: creating qrencode.1
config.status: creating config.h
config.status: executing depfiles commands
config.status: executing libtool commands

Options used to compile and link:
  CC       = gcc
  CFLAGS   = -Wall -g -O2
  CPPFLAGS = 
  CXX      = 
  CXXFLAGS = 
  LDFLAGS  = 

[root@kbsonlong qrencode-3.4.4]# make && make install
make  all-recursive
make[1]: Entering directory `/data/google-authenticator/qrencode-3.4.4'
Making all in .
make[2]: Entering directory `/data/google-authenticator/qrencode-3.4.4'
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.     -Wall -g -O2 -MT qrencode.lo -MD -MP -MF .deps/qrencode.Tpo -c -o qrencode.lo qrencode.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -Wall -g -O2 -MT qrencode.lo -MD -MP -MF .deps/qrencode.Tpo -c qrencode.c  -fPIC -DPIC -o .libs/qrencode.o
mv -f .deps/qrencode.Tpo .deps/qrencode.Plo
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.     -Wall -g -O2 -MT qrinput.lo -MD -MP -MF .deps/qrinput.Tpo -c -o qrinput.lo qrinput.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -Wall -g -O2 -MT qrinput.lo -MD -MP -MF .deps/qrinput.Tpo -c qrinput.c  -fPIC -DPIC -o .libs/qrinput.o
mv -f .deps/qrinput.Tpo .deps/qrinput.Plo
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.     -Wall -g -O2 -MT bitstream.lo -MD -MP -MF .deps/bitstream.Tpo -c -o bitstream.lo bitstream.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -Wall -g -O2 -MT bitstream.lo -MD -MP -MF .deps/bitstream.Tpo -c bitstream.c  -fPIC -DPIC -o .libs/bitstream.o
mv -f .deps/bitstream.Tpo .deps/bitstream.Plo
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.     -Wall -g -O2 -MT qrspec.lo -MD -MP -MF .deps/qrspec.Tpo -c -o qrspec.lo qrspec.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -Wall -g -O2 -MT qrspec.lo -MD -MP -MF .deps/qrspec.Tpo -c qrspec.c  -fPIC -DPIC -o .libs/qrspec.o
mv -f .deps/qrspec.Tpo .deps/qrspec.Plo
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.     -Wall -g -O2 -MT rscode.lo -MD -MP -MF .deps/rscode.Tpo -c -o rscode.lo rscode.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -Wall -g -O2 -MT rscode.lo -MD -MP -MF .deps/rscode.Tpo -c rscode.c  -fPIC -DPIC -o .libs/rscode.o
mv -f .deps/rscode.Tpo .deps/rscode.Plo
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.     -Wall -g -O2 -MT split.lo -MD -MP -MF .deps/split.Tpo -c -o split.lo split.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -Wall -g -O2 -MT split.lo -MD -MP -MF .deps/split.Tpo -c split.c  -fPIC -DPIC -o .libs/split.o
mv -f .deps/split.Tpo .deps/split.Plo
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.     -Wall -g -O2 -MT mask.lo -MD -MP -MF .deps/mask.Tpo -c -o mask.lo mask.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -Wall -g -O2 -MT mask.lo -MD -MP -MF .deps/mask.Tpo -c mask.c  -fPIC -DPIC -o .libs/mask.o
mv -f .deps/mask.Tpo .deps/mask.Plo
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.     -Wall -g -O2 -MT mqrspec.lo -MD -MP -MF .deps/mqrspec.Tpo -c -o mqrspec.lo mqrspec.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -Wall -g -O2 -MT mqrspec.lo -MD -MP -MF .deps/mqrspec.Tpo -c mqrspec.c  -fPIC -DPIC -o .libs/mqrspec.o
mv -f .deps/mqrspec.Tpo .deps/mqrspec.Plo
/bin/sh ./libtool  --tag=CC   --mode=compile gcc -DHAVE_CONFIG_H -I.     -Wall -g -O2 -MT mmask.lo -MD -MP -MF .deps/mmask.Tpo -c -o mmask.lo mmask.c
libtool: compile:  gcc -DHAVE_CONFIG_H -I. -Wall -g -O2 -MT mmask.lo -MD -MP -MF .deps/mmask.Tpo -c mmask.c  -fPIC -DPIC -o .libs/mmask.o
mv -f .deps/mmask.Tpo .deps/mmask.Plo
/bin/sh ./libtool  --tag=CC   --mode=link gcc  -Wall -g -O2 -version-number 3:4:4  -o libqrencode.la -rpath /usr/local/lib qrencode.lo qrinput.lo bitstream.lo qrspec.lo rscode.lo split.lo mask.lo mqrspec.lo mmask.lo  
libtool: link: gcc -shared  -fPIC -DPIC  .libs/qrencode.o .libs/qrinput.o .libs/bitstream.o .libs/qrspec.o .libs/rscode.o .libs/split.o .libs/mask.o .libs/mqrspec.o .libs/mmask.o    -O2   -Wl,-soname -Wl,libqrencode.so.3 -o .libs/libqrencode.so.3.4.4
libtool: link: (cd ".libs" && rm -f "libqrencode.so.3" && ln -s "libqrencode.so.3.4.4" "libqrencode.so.3")
libtool: link: (cd ".libs" && rm -f "libqrencode.so" && ln -s "libqrencode.so.3.4.4" "libqrencode.so")
libtool: link: ( cd ".libs" && rm -f "libqrencode.la" && ln -s "../libqrencode.la" "libqrencode.la" )
gcc -DHAVE_CONFIG_H -I.    -I/usr/include/libpng15   -Wall -g -O2 -MT qrencode-qrenc.o -MD -MP -MF .deps/qrencode-qrenc.Tpo -c -o qrencode-qrenc.o `test -f 'qrenc.c' || echo './'`qrenc.c
mv -f .deps/qrencode-qrenc.Tpo .deps/qrencode-qrenc.Po
/bin/sh ./libtool  --tag=CC   --mode=link gcc -I/usr/include/libpng15   -Wall -g -O2   -o qrencode qrencode-qrenc.o libqrencode.la -lpng15   
libtool: link: gcc -I/usr/include/libpng15 -Wall -g -O2 -o .libs/qrencode qrencode-qrenc.o  ./.libs/libqrencode.so -lpng15
make[2]: Leaving directory `/data/google-authenticator/qrencode-3.4.4'
make[1]: Leaving directory `/data/google-authenticator/qrencode-3.4.4'
Making install in .
make[1]: Entering directory `/data/google-authenticator/qrencode-3.4.4'
make[2]: Entering directory `/data/google-authenticator/qrencode-3.4.4'
 /usr/bin/mkdir -p '/usr/local/lib'
 /bin/sh ./libtool   --mode=install /usr/bin/install -c   libqrencode.la '/usr/local/lib'
libtool: install: /usr/bin/install -c .libs/libqrencode.so.3.4.4 /usr/local/lib/libqrencode.so.3.4.4
libtool: install: (cd /usr/local/lib && { ln -s -f libqrencode.so.3.4.4 libqrencode.so.3 || { rm -f libqrencode.so.3 && ln -s libqrencode.so.3.4.4 libqrencode.so.3; }; })
libtool: install: (cd /usr/local/lib && { ln -s -f libqrencode.so.3.4.4 libqrencode.so || { rm -f libqrencode.so && ln -s libqrencode.so.3.4.4 libqrencode.so; }; })
libtool: install: /usr/bin/install -c .libs/libqrencode.lai /usr/local/lib/libqrencode.la
libtool: finish: PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/root/go/bin:/usr/local/go/bin:/root/bin:/sbin" ldconfig -n /usr/local/lib
----------------------------------------------------------------------
Libraries have been installed in:
   /usr/local/lib

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
 /usr/bin/mkdir -p '/usr/local/bin'
  /bin/sh ./libtool   --mode=install /usr/bin/install -c qrencode '/usr/local/bin'
libtool: install: /usr/bin/install -c .libs/qrencode /usr/local/bin/qrencode
 /usr/bin/mkdir -p '/usr/local/include'
 /usr/bin/install -c -m 644 qrencode.h '/usr/local/include'
 /usr/bin/mkdir -p '/usr/local/share/man/man1'
 /usr/bin/install -c -m 644 qrencode.1 '/usr/local/share/man/man1'
 /usr/bin/mkdir -p '/usr/local/lib/pkgconfig'
 /usr/bin/install -c -m 644 libqrencode.pc '/usr/local/lib/pkgconfig'
make[2]: Leaving directory `/data/google-authenticator/qrencode-3.4.4'
make[1]: Leaving directory `/data/google-authenticator/qrencode-3.4.4'

[root@kbsonlong qrencode-3.4.4]# google-authenticator

Do you want authentication tokens to be time-based (y/n) y
Warning: pasting the following URL into your browser exposes the OTP secret to Google:
  https://www.google.com/chart?chs=200x200&chld=M|0&cht=qr&chl=otpauth://totp/root@kbsonlong%3Fsecret%3DOESKRCPFBHVX4QNLJ6J65MWTR4%26issuer%3Dkbsonlong
                                       
Your new secret key is: OESKRCPFBHVX4QNLJ6J65MWTR4
Your verification code is 170906
Your emergency scratch codes are:
  71500218
  28529324
  55227626
  10866708
  44540819

Do you want me to update your "/root/.google_authenticator" file? (y/n) y

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

By default, a new token is generated every 30 seconds by the mobile app.
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. This allows for a
time skew of up to 30 seconds between authentication server and client. If you
experience problems with poor time synchronization, you can increase the window
from its default size of 3 permitted codes (one previous code, the current
code, the next code) to 17 permitted codes (the 8 previous codes, the current
code, and the 8 next codes). This will permit for a time skew of up to 4 minutes
between client and server.
Do you want to do so? (y/n) y

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
[root@kbsonlong qrencode-3.4.4]# more /root/.google_authenticator 
OESKRCPFBHVX4QNLJ6J65MWTR4
" RATE_LIMIT 3 30
" WINDOW_SIZE 17
" DISALLOW_REUSE
" TOTP_AUTH
71500218
28529324
55227626
10866708
44540819
[root@kbsonlong qrencode-3.4.4]#



三、open***、ssh配置Google Authenticator

3.1 配置ssh


[root@kbsonlong ~]# vim /etc/pam.d/sshd 
 auth       required pam_google_authenticator.so no_increment_hotp

配置sshd服务,/etc/ssh/sshd_config,主要修改以下3个值:

[root@kbsonlong ~]# vim /etc/ssh/sshd_config 
 ...
 PasswordAuthentication yes
 ChallengeResponseAuthentication yes
 UsePAM yes

注意:这里插一条错误记录,测试过程中出现的。
[root@kbsonlong ~]# tail -40f /var/log/secure
 ....
 May 7 16:43:01 kbsonlong sshd[33414]: PAM unable to dlopen(/usr/lib64/security/pam_google_authenticator.so): /usr/lib64/security/pam_google_authenticator.so: cannot open shared object file: No such file or directory
 May 7 16:43:01 kbsonlong sshd[33414]: PAM adding faulty module: /usr/lib64/security/pam_google_authenticator.so
 May 7 16:43:03 kbsonlong sshd[33416]: pam_succeed_if(sshd:auth): requirement "uid >= 1000" not met by user "root"


修改方法:创建软链接即可,必须创建,或者直接复制过去也可。

[root@kbsonlong ~]# ln -s /usr/local/lib/security/pam_google_authenticator.so /usr/lib64/security/pam_google_authenticator.so

之后,重启sshd 服务

[root@kbsonlong ~]# systemctl restart sshd


测试登录

[root@kbsonlong ~]# ssh test@192.168.150.125
Verification code: 
Password: 
Last failed login: Mon May  7 17:35:55 CST 2018 from hadoop1 on ssh:notty
There was 1 failed login attempt since the last successful login.
Last login: Mon May  7 17:33:13 2018
[test@kbsonlong ~]$

利用Google Authenticator实现用户双因素认证_第1张图片


使用xshell等工具登录需要修改登录方式

利用Google Authenticator实现用户双因素认证_第2张图片

登录提示输入验证码

利用Google Authenticator实现用户双因素认证_第3张图片

验证码通过后提示输入密码

利用Google Authenticator实现用户双因素认证_第4张图片



3.2 配置open***


/etc/pam.d/open***
这个配置文件是真正认证 open*** 登录的配置文件,里面内容主要是以下几句:

auth    required    pam_google_authenticator.so nullok forward_pass debug
account required    pam_unix.so


第一行的 forward_pass 参数使得一次读入 google authenticator 的密码,然后把密码扔给后续的pam处理
  debug 参数完全是调试的需要,生产环境可以不用
第二行是必须的,否则 open*** 登录不上


3.3 用户初始化
因为 google authenticator 需要在每个用户的家目录里生成一个叫 .google_authenticator 的文件,里面存有密钥和几个一次性的超级认证码及其他一些配置,所以,我们需要在 open*** 服务器上做一次初始化数据的工作。假设有 10个用户要用这个系统登录 open***、ssh,用户名从 user1 到 user10,那么初始化脚本就是:

for i in {1..10}
 do
     useradd user${i}
     su -c \
         "google-authenticator -t -f -d -w 17 -r 3 -R 30 -q" \
         user${i}
     cat /home/user${i}/.google_authenticator | \
         mail -s "your .google_authenticator is:" \
         user${i}@xxx.com
 done

这里注意,在用户数据初始化的最后部分,将生成的 .google_authenticator 发给了每个用户自己。



四、优化

4.1 不足之处

  上面的环境即使在内网还是需要二次认证;所以这个好解决,将允许本地局域网直接登录系统。

4.2 解决内网主机跳过二次认证

编辑pam.d下的sshd 文件,在第一行增加内容,主要是指定允许的主机信息文件,如下所示:

[root@kbsonlong ~]# more -2 /etc/pam.d/sshd 
 auth [success=1 default=ignore] pam_access.so accessfile=/etc/security/access-localhost.conf
 auth       required pam_google_authenticator.so no_increment_hotp

然后在/etc/security/目录下创建access-localhost.conf文件,并添加内容如下:

[root@kbsonlong ~]# cat /etc/security/access-localhost.conf
 # skipped local network for google auth...
 + : ALL : 192.168.150.0/24
 + : ALL : LOCAL
- : ALL : ALL

最后,重启sshd 服务

[root@kbsonlong ~]# systemctl restart sshd
4.3 测试,内网主机登陆便直接使用密钥登陆了。

sk:~ kbsonlong$ ssh root@192.168.150.125
 Password: 
 Last login: Sun May 07 17:21:46 2018 from 192.168.150.101