利用fwknop給sshd加一道門,向暴力黑客Say no-way!

相信不少Linux服務器的機主對各類暴力攻擊是深惡痛絕的了,尤其是那些針對sshd的愚蠢黑客,成功率極低還給機主帶來不少麻煩。
對付這些拿着毫無技術含量的腳本到處亂撞的低級黑客(在我眼中,稱他們爲黑客是擡舉他們),比較常見的有fail2ban、denyhosts、以及knockd,前兩者的原理是通過對日誌文件的分析找出攻擊者ip,然後設置防火牆屏蔽之,屬於被動防禦,對於受攻擊頻率不高的機器還有點用處;後者則反其道而行,先設置防火牆拒絕任何訪問,合法訪問者須通過“正確”的敲門動作打開門纔可連接登錄,屬於主動防禦。
主動防禦的思路是不錯的,但是knockd的敲門方式私密性不佳,黑客可偵聽並簡單模仿敲門動作而成功連接,安全性低。
下面介紹一款我認爲安全性較高的主動防禦工具:fwknop,她與knockd的最根本區別在於其採用經過加密處理的“單包認證”敲門方式,私密性好得多。
詳細原理及配置就不細說了,有興趣可以去他的官網慢慢看:
http://www.cipherdyne.org/fwknop/docs/fwknop-tutorial.html

本文將安裝、配置的過程簡單羅列出來,分享給有需要的朋友們,少走彎路節省時間。

一、操作系統、工具環境
1.客戶端:Windows 7, Visual Studio 2008或以上版本;Linux。
2.服務器端:CentOS 6.8, gcc等常用開發工具;CentOS 7, firewalld防火牆。

二、安裝、配置客戶端
客戶端是Linux的,根據系統的情況下載安裝整個軟件包,這樣服務端和客戶端就都有了,配置方法參考其官網的教程。
Windows需要下載fwknop源碼自己編譯客戶端,下載地址:https://github.com/mrash/fwknop/releases
1)下載、解壓fwknop-master.zip,進入其win32子目錄;
2)如果你使用的是VS2008,把libfko.sln、libfko.vcproj、fwknop-client.vcproj刪除或改名,把後綴名爲.vs2008的三個文件改爲剛剛被刪除的那三個文件名;否則用純文本編輯器打開libfko.vcproj和fwknop-client.vcproj,找到"..\lib\fko_util.c"、"..\lib\fko_util.h"、"..\lib\strlcat.c"、"..\lib\strlcpy.c"這幾處地方,把其中的lib改爲common,保存。
3)雙擊打開libfko.sln,編譯其中的Release-full-static或者Release-static版本,得到單一的可執行文件fwknop.exe;
4)新建一個空文件夾(譬如D:\fwk)並把此文件拷貝過來,打開一個命令行窗口,然後執行:
D:
cd \fwk
fwknop --version
看到版本信息表明編譯成功了。
5)下載wget:http://www.interlog.com/~tcharron/wgetwin-1_5_3_1-binary.zip,解壓其中的wget.exe,放在和fwknop.exe同一個文件夾裏;
6)在此文件夾內,用純文本編輯器新建一個文件:bwget.bat,內容只有一行:@wget --no-check-certificate %1 %2 %3 %4 %5 %6 %7 %8 2>nul,保存;
7)在剛纔打開的命令行窗口內,執行命令:
fwknop -n cen6 -A tcp/22,tcp/4432 -a 192.168.0.137 -D 192.168.0.186 --use-hmac -p 62201 -P udp -k --save-rc-stanza
下面逐項作解釋:
-n cen6 給後面的參數起一個名字,方便以後調用;
-A tcp/22,tcp/4432 請求服務端打開的端口及其協議;
-a 192.168.0.137 客戶端的IP地址;
-D 192.168.0.186 服務端的IP地址;
--use-hmac 採用hmac加密認證方式;
-p 62201 服務端等待請求的偵聽端口;
-P udp 服務端等待請求的協議;
-k 生成一個加密密鑰;
--save-rc-stanza 保存以上參數的執行結果。
現在,用文本編輯器去打開用戶工作路徑裏的.fwknoprc文件(在我的機器上是C:\Users\suntongo\),其內容如下:
[default]
[cen6]
SPA_SERVER_PROTO            udp
SPA_SERVER_PORT             62201
ALLOW_IP                    192.168.0.137
ACCESS                      tcp/22,tcp/4432
SPA_SERVER                  192.168.0.186
KEY_BASE64                  0hLAT/i8uBuvwU+GiAZQ/X0MkiCq4waCyMWiF8ROkaQ=
HMAC_KEY_BASE64             0hLAT/i8uBuvwU+GiAZQ/X0MkiCq4waCyMWiF8ROkaQyUvkHV7FYJRe2vdkNTl+8gD7Y/picCtdspuKrX0qo5Q==
USE_HMAC                    Y
上面打那麼長的命令行,就是爲了生成這麼一堆內容,對比一下命令行裏的參數,大致都明白其中每行的含義了,其中KEY_BASE64和HMAC_KEY_BASE64就是-k參數自動生成的。
讀者可能會注意到ALLOW_IP設置了固定值,如果客戶端的IP經常變化那怎麼辦呢?很簡單,這配置文件內的每一行都可以被命令行參數覆蓋的,後面會有範例。
另外,如果服務端在外網且有域名,客戶端是在ADSL寬帶撥號的情況下又怎麼辦呢?
且看這個命令行:
fwknop -n cen7 -A tcp/22,tcp/4432 -R -w bwget.bat -D my.server.com --use-hmac -p 62201 -P udp -k --save-rc-stanza
讓我們來看看結果:
[cen7]
SPA_SERVER_PROTO            udp
SPA_SERVER_PORT             62201
ACCESS                      tcp/22,tcp/4432
SPA_SERVER                  my.server.com
KEY_BASE64                  PZVdrTcVnMNvrfdm6gDYQ64pJEP1sjQoyPGP/mNNdIc=
HMAC_KEY_BASE64             PZVdrTcVnMNvrfdm6gDYQ64pJEP1sjQoyPGP/mNNdIdNDiPoE0MLwGxjON7OHaxHNxAL0ydfrPGhUo9wI/e8Wg==
USE_HMAC                    Y
RESOLVE_IP_HTTPS            Y
WGET_CMD                    bwget.bat
在這小節中,SPA_SERVER不再是IP而是域名了,ALLOW_IP不見了,fwknop執行時會調用bwget.bat現場取得你的機器的公網IP用來代替ALLOW_IP,是不是很靈活方便?
OK,客戶端的配置基本完成了,cen6小節的配置適合於客戶端和服務端在同一局域網內的情況,cen7則適合服務端在公網、客戶端爲無固定IP的情況,下面開始分別展開對CentOS6及CentOS7服務端的配置工作了。

三、安裝、配置服務端(CentOS 6)
fwknopd是需要調用iptables的,CentOS 6官方的iptables版本過低,與fwknopd不適合,雖然fwknopd有一個--no-ipt-check-support的選項可迴避這個問題,但我還是建議你自己編譯一個較高版本的iptables。
下載iptables源碼包:wget http://www.netfilter.org/projects/iptables/files/iptables-1.4.11.1.tar.bz2
解壓:tar xf iptables-1.4.11.1.tar.bz2,然後cd進入子路徑裏;
編譯:無非就是 ./config; make; make install。
1)安裝fwknop:yum install fwknop
2)編輯配置文件

vi /etc/fwknop/access.conf

#客戶端IP,建議設置爲ANY,除非客戶端的IP是固定的。
SOURCE                 ANY
#服務器網卡的IP,建議設置爲ANY,如果有多個網卡,則設置爲你需要“開門”的那個網卡的IP。
DESTINATION            ANY
#“敲門”成功後須打開的協議及端口。
OPEN_PORTS             tcp/22,tcp/4432
#根據實驗,這個必須設爲N,否則死活都敲不開這道門。
REQUIRE_SOURCE_ADDRESS N
#複製自客戶端生成的數據(必須保持與客戶端相同)。
KEY_BASE64             0hLAT/i8uBuvwU+GiAZQ/X0MkiCq4waCyMWiF8ROkaQ=
HMAC_KEY_BASE64        0hLAT/i8uBuvwU+GiAZQ/X0MkiCq4waCyMWiF8ROkaQyUvkHV7FYJRe2vdkNTl+8gD7Y/picCtdspuKrX0qo5Q==

vi /etc/fwknop/fwknopd.conf

#網卡的名稱,可用ifconfig查看得到。
PCAP_INTF               eth0;
#“門板”的偵聽協議及端口,推薦用udp。
PCAP_FILTER             udp port 62201;
UDPSERV_PORT            62201;
ENABLE_UDP_SERVER       Y;

#“門板”的偵聽協議及端口,在不宜使用udp的場合(如通過“巨型防火牆”訪問外網),也只好這樣啦。
#PCAP_FILTER             tcp port 62201;
#TCPSERV_PORT            62201;
#ENABLE_TCP_SERVER       Y;
#ENABLE_UDP_SERVER       N;

#“敲門磚”有效期限制,不建議選N。
ENABLE_SPA_PACKET_AGING Y;
#“敲門磚”有效期(秒)
MAX_SPA_PACKET_AGE      60;
#兩次“敲門”之間的“不答應”時間。
PCAP_LOOP_SLEEP         100000;
#“敲門磚”的最大尺寸。
MAX_SNIFF_BYTES         1500;
#爲了安全,不建議設爲Y。
ENABLE_SPA_OVER_HTTP    N;
#以下兩項決定了“敲門”成功後fwknopd對防火牆的操作行爲,具體就不解釋了。
ENABLE_DESTINATION_RULE N;
IPT_INPUT_ACCESS        ACCEPT, filter, INPUT, 1, FWKNOP_INPUT, 1;
#如果使用的防火牆不是系統原配的iptables,那你就需要指明其路徑。
FIREWALL_EXE            /usr/local/sbin/iptables;

3)檢查防火牆的設置,確保fwknopd偵聽的端口及協議是暢通的,如有必要,增加一條規則:
iptables -I INPUT -p udp -m udp --dport 62201 -j ACCEPT
4)先讓服務端進入測試狀態:
[root@s51 ~]# fwknopd -f -t -v
[+] Writing my PID (20359) to the lock file: /var/fwknop/fwknopd.pid
Starting fwknopd
Using Digest Cache: '/var/fwknop/digest.cache' (entry count = 29)
Kicking off UDP server to listen on port 62201.

5)運行客戶端進行“敲門”測試:
fwknop.exe -n cen6

服務端看到類似以下內容的信息(注意最後一行),則表示“敲門”已經成功:
udp_server: Got UDP datagram (225 bytes) from: 192.168.0.137
(stanza #1) SPA Packet from IP: 192.168.0.137 received with access source match
SPA Packet: ....(太長了,省略)
[192.168.0.137] (stanza #1) --test mode enabled, skipping firewall manipulation.

(思考實驗題:製造一次能看到“敲門磚”內容但“敲門”失敗的測試,查看其與成功“敲門”之差別。)
6)在服務端操作窗按Ctrl-C退出測試狀態,可以啓用fwknopd服務進入工作狀態了:
service fwknopd start
7)防火牆設置
先查看一下現有的設置:
iptables-save

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-N FWKNOP_INPUT
-A INPUT -p udp -m udp --dport 62201 -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p udp -m udp --dport 1194 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 4432 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -i tun+ -j ACCEPT
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
COMMIT
可以看到,fwknopd啓用之後,防火牆多了一條規則鏈FWKNOP_INPUT,其內容是空的。
用客戶端丟一個“敲門磚”過來,然後在服務器端用iptables-save查看一下(動作要快),會發現多了兩條規則:
-A FWKNOP_INPUT -s 192.168.0.137/32 -p tcp -m tcp --dport 22 -m comment --comment _exp_1482021946 -j ACCEPT
-A FWKNOP_INPUT -s 192.168.0.137/32 -p tcp -m tcp --dport 4432 -m comment --comment _exp_1482021946 -j ACCEPT
說明“敲門”動作已經成功,防火牆按照預期打開了設定的協議以及端口。
由於fwknopd默認在打開門30秒之後會重新關上(這點可以通過用iptables-save反覆查看來證實),敲門之後應儘快嘗試進行連接。
那麼,在開門期間建立的連接會不會因關門而中斷?還有就是關門是否真的能阻止非法的訪問?
答案是看你的防火牆配置是否符合要求!
要求(1):-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT 這一條規則不可缺少,且其位置應相對靠前;
要求(2):有效的關門條件必須成立。就拿前面的配置來分析吧,由於存在 -A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT 這一條,無論fwknopd開門還是關門,端口22的ssh連接都是暢通的(端口4432也是如此),所以應刪除相關端口的放行規則。
對防火牆的配置也有流派之分,有人喜歡默認放行,然後逐條DROP規則實施必要的阻止;有人則喜歡默認阻止,然後逐條ACCEPT規則選擇性地放行,fwknopd對這兩種流派都能有效發揮作用,總的原則是該放行的就放行,該阻止的就阻止,配置防火牆時周密細緻的安排是必不可少的。
順便舉個例子,如果客戶端IP不是原來設置的值,可以用命令行參數-a覆蓋而不必改動.fwknoprc的內容:
fwknop.exe -n cen6 -a 192.168.0.110
OK,關於CentOS 6的內容就到此爲止,接下來講CentOS 7吧。

四、安裝、配置服務端(CentOS 7)
如果你不打算用CentOS 6作爲服務器操作系統,也請先閱讀一下前一章,有很多隻說了一遍但還是挺重要的內容在後文省略了。
CentOS 7默認安裝中捨棄了iptables服務,保留了iptables及其相關的工具,取而代之的是firewalld服務,有不少習慣了iptables的人總是想法子禁用firewalld服務和恢復iptables服務,如果你繼續堅持這種“前朝遺老”式的心態,那麼fwknopd真的不適合你!
0)先確認一下firewalld服務能正常啓用:
which firewalld
如果沒有,先安裝:yum install firewalld
systemctl status firewalld.service
如果firewalld已經正常運行中,直接跳過,進行步驟1);
如果曾被禁用,還須啓用之:
systemctl enable firewalld.service
並禁用與之衝突的服務:
systemctl disable --now iptables.service
systemctl disable --now ip6tables.service
systemctl disable --now ebtables.service
systemctl disable --now ipset.service
systemctl start firewalld.service
然後用firewall-cmd根據你的需要打開相關的服務端口。

1)安裝fwknop:yum install fwknop
2)編輯配置文件
vi /etc/fwknop/access.conf
SOURCE                 ANY
DESTINATION            ANY
OPEN_PORTS             tcp/22,tcp/4432
REQUIRE_SOURCE_ADDRESS Y
KEY_BASE64             PZVdrTcVnMNvrfdm6gDYQ64pJEP1sjQoyPGP/mNNdIc=
HMAC_KEY_BASE64        PZVdrTcVnMNvrfdm6gDYQ64pJEP1sjQoyPGP/mNNdIdNDiPoE0MLwGxjON7OHaxHNxAL0ydfrPGhUo9wI/e8Wg==

vi /etc/fwknop/fwknopd.conf
PCAP_INTF                   enp3s0;
ENABLE_UDP_SERVER           Y;
UDPSERV_PORT                62201;
PCAP_FILTER                 udp port 62201;
ENABLE_SPA_PACKET_AGING     Y;
MAX_SPA_PACKET_AGE          60;
ENABLE_SPA_OVER_HTTP        N;
ENABLE_DESTINATION_RULE     N;
FLUSH_FIREWD_AT_INIT        Y;
FLUSH_FIREWD_AT_EXIT        Y;
ENABLE_FIREWD_FORWARDING    Y;
ENABLE_FIREWD_LOCAL_NAT     N;
ENABLE_FIREWD_OUTPUT        N;
FIREWD_INPUT_ACCESS         ACCEPT, filter, INPUT, 1, FWKNOP_INPUT, 1;
FIREWD_FORWARD_ACCESS       ACCEPT, filter, FORWARD, 1, FWKNOP_FORWARD, 1;
ENABLE_FIREWD_COMMENT_CHECK N;
FIREWALL_EXE                /usr/bin/firewall-cmd;

3)設置防火牆,確保fwknopd偵聽的端口及協議是暢通的:
firewall-cmd --permanent --new-service=fwknop
firewall-cmd --permanent --service=fwknop --add-port=62201/udp
firewall-cmd --permanent --add-service=fwknop
firewall-cmd --zone=public --add-service=fwknop

4)仔細覈對各項配置符合你的環境及需要,然後開始測試:
fwknopd -f -t -v
5)運行客戶端進行“敲門”測試:
fwknop -n cen7
(測試細節見前文。)
6)在服務端操作窗按Ctrl-C退出測試狀態,可以啓用fwknopd服務進入工作狀態了:
systemctl start fwknopd.service
7)防火牆設置
先查看一下現有的設置:
firewall-cmd --list-all

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp3s0
  sources:
  services: dhcpv6-client fwknop http https ssh
  ports:
  protocols:
  masquerade: no
  forward-ports:
  sourceports:
  icmp-blocks:
  rich rules:

用客戶端丟一個“敲門磚”過來,再在客戶端查看防火牆有什麼新情況:
iptables -L
....
Chain FWKNOP_INPUT (1 references)
target     prot opt source               destination
ACCEPT     tcp  --  113.168.160.52         anywhere             tcp dpt:ssh /* _exp_1482301574 */
ACCEPT     tcp  --  113.168.160.52         anywhere             tcp dpt:4432 /* _exp_1482301574 */
....
以此推知,“敲門”成功,防火牆也把相應的端口打開了,現在可以正式把ssh的門關上,抵禦各路黑客們的暴力攻擊了:
firewall-cmd --zone=public --remove-service=ssh

題外話:關於denyhosts
本人很早就使用denyhosts來進行防禦了,因爲她配置比較簡單而且效果還是不錯的,但是也有被動防禦工具們共同的缺陷:反應滯後、對高密度攻擊抵抗力差。
另外,denyhosts還曾經把機器主人也屏蔽了,究其原因是攻擊者與機主共享公網IP,很多校園網、辦公樓網以及某些無良的“寬帶”奸商都是大批用戶通過NAT或者其他方式共享公網IP上網的,如果恰好攻擊者的公網IP與機主相同,那麼機主也被denyhosts無情地拒絕了。
題外話1:關於ssh
1.改端口問題,很多討論是通過改端口來躲避ssh攻擊,這個方法確可以讓大多數低級黑客無功而返,但是對修爲稍微高一點的黑客是無效的。還有一個嚴重的問題是某巨型防火牆對非22端口的ssh連接一律判定爲可疑動作而干擾、阻止,迫使你還得使用22端口。
2.禁止root用戶登錄,這是個好主意,大大降低了被入侵的機率。
3.棄用口令驗證,採用密鑰驗證,這絕對是明智之舉,配合方法2,堪稱萬全。
題外話2:關於fwknop
1.既然已有萬全之策,何必再來個fwknop?先分析一下黑客的ssh暴力攻擊行爲,黑客測試目標主機的22端口,如可以連接,即保持此連接開始嘗試破解,此時會佔用機器的少量資源,也會在機器的日誌文件中留下記錄,如果多個黑客同時密集攻擊,機器將面臨沉重的負荷而性能下降、日誌文件體積暴增,因此,關門謝客纔是最佳選擇,黑客連最初的連接動作都失敗,自然就不會有後續的攻擊嘗試了,實測效果證明,以前denyhosts每天都新增幾百個攻擊者IP黑名單,多的時候甚至過千,自從安裝了fwknopd,媽媽再也不用耽心我的服務器主機了。
2.fwknop真的就沒有缺陷嗎?當然不是,就拿上述共享公網IP的情況來說,一旦你“敲”開了門,使用相同公網IP的所有機器都可連接,不過因爲開門的時間很短,危險係數還是很低的(除非哪位技術很高的黑客一直在盯着你),就讓那些漫無目的到處亂掃的黑客們到別處涼快去吧。
3.本文介紹fwknop採用HMAC加密,有支持更安全的加密方式嗎?有,去他的官網看看她關於配置gpg加密的範例。
4.除了防禦ssh暴力破解,fwknop還能幹些什麼?防禦ssh暴力破解是fwknop主要目的之一,就其“開門”機理來說,是可以靈活應用的,譬如服務器上安裝了某個(或多個)端口的服務是給自己女朋友專用的,爲安全起見平時也是要把這個端口關上的,那麼你可以在她的電腦上專門配置一個客戶端(Android、iphone也可以哦),然後在服務端增加一個配置小節,這樣就可以你用你的端口她用她的端口,互不干擾。(悄悄問一句:你有幾個npy?)
題外話3:關於fwknop客戶端的-R參數
-R是讓fwknop客戶端通過公網服務器讀取公網IP,默認情況下是由外部命令wget https://www.cipherdyne.org/cgi-bin/myip實現的,wget訪問https是需要配置信任證書的,比較麻煩,可以加上--no-check-certificate選項來回避(前文提到的bwget.bat就是爲解決這個問題的)。另外,默認的網址反應速度比較慢,如果自己有反應快且已配置https支持的web服務器,可以寫幾行代碼實現之,本人正好有一個符合要求的web服務器,是由node.js+express編寫的,改編是如此的簡單:
進入web服務器程序所在路徑後,vi app.js,在適當的地方加入兩行:
....
var getip = require('./routes/getip');
....
app.use('/getip', getip);
....

然後新建一個文件:
vi routes/getip.js

var express = require('express');
var router = express.Router();
/* GET visitor's IP. */
router.get('/', function(req, res, next) {
  res.end(req.connection.remoteAddress + '\r\n');
});
module.exports = router;
保存,重啓web服務。
客戶端:fwknop -n cen7 --resolve-url https://my.server.com/getip或者在.fwknoprc文件的cen7小節內添加一行:
RESOLVE_URL  https://my.server.com/getip
即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章