備忘。認識 iptables

2007-07-11 00:43:26 哇哇 0 0

有意無意中搜尋到的,覺得寫的還不錯,備忘收藏一下^^
http://itzone.hk/article/index.php?tid=14

http://itzone.hk/article/article.php?aid=200502161756193879

您也許已經對「-p」、「-s」、「-i」等選項感到迷惑,這一章正是要介紹這些過濾規則內的詳細設定。

其實iptables是由多 個不同的表組成,包括filter、nat和mangle,我們在過往三章所介紹的,全都是使用filter這個table,即是有關過濾規則的 table,而nat則是關於新建立的網絡連接,有PREROUTING、OUTPUT和POSTROUTING這三道chain,以下將會介紹一切有關filter這個table的過濾規則選項。

(1) -p (Protocol,封包使用協定)

「-p」的語法如下:

-p, --protocol [!] protocol

「protocol」 可以是「tcp」、「udp」、「icmp」或「all」,其中「all」代表所有protocol都能適用於這道規則,若果您輸入「-p all」的話,其效果就等同您沒有輸入過一樣。iptables會查看/etc/protocols內所支援的協定,因此您也可在「protocol」一 欄中輸入那些名字或數字,例如我想過濾所有進入的GGP(Gateway-Gateway Protocol)封包,可使用以下指令:

iptables -A INPUT -p ggp -j DROP

另外,「-p 0」是代表「-p all」,其意義剛才已經解釋過了。

在「protocol」一欄前加上「!」號,代表所有不是該protocol的封包都能符合此規則,例如除了TCP封包外,我想過濾其餘所有封包,可以輸入以下指令:

iptables -A INPUT -p ! tcp -s 127.0.0.1 -j DROP

(2) -s (Source,封包來源)

「-s」的語法如下:

-s, --source [!] address[/mask]

「address」 可以是主機名稱,例如localhost和beryl等,當然也可以是一個IP地址,這樣就能指定封包是源自哪一部電腦。假若您想確定封包是來自哪一個網 絡的話,您便要輸入「mask」,例如您想阻隔來自203.194.207.0/24整個網絡的TCP封包,您可以輸入以下指令

iptables -A INPUT -p tcp -s 203.194.207.0/24 -j DROP

與「-p」類似,在「address」前加上「!」號代表除了該地址外的所有封包都符合此規則,例如您的電腦只容許您某位朋友(如137.189.3.8)連線過來,您可以輸入以下指令:

iptables -A INPUT -p tcp -s ! 137.189.3.8 -j DROP

當 然您也可輸入「iptables -A INPUT -p tcp -s 137.189.3.8 -j ACCEPT」,但這並不代表您已經過濾了其他封包,這樣只是「容許您的朋友進入」,但並未做到「阻止其他人進入」這個效果。因此在設計上您要在這道規則 後加上「iptables -A INPUT -p tcp -j DROP」:

iptables -A INPUT -p tcp -s 137.189.3.8 -j ACCEPT
iptables -A INPUT -p tcp -j DROP

(3) -d (Destination,封包目的地)

「-d」的語法如下:

-d, --destination [!] address[/mask]

與「-s」的設定和概念是一模一樣的,請讀者參閱(2)。

(4) -j (Jump,如何處理封包)

「-j」的語法如下:

-j, --jump target

「Jump」 代表封包符合規則時,應如何處理這個封包,如以往所看到的,「target」可以是DROP和ACCEPT,分別代表把封包消滅和接受封包。另外還有 LOG、REJECT、ULOG和TCPMSS,以及只有在nat table才能使用的SNAT、DNAT、MASQUERADE、REDIRECT,和只有在mangle table才能使用的MARK、TOS、DSCP和ECN。詳細內容將在稍後介紹。

(5) -i (Input interface,網絡介面來源)

「-i」的語法如下:

-i, --in-interface [!] name

每 一個網絡數據都需要經過網絡介面送出或進入,一般電腦的網絡介面名稱為eth0、eth1等,在Sparc電腦的介面名稱為hme0、hme1等,虛擬介 面的名稱可能是eth0:1、eth0:2、eth1:1諸如此類。因為我們的電腦可能有兩張網絡卡,或者在一張網絡卡上有兩個或以上的介面,因此我們會 遇上只想過濾來自某個介面的封包的情形,例如我們想過濾一切來自「lo」這個介面(i.e. loopback)的封包,我們可以使用以下指令:

iptables -A INPUT -i lo -j DROP

「- i」只適用於INPUT、FORWARD和nat所擁有的PREROUTING,因為您不會在OUTPUT內有意思地定義「輸入介面」這個參數。另外,假 若您想同時讓eth0、eth0:1和eth0:2使用同一道過濾規則(常用於擁有多個虛擬網絡介面的電腦),那麼我們可以在「name」後加上「+」 號:

iptables -A INPUT -i eth0+ -p icmp -j DROP

那麼我們便能以一道規則,同時適用於以「eth0」為字首的網絡介面,它能把所有源於「eth0+」的ICMP封包過濾掉。

與「-i」和「-o」類似,在「name」欄前加上「!」號代表顛倒的意思。

(6) -o (Output interface,網絡送出介面)

「-o」的語法如下:

-o, --out-interface [!] name

「-o」的用法與「-i」一模一樣,但「-o」只適於FORWARD、OUTPUT和nat的POSTROUTING。另外,只有FORWARD才要同時使用「-i」和「-o」選項。

 (7) -f (Fragment,封包段)

「-f」的語法如下:

[!]  -f, --fragment

一個封包的大小是有限的,而且每個封包的大小是該協定所決定的,因此您不能隨意更改封包的大小,所以當一個封包從某協定轉移到另一個協定(例如TCP封包被封裝成IP封包),便有可能出現分段化(Fragmentation),把原本大封包分散成數個小封包。

問題是當封包被拆散後,只有第一個小封包擁有該大封包的標頭資料,而第二個和以後的小封包均只剩下一般數據,於是只有第一個封包才有機會符合過濾規則,第二個和以後的封包由於沒有標頭的關係,所以都不會被過濾。因此我們需要「-f」選項來設定過濾第二個和以後的封包。例如

iptables -A INPUT -f -s 137.189.3.4 -j DROP

會消滅所有來自137.189.3.4的第二個或以後的封包段。

其實讓不完整的封包段流入網絡該不會釀成任何危險,因為在接收的一方根本無法把封包段重整還原,於是程式便會把進來封包全部拒絕

(8) -c (Counter,累加器初值設定)

「-c」的語法如下:

-c, --set-counters PKTS BYTES

「-c」在加入過濾規則時會把總封包數目和總數據流量分別設為「PKTS」和「BYTES」。


 剛才八個選項是iptables的核心選項,以下五個選項是較次要的:

(9)  -v (Verbose,詳細內容)

「-v」會把iptables內的所有設定詳細列出,例如「iptables -L -v」。

(10) -n (Numeric,數值顯示)

「-n」會直接將數值資料輸出,例如IP地址、網絡掩碼等。

(11) -x (Exact,精確數值顯示)

「-x」會把數值資料,例如總封包流量及總數據流量,以精確的數值顯示,並不會把數值以GB、MB或KB作為約數顯示。

(12) --line-numbers(行碼顯示)

「--line-numbers」會在每道過濾規則旁邊加上規則行號,例如:

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination        
1      ACCEPT     icmp -- beryl               anywhere          
2      ACCEPT     icmp -- 127.0.0.2           anywhere          
3      ACCEPT     icmp -- 127.0.0.3           anywhere          
4      ACCEPT     icmp -- 127.0.0.4           anywhere          

Chain FORWARD (policy ACCEPT)
num  target     prot opt source               destination        

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination       

(13) --modprobe(載入iptables模組)

「--modprobe」會把iptables的延伸模組載入,供該規則使用。延伸
模組將在下一篇介紹。

資料參考 

[1]  Rusty Russell. "Linux 2.4 Packet Filtering HOWTO" [Online]. Available: http://www.netfilter.org/documentation/HOWTO//packet-filtering-HOWTO.html
[2]  Rusty Russell and Harald Welte. "Linux Netfilter Hacking HOWTO" [Online]. Available: http://www.netfilter.org/documentation/HOWTO//netfilter-hacking-HOWTO.html
[3]  J. Postel. "RFC 793 - Transmission Control Protocol". Sept. 1981 [Online]. Available: http://www.faqs.org/rfcs/rfc793.html


[#M_過濾規則專題(二)
[#M_過濾規則專題(二)|過濾規則專題(二)|http://itzone.hk/article/article.php?aid=200502162126430483

剛才所提到的核心選項其實不足以

應付我們的需求,例如我想過濾所有來自外部的網頁伺服器請求,但我根本無法讓iptables知道要阻 隔送往port 80的封包。因此我們需要擴展iptables的功能,於是便有iptables模組的出現,來支援更複雜的過濾規則。

至 今共有18個流行的iptables模組,我們會逐一介紹。我們可使用「-m」(Match)選項來載入那些模組,例如您想載入「TCP」模組,您便需要輸入「-m tcp」。當我們使用「-p tcp」時,其實iptables會自動載入TCP模組,但只有一小部分「-p」選項有這個例外功能。

更多的iptables模組可往 http://www.netfilter.org 尋找。

(1) TCP

這個該會是大家最常用的選項,只要大家輸入「-p tcp」時便能使用。TCP模組有以下選項:

(1.1) --source-port

即是來源埠,其語法如下:

--source-port [!] port[:port]

假如我想過濾所有來自port 1025的封包,我們可以使用:

iptables -A INPUT -p tcp --source-port 1025 -j DROP

其實「--source-port」也可縮寫為「--sport」。

另外,如果您想一次過過濾某個範圍的port,您可以使用「port:port」,例如您想過濾port 1025至3000的封包:

iptables -A INPUT -p tcp --sport 1025:3000 -j DROP

加上「!」即代表顛倒的意思。

(1.2) --destination-port

即是目的地埠,其語法如下:

--destination-port [!] port[:port]

其用法與「--source-port」相同。其縮寫為「--dport」。

(1.3) --tcp-flags

--tcp-flags [!] mask comp

TCP封包的flag共有六種,分別是SYN、ACK、FIN、RST、URG和PSH,詳細解釋請參閱RFC793。這些不同種類的封包控制了TCP連線的狀態,現在有許多網絡攻擊模式都是以TCP的弱點出發,透過不同的TCP連線狀態來偽裝或竊聽。

若果您想讓您的電腦能主動連接其他主機,但卻不想其他主機主動連接您,您可以過濾所有來自外部,並含「SYN」的封包,因為只有主動連接的主機才會發送「SYN」封包,例子如下:

iptables -A INPUT -p tcp --tcp-flags ALL SYN -j DROP

當中「ALL」代表該規則會查看全部flags,「SYN」則代表該封包要有syn這個flag,而其餘五個flags都沒有被設定。即是說如果我們把剛才的指令寫成:

iptables -A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j DROP

是與剛才的指令等效的。當中「mask」的flags要以逗號分隔。

另外,在「--tcp-flags」後加上「!」號代表顛倒的意思。

設定--tcp-flags的過濾規則需要讀者對TCP和TCP exploit技巧有一定認識,例如FIN攻擊、RST攻擊及連接埠掃描(port scanning)等,在此不作詳談。

(1.4) --syn

[!] --syn

「--syn」即等同於「--tcp-flags SYN,ACK,FIN SYN」,由於太常用的關係,因此額外以一個選項表示。加上「!」號有顛倒的意思。

(1.5) --tcp-option

--tcp-option [!] number

TCP 標頭的其中一個欄是「option」,首一個bytes是option number,即「--tcp-option」後面的「number」,因此「number」的範圍是0至255,根據RFC793,只有number = 0, 1, 2是被定義的,3或以後的選項並未定義。各數字選項的定義請參閱RFC793。

(1.6) --mss

--mss value[:value]

MSS(Maximum Segment Size)代表每個封包的最大容量,每次建立TCP連接時,雙方主機都會交換MSS值,以確保大家有相同的最大封包大小。「value」是以byte為單位,使用「value:value」能設定MSS的範圍。

(2) UDP

只要您使用「-p udp」就會載入UDP模組。它只提供「--source-port 」和「--destination-port」,用法與TCP相同。

(3) ICMP

當大家使用「-p icmp」時,就會載入ICMP模組。

(3.1) --icmp-type [!] typename

「typename」所指的是ICMP封包種類名稱,ICMP定義了大量封包種類,讀者可輸入「iptables -p icmp -h」顯示所有iptables所支援的封包類型。各類型封包的定義請參考RFC792。

大 部份使用ICMP過濾規則的情況,都是為了防止ICMP偽導向攻擊(ICMP redirection attack),即某駭客主機向其他電腦發放ICMP redirection封包,讓受害主機錯誤認為駭客主機才是預設通訊閘(Default gateway),那麼受害主機所有送出網絡的數據都會傳送至駭客主機。ICMP redirection的「typename」有兩種,分別是「network-redirect」和「host-redirect」,一般來說我們都會 消滅這兩類封包。

iptables -A INPUT -p icmp --icmp-typename network-redirect -j DROP
iptables -A INPUT -p icmp --icmp-typename host-redirect -j DROP

(4) MAC

MAC(Medium Access Control)是屬於數據鏈路層(Data-link layer)的,每一個網絡裝置都有一個6 bytes的MAC地址,該6個bytes都以「:」分隔,由於MAC地址是唯一的,因此您可利用MAC地址來確知封包是來自哪一部電腦。

您需要輸入「-m mac」來使用此選項,而並非「-p mac」。

(4.1) --mac-source

--mac-source [!] address

「address」就是MAC地址,其格式為XX:XX:XX:XX:XX:XX,共6個bytes,因為MAC地址並不會重覆,所以您能準確地針對某部主機來過濾封包。

(5) Limit

「Limit」模組是用來限制在某段時間,該規則的核對次數,即是間接限制了某種封包接收和傳送的速度,於是我們可用「Limit」選項來控制網絡流量。您需要輸入「-m limit」來載入Limit模組。

(5.1) --limit

--limit rate

「- -limit」即是在某時段內最高的核對次數,例如「--limit 6/second」就是每秒最多符合五次,若果多過五次的話,則該封包並不符合這規則。除了「second」這個單位外,還有「minute」、 「hour」和「day」,而且「second」可以縮寫為「s」,其他單位亦同樣有縮寫,例如「--limit 6/s」、「--limit 10/m」、「--limit 20/h」等等。

大家可能還未聯想到「核對次數」與「流量控制」的關係,因為您可以控制到每秒、每分鐘和每小時只符合多少次,例如:

iptables -A INPUT -p icmp -s 11.22.33.44 -m limit --limit 6/m -j ACCEPT

那 麼這道規則只會每分鐘核對六次,過了六次後,就算符合「-p icmp -s 127.0.0.1」這個標頭也不算符合。可是這個封包不符合該規則,便會往下層繼續與其他規則核對,到最後這個封包並不能與任何一道規則相符合,而這道 chain的預設處理為ACCEPT,那麼這個封包還是會進入您的網絡,即是說剛才這道過濾規則還不足以把這類濾掉。

於是,我們需要在這道過濾規則下面加上:

iptables -A INPUT -p icmp -s 11.22.33.44 -j DROP

那麼當上面的規則已因超越六次後,已經變成不符合時,該封包會立刻與下面這道規則核對,並且被消滅,情況如下:

PING test (11.22.33.44) 56(84) bytes of data.
64 bytes from 11.22.33.44: icmp_seq=1 ttl=56 time=20.5 ms
64 bytes from 11.22.33.44: icmp_seq=2 ttl=56 time=15.9 ms
64 bytes from 11.22.33.44: icmp_seq=3 ttl=56 time=13.3 ms
64 bytes from 11.22.33.44: icmp_seq=4 ttl=56 time=13.2 ms
64 bytes from 11.22.33.44: icmp_seq=5 ttl=56 time=17.8 ms
64 bytes from 11.22.33.44: icmp_seq=11 ttl=56 time=14.2 ms
64 bytes from 11.22.33.44: icmp_seq=21 ttl=56 time=16.7 ms
64 bytes from 11.22.33.44: icmp_seq=31 ttl=56 time=17.5 ms
64 bytes from 11.22.33.44: icmp_seq=41 ttl=56 time=17.9 ms
64 bytes from 11.22.33.44: icmp_seq=51 ttl=56 time=16.1 ms
64 bytes from 11.22.33.44: icmp_seq=61 ttl=56 time=14.7 ms
64 bytes from 11.22.33.44: icmp_seq=71 ttl=56 time=13.2 ms
64 bytes from 11.22.33.44: icmp_seq=81 ttl=56 time=15.7 ms

Ping會每秒送出一個ICMP封包,從以上的結果我們知道iptables平均每10個封包便過濾了9個,即是每60個封包便會過濾54個,i.e. 每60秒只容許有6個封包經過:

6/m = 6/60s = 1/10s (每10秒1個封包)

另外,「rate」的預設數值為「3/hour」,即每20分鐘一個封包。

(5.2) --limit-burst

--limit-burst number 

從剛才的例子中,大家已經察覺到首5個封包能順利進入網絡,這是因為「--limit-burst」 的預設值為5。「--limit-burst」代表起首共有多少個封包能符合此規則,它是一個累減器,每當有一個合符規則的封包經過時,這個累減器便會自 動減一,直到零為止便否定本來符合規則的封包。此後就會根據「--limit」來限制封包流量,如上一節所提及一般。例如我把「--limit-burst」設定為9:

iptables -R INPUT 1 -p icmp -s 11.22.33.44 -m limit --limit 6/m --limit-burst 9 -j ACCEPT
其結果為:

PING test (11.22.33.44) 56(84) bytes of data.
64 bytes from 11.22.33.44: icmp_seq=1 ttl=56 time=16.1 ms
64 bytes from 11.22.33.44: icmp_seq=2 ttl=56 time=14.5 ms
64 bytes from 11.22.33.44: icmp_seq=3 ttl=56 time=13.6 ms
64 bytes from 11.22.33.44: icmp_seq=4 ttl=56 time=13.1 ms
64 bytes from 11.22.33.44: icmp_seq=5 ttl=56 time=16.7 ms
64 bytes from 11.22.33.44: icmp_seq=6 ttl=56 time=11.9 ms
64 bytes from 11.22.33.44: icmp_seq=7 ttl=56 time=12.2 ms
64 bytes from 11.22.33.44: icmp_seq=8 ttl=56 time=10.5 ms
64 bytes from 11.22.33.44: icmp_seq=9 ttl=56 time=15.7 ms
64 bytes from 11.22.33.44: icmp_seq=11 ttl=56 time=16.8 ms
64 bytes from 11.22.33.44: icmp_seq=21 ttl=56 time=15.2 ms
64 bytes from 11.22.33.44: icmp_seq=31 ttl=56 time=16.5 ms

「--limit-burst」被設定為15

PING test (11.22.33.44) 56(84) bytes of data.
64 bytes from 11.22.33.44: icmp_seq=1 ttl=56 time=17.9 ms
64 bytes from 11.22.33.44: icmp_seq=2 ttl=56 time=13.0 ms
64 bytes from 11.22.33.44: icmp_seq=3 ttl=56 time=14.8 ms
64 bytes from 11.22.33.44: icmp_seq=4 ttl=56 time=13.8 ms
64 bytes from 11.22.33.44: icmp_seq=5 ttl=56 time=14.6 ms
64 bytes from 11.22.33.44: icmp_seq=6 ttl=56 time=12.8 ms
64 bytes from 11.22.33.44: icmp_seq=7 ttl=56 time=14.5 ms
64 bytes from 11.22.33.44: icmp_seq=8 ttl=56 time=13.0 ms
64 bytes from 11.22.33.44: icmp_seq=9 ttl=56 time=19.7 ms
64 bytes from 11.22.33.44: icmp_seq=10 ttl=56 time=13.2 ms
64 bytes from 11.22.33.44: icmp_seq=11 ttl=56 time=14.9 ms
64 bytes from 11.22.33.44: icmp_seq=12 ttl=56 time=15.6 ms
64 bytes from 11.22.33.44: icmp_seq=13 ttl=56 time=12.1 ms
64 bytes from 11.22.33.44: icmp_seq=14 ttl=56 time=13.5 ms
64 bytes from 11.22.33.44: icmp_seq=15 ttl=56 time=16.4 ms
64 bytes from 11.22.33.44: icmp_seq=16 ttl=56 time=14.4 ms
64 bytes from 11.22.33.44: icmp_seq=21 ttl=56 time=19.0 ms
64 bytes from 11.22.33.44: icmp_seq=31 ttl=56 time=14.6 ms
64 bytes from 11.22.33.44: icmp_seq=41 ttl=56 time=13.5 ms
64 bytes from 11.22.33.44: icmp_seq=51 ttl=56 time=15.2 ms

上例中的「icmp_seq=16」這個封包,其實是再上一個例中的「icmp_seq=11」,只是因為把「--limit-burst」設定為15會蓋過了第11個封包,於是它便緊接在第15個封包後送出。

在 以上的例子中,若果連續在1分鐘內沒有封包與這道規則核對,那麼「--limit-burst」的累減器便會被加1,即是說如果「--limit- burst」是15的話,15分鐘內沒有合符該規則的封包,一切便會回復,例如您把Ping指令停止並等候15分鐘,然後再輸入Ping指令,便能得到剛 出的結果。

又說,如果您只等候7分鐘,那麼當時的「--limit-burst」數值該為7,那麼當您再執行Ping指令時,便會有以下結果:

PING test (11.22.33.44) 56(84) bytes of data.
64 bytes from 11.22.33.44: icmp_seq=1 ttl=56 time=17.9 ms
64 bytes from 11.22.33.44: icmp_seq=2 ttl=56 time=13.0 ms
64 bytes from 11.22.33.44: icmp_seq=3 ttl=56 time=14.8 ms
64 bytes from 11.22.33.44: icmp_seq=4 ttl=56 time=13.8 ms
64 bytes from 11.22.33.44: icmp_seq=5 ttl=56 time=14.6 ms
64 bytes from 11.22.33.44: icmp_seq=6 ttl=56 time=12.8 ms
64 bytes from 11.22.33.44: icmp_seq=7 ttl=56 time=14.5 ms
64 bytes from 11.22.33.44: icmp_seq=8 ttl=56 time=13.0 ms
64 bytes from 11.22.33.44: icmp_seq=11 ttl=56 time=14.9 ms
64 bytes from 11.22.33.44: icmp_seq=12 ttl=56 time=15.6 ms
64 bytes from 11.22.33.44: icmp_seq=13 ttl=56 time=12.1 ms
64 bytes from 11.22.33.44: icmp_seq=14 ttl=56 time=13.5 ms
64 bytes from 11.22.33.44: icmp_seq=15 ttl=56 time=16.4 ms
64 bytes from 11.22.33.44: icmp_seq=16 ttl=56 time=14.4 ms
64 bytes from 11.22.33.44: icmp_seq=21 ttl=56 time=19.0 ms
64 bytes from 11.22.33.44: icmp_seq=31 ttl=56 time=14.6 ms
64 bytes from 11.22.33.44: icmp_seq=41 ttl=56 time=13.5 ms
64 bytes from 11.22.33.44: icmp_seq=51 ttl=56 time=15.2 ms


資料參考 

[1]  Rusty Russell. "Linux 2.4 Packet Filtering HOWTO" [Online]. Available: http://www.netfilter.org/documentation/HOWTO//packet-filtering-HOWTO.html
[2]  Rusty Russell and Harald Welte. "Linux Netfilter Hacking HOWTO" [Online]. Available: http://www.netfilter.org/documentation/HOWTO//netfilter-hacking-HOWTO.html
[3]  Jon Postel. "RFC 793 - Transmission Control Protocol". Sept. 1981 [Online]. Available: http://www.faqs.org/rfcs/rfc793.html
[4]  Jon Postel. "RFC 768 - User Datagram Protocol". August 1980 [Online]. Available: http://www.faqs.org/rfcs/rfc768.html
[5]  Jon Postel. "RFC 792 - Internet Control Message Protocol". Sept. 1981 [Online]. Available: http://www.faqs.org/rfcs/rfc792.html_M#]
[#M_過濾規則專題(三)|過濾規則專題(三)| http://itzone.hk/article/article.php?aid=200502172039286058

本人再繼續介紹iptables的延伸模組。

(6) Multiport

「Multiport」 就是您只能同一時間,以同一道規則過濾多個port。「TCP」模組只能讓您輸入一個port,或是一個範圍的port,卻不能輸入多個非連續的 port。「Multiport」只能讓您輸入最多15個不同的port號,而且您必須在事前輸入「-p tcp」或「-p udp」。

(6.1) --source-ports

--source-ports port[,port[,port...]]

您也可使用它的縮寫「--sports」,例子如下:

iptables -A INPUT -p tcp -s 127.0.0.1 -m multiport --source-ports 22,5800,5900 -j DROP

這樣便會把SSH和VNC的服務阻隔。

(6.2) --destination-ports

--destination-ports port[,port[,port...]]

與「--source-ports」的用法相同,它也可以被縮寫成「--dports」。

(6.3) --ports port

--ports port[,port[,port...]]

當目的地port和來源port的號碼是相同時,您可以使用「--ports」。

(7) Owner

這個模組能根據發送數據的程式來過濾封包。

(7.1) --uid-owner

--uid-owner userid

若果發送封包的程式是屬於該用戶,那麼那個封包便會被過濾。「userid」是有效使用者號碼(Effective user ID)。

大家可能會急不及待地嘗試:

iptables -A INPUT -p icmp -m owner --uid-owner 1001 -j DROP

可是iptables會有以下訊息:

iptables: Invalid argument

其實「owner」模組只適用於OUTPUT,因為您無法知道外界進入的封包是屬於誰的。另外,因為ICMP封包是不會由任何一個用戶發出的,所以「owner」也不適用於ICMP。

正確的例子如下:

iptables -A OUTPUT -p tcp -m owner --uid-owner 1001 -j DROP

 (7.2) --gid-owner

--gid-owner groupid

「--gid-owner」是設定群組號碼的,其用法與「--uid-owner」一樣。

(7.3) --pid-owner

--pid-owner processid

顧名思義,這是與執行程式號碼有關的,較為罕見。

(7.4) --sid-owner

--sid-owner sessionid

與「--pid-owner」相似,Session ID是執行程式群組的ID。

(7.5) --cmd-name

--cmd-owner name

「name」是執行程式的名稱。

(8) State

這個模組會根據網絡連線的狀態來過濾封包。

(8.1) --state

--state state

「state」可以有4種數值:NEW(建立新連接的封包)、ESTABLISHED(已建立連接的封包)、RELATED(與連接相關的封包)和INVALID(無法識別的封包)。大家都明白到「state」的功能是相當強大,但卻未必能一時間找到實例,因為各位想到:

iptables -A INPUT -p tcp -m state --state NEW -j DROP
iptables -A INPUT -p tcp -m state --state ESTABLISHED -j DROP

 這兩句的作用是一樣的,而設定INVALID過濾規則的動機也非常簡單,另外大家未必立刻領會到RELATED即是指哪一類封包,現在我們逐一講解。

  有甚麼連接是只有NEW而非ESTABLISHED呢?答案就是ICMP,當您把ICMP請求送出去時,這時的狀態是NEW;當對方回應您的封包時,這時 的狀態是ESTABLISHED。即是說若果您希望您的主機不回應任何ICMP封包,您便要用以下的規則:

 iptables -A OUTPUT -p icmp -m state --state ESTABLISHED -j DROP

若果您是不想接收從外來的ICMP封包,便要使用:

iptables -A INPUT -p icmp -m state --state NEW -j DROP

兩者的分別是使用OUTPUT還是INPUT。

另外,您要想清楚究竟是限制連接,還是過濾連接中的封包,前者當然是用NEW,那麼系統核心便不需預留記憶體來準備接收封包,後者便要使用ESTABLISHED,用來處理已成功連接的封包。

至於RELATED,您需要明白各種協定的封包種類,才能具體地感受到其意義。「RELATED」代表在現有的網絡連接上,有其他所謂「相關的」連接中發出的封包,

筆者沒有多大的機會使用RELA
TED這個狀態,因此本人引用了James C. Stephens的文章「Iptables connection tracking」作說明:

(1) ICMP封包可以歸納為三類訊息:請求、回應以及其他。請求封包包括ping、timestamp、netmask request等;回應封包包括pong、timestamp reply、netmask reply等。其中請求封包屬於NEW,回應封包屬於ESTABLISHED,至於其他封包,例如預設閘重定向則屬於RELATED,因為它並不屬於請求 或回應封包。

(2) FTP的網絡連接可以分為主動和被動模式,在主動模式下,伺服器會主動連接客戶端的電腦,用作資料及檔案傳輸,在建立這個連接前,客戶端會發送PORT命 令(包含port號碼),讓伺服器知道該連接客戶端的哪一個port。由於這個新連接,是基於FTP(port 21)控制命令連接而建立的,因此它是屬於RELATED。

(源:http://www.sns.ias.edu/~jns/security/iptables/iptables_conntrack.html)

最 後是INVALID狀態,由於該封包不是出於任何現有網絡連接的主機,就算它進入了網絡後,也沒有主機會接收此封包,因此在一部份情況下,我們都把這類封 包濾掉。另外,man-in-middle attack主要是把偽冒封包插入某網絡連接,然後偽裝為主機,若果這個偽冒封包能被濾掉,那就能防止man-in-middle attack。

(9) ConnTrack(Connection Tracking)

連 接追蹤是State的加強版本,由Marc Boucher開發成iptables的延伸模組。原本iptables是沒有狀態(stateless)記錄的防火牆,加入了ConnTrack模組 後,iptables會追蹤網絡連接中的封包去向,並能推斷進出網絡的封包是否為傳送及回覆關係,令iptables變成有狀態(stateful)記錄 的防火牆。ConnTrack與State是兼容的,而且ConnTrack的功能比State更為強大。以下是兼容性的例子:

iptables -A FORWARD -m conntrack --ctstate RELATED --ctproto tcp -j DROP

那麼所有TCP封包(只限RELATED)都會被濾掉,與「iptables -A OUTPUT -p tcp -m state --state RELATED -j DROP」的效果相同。

(9.1) --ctstate

 [!] --ctstate [INVALID|ESTABLISHED|NEW|RELATED|SNAT|DNAT][,...]

  「SNAT」和「DNAT」是新增的,分別代表Source NAT和Destination NAT,SNAT即是說在同一個網絡連接裡,發放封包的主機並不等同於封包回覆主機,中間必定經過網絡地址轉譯(NAT,Network Address Translation);DNAT則代表封包的目的主機與發放回覆封包的主機不同,也即是說中間曾經過網絡地址轉譯。NAT的封包過濾在此不作詳談,在 稍後的章節會為大家介紹。

(9.2) --ctproto

[!] --ctproto proto

「--ctproto」指定了這道規則適用於哪一種協定,與「-p」的性質相同。您可以在「proto」中輸入數字(根據/etc/protocols)或協定名稱。

(9.3) Source and Destination

--ctorigsrc [!] address[/mask]
--ctorigdst [!] address[/mask]
--ctreplsrc [!] address[/mask]
--ctrepldst [!] address[/mask]

它 們分別是「original source address」、「original destination address」、「reply source address」及「reply destination address」,每個IP封包都會列明它是來自哪裡,以及送往哪裡,ConnTrack模組能辨認出這一個封包(不論它是從外部進入,或是內部送出)的 四種不同主機地址。以下是一例子

我們先設定以下規則在主機A:

iptables -A INPUT -m conntrack --ctproto icmp --ctorigsrc beryl -j DROP

這道規則的目的是,當我們從主機A(beryl)發送ping封包給主機B時,主機B會接收該封包,並回覆ping封包,但主機A因為知道這個回覆封包是來自beryl,即是自己,那麼便符合剛才的規則,把封包過濾掉。

然後再在主機B設下以下規則:

iptables -A INPUT -p icmp -s beryl -j ACCEPT

其目的只在於記錄並證明,主機B能收到從主機A送來的ping封包。以下是實驗結果:

主機A:

# ping machineb
PING machineb (11.22.33.44) 56(84) bytes of data.

--- machineb ping statistics ---
16 packets transmitted, 0 received, 100% packet loss, time 15013ms

主機B:

[root@machineb bio]# iptables -L INPUT -v
Chain INPUT (policy ACCEPT 31 packets, 2706 bytes)
 pkts bytes target     prot opt in     out     source               destination        
    0     0 ACCEPT     icmp --  any   any     machinea anywhere          
[root@machineb bio]# iptables -L INPUT -v
Chain INPUT (policy ACCEPT 39 packets, 3416 bytes)
 pkts bytes target     prot opt in     out     source               destination        
    1    84 ACCEPT     icmp --  any   any     machinea anywhere          
[root@machineb bio]# iptables -L INPUT -v
Chain INPUT (policy ACCEPT 47 packets, 4126 bytes)
 pkts bytes target     prot opt in     out     source               destination        
    2   168 ACCEPT     icmp --  any   any     machinea anywhere          
[root@machineb bio]# iptables -L INPUT -v
Chain INPUT (policy ACCEPT 57 packets, 4940 bytes)
 pkts bytes target     prot opt in     out     source               destination        
    3   252 ACCEPT     icmp --  any   any     machinea anywhere          
[root@machineb bio]# iptables -L INPUT -v
Chain INPUT (policy ACCEPT 65 packets, 5650 bytes)
 pkts bytes target     prot opt in     out     source               destination        
    4   336 ACCEPT     icmp --  any   any     machinea anywhere          
[root@machineb bio]# iptables -L INPUT -v
Chain INPUT (policy ACCEPT 74 packets, 6412 bytes)
 pkts bytes target     prot opt in     out     source               destination        
    5   420 ACCEPT     icmp --  any   any     machinea anywhere          
...
...

這個例子讓我們知道,一個封包除了能透露出它的來源和目的地外,我們還可以知道上一個封包的來源和目的地,只要我們有追蹤這個網絡連接的封包傳送便可。(注:傳送封包的主機,並不一定相等於接收回覆封包的主機,這是有NAT的關係)

(9.4) --ctstatus

[!] --ctstatus [NONE|EXPECTED|SEEN_REPLY|ASSURED][,...]

「--ctstatus」所指涉的是ConnTrack的內部狀態,只要您的Linux核心已加入ConnTrack這個模組,那麼在「/proc/net/ip_conntrack」就會記錄了現時被追蹤的網絡連接,例如

tcp     6 432000 ESTABLISHED src=11.22.33.44 dst=192.168.2.116 sport=65062 dport=22 src=192.168.2.116 dst=11.22.33.44 sport=22 dport=65062 [ASSURED] use=1
tcp      6 430202 ESTABLISHED src=192.168.3.1 dst=192.168.3.113 sport=32826 dport=22 src=192.168.3.113 dst=192.168.3.1 sport=22 dport=32826 [ASSURED] use=1

這 裡記錄了兩個SSH的連接,第一欄是協定名稱(e.g. TCP),第二欄是協定名稱號碼(e.g. 6),在/etc/protocols中可以找到這個號碼是相對於哪個協定名稱,當然,第一欄和第二欄永遠是互相對應的。第三欄是這個連接追蹤記錄的生存 期,當這個連接沒有資料傳輸時,這欄的數字就會被減去一,直到零為止,便會從ip_conntrack中移除,只要連接時有資料傳輸,便會重新設定為初 值。例如:

tcp      6 431999 ESTABLISHED src=11.22.33.44 dst=192.168.2.116 sport=61140 dport=22 src=192.168.2.116 dst=11.22.33.44 sport=22 dport=61140 [ASSURED] use=1

tcp      6 431996 ESTABLISHED src=11.22.33.44 dst=192.168.2.116 sport=61140 dport=22 src=192.168.2.116 dst=11.22.33.44 sport=22 dport=61140 [ASSURED] use=1

這個數值跌了三,即是這個連接在某段時間內沒有資料傳輸,一旦我們再按一按鍵(在SSH客戶端發送字元),便會還原為初值:

tcp     6 431999 ESTABLISHED src=11.22.33.44 dst=192.168.2.116 sport=61140 dport=22 src=192.168.2.116 dst=11.22.33.44 sport=22 dport=61140 [ASSURED] use=1

由於時間的延誤關係,它已經從初值(432000)跌至431999。

432000秒即是5日,這只是狀態為ESTABLISHED時的初值,至於其他狀態的初值(即連接追蹤的限期),可以參考Linux核心程式碼,在「net/ipv4/netfilter」中的「ip_conntrack_proto_tcp.c」:

static unsigned long tcp_timeouts[]
= { 30 MINS,    /*  TCP_CONNTRACK_NONE, */
    5 DAYS, /*  TCP_CONNTRACK_ESTABLISHED,  */
    2 MINS, /*  TCP_CONNTRACK_SYN_SENT, */
    60 SECS,    /*  TCP_CONNTRACK_SYN_RECV, */
    2 MINS, /*  TCP_CONNTRACK_FIN_WAIT, */
    2 MINS, /*  TCP_CONNTRACK_TIME_WAIT,    */
    10 SECS,    /*  TCP_CONNTRACK_CLOSE,    */
    60 SECS,    /*  TCP_CONNTRACK_CLOSE_WAIT,   */
    30 SECS,    /*  TCP_CONNTRACK_LAST_ACK, */
    2 MINS, /*  TCP_CONNTRACK_LISTEN,   */
};

第四欄是連接狀態,亦在「ip_conntrack_proto_tcp.c」中定義:

static const char *tcp_conntrack_names[] = {
    "NONE",
    "ESTABLISHED",
    "SYN_SENT",
    "SYN_RECV",
    "FIN_WAIT",
    "TIME_WAIT",
    "CLOSE",
    "CLOSE_WAIT",
    "LAST_ACK",
    "LISTEN"
};

各連接狀態的意義不在此談,讀者應參考RFC 793。

其後的「src」、「sport」和「dport」就是雙方主機的資料,最後我們看見「ASSURED」,這就是ConnTrack的內部狀態:(源:https://lists.netfilter.org/pipermail/netfilter-devel/2002-July/008432.html)

ASSURED: ConnTrack知道連接已受確認,在TCP連接中(3- way handshake),由客戶端發出SYN封包,再由伺服器端發出SYN/ACK封包,最後由客戶端發放ACK封包來完成連接確認,這個時候 ConnTrack便知道連接已經成功,並把追蹤連接狀態定為ASSURED。

參考資料

[1] Ipsysctl tutorial 1.0.4, Chapter 3. IPv4 variable reference 3.7  Netfilter Reference.
http://bec.at/support/ipsysctl-tutorial/netfilterreference.html

[2] Antony Stone. Netfilter / IPTables Stateful packet filter firewalling with Linux.
http://www.ukuug.org/events/linux2004/programme/paper-AStone-2/Firewalls.pdf

[3] conntrack performance/DoS formula (netfilter-devel) on lists.netfilter.org, July 2002 https://lists.netfilter.org/pipermail/netfilter-devel/2002-July/008432.html

_M#]
P.S.說有意無意是好聽,說難聽就是小白多,工廠一個小小的站,有需要50個以上的連線嗎??
更多資訊請參考:
最新超值旗艦機開箱
比螺旋燈泡還省電的迷你 NAS
26800mAh筆電行動電源