设为首页收藏本站

LinuxTone | 运维专家网论坛 - 最棒的Linux运维与开源架构技术交流社区!

 找回密码
 注册

QQ登录

只需一步,快速开始

#公告#抱歉,网站将关闭,不再开放。由于PC时代已远逝 。在这个后移动互联网时代,我们继续携手前行,保持对技术的热情。共同构建linuxtone知识星球欢迎加入,一起讨论技术、招聘人才、分享资源。请新老linuxtone人 扫码移步到 知识星球:linuxtone

学习是一种信仰!分享是一种快乐!能力= 心态 * 沟通 * 知识 (你的每一天需要正能量!)

 网站的发展需要你贡献一份力量!希望你能每天坚持看贴1小时,并回答网友的问题!祝你在浏览论坛的过程中取得进步!谢谢!linuxtone加油!大家加油! 友情提示: 你今天学习了吗?你今天进步了吗?少一点抱怨!多一点进步!Life is short ! Why not linuxtone ?  

网站的发展、感谢每位坛友的努力!

查看: 3072|回复: 1

[系统安全] 用Google Authenticator加强SSH登录安全性 [复制链接]

Rank: 8Rank: 8

签到
645
注册时间
2011-3-5
最后登录
2015-7-22
在线时间
459 小时
阅读权限
90
积分
66622
帖子
141
主题
10
精华
0
UID
12263
发表于 2012-7-28 20:08:06 |显示全部楼层
本帖最后由 zflczx 于 2012-7-28 20:09 编辑
环境:
CentOS 6.3 minimal i386

基础组件安装:
1
yum -y install wget gcc make pam-devel libpng-devel

一、安装qrencode
在Linux上,有一个名为 QrenCode 的命令行工具可以很容易帮我们生成二维码,google authenticator命令行生成二维码就是调用它。
1
wget http://fukuchi.org/works/qrencode/qrencode-3.3.1.tar.gz
2
tar zxf qrencode-3.3.1.tar.gz
3
cd qrencode-3.3.1
4
./configure --prefix=/usr && make && make install

二、安装google authenticator PAM插件
1
wget http://google-authenticator.goog ... -1.0-source.tar.bz2
2
tar jxf libpam-google-authenticator-1.0-source.tar.bz2
3
cd libpam-google-authenticator-1.0
4
make && make install

三、配置google authenticator
Google Authenticator 的服务器端已经安装好了,那么客户端呢?Android 用户请点这里安装,iOS 用户请点这里安装,其他智能手机用户也有相应的开源解决方案,请自行搜索下载。非智能手机用户暂时无解。
Google Authenticator 其实是一套开源的解决方案,所以不仅在 Google 的网站上能用,在其他地方也能用的。然而,在 Google 的网站上,会直接给你一个 QR 码让你扫的,而自己配置的 Google Authenticator 则要自己生成了。
首先需要切换到对应的用户,如果 VPS 上只有一个用户的话,自然是可以省略这一步的,但是多用户的 VPS 需要先切换到对应的用户,再运行 google-authenticator 命令,程序会问你Do you want authentication tokens to be time-based (y/n),大意是基于时间生成验证码(及TOTP),这里选择y。结果类似这样:

这个 QR 码自然是给 Google Authenticator 应用程序来扫描的,也可以访问上面的那个链接,用 Google Chart API 生成的 QR 码来扫描。还可以照着 QR 码下面的文字密钥手工输入。当 Google Authenticator 识别了这个账号之后,验证器就配置好了。在文字密钥下面还提供了几个应急码,为手机丢了等情况下所用的,可以妥善保管。
这时 Google Authenticator 虽然运行了,但是相关设置还没有保存,程序会问你 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, tokens are good for 30 seconds and 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 1:30min to about 4min. Do you want to do so (y/n)
大意是问是否打开时间容错以防止客户端与服务器时间相差太大导致认证失败。这个可以根据实际情况来。我的ipad时间很准(与网络同步的),所以答 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。
问题答完了,家目录中多出一个 .google_authenticator 文件(默认权限为 400),这时客户端与服务端已经配套起来了,以后不用再运行 google-authenticator 命令了,否则会重新生成一组密码。
四、配置SSH验证
此时虽然 Google Authenticator 已经配置好了,但是并没有任何程序会去调用它。所以需要设置 SSH 登录的时候去通过它验证。
打开 /etc/pam.d/sshd 文件,添加
auth required pam_google_authenticator.so
这一行,保存。再打开 /etc/ssh/sshd_config 文件,找到
ChallengeResponseAuthentication no
把它改成
ChallengeResponseAuthentication yes
并保存。最后,输入
service ssh restart
来重启 SSH 服务以应用新的配置。
这时候再用 SSH 登录的话就会这样了:

这样就成功了。

五、错误解决
5.1 selinux需设定为disabled,不然SSH就无法登陆了。(不关闭的方法还没找到,继续探索中…)
5.2 google authenticator命令行下不生成二维码问题解决方法
strace -o log google-authenticator
log信息如下:
execve("/usr/local/bin/google-authenticator", ["google-authenticator"], [/* 20 vars */]) = 0
brk(0)                                  = 0x9993000
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77ce000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=24158, ...}) = 0
mmap2(NULL, 24158, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77c8000
close(3)                                = 0
open("/lib/libdl.so.2", O_RDONLY)       = 3
read(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) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=17892, ...}) = 0
mmap2(NULL, 16500, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x415000
mmap2(0x418000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x2) = 0x418000
close(3)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 3
read(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) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1886288, ...}) = 0
mmap2(NULL, 1644936, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x71d000
mmap2(0x8a9000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x18c) = 0x8a9000
mmap2(0x8ac000, 10632, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x8ac000
close(3)                                = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77c7000
set_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}) = 0
mprotect(0x8a9000, 8192, PROT_READ)     = 0
mprotect(0x418000, 4096, PROT_READ)     = 0
mprotect(0x384000, 4096, PROT_READ)     = 0
munmap(0xb77c8000, 24158)               = 0
getuid32()                              = 0
brk(0)                                  = 0x9993000
brk(0x99b4000)                          = 0x99b4000
socket(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
socket(PF_FILE, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 3
connect(3, {sa_family=AF_FILE, path="/var/run/nscd/socket"}, 110) = -1 ENOENT (No such file or directory)
close(3)                                = 0
open("/etc/nsswitch.conf", O_RDONLY)    = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=1688, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77cd000
read(3, "#\n# /etc/nsswitch.conf\n#\n# An ex"..., 4096) = 1688
read(3, "", 4096)                       = 0
close(3)                                = 0
munmap(0xb77cd000, 4096)                = 0
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=24158, ...}) = 0
mmap2(NULL, 24158, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb77c8000
close(3)                                = 0
open("/lib/libnss_files.so.2", O_RDONLY) = 3
read(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) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=58704, ...}) = 0
mmap2(NULL, 53964, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x564000
mmap2(0x570000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0xb) = 0x570000
close(3)                                = 0
mprotect(0x570000, 4096, PROT_READ)     = 0
munmap(0xb77c8000, 24158)               = 0
open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
fcntl64(3, F_GETFD)                     = 0x1 (flags FD_CLOEXEC)
fstat64(3, {st_mode=S_IFREG|0644, st_size=1471, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77cd000
read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1471
close(3)                                = 0
munmap(0xb77cd000, 4096)                = 0
uname({sys="Linux", node="srv", ...})   = 0
open("/dev/urandom", O_RDONLY)          = 3
read(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) = 30
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77cd000
write(1, "\n", 1)                       = 1
write(1, "Do you want authentication token"..., 57) = 57
fstat64(0, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb77cc000
read(0, "y\n", 1024)                    = 2
write(1, "https://www.google.com/chart?chs"..., 113) = 113
ioctl(1, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
open("/etc/ld.so.cache", O_RDONLY)      = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=24158, ...}) = 0
mmap2(NULL, 24158, PROT_READ, MAP_PRIVATE, 4, 0) = 0xb77c1000
close(4)                                = 0
open("/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, ...}) = 0
open("/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, ...}) = 0
open("/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, ...}) = 0
open("/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, ...}) = 0
open("/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, ...}) = 0
open("/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, ...}) = 0
munmap(0xb77c1000, 24158)               = 0
open("/etc/ld.so.cache", O_RDONLY)      = 4
fstat64(4, {st_mode=S_IFREG|0644, st_size=24158, ...}) = 0
mmap2(NULL, 24158, PROT_READ, MAP_PRIVATE, 4, 0) = 0xb77c1000
close(4)                                = 0
open("/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)               = 0
write(1, "Your new secret key is: ZDJICG7Z"..., 41) = 41
write(1, "Your verification code is 770393"..., 33) = 33
write(1, "Your emergency scratch codes are"..., 34) = 34
write(1, "  42189708\n", 11)            = 11
write(1, "  50825864\n", 11)            = 11
write(1, "  83761911\n", 11)            = 11
write(1, "  12434961\n", 11)            = 11
read(3, "\345\216Qk", 4)                = 4
read(3, "\260\3374\0", 4)               = 4
write(1, "  19934208\n", 11)            = 11
close(3)                                = 0
write(1, "\n", 1)                       = 1
write(1, "Do you want me to update your \"/"..., 71) = 71
read(0, "n\n", 1024)                    = 2
exit_group(0)                           = ?
问题出在google-authenticator调用libqrencode.so.3时,在相应路径查询不到,解决方法很简单。
①编译qrencode时指定路径即可及。./configure –prefix=/usr。(默认编译安装至/usr/local)
这样libqrencode.so.3就会安装到/usr/lib目录下。
②还有种方法就是默认编译安装,然后做个软连接。

参考:
https://wzyboy.im/post/765.html


原文:http://m114.org/system/google-au ... login-security.html
个人博客:http://m114.org/

Rank: 8Rank: 8

注册时间
2011-9-16
最后登录
2020-3-29
在线时间
959 小时
阅读权限
90
积分
269345
帖子
2158
主题
2
精华
0
UID
15647
发表于 2012-7-29 09:32:58 |显示全部楼层
感谢楼主分享,学习一下。

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

IT运维专家网感谢您的支持

合作联系: QQ:67888954/MSN:cnseek@msn.com/mail:netseek@linuxtone.org

Archiver|手机版|感谢所有关心和支持过LinuxTone的朋友们 转载本站内容请注明原作者名及出处 ( 京ICP备08103151 )   |

GMT+8, 2020-3-30 13:07 , Processed in 0.025095 second(s), 14 queries , Apc On.

Powered by Discuz! X2 Licensed

© 2001-2011 Comsenz Inc.

回顶部