閱讀 2,376 次

Portknocking 可以用來,當我們需要保護一台公開的伺服器對任意ip公開ssh或ftp等服務埠時,又同時需要對抗惡意人士的tcp port掃瞄或是暴力連接測試。其實後者是多講的,以一位負責的管理者而言,責任內的每一台公開伺服器,他就必需盡最大的能力,將它保護起來,同時又保持對善意人士的開放服務。

這個 Portknocking 觀念,我是上個月才知道的,但就我所看到的網頁資料,它的觀念到少已經出來5年了。我卻很少查到中文網頁有介紹這項觀念與技術。

問題是它在網路安全的防範上,又相當的強固。實在搞不懂為什麼沒有人介紹它。我想原因應該是,知道的人自己看國外網站資料就行了,不需要靠中文網站資料,不知道的人永遠不會知道,所以完全用不著,加上這名詞太生澀,中譯名可能不統一。

ok,回到主題。先介紹觀念:

Portknocking 觀念示意圖一言以蔽之,就是芝麻.開門-芝麻.開門技術。瞭解了嗎?不瞭解?好,大陸有很專業的人士,翻譯做「端口碰撞技術」。這麼專業的詞彙,聰明的你就瞭解了吧?

大陸有那麼多看得懂英語的人,卻說不好中文,經常把英文詞彙翻得怪裡怪氣。我想他們看台灣翻的,一樣也覺得怪裡怪氣吧。

哇又離題了。什麼叫芝麻開門?就是當不知道口令的陌生人來到我們家門口時,門神永遠讓它吃閉門羹。但若來人以正確的順序及文字說出:芝麻.開門! 的時候,門就晃郎郎地打開了,金銀財寶隨便你進去拿。

這看過阿里巴巴卡通的小學生都知道,那跟我的網路安全保護有什麼關係?有,當惡意的陌生人,如果做不到芝麻開門的暗號動作時,那我們的重要服務埠(如SSH的 22)就不會對他開放。如果我們在連到真正的重要服務之前,有先設定做一些連線敲門動作(即芝麻開門暗號),讓公開伺服器察覺到,這是主人來了,才自動開22的門,於是我們就可以連進去了。

通常這類芝麻開門的暗號動作,是主人以「先嘗試連65535個埠中某一個埠」,「再嘗試連65535個埠中的另一個埠」,這種類似保險箱的密碼組合,為開門暗號。惡意人士,很難從65535個埠中選2個為組合(高中機率基礎計算 C-6萬5千取2),找出正確的開門暗號。因此它相當強固。若要更強固,我們可以 C-6萬5千取4,就如左圖的說明,要先經過正確的先敲1號門、再敲2號門、再敲3號門,再敲4號門,真正的 n 號蓬門始為君開。這是幾乎不可能被猜出來的埠號組合。

什麼?這不就是搞老式保險箱轉盤號碼鎖嗎?對啊。不過「端口碰撞技術」感覺高深多了,可以讓你的老闆和同事對你肅然起敬,整個FU就是不一樣;要是跟他們說「我使用芝麻開門技術」來保護伺服器,顯得多麼沒有水準呢!(大陸稱為技術含量 呵呵)

 
接下來介紹轉盤號碼鎖,也就是門神的實作。實作的PK技術有很多。早期 iptables 還沒有強大外掛模組功能時,許多人用 bash 或者是 c 寫了不少服務器來實作這個觀念,例如 Knockd, PortKnockO等等…但載入這些服務器後,總是會多佔系統資源。又因為現在的每一台對外公開服務的 Linux 機器,都必定會使用 iptables 來做基本的防火牆功能,所以我選擇的實作,又是簡單省資源又高效率的 iptables + recent 模組方法。先前已經提過它可以用來阻當高頻率的連線。

以下範例使用新增一個 chain,和設定一些封包檢查與貼標籤的規則,要求以5秒內正確做出連線組合動作,先連168 port,再連978 port,來做為保護SSH 22 port ,的實作說明。

如果你使用檔案: /etc/sysconfig/iptables, 正常方式來儲存 iptables 的設定的話,將下列幾段文字加入該檔案的最後,COMMIT行之前。

如果你使用命令方式/sbin/iptables -A ..如此如此..這般這般…. 直接下的話,要以 iptables -N INTO-PHASE2 新增一個 chain。

:INTO-PHASE2 

--A INTO-PHASE2 -m recent --name PHASE1 --remove-A INTO-PHASE2 -m recent --name PHASE2 --set          

-A INTO-PHASE2 -j LOG --log-prefix "INTO PHASE2: "-A INPUT -m recent --update --name PHASE1          

-A INPUT -p tcp --dport 168 -m recent --set --name PHASE1          

-A INPUT -p tcp --dport 978 -m recent --rcheck --name PHASE1 -j INTO-PHASE2          

-A INPUT -p tcp -s YOUR_HOST_IP --dport 22 -m recent --rcheck --seconds 5 --name PHASE2 -j ACCEPT

每一行的順序不能變,一行一行解釋如下:

第一行:INTO-PHASE2 -

新增一個叫做INTO-PHASE2 的 chain,沒有預設的放行或丟棄等動作。

第二行:把進來INTO-PHASE2 chain裡的封包,除去標籤名為 PHASE1 的封包。

第三行:把進來INTO-PHASE2 chain裡的封包,貼上標籤名為 PHASE2 的封包。

第四行:把進來INTO-PHASE2 chain裡的封包,留下一個系統 syslog 記錄 (本行可要可不要)

第五行:把連線目標埠為168的封包,貼上 PHASE1 的標籤。

第六行:把連線目標埠為978、同時也要有貼著 PHASE1標籤的封包,送到 INTO-PHASE2 處理

===> 也就是被移去 PHASE1標籤、然後被貼上 PHASE2 標籤。

第七行:被貼上 PHASE2 標籤的封包,同時也想連我伺服器 IP 的 22 SSH port 時,讓它通過。

有人可能會問,為什麼要照上面的順序動作設,這要是講到完,眼淚就流不完了。主要的想法是,我們5秒內正確順序連168再接978的一個連線封包會被依次貼上 PHASE1再清除,再被貼上 PHASE2 的標籤,有著 PHASE2 的標籤後,才能通過22 port 。

那 麼我們要如何發出口令暗號?

很多方法,有慢慢一行一行下口令,然後手忙腳亂;也可以寫個小 script,只要用 telnet 或 nmap 之類的網路連線工具,先後快速連168埠再接著馬上連978。然後馬上使用標準的 ssh客戶端來連22,才(就)會通了。

opendoor.sh 示意, opendoor.sh IP 168 978:

#!/bin/bash          

# $1 host name or IP address          

telnet $1 $2 &> /dev/null          

telnet $1 $3 &> /dev/null          

ssh $1
RSS Trackback URL ming | 一月 12, 2008 (12:47 下午)

Linux

3 個回應

留下回應»
  1. 1

    感謝您的好文分享,我參考你的這篇文章實作成功了。底下是我實作成功的筆記 http://dominic16y.world.edoors.com/C6iVNy67IcS4

  2. 2

    哈哈 謝謝你的更正啊~保護ssh的話,我現在是用「金鑰交換認證ONLY」了。比較懶人,強度也還算夠(當然,得相信客戶端是安全不被入侵的)。

    但要保護其它通訊應用,如果是自己寫的AP,或許這個觀念是可以採納的。

  3. 3

    難得一見的好文
    剛好有需要參考到 感激不盡

留下回應