Use Google Authenticator to enhance SSH login security

Source: Internet
Author: User
Tags new set

Environment:

CentOS 6.3 minimal i386
 
Basic component installation:

yum -y install wget gcc make pam-devel libpng-devel

 
1. Install qrencode
On Linux, a command line tool named QrenCode can easily generate a QR code. The google authenticator command line generates a QR code and calls it.

wget http://fukuchi.org/works/qrencode/qrencode-3.3.1.tar.gztar zxf qrencode-3.3.1.tar.gzcd qrencode-3.3.1./configure --prefix=/usr && make && make install 

2. Install the google authenticator PAM plug-in

wget http://google-authenticator.googlecode.com/files/libpam-google-authenticator-1.0-source.tar.bz2tar jxf libpam-google-authenticator-1.0-source.tar.bz2cd libpam-google-authenticator-1.0make && make install

 
3. Configure google authenticator
The server of Google Authenticator has been installed. What about the client? For Android users, click here to install the SDK. for iOS users, click here to install the SDK. For other smartphone users, there are also open-source solutions. Please search and download the SDK by yourself. Non-smartphone users have no solutions for the moment.
Google Authenticator is actually an open-source solution, so it can be used not only on Google's website, but also elsewhere. However, on Google's website, a QR code will be directly sent to you for scanning, and Google Authenticator configured by yourself will be generated by yourself.
First, you need to switch to the corresponding user. If there is only one user on the VPS, you can skip this step, but the VPS of multiple users needs to switch to the corresponding user first, run the google-authenticator command again. The program will ask you Do you want authentication tokens to be time-based (y/n) to generate a verification code (and TOTP) based on time ), select y here. The result is similar to the following:
& Lt; img src = "http://www.bkjia.com/uploadfile/2014/0119/20140119100218867.png" alt = "\" title = "ssh-ga01" width = "688" height = "407" class = "alignnone size-full wp-image-1312"/& gt;
This QR code is naturally scanned by the Google Authenticator application. You can also visit the link above and use the QR code generated by the Google Chart API for scanning. You can also manually enter the text key following the QR code. After Google Authenticator recognizes this account, the validator is configured. Several emergency codes are provided under the text key, which can be properly kept if the mobile phone is lost.
At this time, although Google Authenticator is running, but the relevant settings have not been saved, the program will ask you Do you want me to update your "/root /. google_authenticator "file (y/n) (whether to write the configuration to the configuration file in the home directory), of course, Answer y. I will ask again

Do you want to disallow multiple uses of the same authenticationtoken? This restricts you to one login about every 30s, but it increasesyour chances to notice or even prevent man-in-the-middle attacks (y/n)

The general idea is whether to prohibit multiple use of a single password. Naturally, it is also a question of y. The next question is

By default, tokens are good for 30 seconds and in order to compensate forpossible time-skew between the client and the server, we allow an extratoken before and after the current time. If you experience problems with poortime synchronization, you can increase the window from its defaultsize of 1:30min to about 4min. Do you want to do so (y/n)

The question is whether to enable time tolerance to prevent authentication failure due to time difference between the client and the server. This can be based on the actual situation. My ipad has a very accurate time (synchronized with the network), so answer n. If some tablet computers are not connected to the network, Answer y to prevent authentication failure due to time errors. Another problem is that

If the computer that you are logging into isn't hardened against brute-forcelogin 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)

Select whether to enable the limit on the number of attempts (to prevent brute force attacks). A natural answer is y.
After answering the question, the home directory contains one more. the google_authenticator file (the default permission is 400). Now the client and the server are ready for use. You do not need to run the google-authenticator command in the future. Otherwise, a new set of passwords will be generated.

4. Configure SSH Authentication
Although Google Authenticator has been configured, no program will call it. Therefore, you need to set up SSH to log on through it for verification.
Open the/etc/pam. d/sshd file and add
Auth required pam_google_authenticator.so

Save this line. Open the/etc/ssh/sshd_config file and find
ChallengeResponseAuthentication no

Change it
ChallengeResponseAuthentication yes

And save. Finally, enter
Service ssh restart

To restart the SSH service to apply new configurations.
At this time, SSH Login will be like this:
& Lt; img src = "http://www.bkjia.com/uploadfile/2014/0119/20140119100220840.png" alt = "\" title = "ssh-ga02" width = "365" height = "82" class = "alignnone size-full wp-image-1313"/& gt;
In this way, the operation is successful.
 
V. troubleshooting
5.1 selinux must be set to disabled, otherwise SSH will not be able to log on. (The method of not closing is not found yet. Continue to explore ...)
5.2 google authenticator command line does not generate QR code Solution
Strace-o log google-authenticator
The log information is as follows:

execve("/usr/local/bin/google-authenticator", ["google-authenticator"], [/* 20 vars */]) = 0brk(0)                                  = 0x9993000mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77ce000access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)open("/etc/ld.so.cache", O_RDONLY)      = 3fstat64(3, {st_mode=S_IFREG|0644, st_size=24158, ...}) = 0mmap2(NULL, 24158, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77c8000close(3)                                = 0open("/lib/libdl.so.2", O_RDONLY)       = 3read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0`\n\0\0004\0\0\0"..., 512) = 512fstat64(3, {st_mode=S_IFREG|0755, st_size=17892, ...}) = 0mmap2(NULL, 16500, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x415000mmap2(0x418000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2) = 0x418000close(3)                                = 0open("/lib/libc.so.6", O_RDONLY)        = 3read(3, "\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0@n\1\0004\0\0\0"..., 512) = 512fstat64(3, {st_mode=S_IFREG|0755, st_size=1886288, ...}) = 0mmap2(NULL, 1644936, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x71d000mmap2(0x8a9000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18c) = 0x8a9000mmap2(0x8ac000, 10632, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x8ac000close(3)                                = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77c7000set_thread_area({entry_number:-1 -> 6, base_addr:0xb77c76c0, limit:1048575, seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, seg_not_present:0, useable:1}) = 0mprotect(0x8a9000, 8192, PROT_READ)     = 0mprotect(0x418000, 4096, PROT_READ)     = 0mprotect(0x384000, 4096, PROT_READ)     = 0munmap(0xb77c8000, 24158)               = 0getuid32()                              = 0brk(0)                                  = 0x9993000brk(0x99b4000)                          = 0x99b4000socket(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)close(3)                                = 0socket(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)close(3)                                = 0open("/etc/nsswitch.conf", O_RDONLY)    = 3fstat64(3, {st_mode=S_IFREG|0644, st_size=1688, ...}) = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77cd000read(3, "#\n# /etc/nsswitch.conf\n#\n# An ex"..., 4096) = 1688read(3, "", 4096)                       = 0close(3)                                = 0munmap(0xb77cd000, 4096)                = 0open("/etc/ld.so.cache", O_RDONLY)      = 3fstat64(3, {st_mode=S_IFREG|0644, st_size=24158, ...}) = 0mmap2(NULL, 24158, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77c8000close(3)                                = 0open("/lib/libnss_files.so.2", O_RDONLY) = 3read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\240\32\0\0004\0\0\0"..., 512) = 512fstat64(3, {st_mode=S_IFREG|0755, st_size=58704, ...}) = 0mmap2(NULL, 53964, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x564000mmap2(0x570000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xb) = 0x570000close(3)                                = 0mprotect(0x570000, 4096, PROT_READ)     = 0munmap(0xb77c8000, 24158)               = 0open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3fcntl64(3, F_GETFD)                     = 0x1 (flags FD_CLOEXEC)fstat64(3, {st_mode=S_IFREG|0644, st_size=1471, ...}) = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77cd000read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1471close(3)                                = 0munmap(0xb77cd000, 4096)                = 0uname({sys="Linux", node="srv", ...})   = 0open("/dev/urandom", O_RDONLY)          = 3read(3, "\310\322\201\33\371\21\222\357YLD\24n\214&\312\320\210\306\216\305\367\274X\210\21*\2\214\377", 30) = 30fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77cd000write(1, "\n", 1)                       = 1write(1, "Do you want authentication token"..., 57) = 57fstat64(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77cc000read(0, "y\n", 1024)                    = 2write(1, "https://www.google.com/chart?chs"..., 113) = 113ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0open("/etc/ld.so.cache", O_RDONLY)      = 4fstat64(4, {st_mode=S_IFREG|0644, st_size=24158, ...}) = 0mmap2(NULL, 24158, PROT_READ, MAP_PRIVATE, 4, 0) = 0xb77c1000close(4)                                = 0open("/lib/tls/i686/sse2/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/lib/tls/i686/sse2", 0xbfda1c78) = -1 ENOENT (No such file or directory)open("/lib/tls/i686/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/lib/tls/i686", 0xbfda1c78)     = -1 ENOENT (No such file or directory)open("/lib/tls/sse2/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/lib/tls/sse2", 0xbfda1c78)     = -1 ENOENT (No such file or directory)open("/lib/tls/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/lib/tls", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0open("/lib/i686/sse2/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/lib/i686/sse2", 0xbfda1c78)    = -1 ENOENT (No such file or directory)open("/lib/i686/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/lib/i686", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0open("/lib/sse2/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/lib/sse2", 0xbfda1c78)         = -1 ENOENT (No such file or directory)open("/lib/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/lib", {st_mode=S_IFDIR|0555, st_size=12288, ...}) = 0open("/usr/lib/tls/i686/sse2/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/usr/lib/tls/i686/sse2", 0xbfda1c78) = -1 ENOENT (No such file or directory)open("/usr/lib/tls/i686/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/usr/lib/tls/i686", 0xbfda1c78) = -1 ENOENT (No such file or directory)open("/usr/lib/tls/sse2/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/usr/lib/tls/sse2", 0xbfda1c78) = -1 ENOENT (No such file or directory)open("/usr/lib/tls/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/usr/lib/tls", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0open("/usr/lib/i686/sse2/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/usr/lib/i686/sse2", 0xbfda1c78) = -1 ENOENT (No such file or directory)open("/usr/lib/i686/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/usr/lib/i686", 0xbfda1c78)     = -1 ENOENT (No such file or directory)open("/usr/lib/sse2/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/usr/lib/sse2", {st_mode=S_IFDIR|0555, st_size=4096, ...}) = 0open("/usr/lib/libqrencode.so.2", O_RDONLY) = -1 ENOENT (No such file or directory)stat64("/usr/lib", {st_mode=S_IFDIR|0555, st_size=20480, ...}) = 0munmap(0xb77c1000, 24158)               = 0open("/etc/ld.so.cache", O_RDONLY)      = 4fstat64(4, {st_mode=S_IFREG|0644, st_size=24158, ...}) = 0mmap2(NULL, 24158, PROT_READ, MAP_PRIVATE, 4, 0) = 0xb77c1000close(4)                                = 0open("/lib/tls/libqrencode.so.3", O_RDONLY) = -1 ENOENT (No such file or directory)open("/lib/i686/libqrencode.so.3", O_RDONLY) = -1 ENOENT (No such file or directory)open("/lib/libqrencode.so.3", O_RDONLY) = -1 ENOENT (No such file or directory)open("/usr/lib/tls/libqrencode.so.3", O_RDONLY) = -1 ENOENT (No such file or directory)open("/usr/lib/sse2/libqrencode.so.3", O_RDONLY) = -1 ENOENT (No such file or directory)open("/usr/lib/libqrencode.so.3", O_RDONLY) = -1 ENOENT (No such file or directory)munmap(0xb77c1000, 24158)               = 0write(1, "Your new secret key is: ZDJICG7Z"..., 41) = 41write(1, "Your verification code is 770393"..., 33) = 33write(1, "Your emergency scratch codes are"..., 34) = 34write(1, "  42189708\n", 11)            = 11write(1, "  50825864\n", 11)            = 11write(1, "  83761911\n", 11)            = 11write(1, "  12434961\n", 11)            = 11read(3, "\345\216Qk", 4)                = 4read(3, "\260\3374\0", 4)               = 4write(1, "  19934208\n", 11)            = 11close(3)                                = 0write(1, "\n", 1)                       = 1write(1, "Do you want me to update your \"/"..., 71) = 71read(0, "n\n", 1024)                    = 2exit_group(0)                           = ?

The problem is that when google-authenticator calls libqrencode. so.3, the corresponding path cannot be queried. The solution is simple.
① Specify the path when compiling qrencode .. /Configure-prefix =/usr. (By default, It is compiled and installed to/usr/local)
In this way, libqrencode. so.3 will be installed in the/usr/lib directory.
② Another way is to compile and install by default, and then make a soft connection.
 
Refer:

Https://wzyboy.im/post/765.html

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.