基於Linux系統的包過濾防火牆(2)(轉)

amyz發表於2007-08-13
基於Linux系統的包過濾防火牆(2)(轉)[@more@]

  第2章、用使用者空間命令iptables實現包過濾

  2.1 相關的TCP/IP知識

  2.1.1建立TCP連線(透過3次握手實現)

  假如伺服器A和客戶機B通訊。

  (1)B->;A。當B要和A通訊時,B首先向A發一個SYN標記的包,告訴A請求建立連線。只有當A收到B發來的SYN包,才可以建立連線,除此之外別無它法。因此,如果你的防火牆丟棄所有的發往外網介面的SYN包,那麼你將不能讓外部任何主機主動建立連線。

  (2)B

  (3)B->;A。B收到SYN/ACK包後,B發一個確認包(ACK),通知A連線已建立。至此,3次握手完成,一個TCP連線完成。

  需要注意的是,當3次握手完成、連線建立以後,TCP連線的每個包都會設定ACK位。這就是為何連線跟蹤很重要的原因了,沒有連線跟蹤,防火牆將無法判斷收到的ACK包是否屬於一個已經建立的連線。

  2.1.2 結束TCP連線(透過4次握手實現)

  假如伺服器A和客戶機B通訊。注意,由於TCP連線是雙向連線,因此關閉連線需要在兩個方向上做。

  (1)B->;A。當B要與A結束通訊時,B首先向A發一個FIN標記的包,告訴A請求結束連線。由於連線還沒有關閉,FIN包總是打上ACK標記。沒有ACK標記而僅有FIN標記的包不是合法的包,並且通常被認為是惡意的。

  (2)B;A傳輸通道。不過A->;B可能還有資料包需要傳送,所以A->;B傳輸通道仍舊繼續暢通,直到傳輸完畢才會進入下一步。

  (3)B

  (4)B->;A。B送出ACK包給A進行確認。

  2.1.3 傳送連線復位包結束TCP連線

  4次握手不是結束TCP連線的唯一方法。有時,如果主機需要儘快關閉連線(或連線超時,埠或主機不可達),RST包將被髮送。注意,由於RST包不是 TCP連線中的必須部分,可以只傳送RST包(即不帶ACK標記)。但在正常的TCP連線中RST包可以帶ACK確認標記。注意,RST包是可以不要收方進行確認的。

  2.1.4 無效的TCP標記

  至此,已經看到了SYN、ACK、FIN、和RST標記。另外,還有PSH和URG標記。

  最常見的非法組合是SYN/FIN包。注意,由於SYN包是用來初始化連線的,它不可能和FIN以及RST標記一起出現,這也是一個惡意攻擊。

  當網路中出現別的一些組合(如SYN/FIN/PSH、SYN/FIN/RST、SYN/FIN/RST/PSH),很明顯網路肯定受到了攻擊。

  另外,已知的非法包還有FIN(無ACK標記)和“NULL”包。如同早先討論的,由於ACK/FIN包的出現是為了結束一個TCP連線,那麼正常的 FIN包總是帶有ACK標記的。“NULL”包就是沒有任何TCP標記的包(URG、ACK、PSH、RST、SYN、FIN都為0)。

  在正常的網路活動下,到目前為止TCP協議棧不可能產生帶有上面提到的任何一個標記組合的TCP包。當你發現這些不正常的包時,肯定有人對你的網路不懷好意。

  2.1.5 ICMP型別

  ICMP是網間控制訊息協議,用來在主機/路由器之間傳遞控制資訊的協議。ICMP包可以包含診斷資訊(ping 、 tracerouter)、錯誤資訊(網路/主機/埠不可達),資訊(時間戳timestamp,地址掩碼address mask等)、或控制資訊(source quench、redirect等)。

  使用包過濾可以拒絕指定的ICMP型別。

  此外,下面型別的ICMP資訊建議丟棄。

  Redirect(5)、Alternate Host Address(6)、Router Advertisement(9)能用來轉發通訊。    

  Echo(8)、Timestamp(13)、Address Mask Request(17)能用來分別判斷主機是否啟動、本地時間和地址掩碼。它們是和返回的資訊類別有關的。其本身是不能被利用的,但它們洩漏出的資訊對攻擊者是有用的,所以建議丟棄這些型別的ICMP。

  關於ICMP型別的更詳細的表述參見RFC792。

  2.2 iptables語法

  2.2.1 Iptables的優點

  → iptables允許建立狀態(stateful)防火牆,就是在記憶體中儲存穿過防火牆的每條連線。這種模式對於有效地配置FTP和DNS以及其它網路服務是必要的。

  →iptables能夠過濾TCP標誌任意組合報文,還能夠過濾MAC地址。

  →系統日誌比ipchains更容易配置,擴充套件性也更好。

  →對於網路地址轉換(Network Address Translation)和透明代理的支援,Netfilter更為強大和易於使用。

  →iptables能夠阻止某些DoS攻擊,例如SYS洪泛攻擊。

  2.2.2 Iptables的規則要素

  一條iptables規則基本上應該包含5個要素:

  →指定表(table)

  →指定操作命令(command)

  →指定鏈(chains)

  →指定規則匹配器(matcher)

  →指定目標動作(target)

  (1)表。Iptables從其使用的3個表而得名,分別是filter、nat、mangle。對於包過濾防火牆只使用filter表。表filter是預設的表,無需顯示說明。

  (2)操作命令。包括新增、刪除、更新等。

  (3)鏈。對於包過濾防火牆可操作filter表中的INPUT鏈、OUTPUT鏈和FORWARD鏈。也可以操作由使用者自己定義的自定義鏈。

  (4)規則匹配器。可以指定各種規則匹配,如IP地址、埠、包型別等。

  目標動作。當規則匹配一個包時,真正要執行的任務用目標標識。最常用的內建目標分別是:

  →ACCEPT表示允許包透過

  →DROP表示被丟棄

  此外,包過濾防火牆還可以使用擴充套件的目標:

  →REJECT表示拒絕包,丟棄包的同時給傳送者傳送沒有接受的通知。

  →LOG表示包的有關資訊被記錄日誌。

  →TOS表示改寫包的ToS的值。

  要使用上述的擴充套件目標,必須在核心中啟用相應選項或者裝載了相應的核心模組。

  2.2.3 Iptables工具的呼叫語法

  Iptables的語法非常複雜,要檢視該工具的完整語法,應該檢視其手冊頁。

  Iptables的語法通常可以簡化為下面的形式:

  Iptables[-t table]CMD[chain][rule-matcher][-j target]

  其中:tables為表名,CMD為操作命令,chain為鏈名,rule-matcher為規則匹配器,target為目標動作。

  2.2.4 制定永久性規則

  iptables軟體包提供了兩個命令分別用於儲存和恢復規則集。可以使用下在的命令轉儲在記憶體中的核心規則集。其中/etc/sysconfig/iptables是iptables守護程式呼叫的預設規則集檔案:

  #/sbin/iptables-save >; /etc/sysconfig/iptables

  要恢復原來的規則庫,需使用命令:

  #/sbin/iptables-restore < /etc/sysconfig/iptables

  為了使得用iptables命令配置的規則在下次啟動機器時還能被使用,有兩種主法。

  (1)使用iptables的啟動指令碼實現。Iptables的啟動指令碼/etc/rc.d/init.d/iptables每次啟動時都使用/etc/sysconfig/iptables所提供的規則進行規則恢復,並可以使用如下的命令儲存規則:

  #service iptables save

  (2) 在自定義指令碼中用iptables命令直接建立規則集。可以直接用iptables命令編寫一個規則指令碼,並在啟動時執行這個指令碼。

  例如:若規則指令碼的檔名為/etc/fw/rules,則可以在啟動指令碼/etc/rd.d/init.d/rc.local中加入下面的程式碼:

  if[-x /etc/fw/rules];then /etc/fw/rules;fi;

  這樣,機器每次啟動時即可執行該規則指令碼。

  如果使用此種方式,建議使用ntsysv命令關閉系統的iptables守護程式。

  2.3 iptables命令使用舉例

  2.3.1 鏈的基本操作

  (1)清除所有的規則。通常在開始配置包過濾防火牆之初清除所有的規則,重新開始配置,以免原有的規則影響新的設定。使用如下命令進行:

  1)    清除預設表filter中所有規則鏈中的規則。

  #iptables -F

  2)清除預設表filter中使用者自定義鏈中的規則。

  #iptables -X

  3)將指定鏈所有規則的包位元組記數器清零。

  #iptables -Z

  (2)設定鏈的預設策略。一般地,配置鏈的預設策略有兩種方法。

  1)    首先允許所有的包,然後再禁止有危險的包透過防火牆。即“沒有被拒絕的都允許”。這種方法對於使用者而言比較靈活方便,但對系統而言,容易引起嚴重的安全問題。

  為此,應該使用如下的初始化命令:

  #iptables -P INPUT ACCEPT

  #iptables -P OUTPUT ACCEPT

  #iptables -P FORWARD ACCEPT

  2)    首先禁止所有的包,然後再根據需要的服務允許特定的包透過防火牆。即“沒有明確允許的都被拒絕”。這種方法最安全,但不太方便。為了使得系統有足夠的安全性,一般採用此種策略進行iptables防火牆的配置。

  為此,應該使用如下的初始化命令:

  #iptables -P INPUT DROP

  #iptables -P OUTPUT DROP

  #iptables -P FORWAED DROP

  3)列出表/鏈中的所有規則。包過濾防火牆只使用filter表,此表為預設的表,因此可以使用下面的命令列出filter表中所有規則:

  #iptables -L

  使用上面的命令時,iptables將逆向解析IP地址,這將發費很多時間,從而造成資訊出來的非常慢。為了解決這個問題,可以使用下面的帶有-n引數的命令(-n引數用於顯示數字化的地址和埠):

  #iptables -L -n

  4)向鏈中新增規則。下面的語句用於開放網路介面:

  #iptables -A INPUT -i lo -j ACCEPT

  #iptables -A OUTPUT -o lo -j ACCEPT

  #iptables -A INPUT -i eth0 -j ACCEPT 

  #iptables -A OUTPUT -o eth0 -j ACCEPT

  #iptables -A FORWARD -i eth0 -j ACCEPT

  #iptables -A FPRWAED -o eth0 -j ACCEPT

  5)使用使用者自定義鏈。下面是一個使用者自定義鏈的建立、修改和呼叫的簡單命令序列:

  #iptables -N custom

  #iptables -A custom -s 0/0 -d 0/0 -p icmp -j DROP

  #iptables -A INPUT -s 0/0 -d 0/0 -j custom

  首先使用帶-N引數的iptables命令新建了一個名為custom的使用者逢定義鏈。然後使用帶-A引數的命令新增了一條使用者自定義的堵截規則,該規則丟棄全部的ICMP包。最後向預設的INPUT鏈加入一條規則,使所有的包都由custom自定義鏈處理。結果全部的ICMP包都將被丟棄。

  2.3.2 設定基本的規則匹配

  下面舉例說明iptables的基本規則匹配(忽略目標動作):

  (1)指定協議匹配

  1)匹配指定的協議

  #iptables -A INPUT -p tcp

  2)匹配指定協議之外的所有協議

  #iptables -A INPUT -p !tcp

  (2)指定地址匹配

  1)指定匹配的主機

  #iptables -A INPUT -s 192.168.1.1

  2)指定匹配的網路

  #iptables -A INPUT -s 192.168.1.0/24

  3)匹配指定主機之外的地址。

  #iptables -A FORWARD -s ! 192.168.0.1

  4)匹配指定網路之外的網路

  #iptables -A FORWARD -s ! 192.168.0.0/24

  (3)指定網路介面匹配。

  1)指定單一的網路介面匹配。

  #iptables -A INPUT -i eth0

  #iptables -A FORWARD -o eth0

  2)指定同型別的網路介面匹配

  #iptables -A FORWARD -o ppp+

  (4)指定埠匹配

  1)指定單一的埠匹配。

  #iptables -A INPUT -p tcp-sport www

  #iptables -A INPUT -p tcp-sport 80

  #iptables -A INPUT -p tcp-sport 53

  #iptables -A INPUT -p udp-dport 53

  2)匹配指定埠之外的埠。

  #iptables -A INPUT -p tcp-dport ! 22

  3)匹配指定埠的範圍。

  #iptables -A INPUT -p tcp-soprt 22:80

  4)匹配ICMP埠和ICMP型別。

  #iptables -A INPUT -p icmp --icmp-type 8

  5)指定ip碎片

  在TCP/IP通訊過程中,每一個網路介面都有一個最大的傳輸單元(MTU),這個引數定義了可以透過的資料包的最大尺寸。如果一個資料包大於這個引數值時,系統會將其劃分成更小的數個資料包(稱之為ip碎片)來傳輸,而接收方則對這些ip碎片再進行重組以還原整個包。

  但是在進行包過濾的時候,ip碎片會導致這樣一個問題:當系統將大資料包劃分成ip碎片傳送時,第一個碎片含有完整的包頭資訊(IP+TCP、UDP和 ICMP),但是後續的碎片只有包頭的部分資訊(如源地址、目的地址)。因此,檢查後面的ip碎片的頭部(就像有TCP、UDP和ICMP一樣)是不可能的。假如有這樣一條規則:

  #iptables -A FORWARD -p tcp -s 192.168.1.0/24 -d 192.168.2.100 --dport 80 -j ACCEPT

  並且這時的FORWARD的策略(policy)為DROP時,系統只會讓第一個ip碎片透過,而丟掉其餘的ip碎片,因為第一個碎片含有完整的包頭資訊,可以滿足該規則的條件,而餘下的碎片因為包頭資訊不完整而無法滿足規則定義的條件,因而無法透過。

  可以透過-fragment/-f選項來指定第二個及其以後的ip碎片,以上面的例子為例,我們可以再加上這樣一條規則來解決這個問題:

  #iptables -A FORWARD -f -s 192.168.1.0/24 -d 192.168.2.100 -j ACCEPT

  但是需要注意的是,現在已經有許多進行ip碎片攻擊的例項(例如向Win98 NT4SP5,6 Win2K傳送大量的ip碎片進行DoS攻擊),因此允許ip碎片透過是有安全隱患的,對於這一點可以採用iptables的匹配擴充套件來進行限制。

  2.3.3 設定擴充套件的規則匹配

  要獲得匹配的簡要說明,可以使用如下的命令:

  #iptables -m name_of_match -help

  下面舉例說明iptables的擴充套件規則匹配(忽略目標動作):

  (1)多埠匹配擴充套件。

  1)匹配多個源埠。

  #iptables -A INPUT -p tcp -m multiport-source-port 22,53,80,110

  2)匹配多個目的埠

  #iptables -A INPUT -p tcp -m multiport-destionation-port 22,53,80,110

  3)匹配多個埠(無論源源埠還是目的埠)。

  #iptables -A INPUT -p tcp -m multiport -port 22,53,80,110

  (2)指定TCP匹配擴充套件

  透過使用-tcp-flags選項可以根據tcp包的標誌位進行過濾,該選項後接兩個引數:第一個引數為要檢查的標誌位,可以是SYN、ACK、FIN、URG、PSH的組合,可以用ALL指定所有標誌位:第二個引數是標誌位值為1的標誌。

  #iptables -A INPUT -p tcp-tcp-flags SYN,FIN,ACK SYN

  表示SYN、ACK、FIN的標誌都要被檢查,但是隻有設定了SYN的才匹配。

  #iptables -A INPUT -p tcp-tcp-flags ALL SYN,ACK

  表示ALL(SYN,ACK,FIN,RST,URG,PSH)的標誌都要被檢查,但是隻有設定了SYN和ACK的才匹配。

  選項-syn是以上的一種特殊情況,相當於“--tcp-flags SYN,RST,ACK SYN“的簡寫。

  #iptables -p tc-syn

  (3)limit速率匹配擴充套件。

  1)指定單位時間內允許透過的資料包的個數。

  單位時間可以是/second、/minute、/hour、/day或使用第一個字母。例如:

  #iptables -A INPUT -m limit-limit 300/hour

  表示限制每小時允許透過300個資料包。

  2)指定觸發事件的閥值。

  使用-limit-burst指定觸發事件的閥值(預設是5),用來比對瞬間大量資料包的數量。

  #iptables -A INPUT -m limit-limit-burst 10

  上面的例子是用來比對一次同時湧入的封包是否超過10個,超過此上限的包將被直接丟棄。

  3)同時指定速率限制和觸發閥值。

  #iptables -A INPUT -p icmp -m limit-limit 3/m-limit-burst 3

  假設均勻透過,平均每分鐘3個,那麼觸發閥值burst保持為3個,如果每分鐘透過的包的數目小於3,那麼觸發閥值burst將在每個週期(若每分鐘允許透過3個,則週期數為20秒)後加1,但最大值為3。每分鐘要透過的包的數量如果超過3,那麼觸發閥值burst將減掉超出的數值,例如第二分鐘有4個包,那麼觸發閥值burst變成2,同時4個包都可以透過,第三分鐘有6個包,則只能透過5個,觸發閥值burst將變成0。之後,每分鐘如果包數小於等於3,則觸發閥值burst將加1,如果每分鐘包數大於3,觸發閥值burst將逐漸減小最終維持為0。

  即每分鐘所允許的最大包數量為限制速率(本例為3)加上當前的觸發閥值burst數。在任何情況下,都可以保證3個包透過,觸發閥值burst相當於是允許額外的包數量。

  (4)基於狀態的匹配擴充套件(連線跟蹤)。 

  每個網路連線包括以下資訊:源地址、目的地址、源埠、目的湍口,稱為套接字對(socket pairs);協議型別、連線狀態(TCP協議)和超時時間等。防火牆把這些資訊稱為狀態(stateful),能夠檢測每個連線狀態的防火牆叫作狀態包過濾防火牆。它除了能夠完成簡單包過濾防火牆的包過濾工作外,還在自己的記憶體中維護一個跟蹤連線狀態的表,比簡單包過濾防火牆具有更大的安全性。 iptables與ipchains的不同之處在於iptables可以使用連線狀態資訊,建立基於包的狀態的規則匹配。

  基於狀態匹配建立規則的命令格式如下:

  iptables -m state-state [!]state [,state,state,state]

  其中,state表是一個用逗號分割的列表,用來指定的連線狀態可以是如下的4種:

  →NEW:該包想要開始一個連線(重新連線或將連線重定向)。

  →RELATED:該包是屬於某個已經建立連線所建立的新連線。例如:FTP的資料傳輸連線和控制連線之間就是RELATED關係。

  →ESTABLISHED:該包屬於某個已經建立的連線。

  →INVALID:該包不匹配於任何連線,通常這些包會被DROP。

  例如:

  1)在INPUT鏈新增一條規則,匹配已經建立的連線或由已經建立的連線所建立的新連線。即匹配所有的TCP回應包。

  #iptables -A INPUT -m state-state RELATED,ESTABLISHED

  2)在INPUTP鏈新增一條規則,匹配所有從非eth0介面來的連線請求包。

  #iptables -A INPUT -m state-state NEW -i ! eth0

  又如,對於ftp連線可以使用下面的連線跟蹤:1)被動ftp連線模式。

  #iptables -A INPUT -p tcp-sport 1024: --dport 1024: -m state-state ESTABLES -j ACCEPT

  #iptables -A OUTPUT -p tcp-sport 1024: --dport 1024: -m state-state ESTABLISHED,RELATED -j ACCEPT

  2)主動ftp連線模式。

  #iptables -A INPUT -p tcp-sport 20 -m state-state ESTABLISHED,RELATED -j ACCEPT -m state-state ESTABLISHED -j ACCEPT

  (5)TOS匹配擴充套件。

  所有資料包的首部都有一個稱為服務型別的專用欄位。該欄位用於當資料包經過路由器時區分優先順序。

  使用ToS欄位,可以使用某種型別的資料包優先於其它的資料包。有標記的資料包在路由器中進行不同的處理。設定ToS欄位的工作是在網路層進行的。有關ToS的具體工作過程請參專考RFC1349。

  在資料包中設定ToS欄位的主要原因是:對不同型別的資料包加以區分,從而在流量較高的網路上減少網路擁塞。

  資料包的ToS欄位用一個位元組表示。此位元組的高3位捨棄不用,最低位使用固定值0,因此,有效位共有4個。有效位分別用來控制資料包的最小延時,最大吞吐量,最大可靠度和最小成本。其中,

  →最小延時:用於減少資料包從路由到達主機的時間。

  →最大吞吐量:用於提高資料傳輸量。適用於FTP資料埠,HTTP大檔案傳輸和大量的POP3傳輸。

  →最大可靠度:用來試圖減少資料重傳。

  →最小成本:通常只在商業產品中使用。

  要建立與ToS欄位匹配的規則,可以使用下面的語法:

  iptables [-t table]CMD[chain]-m tos tos_value [-j target]

  其中tos_value可以是0x02、0x04、0x06、0x08、0x10。

  例如:

  #iptables -A INPUT -p tcp -m tos 0x08

  表示匹配在ToS欄位中設定了最大吞吐量的包。

  2.3.4 設定目標擴充套件

  要獲得目標的簡要說明,可以使用如下的命令:

  #iptables -j name_of_TARGET-help

  目標擴充套件由核心模組組成,而且iptables的一個可選擴充套件提供了新的命令列選項。在幾個擴充套件是包含在預設netfilter釋出中的。

  (1)設定包的ToS值。為了設定資料包的ToS值,需要使用ToS目標擴充套件。設定ToS的值,只能對FORWARD、OUTPUT和PREROUTING鏈進行。語法如下:

  iptables [-t table]CMD[chain][rule-matcher]-j TOS-set-tos tos_value

  其中tos_value可以是0x02、0x04、0x06、0x08、0x10。

  下面是使用ToS目標擴充套件設定ToS值的一些例子:

  #iptables -A OUTPUT -p tcp -m tcp-dport 21 -j TOS-set-tos 0x10

  #iptables -A OUTPUT -p tcp -m tcp-dport 22 -j TOS-set-tos 0x10

  #iptables -A OUTPUT -p tcp -m tcp-dport 110 -j TOS-set-tos 0x08

  (2)日誌記錄。iptables使用新的目標擴充套件LOG來實現日誌記錄。LOG目標用syslogd記錄此包並繼續傳播。LOG目標擴充套件還可以使用如下的一些引數:

  → --log-level

  跟蹤一個級別名稱或數字。合適的名字是'debug'、'info'、'notice'、'warning'、'err'、'crit'、'alert' 和'emerg',相當於數字7到0。參考syslog.conf的手冊可獲取這些級別的說明。預設是'warning'。

  → --log-prefix

  跟蹤一個最多29個字元的字串,它被寫入到log資訊的開始處,這樣可以方便地使用grep對日誌進行過濾。

  另外,在使用LOG目標擴充套件的同時,還可以使用limit match,這樣可以使記錄有用日誌的同時確保日誌記錄不會變得冗長。

  下面是使用LOG目標擴充套件的一些例子:

  #iptables -A FORWARD -m tcp -p tcp -j LOG

  #iptables -A FORWARD -m icmp -p icmp-sport echo-reply -j LOG

  #iptables -A INPUT -m limit-limit 3/m-limit-burst 3 -j LOG-log-prefix "INPUT packet died:"

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

相關文章