動態iptables 防火牆


文檔選項
將打印機的版面設置成橫向打印模式

打印本頁

將此頁作爲電子郵件發送

將此頁作爲電子郵件發送


級別: 初級

Daniel Robbins ([email protected]), 總裁兼 CEO, Gentoo Technologies, Inc.

2001 年 4 月 01 日

防火牆非常有趣,但在需要對防火牆規則進行快速且複雜的更改時,您會做些什麼?很簡單。請使用本文中演示的 Daniel Robbins 的動態防火牆腳本。可以使用這些腳本來增加網絡安全性和響應性,並激發您自己的創造性設計。

瞭解動態防火牆腳本好處的最佳方法是在運行時查看它們。要這樣做,讓我們假設我是一家 ISP 的系統管理員,最近我建立了基於 Linux 的防火牆,用於保護我的客戶和內部系統免遭因特網上惡意用戶的攻擊。爲了實現這個目的,我的防火牆使用新的 Linux 2.4 iptables 有狀態功能,以允許我的客戶和服務器建立新的外出連接,當然還允許新的進入連接,但僅限於“公共”服務,如 web、ftp、ssh 和 SMTP。由於我使用了缺省拒絕設計,因此會自動拒絕任何從因特網到非公共服務(如 squid 代理緩存或 Samba 服務器)的連接。現在,我有一個非常不錯的防火牆,它爲我公司的所有客戶提供了非常好的保護。

在第一個星期左右,防火牆的工作非常出色,但在這之後卻發生了件討厭的事:我最大的對手 Bob(他爲另一家 ISP 工作,是我們的競爭對手)決定用大量信息包攻擊我的網絡,試圖阻止我向客戶提供服務。糟糕的是,Bob 已經仔細研究了我的防火牆,他知道我在保護內部服務時,端口 25 和 80 必定是可以公開訪問的,這樣我纔可以接收郵件和響應 HTTP 請求。Bob 決定利用這一點,他想用吸乾帶寬的方法來攻擊我的 Web 和郵件服務器。

大約在 Bob 實施攻擊一分鐘之後,我注意到信息包逐漸佔滿了上行鏈路。在查看了 tcpdump 的情況之後,我確定這還是 Bob 實施的另一次攻擊,我推算出他用於發起攻擊的 IP 地址。現在我已經有了這個信息,我需要做的就是阻止這些 IP 地址,我想這大概能解決問題 -- 很簡單的解決方案。

響應攻擊

我迅速使用 vi 打開防火牆設置腳本,並開始改動 iptables 規則、修改防火牆,這樣它就可以阻止那些 Bob 發出的惡意進入信息包。大約一分鐘左右,我找到了添加合適 DROP 規則的確切位置,並添加了這些規則。然後,我啓動防火牆,但又馬上停止了它……哎,我在添加規則時犯了一個小錯。我再次裝入防火牆腳本,改正問題,30 秒之後,將已將防火牆調整成阻止這個月內 Bob 發起的所有攻擊。起先,它似乎成功地挫敗了攻擊……直到問訊臺的電話鈴聲響起。顯然,Bob 已經中斷我的網絡大約 10 分鐘,現在我的客戶打電話來詢問究竟發生了什麼情況。更遭的是,幾分鐘後,我發現上行鏈路又被佔滿了。看來 Bob 這次使用了一組全新的 IP 地址來實施攻擊。我也做出響應,立即開始修改防火牆腳本,只不過這次我有一點驚慌 -- 也許我的解決方案還不那麼完美。

以下就是上述情況中出錯的原因。雖然我有一個不錯的防火牆,還迅速標識了網絡問題的原因,但我無法修改防火牆的行爲以使它能夠及時應付威脅。當然,當網絡受到攻擊時,您希望能夠立即響應,在緊急狀態下被迫修改主防火牆設置腳本不僅在時間上很緊迫,而且效率非常低。





回頁首


ipdrop

如果有一個特別設計的特殊 "ipdrop" 腳本,它可以插入阻止我指定的 IP 地址所需的規則,那麼情況會好多了。有了這樣的腳本,阻止防火牆就不再是兩分鐘的折磨;它只需 5 秒鐘。由於這個腳本可以讓我不必手工編輯防火牆規則,這就消除了出錯的主要根源。我所要做的只是確定要阻止的 IP 地址,然後輸入:

# 
        
        ipdrop 129.24.8.1 on
IP 129.24.8.1 drop on.
      
      

ipdrop 腳本會立即阻止 129.24.8.1,這是本週 Bob 的當前惡意 IP 地址。這個腳本明顯提高了您的防禦能力,因爲現在阻止 IP 並不是件費神的事。現在,讓我們看一下 ipdrop 腳本的實現:


ipdrop bash 腳本
#!/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 行執行時,會適當插入或刪除特定規則。

現在,讓我們看一下規則本身的功能,規則應該與任何類型的現有防火牆或甚至在沒有防火牆的系統上正常工作;您所需要的只是 2.4 內核中的內置 iptables 支持。我們阻止來自惡意 IP(第一個以 iptables 開頭的行)的進入信息包,阻止標題爲惡意 IP(下一個以 iptables 開頭的行)的外出信息包,然後關閉涉及這個特殊 IP(最後兩個以 iptables 開頭的行)的轉發。一旦這些規則就位,系統就只廢棄任何屬於其中一個類別的信息包。

另一個簡短註釋:您還會注意到對 "rec_check"、"unrecord"、"record" 和 "args" 的調用。這些是在 "dynfw.sh" 中定義的 helper bash 函數。"record" 函數將被阻止的 IP 記錄到 /root/.dynfw-ipdrop 文件中,而 "unrecord" 從 /root/.dynfw-ipdrop 中除去記錄項。如果要重新阻止一個已被阻止的 IP,或者取消阻止當前未阻止的 IP,可以使用 "rec_check" 函數來放棄帶錯誤消息的腳本。"args" 函數負責確保我們接收到正確數量的命令行自變量,它還負責打印有幫助的用法信息。我已經創建了包含所有這些工具的 dynfw-1.0.tar.gz;有關詳細信息,請參閱本文結尾的 參考資料部分。





回頁首


tcplimit

如果需要限制使用某個特定基於 TCP 的網絡服務,可能是某些會在終端上產生大量 CPU 負載的服務,那麼下一個動態防火牆腳本會非常有用。這個腳本稱作 "tcplimit",它使用一個 TCP 端口、一個速率、一個比例和 "on" 或 "off" 作爲自變量:

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

tcplimit 使用新的 iptables "state" 模塊(確保已經在內核中啓用了這個模塊或已經裝入了這個模塊),以在某個特定時間週期內只允許一定數量的新進入連接。在本示例中,防火牆只允許每分鐘有 5 個新連接到 rsync 服務器(端口 873) -- 如有必要,可以指定您希望每秒/分鐘/小時或每天有多少連接。

tcplimit 爲限制非基本服務提供了一個好方法 -- 因此對非基本服務的大量通信量不會中斷網絡或服務器。在我遇到的情況中,我使用 tcplimit 來設置使用 rsync 的最大上限,以防止太多 rsync 連接佔據我的 DSL 線路。限制了連接的服務都記錄在 /root/.dynfw-tcplimit 中,如果我要關閉新連接限制,只要輸入:

# 
        
        tcplimit 873 5 minute off
Port 873 new connection limit off.
      
      

tcplimit 運行時會在 "filter" 表中創建一個全新的鏈。這個新的鏈將拒絕所有超出指定限度的信息包。然後,一個規則將插入 INPUT 鏈,該 INPUT 鏈將要發送到目標端口(本例中是 873)的所有進入 NEW 連接信息包重定向到這個特定鏈,這樣便有效地限制了新的進入連接,但又不會影響所建立連接中的信息包。

關閉 tcplimit 時,INPUT 規則和該特定鏈將被刪除。這是件奇妙的事,它真正體現了讓經過精心測試的、可靠的腳本來爲您管理防火牆規則的重要性。由於使用了 ipblock,tcplimit 腳本將與任何類型的防火牆,甚至 沒有 防火牆的系統兼容,只要您在內核中啓用了正確的 iptables 功能。





回頁首


host-tcplimit

host-tcplimit 非常類似於 tcplimit,但它限制某些新的 TCP 連接,這些連接來自某個特定 IP 地址並且指向您的服務器上某個特定 TCP 端口。host-tcplimit 特別適用於防止某個人濫用您的網絡資源。例如,假設您在運行 CVS 服務器,而您發現某個新的開發人員似乎建立了一個腳本來每隔 10 分鐘就用資源庫更新它的源碼,這樣每天就消耗了大量的多餘網絡資源。然而,當您給他發送電子郵件以指出他的錯誤行爲時,卻會收到一條進入消息,全文如下:

嗨,夥計!
我很榮幸能參與您的開發項目。我剛創建了一個腳本,
用來每隔 10 分鐘更新一次代碼的本地副本。我將出去
旅遊兩個星期,但等到回來之後,我將會得到最新的源
代碼,那時我就可以交差了!現在我要出門了……兩週
後再見!
謹啓,
Newbie(新手)

對於這種情況,一個簡單的 host-tcplimit 命令就可以解決問題:

# 
        
        host-tcplimit 1.1.1.1 2401 1 day on
			
      
      

現在,限定了 Newbie 先生(IP 地址 1.1.1.1)每天只能有一個 CVS 連接(端口 2401),這樣就節省了許多網絡帶寬。





回頁首


user-outblock

最後一個,也可能是所有動態防火牆腳本中最有趣的一個就是 user-outblock。這個腳本提供了一種理想的方式,它允許特定用戶 telnet 或 ssh 到您的系統中,但不允許這個用戶從命令行建立任何新的外出連接。以下的示例適合於使用 user-outblock。假設有一個特殊家庭在我的 ISP 擁有帳戶。父母使用圖形電子郵件客戶機來閱讀他們的郵件,偶爾也會在網上衝浪,但他們的兒子恰巧是位狂熱的黑客,他經常使用 shell 訪問來對他人的計算機搞一些惡作劇。

一天,您發現他與一些系統建立了 ssh 連接,而那些系統似乎屬於巴基斯坦武裝力量 -- 啊,天哪!您想要引導這個年輕人蔘加更有益的活動,所以應執行以下操作:

首先,應檢查系統,確保已除去了所有網絡二進制程序(如 ssh)中的 suid 位:

# 
        
        chmod u-s /usr/bin/ssh
			
      
      

現在,他試圖用來與網絡交互的任何進程都屬於他自己的用戶標識。現在您可以使用 user-outblock 阻止這個用戶標識(恰巧是 2049)啓動的所有外出 TCP 連接:

# 
        
        user-outblock 2049 on
UID 2049 block on.
      
      

現在,他可以登錄和閱讀郵件,但不能使用您的服務器來建立 ssh 連接以及類似連接。現在,他可以在自己家的個人計算機上安裝 ssh 客戶機。然而,如果要限制他家的個人電腦到 Web、郵件和外出 ssh 連接(僅限於到您的服務器),建立這樣的動態防火牆腳本也不太難。



參考資料

  • 您可以參閱本文在 developerWorks 全球站點上的 英文原文
  • 由於我發現這些動態防火牆腳本如此實用,我已經創建了一個小巧的 tarball (dynfw-1.0.tar.gz) 文件,您可以將它下載並安裝到您的機器上。

    如果要安裝,解開 tarball,運行其中的 install.sh 腳本。此腳本將一個共享的 bash 腳本安裝到 /usr/local/share/dynfw.sh 中,並將動態防火牆腳本安裝到 /usr/local/sbin。如果希望將它們安裝到 /usr/share 和 /usr/sbin 中,在運行 install.sh 之前只要輸入以下命令:

    						
                
                # export PREFIX=/usr
    
    					
              
              

    我還將動態防火牆腳本代碼部分添加到 Gentoo Linux 網站上,您可以訪問這個網站以獲取最新版本的 tar 文件。我還要繼續改進,並添加到這個集合中,以使全世界的系統管理員可以使用真正實用的資源。在我們的內核中已經有了 iptables,應該開始利用它!


  • tcpdump 是研究低級信息包交換和驗證防火牆是否正常工作的必備工具。如果您還沒有,想方法弄到它。如果已經有了,則應該使用它。如果已經使用它了……幹得好!:) 

  • netfilter 小組的主頁 上有許多優秀的資源,包括 iptables 源碼,有 Rusty 的優秀作品 "unreliable guides" 。這些作品包括基本網絡概念 HOWTO、netfilter (iptables) HOWTO、NAT HOWTO 和適合於開發人員的 netfilter 修改 HOWTO。該網站上還有 netfilter 常見問題解答以及其它內容。 

  • 網上還有許多好的 netfilter 資源;但是,不要忘了基礎知識。iptables man 頁面非常詳細,並且它是 man 頁面的範例。 
  • 現在可以使用 高級 Linux 路由和流量控制 HOWTO 。它很好地顯示瞭如何使用 iptables 來標記信息包,然後根據這些標記來使用 Linux 路由功能發送信息包。 

  • 可以使用 netfilter (iptables) 郵件列表,而且 有一個適用於 netfilter 開發人員。使用這些 URL 還可以訪問郵件列表檔案。 


關於作者

作者

Daniel Robbins 居住在新墨西哥州的 Albuquerque。他是 Gentoo Technologies, Inc. 的總裁兼 CEO, Gentoo Linux (用於 PC 的高級 Linux)和 Portage 系統(Linux 的下一代移植系統)的創始人。他還是 Macmillan 書籍 Caldera OpenLinux Unleashed、 SuSE Linux Unleashed和 Samba Unleashed 的合作者。Daniel 自二年級起就與計算機結下不解之緣,那時他首先接觸的是 Logo 程序語言,並沉溺於 Pac-Man 遊戲中。這也許就是他至今仍擔任 SONY Electronic Publishing/Psygnosis 的首席圖形設計師的原因所在。Daniel 喜歡與妻子 Mary 和新出生的女兒 Hadassah 一起共度時光。可通過 [email protected] 與 Daniel 聯繫。

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