使用iptable實現動態防火牆(轉)

post0發表於2007-08-10
使用iptable實現動態防火牆(轉)[@more@]

防火牆是一個非常重要的網路安全工具,但是如果在需要對防火牆規則進行快速、複雜的動態修改時你該如何實現呢?如果你使用本文介紹的Daniel Robbins 的動態防火牆指令碼,這將是一件非常容易的工作。你可以利用這些指令碼來增強你網路的安全性和對網路攻擊的實時響應性,並基於該指令碼進行自己的創造性設計。

理解動態防火牆的指令碼能夠帶來的益處的最好方法就是看它們在實際中的應用。假設我是一個某個ISP的系統管理員,我最近架設了一個基於Linux的防火牆來保護我的客戶和內部系統,防止外部惡意使用者的攻擊。為了實現該系統我使用了新版Linux2.4核心的iptables工具來實現,防火牆允許客戶和內部伺服器向Internet建立連線,也允許從Internet向內部系統的公共服務如web伺服器、ftp伺服器等建立新的連線。由於這裡我使用了預設拒絕任何服務,只開放允許的服務的策略,因此從Internet到非公共服務如squid的代理服務、samba服務的連線是被拒絕的。目前我已經有了一個功能完備的、滿足安全需求的防火牆系統,其能對ISP的所有使用者提供很好的保護。

剛剛開始的一個星期防火牆工作情況良好,但是隨後一些糟糕的事情發生了。Bob-一個攻擊者對我的網路進行了攻擊,它採用了使用垃圾資料包淹沒我的ISP網路的方法來對我的客戶進行Dos攻擊。不幸的是Bob 已經對我的防火牆進行了仔細的研究,知道雖然我對內部服務進行了保護但是25埠和80埠都是開放的以收發Emai和開放www服務。Bob決定對我的 Email和WWW伺服器進行Dos的攻擊。

Bob開始攻擊的1-2分鐘以後我發現我的線路出現嚴重的擁塞情況。透過tcpdump察看我發現這是Bob進行的一次攻擊。並且我得到了它的攻擊源地址。現在我就需要阻止這些IP地址對我的公共伺服器的連線。下面我就討論一種簡單方便的解決方案。

阻止攻擊

我馬上採取行動,載入我的防火牆啟動指令碼並使用vi對 iptables 規則進行編輯,來阻塞這些Bob發出的惡意攻擊資料的源地址的資料包。大約一分鐘以後我找到了在防火牆啟動指令碼中新增新的DROP規則的位置,我馬上新增了新的規則並重新啟動了防火牆。很快防火牆發揮了作用,Bob的攻擊得到了遏制。現在看起來我成功的擊潰了Bob的攻擊,可是不久網路值班電話又響了起來,原來是客戶發現網路不可用而打過來的投訴電話。可是更加糟糕的是幾分鐘以後我注意到我的Internet連線線路又開始出現嚴重阻塞。我仔細察看原來是Bob使用了新的IP地址進行攻擊行動。我只好不得不再次修改防火牆啟動指令碼來阻止它的攻擊。我就這樣一直在Bob的屁股後面疲於奔命。

問題出在哪裡呢?雖然我建立了功能完備的、滿足安全需求的防火牆系統並且快速的發現了網路出現問題的原因,但是我卻不能在第一時間內對我的防火牆規則進行調整來響應Bob的攻擊。當網路被攻擊時,被動慌亂地快速對攻擊做出防範反應,對防火牆規則配置指令碼進行修改不但是壓力巨大,而且效率低下。

ipdrop

如果能建立一個特殊的"ipdrop"指令碼,其被設計為能方便地插入一個規則來阻塞指定的IP,那麼將上面的工作將非常容易。透過該指令碼阻塞某個IP將是非常容易的工作,只需要幾秒鐘就可以實現。而且透過該指令碼還可以防止手工加入規則時容易出現的錯誤。因此阻塞Bob的攻擊將變為確定其攻擊源地址。然後透過如下命令:

# ipdrop 129.24.8.1 on

IP 129.24.8.1 drop on.

ipdrop指令碼將立即阻塞129.24.8.1。透過使用該指令碼能顯著地提高你的防衛能力。下面就是ipdrop指令碼的實現:

The ipdrop bash script

#!/bin/bash

source /usr/local/share/dynfw.sh

args 2 $# "${0} IPADDR {on/off}" "Drops packets to/from IPADDR. Good for obnoxious networks/hosts/DoS"

if [ "$2" == "on" ]

then

#rules will be appended or inserted as normal

APPEND="-A"

INSERT="-I"

rec_check ipdrop $1 "$1 already blocked" on

record ipdrop $1

elif [ "$2" == "off" ]

then

#rules will be deleted instead

APPEND="-D"

INSERT="-D"

rec_check ipdrop $1 "$1 not currently blocked" off

unrecord ipdrop $1

else

echo "Error: "off" or "on" expected as second argument"

exit 1

fi

#block outside IP address that's causing problems

#attacker's incoming TCP connections will take a minute or so to time out,

#reducing DoS effectiveness.

iptables $INSERT INPUT -s $1 -j DROP

iptables $INSERT OUTPUT -d $1 -j DROP

iptables $INSERT FORWARD -d $1 -j DROP

iptables $INSERT FORWARD -s $1 -j DROP

echo "IP ${1} drop ${2}."

ipdrop:解釋

從上面的指令碼原始碼中最後四行加粗的內容可以看到實際的命令是在防火牆表中插入適當的規則。可以看到$INSERT變數的值取決於在命令列引數中是使用"on"還是"off"模式。當iptables行被執行時特定的規則將被適當的插入或刪除。

現在我們看看這些規則本身的功能,它們能和任何型別的防火牆一起發揮作用,甚至在沒有部署防火牆的系統上。需要的條件僅僅是支援iptables的 Linux2.4版本的核心。我們阻塞來自惡意IP的攻擊資料包(第一條iptables語句),阻塞發向惡意攻擊IP的資料包(第二條iptables 語句),並且對該IP關閉任意方向的資料轉發(最後兩條iptables工具)。一旦這些規則發揮作用系統將丟棄滿足這些條件的任何資料包。

另外一個需要注意的是:指令碼中呼叫了"rec_check", "unrecord", "record",和"args"。這些都是定義在"dynfw.sh"中的特殊的bash函式。"record"函式實現將被阻塞的IP記錄在檔案 /root/.dynfw-ipdrop檔案中,而"unrecord"則是將其從檔案/root/.dynfw-ipdrop中去除。 "rec_check"函式是在發現試圖重新阻塞某個已經阻塞的IP地址或取消某個沒有被阻塞的IP地址時輸出錯誤資訊並停止指令碼執行。"args"函式實現確保命令列引數的正確性,並實現列印指令碼幫助命令。檔案dynfw-1.0.tar.gz包含所有的這些工具,具體情況請見文章最後的資源部分。

tcplimit

如果你需要對某個特殊的基於TCP的網路服務的使用進行限制(例如在端系統上產生嚴重負載時),則tcplimit指令碼則可以幫助你達到這個目的,該指令碼使用TCP埠、一個率值和"on"或"off"作為引數:

# tcplimit 873 5 minute on

Port 873 new connection limit (5/minute, burst=5) on.

tcplimit使用iptables的"state"模組(應確保在核心中開啟該選項或載入模組)來實現在某段時間內只允許特定數目的連線請求透過。在本例中防火牆將限制每分鐘只允許5個新連線到我的rsync伺服器(port 873)。當然你可以根據需要選擇時間單位為秒鐘/分鐘/小時。

tcplimit 提供了一個限制對非關鍵服務的使用的非常好的方法-這樣大量到非關鍵服務的資料不會破壞伺服器。在上面的例子中使用tcplimit來設定使用rsync 的限制,以防止tsync資料佔用了Internet連線的所有頻寬。其中連線服務限制資訊記錄在檔案/root/.dynfw-tcplimit中。若想關閉該限制只需要鍵入如下命令:

# tcplimit 873 5 minute off

Port 873 new connection limit off.

tcplimit 透過在"filter"表中建立一個新的規則鏈來實現。這個新的規則鏈將拒絕所有超過指定限制的資料包,同時將一個規則插入到INPUT規則鏈中,其將所有的到目標埠(在本例中是873埠)的新連線資料包定向到這個新的規則鏈。新規則鏈只會影響新的超過限制的連線而不會影響已經建立的連線。

當tcplimit定義的規則被關閉,INPUT規則和新規則鏈則會被刪除。象ipdrop一樣其tcplimit可以和任何型別的防火牆一起工作。

host-tcplimit

host -tcplimit和tcplimit非常類似,但是它是限制來自一個特定的IP的到伺服器上某個特定埠的TCP連線數量。host-tcplimit 在防止某個特定的人濫用你的網路資源時非常有用處。例如你維護有一個CVS伺服器,有一天突然發現一個特殊的新開發者出現了,他好像建立了一個指令碼每十分鐘更新它的資源。佔用了大量的網路資源。然後你就給他傳送信件說明他的行為的錯誤之處。但是你收到他如下的回信:

Hi guys!

I'm really excited to be part of your development project. I just set up a

script to update my local copy of the code every ten minutes. I'm about to

leave on a two-week cruise, but when I get back, my sources will be totally

up-to-date and I'll be ready to help out! I'm heading out the door now...see

you in two weeks!

Sincerely,

Mr. Newbie

對於這種情況,使用host-tcplimit可以非常容易的解決問題:

# host-tcplimit 1.1.1.1 2401 1 day on

現在Newbie先生(IP地址為1.1.1.1)被限制為每天只能進行一次CVS連線從而節省了網路頻寬。

user-outblock

最後一個,也是這幾個防火牆指令碼中最有趣的是user-outblock。這個指令碼提供了一種實現允許某個使用者透過SSH或telnet登入到系統上但是不允許它透過命令列命令建立向外連線去的一個很理想的方法。下面是一個應用user-outblock的一個示例場合。假設一個特殊的家庭在我們的ISP擁有一個賬號。媽媽和爸爸使用圖形化的email客戶端程式閱讀自己的信件,偶爾會衝浪Internet,但是他們的兒子卻是一個熱衷的hacker分子,他常常使用它的shell訪問許可權來對其他的機器做一些淘氣的事情。

有一天你發現他和若干系統建立ssh連線,發現目標地址是屬於巴基斯坦軍事網站。你希望幫助這個小孩子走向正道,因此你採取了以下的行動:

首先,你檢查自己的系統並確保去掉了所有和網路相關的程式的suid位,例如ssh:

# chmod u-s /usr/bin/ssh

現在他企圖使用的任何和網路相關的程式都會擁有自己的UID。你現在可以使用user-outblock來阻塞所有該UID發出的的向外TCP連線(假設其UID為2049):

# user-outblock 2049 on

UID 2049 block on.

現在他只能登入到系統中閱讀自己的信件,但是他不能使用你的伺服器建立SSH連線。

資源

* 由於發現動態這些防火牆指令碼非常有用,因此將它們打包(dynfw-1.0.tar.gz)以供下載安裝。

要進行安裝只需要解壓縮包,執行其中的install.sh檔案。該指令碼將安裝一個共享bash指令碼為 /usr/local/share/dynfw.sh,並且安裝動態防火牆指令碼到/usr/local/sbin目錄下。若希望安裝在其他指令碼中,則只需要在執行install.sh以前執行:

# export PREFIX=/usr

還可以在dynamic firewall scripts section to the Gentoo Linux Web site下載dynfw的最新版本。

* tcpdump是一個非常重要的探測底層的IP報交換的工具,使用它可以驗證防火牆工作是否正常

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-940678/,如需轉載,請註明出處,否則將追究法律責任。

相關文章