gtxyzz

为Apache和SSH搭建双因子验证系统

gtxyzz 安全防护 2022-12-25 315浏览 0

如果你在运行一台公众可以访问,但仅供自己使用的Web服务器(咱们实话实说吧,如果你在阅读本文,很有可能运行这样一台服务器),那么你该如何着手限制有人访问你网站、搞破坏活动的风险?SSH又如何呢?SSH是更大的隐患!在如今这个环境下,有必要考虑你面临的风险,并采取必要的措施,尽可能减小风险。

我在本教程中将详细介绍具体的步骤,以便实施一套自行搭建的双因子验证系统,以便用于访问你的网站和用于SSH访问。

基础设施和“挑战”

运行自己的硬件可能令人讨厌。你在处理风扇失效、电源失效和硬盘坏掉等各种硬件故障后,最终可能决定丢弃你在托管中心或自家卧室的机柜和硬件,毅然决然地投入弹性计算的怀抱。亚马逊的EC2平台就是这样一种选择,该平台提供了众多Linux版本,拥有市面上最可靠、最成熟的云平台之一。我可不是亚马逊的代表,但我还是要说试一试。这个产品很出色,微实例(micro instance)可以免费使用一年。

在针对本文的测试场景下,我使用了一台运行Ubuntu 12.04 LTS的亚马逊EC2服务器,来托管运行几个Web应用程序。如果你使用不同的Linux版本,那么操作步骤只需稍加改动,就能满足你的具体要求。假设这些应用程序多半仅供个人使用。要是只从办公场所或家里访问网站,你只要创建防火墙规则,只允许从那些IP地址访问Web流量,就可以为网站保驾护航。捎带提一下,这正是你确保SSH安全的做法。

不过,假设这个做法并不适合你的Web应用程序,因为你频繁出差,出门在外时需要也能够访问那些应用程序,所以单单几个防火墙规则帮不了你。另外假设,你的应用程序有自己的安全系统,但是你仍想要一层额外的安全机制。

你可以搭建一台虚拟专用网(VPN)服务器,但你可能想让家庭成员访问其中一个网站,所以VPN方法行不通。

可以考虑的另一个方法是使用谷歌身份验证器(Google Authenticator),实现真正的双因子验证。你当然可以选择走这条路,但你寻求的是能自己动手做的系统,独立的、属于你的系统。

就跟Linux领域的许多事情一样,只要有意愿,办法总归有的!结果证明,你很容易就能组建自己的双因子验证解决方案,并用它来控制对你的Web应用程序和SSH的访问,同时又可以允许其他用户偶尔访问你的网站。

Apache验证和授权

由于本例子中的Web服务器是Apache服务器,不妨充分利用该服务器的验证和授权功能,要求用户先提供一系列登录凭证,之后你的任何网站才提供服务给用户。

为了力求简单,又由于你会遵守最佳实践,只允许https流量进出你的Web服务器,不妨使用mod_auth_basic模块用于验证。

首先成为根用户,在你全新安装的Ubuntu上安装Apache:

sudo su  
apt-get install apache2

假设你的Web应用程序在主www文档文件夹的子文件夹中运行。这样你只要在http服务器的根文件夹里面创建一个.htaccss文件,就可以管理你的所有网站:

vim /var/www/.htaccess

现在,不妨添加几行,命令Apache要求验证、哪里寻找密码文件:

AuthType Basic 
AuthName "restricted area" 
AuthUserFile /home/ubuntu/.htpasswd 
require valid-user

这一步完成后,现在你需要更改文件的所有权,以便Apache进程能读取文件内容:

chown www-data:www-data /var/www/.htaccess

下一步,你需要创建在.htaccess文件中参照的.htpasswd文件,并且配置其所有权,以便Web服务器能读取该文件:

htpasswd -cb /home/ubuntu/.htpasswd jameslitton test123 
chown www-data:www-data /home/ubuntu/.htpasswd

现在,你需要命令Apache要求验证、使用用于验证的mod_auth_basic模块:

vim /etc/apache2/sites-available/default-ssl

然后,你需要将AllowOverride None改成AllowOverride AuthConfig:

Service apache2 restart

现在访问你的网站会提示输入用户名和密码(见图1)。

为Apache和SSH搭建双因子验证系统

图1:来自mod_auth_basic的验证请求

每天一次的密码/PIN

我在这里要采用的方法是,让你的辅助验证密码每天更改一次,而不是更频繁地更改。这让上述的mod_auth_basic方法得以奏效。我不会在此深入探讨细节,但就一句话:每当密码更改,就需要立即重新验证,这可不是你所需要的那种行为。

假设我们采用一个六个数的数字PIN码,在每天半夜这个时段将该PIN发送到手机上。我非常喜欢Pushover,这项服务可以从你自己的脚本和应用程序,将即时通知迅速发送到手机和平板电脑上。

为了实现这个机制,创建一个bash脚本:

vim /home/ubuntu/2fac.sh

现在,添加下面几行:

1 #!/bin/bash
2 ppwd=`od -vAn -N4 -tu4 < /dev/urandom | tr -d '\n' | tail -c 6`
3 curl -s -F "token=id" -F "user=id" -F "message=$ppwd"
 &rarrhk;https://api.pushover.net/1/messages.json
4 htpasswd -b /home/ubuntu/.htpasswd jameslitton $ppwd
5 echo $ppwd | base64 >/home/ubuntu/.2fac

第2行生成一个随机性的六位数PIN码,并将其分配给一个名为ppwd的变量。第3行将PIN发送到Pushover服务,以便进而将PIN发送到你的手机。第4行用新密码更新.htpasswd文件;最后但并非最不重要的是,第5行以一种可以恢复的方式保存PIN的副本,你在后文会有所看到。

现在,保存脚本,让它成为可执行脚本:

chmod +x /home/ubuntu/2fac.sh

想完成该解决方案的最后一步,你只要通过计划任务(cron),安排脚本在每天半夜运行:

crontab -e 
00 00 * * * /home/ubuntu/2fac.sh

让它可以通过Web访问

当然你可以不用管它,就算大功告成,但假设你没有收到PIN码、想要强行更改。或者可能你之前允许某人临时访问你的网站,但现在想强行更改密码,确保那个人再也无法访问网站。你总是可以使用SSH连接到服务器,并且手动运行脚本,但这太费劲了。不妨创建一个可以通过Web访问的PHP脚本,让它替你处理这一切。

首先,更改2fac.sh脚本的所有权,那样你的Web服务器就能运行它:

chown www-data:www-data /home/Ubuntu/2fac.sh

现在,你需要创建一个新的文件夹来放置脚本,并创建PHP脚本本身,允许新的“密钥”可以手动运行:

mkdir /vaw/www/twofactor vim /var/www/twofactor/index.php

1 <?php 2 exec('/home/ubuntu/2fac.sh'); 3 header('Location: http://www.google.com'); 4 ?>

由于这可以想象:由于未收到之前的密钥,你需要强行使用一个新密钥,就需要确保放置该脚本的那个文件夹不需要验证。为此,你需要改动Apache配置:

vim /etc/apache2/sites-available/default-ssl

现在,在/var/www的Directory命令下面添加下面内容:

<Directory /var/www/twofactor/>
 satisfy any
</Directory>

现在不妨配置所有权、重启Apache:

chown -R www-data:www-data /var/www/twofactor
Service apache2 restart

所以彻底考虑这点后,可以想象:Pushover服务可能完全无法使用。这会让你面临糟糕的情形:你无法访问自己的网站。应该针对这种场景为紧急情况做好准备。

为此,不妨建立第二个脚本,以便获取你PIN的副本(别忘了之前保存的.2fac文件),然后通过电子邮件发给你。在本例中,不妨使用移动运营商的电子邮件至短信网桥功能,以短信方式将信息发给你。

开始安装mailutils,如果你之前还没有安装的话;务必要选择互联网选项:

apt-get install mailutils

现在,创建第二个脚本:

vim /home/Ubuntu/2fac2.sh

然后,添加代码:

#!/bin/bash
ppwd=`cat /home/ubuntu/.2fac | base64 --decode`
echo " " | mail -s $ppwd xxx5551212@vtext.com

别忘了更改文件的所有权:

chown www-data:www-data /home/ubuntu/2fac2.sh
chown www-data:www-data /home/ubuntu/.2fac

完成这一步后,现在你需要改动PHP脚本:

vim /var/www/twofactor/index.php

把第2行换成下列:

2 if (isset($_GET["sms"])) {
3 exec('/home/ubuntu/2fac2.sh');
4 } else {
5 exec('/home/ubuntu/2fac.sh');
6 }

然后,创建两个书签,那样无论何时你想生成一个新的PIN,并通过Pushover发送给自己,只需点击链接,就大功告成了。万一出现Pushover服务无法使用这种小几率情形,第二个书签会将现有PIN的副本发送到你所选择的电子邮件地址。

2Factor = https://www.thelittonfamily.com/twofactor/index.php 
2Factor-SMS = https://www.thelittonfamily.com/twofactor/index.php?sms=1

扩展到SSH

扩展该解决方案以涵盖SSH其实相当简单。关键在于使用sshd_config文件中不大知名的ForceCommand命令。这迫使SSH守护程序在生成终端会话之前运行脚本。

不妨从这个脚本开始:

vim /home/ubuntu/tfac-ssh.sh

现在,添加下面几行:

1 #!/bin/bash
2 code=`cat .2fac | base64 --decode`
3 echo -ne "Enter PIN: "
4 while IFS= read -r -s -n1 pass; do
5 if [[ -z $pass ]]; then
6 echo
7 break
8 else
9 echo -n '*'
10 input+=$pass
11 fi
12 done
13 if [ $code = $input ];
14 then
15 sleep 1
16 clear
17 /bin/bash
18 else
19 sleep 1
20 curl -s -F "token=id" -F "user=id" -F "message=$input"
 &rarrhk;https://api.pushover.net/1/messages.json
21 fi

第2行将PIN装入到一个变量。第3行至第12行提示输入PIN,并针对每次按键回送一个星号。第13行将用户输入的PIN与PIN进行比对。如果两者匹配,第14行至第17行就会清空屏幕,启动bash会话。要是用户输入的PIN与PIN不匹配,第18行至第21行就发送通知到Pushover,那样你知道发生了故障,然后结束会话。

不妨配置SSH守护程序以运行脚本:

vim /etc/ssh/sshd_config

现在,将下面这一行添加到文件顶部:

ForceCommand /home/ubuntu/tfac-ssh.sh

为Apache和SSH搭建双因子验证系统

图2:来自SSH的双因子验证请求

这个方法很管用。唯一的局限在于没有退格。如果你按错了键,会话就会被终结,你就只好重新试一下。

就这样,这是一种简易的双因子验证系统,根本不需要花多大力气;根据我的经验,它运行起来非常可靠!

原文地址:http://www.linuxjournal.com/content/two-factor-authentication-system-apache-and-ssh

继续浏览有关 安全 的文章
发表评论