為Apache和SSH搭建雙因子驗(yàn)證系統(tǒng)
譯文如果你在運(yùn)行一臺(tái)公眾可以訪問,但僅供自己使用的Web服務(wù)器(咱們實(shí)話實(shí)說吧,如果你在閱讀本文,很有可能運(yùn)行這樣一臺(tái)服務(wù)器),那么你該如何著手限制有人訪問你網(wǎng)站、搞破壞活動(dòng)的風(fēng)險(xiǎn)?SSH又如何呢?SSH是更大的隱患!在如今這個(gè)環(huán)境下,有必要考慮你面臨的風(fēng)險(xiǎn),并采取必要的措施,盡可能減小風(fēng)險(xiǎn)。
我在本教程中將詳細(xì)介紹具體的步驟,以便實(shí)施一套自行搭建的雙因子驗(yàn)證系統(tǒng),以便用于訪問你的網(wǎng)站和用于SSH訪問。
基礎(chǔ)設(shè)施和“挑戰(zhàn)”
運(yùn)行自己的硬件可能令人討厭。你在處理風(fēng)扇失效、電源失效和硬盤壞掉等各種硬件故障后,最終可能決定丟棄你在托管中心或自家臥室的機(jī)柜和硬件,毅然決然地投入彈性計(jì)算的懷抱。亞馬遜的EC2平臺(tái)就是這樣一種選擇,該平臺(tái)提供了眾多Linux版本,擁有市面上最可靠、最成熟的云平臺(tái)之一。我可不是亞馬遜的代表,但我還是要說試一試。這個(gè)產(chǎn)品很出色,微實(shí)例(micro instance)可以免費(fèi)使用一年。
在針對(duì)本文的測(cè)試場(chǎng)景下,我使用了一臺(tái)運(yùn)行Ubuntu 12.04 LTS的亞馬遜EC2服務(wù)器,來托管運(yùn)行幾個(gè)Web應(yīng)用程序。如果你使用不同的Linux版本,那么操作步驟只需稍加改動(dòng),就能滿足你的具體要求。假設(shè)這些應(yīng)用程序多半僅供個(gè)人使用。要是只從辦公場(chǎng)所或家里訪問網(wǎng)站,你只要?jiǎng)?chuàng)建防火墻規(guī)則,只允許從那些IP地址訪問Web流量,就可以為網(wǎng)站保駕護(hù)航。捎帶提一下,這正是你確保SSH安全的做法。
不過,假設(shè)這個(gè)做法并不適合你的Web應(yīng)用程序,因?yàn)槟泐l繁出差,出門在外時(shí)需要也能夠訪問那些應(yīng)用程序,所以單單幾個(gè)防火墻規(guī)則幫不了你。另外假設(shè),你的應(yīng)用程序有自己的安全系統(tǒng),但是你仍想要一層額外的安全機(jī)制。
你可以搭建一臺(tái)虛擬專用網(wǎng)(VPN)服務(wù)器,但你可能想讓家庭成員訪問其中一個(gè)網(wǎng)站,所以VPN方法行不通。
可以考慮的另一個(gè)方法是使用谷歌身份驗(yàn)證器(Google Authenticator),實(shí)現(xiàn)真正的雙因子驗(yàn)證。你當(dāng)然可以選擇走這條路,但你尋求的是能自己動(dòng)手做的系統(tǒng),獨(dú)立的、屬于你的系統(tǒng)。
就跟Linux領(lǐng)域的許多事情一樣,只要有意愿,辦法總歸有的!結(jié)果證明,你很容易就能組建自己的雙因子驗(yàn)證解決方案,并用它來控制對(duì)你的Web應(yīng)用程序和SSH的訪問,同時(shí)又可以允許其他用戶偶爾訪問你的網(wǎng)站。
Apache驗(yàn)證和授權(quán)
由于本例子中的Web服務(wù)器是Apache服務(wù)器,不妨充分利用該服務(wù)器的驗(yàn)證和授權(quán)功能,要求用戶先提供一系列登錄憑證,之后你的任何網(wǎng)站才提供服務(wù)給用戶。
為了力求簡(jiǎn)單,又由于你會(huì)遵守最佳實(shí)踐,只允許https流量進(jìn)出你的Web服務(wù)器,不妨使用mod_auth_basic模塊用于驗(yàn)證。
首先成為根用戶,在你全新安裝的Ubuntu上安裝Apache:
sudo su apt-get install apache2
假設(shè)你的Web應(yīng)用程序在主www文檔文件夾的子文件夾中運(yùn)行。這樣你只要在http服務(wù)器的根文件夾里面創(chuàng)建一個(gè).htaccss文件,就可以管理你的所有網(wǎng)站:
vim /var/www/.htaccess
現(xiàn)在,不妨添加幾行,命令A(yù)pache要求驗(yàn)證、哪里尋找密碼文件:
AuthType Basic AuthName "restricted area" AuthUserFile /home/ubuntu/.htpasswd require valid-user
這一步完成后,現(xiàn)在你需要更改文件的所有權(quán),以便Apache進(jìn)程能讀取文件內(nèi)容:
chown www-data:www-data /var/www/.htaccess
下一步,你需要?jiǎng)?chuàng)建在.htaccess文件中參照的.htpasswd文件,并且配置其所有權(quán),以便Web服務(wù)器能讀取該文件:
htpasswd -cb /home/ubuntu/.htpasswd jameslitton test123 chown www-data:www-data /home/ubuntu/.htpasswd
現(xiàn)在,你需要命令A(yù)pache要求驗(yàn)證、使用用于驗(yàn)證的mod_auth_basic模塊:
vim /etc/apache2/sites-available/default-ssl
然后,你需要將AllowOverride None改成AllowOverride AuthConfig:
Service apache2 restart
現(xiàn)在訪問你的網(wǎng)站會(huì)提示輸入用戶名和密碼(見圖1)。
圖1:來自mod_auth_basic的驗(yàn)證請(qǐng)求
每天一次的密碼/PIN
我在這里要采用的方法是,讓你的輔助驗(yàn)證密碼每天更改一次,而不是更頻繁地更改。這讓上述的mod_auth_basic方法得以奏效。我不會(huì)在此深入探討細(xì)節(jié),但就一句話:每當(dāng)密碼更改,就需要立即重新驗(yàn)證,這可不是你所需要的那種行為。
假設(shè)我們采用一個(gè)六個(gè)數(shù)的數(shù)字PIN碼,在每天半夜這個(gè)時(shí)段將該P(yáng)IN發(fā)送到手機(jī)上。我非常喜歡Pushover,這項(xiàng)服務(wù)可以從你自己的腳本和應(yīng)用程序,將即時(shí)通知迅速發(fā)送到手機(jī)和平板電腦上。
為了實(shí)現(xiàn)這個(gè)機(jī)制,創(chuàng)建一個(gè)bash腳本:
vim /home/ubuntu/2fac.sh
現(xiàn)在,添加下面幾行:
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"
↪https://api.pushover.net/1/messages.json
4 htpasswd -b /home/ubuntu/.htpasswd jameslitton $ppwd
5 echo $ppwd | base64 >/home/ubuntu/.2fac
第2行生成一個(gè)隨機(jī)性的六位數(shù)PIN碼,并將其分配給一個(gè)名為ppwd的變量。第3行將PIN發(fā)送到Pushover服務(wù),以便進(jìn)而將PIN發(fā)送到你的手機(jī)。第4行用新密碼更新.htpasswd文件;最后但并非最不重要的是,第5行以一種可以恢復(fù)的方式保存PIN的副本,你在后文會(huì)有所看到。
現(xiàn)在,保存腳本,讓它成為可執(zhí)行腳本:
chmod +x /home/ubuntu/2fac.sh
想完成該解決方案的最后一步,你只要通過計(jì)劃任務(wù)(cron),安排腳本在每天半夜運(yùn)行:
crontab -e 00 00 * * * /home/ubuntu/2fac.sh
讓它可以通過Web訪問
當(dāng)然你可以不用管它,就算大功告成,但假設(shè)你沒有收到PIN碼、想要強(qiáng)行更改?;蛘呖赡苣阒霸试S某人臨時(shí)訪問你的網(wǎng)站,但現(xiàn)在想強(qiáng)行更改密碼,確保那個(gè)人再也無法訪問網(wǎng)站。你總是可以使用SSH連接到服務(wù)器,并且手動(dòng)運(yùn)行腳本,但這太費(fèi)勁了。不妨創(chuàng)建一個(gè)可以通過Web訪問的PHP腳本,讓它替你處理這一切。
首先,更改2fac.sh腳本的所有權(quán),那樣你的Web服務(wù)器就能運(yùn)行它:
chown www-data:www-data /home/Ubuntu/2fac.sh
現(xiàn)在,你需要?jiǎng)?chuàng)建一個(gè)新的文件夾來放置腳本,并創(chuàng)建PHP腳本本身,允許新的“密鑰”可以手動(dòng)運(yùn)行:
mkdir /vaw/www/twofactor
vim /var/www/twofactor/index.php1 <?php
2 exec('/home/ubuntu/2fac.sh');
3 header('Location: );
4 ?>
由于這可以想象:由于未收到之前的密鑰,你需要強(qiáng)行使用一個(gè)新密鑰,就需要確保放置該腳本的那個(gè)文件夾不需要驗(yàn)證。為此,你需要改動(dòng)Apache配置:
vim /etc/apache2/sites-available/default-ssl
現(xiàn)在,在/var/www的Directory命令下面添加下面內(nèi)容:
<Directory /var/www/twofactor/>
satisfy any
</Directory>
現(xiàn)在不妨配置所有權(quán)、重啟Apache:
chown -R www-data:www-data /var/www/twofactor
Service apache2 restart
所以徹底考慮這點(diǎn)后,可以想象:Pushover服務(wù)可能完全無法使用。這會(huì)讓你面臨糟糕的情形:你無法訪問自己的網(wǎng)站。應(yīng)該針對(duì)這種場(chǎng)景為緊急情況做好準(zhǔn)備。
為此,不妨建立第二個(gè)腳本,以便獲取你PIN的副本(別忘了之前保存的.2fac文件),然后通過電子郵件發(fā)給你。在本例中,不妨使用移動(dòng)運(yùn)營商的電子郵件至短信網(wǎng)橋功能,以短信方式將信息發(fā)給你。
開始安裝mailutils,如果你之前還沒有安裝的話;務(wù)必要選擇互聯(lián)網(wǎng)選項(xiàng):
apt-get install mailutils
現(xiàn)在,創(chuàng)建第二個(gè)腳本:
vim /home/Ubuntu/2fac2.sh
然后,添加代碼:
#!/bin/bash
ppwd=`cat /home/ubuntu/.2fac | base64 --decode`
echo " " | mail -s $ppwd xxx5551212@vtext.com
別忘了更改文件的所有權(quán):
chown www-data:www-data /home/ubuntu/2fac2.sh
chown www-data:www-data /home/ubuntu/.2fac
完成這一步后,現(xiàn)在你需要改動(dòng)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 }
然后,創(chuàng)建兩個(gè)書簽,那樣無論何時(shí)你想生成一個(gè)新的PIN,并通過Pushover發(fā)送給自己,只需點(diǎn)擊鏈接,就大功告成了。萬一出現(xiàn)Pushover服務(wù)無法使用這種小幾率情形,第二個(gè)書簽會(huì)將現(xiàn)有PIN的副本發(fā)送到你所選擇的電子郵件地址。
2Factor = https://www.thelittonfamily.com/twofactor/index.php
2Factor-SMS = https://www.thelittonfamily.com/twofactor/index.php?sms=1
擴(kuò)展到SSH
擴(kuò)展該解決方案以涵蓋SSH其實(shí)相當(dāng)簡(jiǎn)單。關(guān)鍵在于使用sshd_config文件中不大知名的ForceCommand命令。這迫使SSH守護(hù)程序在生成終端會(huì)話之前運(yùn)行腳本。
不妨從這個(gè)腳本開始:
vim /home/ubuntu/tfac-ssh.sh
現(xiàn)在,添加下面幾行:
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"
↪https://api.pushover.net/1/messages.json
21 fi
第2行將PIN裝入到一個(gè)變量。第3行至第12行提示輸入PIN,并針對(duì)每次按鍵回送一個(gè)星號(hào)。第13行將用戶輸入的PIN與PIN進(jìn)行比對(duì)。如果兩者匹配,第14行至第17行就會(huì)清空屏幕,啟動(dòng)bash會(huì)話。要是用戶輸入的PIN與PIN不匹配,第18行至第21行就發(fā)送通知到Pushover,那樣你知道發(fā)生了故障,然后結(jié)束會(huì)話。
不妨配置SSH守護(hù)程序以運(yùn)行腳本:
vim /etc/ssh/sshd_config
現(xiàn)在,將下面這一行添加到文件頂部:
ForceCommand /home/ubuntu/tfac-ssh.sh
圖2:來自SSH的雙因子驗(yàn)證請(qǐng)求
這個(gè)方法很管用。唯一的局限在于沒有退格。如果你按錯(cuò)了鍵,會(huì)話就會(huì)被終結(jié),你就只好重新試一下。
就這樣,這是一種簡(jiǎn)易的雙因子驗(yàn)證系統(tǒng),根本不需要花多大力氣;根據(jù)我的經(jīng)驗(yàn),它運(yùn)行起來非??煽?
原文地址:http://www.linuxjournal.com/content/two-factor-authentication-system-apache-and-ssh