所屬分類:IPtables Linux基礎
在本博客中,從理論到實踐,系統的介紹了iptables,如果你想要從頭開始了解iptables,可以查看iptables文章列表,直達鏈接如下
iptables零基礎快速入門系列
經過前文的總結,我們已經能夠熟練的管理規則了,但是我們使用過的"匹配條件"少得可憐,之前的示例中,我們只使用過一種匹配條件,就是將"源地址"作為匹配條件。
那么這篇文章中,我們就來了解一下更多的匹配條件,以及匹配條件的更多用法。
注意:在參照本文進行iptables實驗時,請務必在個人的測試機上進行,因為如果iptables規則設置不當,有可能使你無法連接到遠程主機中。
匹配條件的更多用法
還是從我們最常用的"源地址"說起吧,我們知道,使用-s選項作為匹配條件,可以匹配報文的源地址,但是之前的示例中,我們每次指定源地址,都只是指定單個IP,示例如下。
其實,我們也可以在指定源地址時,一次指定多個,用"逗號"隔開即可,示例如下。
可以看出,上例中,一次添加了兩條規則,兩條規則只是源地址對應的IP不同,注意,上例中的"逗號"兩側均不能包含空格,多個IP之間必須與逗號相連。
除了能指定具體的IP地址,還能指定某個網段,示例如下
上例表示,如果報文的源地址IP在10.6.0.0/16網段內,當報文經過INPUT鏈時就會被DROP掉。
其實,我們還可以對匹配條件取反,先看示例,如下。
上圖中,使用"! -s 192.168.1.146"表示對 -s 192.168.1.146這個匹配條件取反, -s 192.168.1.146表示報文源IP地址為192.168.1.146即可滿足匹配條件,使用 "!" 取反后則表示,報文源地址IP只要不為192.168.1.146即滿足條件,那么,上例中規則表達的意思就是,只要發往本機的報文的源地址不是192.168.1.146,就接受報文。
此刻,你猜猜,按照上例中的配置,如果此時從146主機上向防火牆所在的主機發送ping請求,146主機能得到回應嗎?(此處不考慮其他鏈,只考慮filter表的INPUT鏈)
為了給你思考的空間,我把答案寫的遠一點。
答案是:能,也就是說,按照上例的配置,146主機仍然能夠ping通當前主機,為什么呢?我們來分析一下。
上例中,filter表的INPUT鏈中只有一條規則,這條規則要表達的意思就是:
只要報文的源IP不是192.168.1.146,那么就接受此報文,但是,某些小伙伴可能會誤會,把上例中的規則理解成如下含義,
只要報文的源IP是192.168.1.146,那么就不接受此報文,這種理解與上述理解看似差別不大,其實完全不一樣,這樣理解是錯誤的,上述理解才是正確的。
換句話說就是,報文的源IP不是192.168.1.146時,會被接收,並不能代表,報文的源IP是192.168.1.146時,會被拒絕。
上例中,因為並沒有任何一條規則指明源IP是192.168.1.146時,該執行怎樣的動作,所以,當來自192.168.1.146的報文經過INPUT鏈時,並不能匹配上例中的規則,於是,此報文就繼續匹配后面的規則,可是,上例中只有一條規則,這條規則后面沒有其他可以匹配的規則,於是,此報文就會去匹配當前鏈的默認動作(默認策略),而上例中,INPUT鏈的默認動作為ACCEPT,所以,來自146的ping報文就被接收了,如果,把上例中INPUT鏈的默認策略改為DROP,那么,146的報文將會被丟棄,146上的ping命令將得不到任何回應,但是如果將INPUT鏈的默認策略設置為DROP,當INPUT鏈中沒有任何規則時,所有外來報文將會被丟棄,包括我們ssh遠程連接。
好了,我們通過上例,不僅了解到了怎樣對匹配條件取反,還加深了我們對默認策略的了解,一舉兩得,我們繼續聊。
匹配條件:目標IP地址
除了可以通過-s選項指定源地址作為匹配條件,我們還可以使用-d選項指定"目標地址"作為匹配條件。
源地址表示報文從哪里來,目標地址表示報文要到哪里去。
除了127.0.0.1回環地址以外,當前機器有兩個IP地址,IP如下。
假設,我們想要拒絕146主機發來的報文,但是我們只想拒絕146向156這個IP發送報文,並不想要防止146向101這個IP發送報文,我們就可以指定目標地址作為匹配條件,示例如下。
上例表示只丟棄從146發往156這個IP的報文,但是146發往101這個IP的報文並不會被丟棄,如果我們不指定任何目標地址,則目標地址默認為0.0.0.0/0,同理,如果我們不指定源地址,源地址默認為0.0.0.0/0,0.0.0.0/0表示所有IP,示例如下。
上例表示,所有IP發送往101的報文都將被丟棄。
與-s選項一樣,-d選項也可以使用"嘆號"進行取反,也能夠同時指定多個IP地址,使用"逗號"隔開即可。
但是請注意,不管是-s選項還是-d選項,取反操作與同時指定多個IP的操作不能同時使用。
需要明確的一點就是:當一條規則中有多個匹配條件時,這多個匹配條件之間,默認存在"與"的關系。
說白了就是,當一條規則中存在多個匹配條件時,報文必須同時滿足這些條件,才算做被規則匹配。
就如下例所示,下圖中的規則包含有兩個匹配條件,源地址與目標地址,報文必須同時能被這兩個條件匹配,才算作被當前規則匹配,也就是說,下例中,報文必須來自146,同時報文的目標地址必須為101,才會被如下規則匹配,兩個條件必須同時滿足。
我們除了能夠使用-s選項和-d選項匹配源IP與目標IP以外,還能夠匹配"源端口"與"目標端口",但是我們一會兒再聊怎樣匹配端口,我們先聊聊其他選項。
匹配條件:協議類型
我們可以使用-p選項,指定需要匹配的報文的協議類型。
假設,我們只想要拒絕來自146的tcp類型的請求,那么可以進行如下設置
上圖中,防火牆拒絕了來自146的tcp報文發往156這個IP,那么我們來測試一下,我們在146上使用ssh連接101這個IP試試(ssh協議的傳輸層協議屬於tcp協議類型)
如上圖所示,ssh連接被拒絕了,那么我們使用ping命令試試 (ping命令使用icmp協議),看看能不能ping通156。
可以看到,PING命令可以ping通156,證明icmp協議並沒有被規則匹配到,只有tcp類型的報文被匹配到了。
那么,-p選項都支持匹配哪些協議呢?我們總結一下
centos6中,-p選項支持如下協議類型
tcp, udp, udplite, icmp, esp, ah, sctp
centos7中,-p選項支持如下協議類型
tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh
當不使用-p指定協議類型時,默認表示所有類型的協議都會被匹配到,與使用-p all的效果相同。
匹配條件:網卡接口
我們再來認識一個新的匹配條件,當本機有多個網卡時,我們可以使用 -i 選項去匹配報文是通過哪塊網卡流入本機的。
我們先動手做個小例子,對-i選項有一個初步的了解以后,再結合理論去看。
當前主機的網卡名稱為eth4,如下圖
假設想要拒絕由網卡eth4流入的ping請求報文,則可以進行如下設置。
上圖中,使用-i選項,指定網卡名稱,使用-p選項,指定了需要匹配的報文協議類型,上例表示丟棄由eth4網卡流入的icmp類型的報文。
是不是很容易理解,但是,我們需要考慮一個問題,-i選項是用於匹配報文流入的網卡的,也就是說,從本機發出的報文是不可能會使用到-i選項的,因為這些由本機發出的報文壓根不是從網卡流入的,而是要通過網卡發出的,從這個角度考慮,-i選項的使用是有限制的。
為了更好的解釋-i選項,我們回顧一下在理論總結中的一張iptables全局報文流向圖,如下。
既然-i選項是用於判斷報文是從哪個網卡流入的,那么,-i選項只能用於上圖中的PREROUTING鏈、INPUT鏈、FORWARD鏈,這是-i選項的特殊性,因為它只是用於判斷報文是從哪個網卡流入的,所以只能在上圖中"數據流入流向"的鏈中與FORWARD鏈中存在,而上圖中的"數據發出流向"經過的鏈中,是不可能使用-i選項的,比如上圖中的OUTPUT鏈與POSTROUTING鏈,他們都不能使用-i選項。
理解完-i選項,再來理解-o選項就好辦了。
當主機有多塊網卡時,可以使用-o選項,匹配報文將由哪塊網卡流出,沒錯,-o選項與-i選項是相對的,-i選項用於匹配報文從哪個網卡流入,-o選項用於匹配報文將從哪個網卡流出。
聰明如你,一定想到了,-i選項只能用於PREROUTING鏈、INPUT鏈、FORWARD鏈,那么-o選項只能用於FORWARD鏈、OUTPUT鏈、POSTROUTING鏈。
因為-o選項是用於匹配報文將由哪個網卡"流出"的,所以與上圖中的"數據進入流向"中的鏈沒有任何緣分,所以,-o選項只能用於FORWARD鏈、OUTPUT鏈、POSTROUTING鏈中。
看來,FORWARD鏈屬於"中立國",它能同時使用-i選項與-o選項。
擴展匹配條件
好了,現在,我們就要聊聊,怎樣匹配報文的"源端口"與"目標端口"。
在上文中,我們總結了"源地址"與"目標地址"以后,就順便提到了"源端口"與"目標端口",但是,為什么剛才不介紹"源端口"與"目標端口",非要現在介紹呢?這是因為"源端口"與"目標端口"屬於擴展匹配條件,"源地址"與"目標地址"屬於基本匹配條件,上文中介紹到的匹配條件,都屬於基本匹配條件,所以,我們單獨把"源端口"與"目標端口",放在后面總結,是為了引出擴展匹配條件的概念。
那么,先來了解一下,什么是擴展匹配條件。
不是基本匹配條件的就是擴展匹配條件,這樣說好像是句廢話,我們可以這樣理解,基本匹配條件我們可以直接使用,而如果想要使用擴展匹配條件,則需要依賴一些擴展模塊,或者說,在使用擴展匹配條件之前,需要指定相應的擴展模塊才行,這樣說不容易明白,我們做個例子,就能夠明白。
我們知道,sshd服務的默認端口為22,當我們使用ssh工具遠程連接主機時,默認會連接服務端的22號端口,假設,我們現在想要使用iptables設置一條規則,拒絕來自192.168.1.146的ssh請求,我們就可以拒絕146上的報文能夠發往本機的22號端口,這個時候,就需要用到"目標端口"選項。
使用選項--dport可以匹配報文的目標端口,--dport意為destination-port,即表示目標端口。
注意,與之前的選項不同,--dport前有兩條"橫杠",而且,使用--dport選項時,必須事先指定了使用哪種協議,即必須先使用-p選項,示例如下
上圖中,我們就使用了擴展匹配條件--dport,指定了匹配報文的目標端口,如果外來報文的目標端口為本機的22號端口(ssh默認端口),則拒絕之,而在使用--dport之前,我們使用-m選項,指定了對應的擴展模塊為tcp,也就是說,如果想要使用--dport這個擴展匹配條件,則必須依靠某個擴折模塊完成,上例中,這個擴展模塊就是tcp擴展模塊,最終,我們使用的是tcp擴展模塊中的dport擴展匹配條件。
現在,我們再回過頭來看看擴展匹配條件的概念,就更加明白了。
擴展匹配條件被使用時,則需要依賴一些擴展模塊,或者說,在使用擴展匹配條件之前,需要指定相應的擴展模塊才行。
現在你明白了嗎? -m tcp表示使用tcp擴展模塊,--dport表示tcp擴展模塊中的一個擴展匹配條件,可用於匹配報文的目標端口。
注意,-p tcp與 -m tcp並不沖突,-p用於匹配報文的協議,-m 用於指定擴展模塊的名稱,正好,這個擴展模塊也叫tcp。
其實,上例中,我們可以省略-m選項,示例如下。
當使用-p選項指定了報文的協議時,如果在沒有使用-m指定對應的擴展模塊名稱的情況下,使用了擴展匹配條件, iptables默認會調用與-p選項對應的協議名稱相同的模塊。
上例中,我們使用-p選項指定了協議名稱,使用擴展匹配條件--dport指定了目標端口,在使用擴展匹配條件的時候,如果沒有使用-m指定使用哪個擴展模塊,iptables會默認使用"-m 協議名",而協議名就是-p選項對應的協議名,上例中,-p 對應的值為tcp,所以默認調用的擴展模塊就為-m tcp,如果-p對應的值為udp,那么默認調用的擴展模塊就為-m udp。
所以,上例中,其實"隱式"的指定了擴展模塊,只是沒有表現出來罷了。
所以,在使用擴展匹配條件時,一定要注意,如果這個擴展匹配條件所依賴的擴展模塊名正好與-p對應的協議名稱相同,那么則可省略-m選項,否則則不能省略-m選項,必須使用-m選項指定對應的擴展模塊名稱,這樣說可能還是不是特別明了,在后續的舉例中,我們會更加明了的理解這些概念。
有"目標端口",就有"源端口",代表"源端口"的擴展匹配條件為--sport
使用--sport可以判斷報文是否從指定的端口發出,即匹配報文的源端口是否與指定的端口一致,--sport表示source-port,即表示源端口之意。
因為我們已經搞明白了dport,那么sport我就不再贅述了,示例如下
上例中,隱含了"-m tcp"之意,表示使用了tcp擴展模塊的--sport擴展匹配條件。
擴展匹配條件是可以取反的,同樣是使用"!"進行取反,比如 "! --dport 22",表示目標端口不是22的報文將會被匹配到。
不管是--sport還是--dsport,都能夠指定一個端口范圍,比如,--dport 22:25表示目標端口為22到25之間的所有端口,即22端口、23端口、24端口、25端口,示例如下
也可以寫成如下圖中的模樣,下圖中第一條規則表示匹配0號到22號之間的所有端口,下圖中的第二條規則表示匹配80號端口以及其以后的所有端口(直到65535)。
剛才聊到的兩個擴展匹配條件都是tcp擴展模塊的,其實,tcp擴展模塊還有一個比較有用的擴展匹配條件叫做"--tcp-flags",但是由於篇幅原因,以后再對這個擴展匹配條件進行總結。
借助tcp擴展模塊的--sport或者--dport都可以指定一個連續的端口范圍,但是無法同時指定多個離散的、不連續的端口,如果想要同時指定多個離散的端口,需要借助另一個擴展模塊,"multiport"模塊。
我們可以使用multiport模塊的--sports擴展條件同時指定多個離散的源端口。
我們可以使用multiport模塊的--dports擴展條件同時指定多個離散的目標端口。
示例如下
上圖示例表示,禁止來自146的主機上的tcp報文訪問本機的22號端口、36號端口以及80號端口。
上圖中,"-m multiport --dports 22,36,80"表示使用了multiport擴展模塊的--dports擴展條件,以同時指定了多個離散的端口,每個端口之間用逗號隔開。
上圖中的-m multiport是不能省略的,如果你省略了-m multiport,就相當於在沒有指定擴展模塊的情況下,使用了擴展條件("--dports"),那么上例中,iptables會默認調用"-m tcp",但是,"--dports擴展條件"並不屬於"tcp擴展模塊",而是屬於"multiport擴展模塊",所以,這時就會報錯。
綜上所述,當使用--dports或者--sports這種擴展匹配條件時,必須使用-m指定模塊的名稱。
其實,使用multiport模塊的--sports與--dpors時,也可以指定連續的端口范圍,並且能夠在指定連續的端口范圍的同時,指定離散的端口號,示例如下。
上例中的命令表示拒絕來自192.168.1.146的tcp報文訪問當前主機的22號端口以及80到88之間的所有端口號,是不是很方便?有沒有很靈活?
不過需要注意,multiport擴展只能用於tcp協議與udp協議,即配合-p tcp或者-p udp使用。
再回過頭看之前的概念,我想,你應該就更加明白了。
今天,我們只是初步的認識了擴展模塊,以及擴展匹配條件,還有一些模塊我們並沒有總結,好飯不怕晚,后續會有對它們的總結。
小結
這篇文章中,我們主要總結了一些常用的"基礎匹配條件",並且初步的認識了兩個"擴展模塊"以及這兩個擴展模塊中一些常用的擴展條件,為了方便以后回顧,我們將它們總結如下。
首先我們要明確一點,當規則中同時存在多個匹配條件時,多個條件之間默認存在"與"的關系,即報文必須同時滿足所有條件,才能被規則匹配。
基本匹配條件總結
-s用於匹配報文的源地址,可以同時指定多個源地址,每個IP之間用逗號隔開,也可以指定為一個網段。
Shell
1 2 3 4 |
#示例如下 iptables -t filter -I INPUT -s 192.168.1.111,192.168.1.118 -j DROP iptables -t filter -I INPUT -s 192.168.1.0/24 -j ACCEPT iptables -t filter -I INPUT ! -s 192.168.1.0/24 -j ACCEPT |
-d用於匹配報文的目標地址,可以同時指定多個目標地址,每個IP之間用逗號隔開,也可以指定為一個網段。
Shell
1 2 3 4 |
#示例如下 iptables -t filter -I OUTPUT -d 192.168.1.111,192.168.1.118 -j DROP iptables -t filter -I INPUT -d 192.168.1.0/24 -j ACCEPT iptables -t filter -I INPUT ! -d 192.168.1.0/24 -j ACCEPT |
-p用於匹配報文的協議類型,可以匹配的協議類型tcp、udp、udplite、icmp、esp、ah、sctp等(centos7中還支持icmpv6、mh)。
Shell
1 2 3 |
#示例如下 iptables -t filter -I INPUT -p tcp -s 192.168.1.146 -j ACCEPT iptables -t filter -I INPUT ! -p udp -s 192.168.1.146 -j ACCEPT |
-i用於匹配報文是從哪個網卡接口流入本機的,由於匹配條件只是用於匹配報文流入的網卡,所以在OUTPUT鏈與POSTROUTING鏈中不能使用此選項。
Shell
1 2 3 |
#示例如下 iptables -t filter -I INPUT -p icmp -i eth4 -j DROP iptables -t filter -I INPUT -p icmp ! -i eth4 -j DROP |
-o用於匹配報文將要從哪個網卡接口流出本機,於匹配條件只是用於匹配報文流出的網卡,所以在INPUT鏈與PREROUTING鏈中不能使用此選項。
Shell
1 2 3 |
#示例如下 iptables -t filter -I OUTPUT -p icmp -o eth4 -j DROP iptables -t filter -I OUTPUT -p icmp ! -o eth4 -j DROP |
擴展匹配條件總結
我們來總結一下今天認識的兩個擴展模塊,以及其中的擴展條件(並非全部,只是這篇文章中介紹過的)
tcp擴展模塊
常用的擴展匹配條件如下:
-p tcp -m tcp --sport 用於匹配tcp協議報文的源端口,可以使用冒號指定一個連續的端口范圍
-p tcp -m tcp --dport 用於匹配tcp協議報文的目標端口,可以使用冒號指定一個連續的端口范圍
Shell
1 2 3 4 5 6 |
#示例如下 iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp --sport 22 -j REJECT iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 22:25 -j REJECT iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport :22 -j REJECT iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m tcp --dport 80: -j REJECT iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp ! --sport 22 -j ACCEPT |
multiport擴展模塊
常用的擴展匹配條件如下:
-p tcp -m multiport --sports 用於匹配報文的源端口,可以指定離散的多個端口號,端口之間用"逗號"隔開
-p udp -m multiport --dports 用於匹配報文的目標端口,可以指定離散的多個端口號,端口之間用"逗號"隔開
Shell
1 2 3 4 5 6 |
#示例如下 iptables -t filter -I OUTPUT -d 192.168.1.146 -p udp -m multiport --sports 137,138 -j REJECT iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 22,80 -j REJECT iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport ! --dports 22,80 -j REJECT iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 80:88 -j REJECT iptables -t filter -I INPUT -s 192.168.1.146 -p tcp -m multiport --dports 22,80:88 -j REJECT |