iptables詳解及應用(史上最全)

1.1 iptables概念

從邏輯上講。防火牆可以大體分爲主機防火牆和網絡防火牆。
主機防火牆:針對於單個主機進行防護。
網絡防火牆:往往處於網絡入口或邊緣,針對於網絡入口進行防護,服務於防火牆背後的本地局域網。
網絡防火牆和主機防火牆並不衝突,可以理解爲,網絡防火牆主外(集體), 主機防火牆主內(個人)。
從物理上講,防火牆可以分爲硬件防火牆和軟件防火牆。
硬件防火牆:在硬件級別實現部分防火牆功能,另一部分功能基於軟件實現,性能高,成本高。
軟件防火牆:應用軟件處理邏輯運行於通用硬件平臺之上的防火牆,性能低,成本低
iptables其實不是真正的防火牆,我們可以把它理解成一個客戶端代理,用戶通過iptables這個代理,將用戶的安全設定執行到對應的"安全框架"中,這個"安全框架"纔是真正的防火牆,這個框架的名字叫netfilter
netfilter纔是防火牆真正的安全框架(framework),netfilter位於內核空間。
iptables其實是一個命令行工具,位於用戶空間,我們用這個工具操作真正的框架。
netfilter/iptables(下文中簡稱爲iptables)組成Linux平臺下的包過濾防火牆,與大多數的Linux軟件一樣,這個包過濾防火牆是免費的,它可以代替昂貴的商業防火牆解決方案,完成封包過濾、封包重定向和網絡地址轉換(NAT)等功能。
Netfilter是Linux操作系統核心層內部的一個數據包處理模塊,它具有如下功能:
網絡地址轉換(Network Address Translate)
數據包內容修改
以及數據包過濾的防火牆功能
所以說,雖然我們使用service iptables start啓動iptables"服務",但是其實準確的來說,iptables並沒有一個守護進程,所以並不能算是真正意義上的服務,而應該算是內核提供的功能。

1.1.1 鏈的概念

現在,我們想象一下,這些"關卡"在iptables中爲什麼被稱作"鏈"呢?我們知道,防火牆的作用就在於對經過的報文匹配"規則",然後執行對應的"動作",所以,當報文經過這些關卡的時候,則必須匹配這個關卡上的規則,但是,這個關卡上可能不止有一條規則,而是有很多條規則,當我們把這些規則串到一個鏈條上的時候,就形成了"鏈",所以,我們把每一個"關卡"想象成如下圖中的模樣 ,這樣來說,把他們稱爲"鏈"更爲合適,每個經過這個"關卡"的報文,都要將這條"鏈"上的所有規則匹配一遍,如果有符合條件的規則,則執行規則對應的動作。

1.1.2 表的概念

我們再想想另外一個問題,我們對每個"鏈"上都放置了一串規則,但是這些規則有些很相似,比如,A類規則都是對IP或者端口的過濾,B類規則是修改報文,那麼這個時候,我們是不是能把實現相同功能的規則放在一起呢,必須能的。
我們把具有相同功能的規則的集合叫做"表",所以說,不同功能的規則,我們可以放置在不同的表中進行管理,而iptables已經爲我們定義了4種表,每種表對應了不同的功能,而我們定義的規則也都逃脫不了這4種功能的範圍,所以,學習iptables之前,我們必須先搞明白每種表 的作用。
表,可以理解成配置文件,把每個鉤子函數的參數寫在配置文件中,才能生效。鉤子函數本身就是個函數。
iptables爲我們提供瞭如下規則的分類,
filter表:負責過濾功能,防火牆;內核模塊:iptables_filter
nat表:network address translation,網絡地址轉換功能;內核模塊:iptable_nat
mangle表:拆解報文,做出修改,並重新封裝 的功能;iptable_mangle
raw表:關閉nat表上啓用的連接追蹤機制;iptable_raw
也就是說,我們自定義的所有規則,都是這四種分類中的規則,或者說,所有規則都存在於這4張"表"中。

1.1.3 錶鏈關係

但是我們需要注意的是,某些"鏈"中註定不會包含"某類規則",就像某些"關卡"天生就不具備某些功能一樣,比如,A"關卡"只負責打擊陸地敵人,沒有防空能力,B"關卡"只負責打擊空中敵人,沒有防禦步兵的能力,C"關卡"可能比較NB,既能防空,也能防禦陸地敵人,D"關卡"最屌,海陸空都能防。
那讓我們來看看,每個"關卡"都有哪些能力,或者說,讓我們看看每個"鏈"上的規則都存在於哪些"表"中。
prerouting"鏈"只擁有nat表、raw表和mangle表所對應的功能,所以,prerouting中的規則只能存放於nat表、raw表和mangle表中。
那麼,根據上述思路,我們來總結一下,每個"關卡"都擁有什麼功能,
或者說,每個"鏈"中的規則都存在於哪些"表"中。
PREROUTING 的規則可以存在於:raw表,mangle表,nat表。
INPUT 的規則可以存在於:mangle表,filter表,(centos7中還有nat表,centos6中沒有)。
FORWARD 的規則可以存在於:mangle表,filter表。
OUTPUT 的規則可以存在於:raw表mangle表,nat表,filter表。
POSTROUTING 的規則可以存在於:mangle表,nat表
但是,我們在實際的使用過程中,往往是通過"表"作爲操作入口,對規則進行定義的,之所以按照上述過程介紹iptables,是因爲從"關卡"的角度更容易從入門的角度理解,但是爲了以便在實際使用的時候,更加順暢的理解它們,此處我們還要將各"表"與"鏈"的關係羅列出來,
表(功能)<–> 鏈(鉤子):
raw 表中的規則可以被哪些鏈使用:PREROUTING,OUTPUT
mangle 表中的規則可以被哪些鏈使用:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
nat 表中的規則可以被哪些鏈使用:PREROUTING,OUTPUT,POSTROUTING(centos7中還有INPUT,centos6中沒有)
filter 表中的規則可以被哪些鏈使用:INPUT,FORWARD,OUTPUT
其實我們還需要注意一點,因爲數據包經過一個"鏈"的時候,會將當前鏈的所有規則都匹配一遍,但是匹配時總歸要有順序,我們應該一條一條的去匹配,而且我們說過,相同功能類型的規則會匯聚在一張"表"中,那麼,哪些"表"中的規則會放在"鏈"的最前面執行呢,這時候就需要有一個優先級的問題
prerouting鏈中的規則存放於三張表中,而這三張表中的規則執行的優先級如下:
raw --> mangle --> nat
但是我們知道,iptables爲我們定義了4張"表",當他們處於同一條"鏈"時,執行的優先級如下。
優先級次序(由高而低):
raw --> mangle --> nat --> filter
但是我們前面說過,某些鏈天生就不能使用某些表中的規則,所以,4張表中的規則處於同一條鏈的目前只有output鏈,它就是傳說中海陸空都能防守的關卡。
爲了更方便的管理,我們還可以在某個表裏面創建自定義鏈,將針對某個應用程序所設置的規則放置在這個自定義鏈中,但是自定義鏈接不能直接使用,只能被某個默認的鏈當做動作去調用才能起作用,我們可以這樣想象,自定義鏈就是一段比較"短"的鏈子,這條"短"鏈子上的規則都是針對某個應用程序制定的,但是這條短的鏈子並不能直接使用,而是需要"焊接"在iptables默認定義鏈子上,才能被IPtables使用,這就是爲什麼默認定義的"鏈"需要把"自定義鏈"當做"動作"去引用的原因。這是後話,後面再聊,在實際使用時我們即可更加的明白。

1.1.4 數據經過防火牆的流程

鏈的規則存放於哪些表中(從鏈到表的對應關係):
PREROUTING 的規則可以存在於:raw表,mangle表,nat表。
INPUT 的規則可以存在於:mangle表,filter表,(centos7中還有nat表,centos6中沒有)。
FORWARD 的規則可以存在於:mangle表,filter表。
OUTPUT 的規則可以存在於:raw表mangle表,nat表,filter表。
POSTROUTING 的規則可以存在於:mangle表,nat表。
表中的規則可以被哪些鏈使用(從表到鏈的對應關係):
raw 表中的規則可以被哪些鏈使用:PREROUTING,OUTPUT
mangle 表中的規則可以被哪些鏈使用:PREROUTING,INPUT,FORWARD,OUTPUT,POSTROUTING
nat 表中的規則可以被哪些鏈使用:PREROUTING,OUTPUT,POSTROUTING(centos7中還有INPUT,centos6中沒有)
filter 表中的規則可以被哪些鏈使用:INPUT,FORWARD,OUTPUT

1.1.5 規則的概念

先說說規則的概念,然後再通俗的解釋它。
規則:根據指定的匹配條件來嘗試匹配每個流經此處的報文,一旦匹配成功,則由規則後面指定的處理動作進行處理;
那麼我們來通俗的解釋一下什麼是iptables的規則,之前打過一個比方,每條"鏈"都是一個"關卡",每個通過這個"關卡"的報文都要匹配這個關卡上的規則,如果匹配,則對報文進行對應的處理,比如說,你我二人此刻就好像兩個"報文",你我二人此刻都要入關,可是城主有命,只有器宇軒昂的人才能入關,不符合此條件的人不能入關,於是守關將士按照城主制定的"規則",開始打量你我二人,最終,你順利入關了,而我已被拒之門外,因爲你符合"器宇軒昂"的標準,所以把你"放行"了,而我不符合標準,所以沒有被放行,其實,“器宇軒昂"就是一種"匹配條件”,“放行"就是一種"動作”,"匹配條件"與"動作"組成了規則。
瞭解了規則的概念,那我們來聊聊規則的組成部分,此處只是大概的將規則的結構列出,後面的文章中會單獨對規則進行總結。
規則由匹配條件和處理動作組成
匹配條件
匹配條件分爲基本匹配條件與擴展匹配條件
基本匹配條件:
源地址Source IP,目標地址 Destination IP
上述內容都可以作爲基本匹配條件。
擴展匹配條件:
除了上述的條件可以用於匹配,還有很多其他的條件可以用於匹配,這些條件泛稱爲擴展條件,這些擴展條件其實也是netfilter中的一部分,只是以模塊的形式存在,如果想要使用這些條件,則需要依賴對應的擴展模塊。
源端口Source Port, 目標端口Destination Port
上述內容都可以作爲擴展匹配條件
處理動作
處理動作在iptables中被稱爲target(這樣說並不準確,我們暫且這樣稱呼),動作也可以分爲基本動作和擴展動作。
此處列出一些常用的動作,之後的文章會對它們進行詳細的示例與總結:
ACCEPT:允許數據包通過。
DROP:直接丟棄數據包,不給任何迴應信息,這時候客戶端會感覺自己的請求泥牛入海了,過了超時時間纔會有反應。
REJECT:拒絕數據包通過,必要時會給數據發送端一個響應的信息,客戶端剛請求就會收到拒絕的信息。
SNAT:源地址轉換,解決內網用戶用同一個公網地址上網的問題。
MASQUERADE:是SNAT的一種特殊形式,適用於動態的、臨時會變的ip上。
DNAT:目標地址轉換。
REDIRECT:在本機做端口映射。
LOG:在/var/log/messages文件中記錄日誌信息,然後將數據包傳遞給下一條規則,也就是說除了記錄以外不對數據包做任何其他操作,仍然讓下一條規則去匹配

1.2 iptables實際操作之規則查詢

之前在iptables的概念中已經提到過,在實際操作iptables的過程中,是以"表"作爲操作入口的,如果你經常操作關係型數據庫,那麼當你聽到"表"這個詞的時候,你可能會聯想到另一個詞----“增刪改查”,當我們定義iptables規則時,所做的操作其實類似於"增刪改查",那麼,我們就先從最簡單的"查"操作入手,開始實際操作iptables。
在之前的文章中,我們已經總結過,iptables爲我們預定義了4張表,它們分別是raw表、mangle表、nat表、filter表,不同的表擁有不同的功能。
filter負責過濾功能,比如允許哪些IP地址訪問,拒絕哪些IP地址訪問,允許訪問哪些端口,禁止訪問哪些端口,filter表會根據我們定義的規則進行過濾,filter表應該是我們最常用到的表了,所以此處,我們以filter表爲例,開始學習怎樣實際操作iptables
INPUT鏈、FORWARD鏈、OUTPUT鏈,每條鏈中都有自己的規則,前文中,我們打過一個比方,把"鏈"比作"關卡",不同的"關卡"擁有不同的能力,
我們在理論總結中已經提到過,報文發往本機時,會經過PREROUTING鏈與INPUT鏈(如果你沒有明白,請回顧前文),所以,如果我們想要禁止某些報文發往本機,我們只能在PREROUTING鏈和INPUT鏈中定義規則,但是PREROUTING鏈並不存在於filter表中,換句話說就是,PREROUTING關卡天生就沒有過濾的能力,所以,我們只能在INPUT鏈中定義,當然,如果是其他工作場景,可能需要在FORWARD鏈或者OUTPUT鏈中定義過濾規則。
剛纔提到,我們可以使用iptables -t filter -L命令列出filter表中的所有規則,那麼舉一反三,我們也可以查看其它表中的規則,示例如下。
iptables -t raw -L
iptables -t mangle -L
iptables -t nat -L
其實,我們可以省略-t filter,當沒有使用-t選項指定表時,默認爲操作filter表,即iptables -L表示列出filter表中的所有規則。
可以看到,使用-v選項後,iptables爲我們展示的信息更多了,那麼,這些字段都是什麼意思呢?我們來總結一下,看不懂沒關係,等到實際使用的時候,自然會明白,此處大概瞭解一下即可。
其實,這些字段就是規則對應的屬性,說白了就是規則的各種信息,那麼我們來總結一下這些字段的含義。
pkts:對應規則匹配到的報文的個數。
bytes:對應匹配到的報文包的大小總和。
target:規則對應的target,往往表示規則對應的"動作",即規則匹配成功後需要採取的措施。
prot:表示規則對應的協議,是否只針對某些協議應用此規則。
opt:表示規則對應的選項。
in:表示數據包由哪個接口(網卡)流入,我們可以設置通過哪塊網卡流入的報文需要匹配當前規則。
out:表示數據包由哪個接口(網卡)流出,我們可以設置通過哪塊網卡流出的報文需要匹配當前規則。
source:表示規則對應的源頭地址,可以是一個IP,也可以是一個網段。
destination:表示規則對應的目標地址。可以是一個IP,也可以是一個網段。
當然,我們也可以只查看某個鏈的規則,並且不讓IP進行反解,這樣更清晰一些,比如 iptables -nvL INPUT
-line-numbers選項並沒有對應的短選項,不過我們縮寫成–line時,centos中的iptables也可以識別
policy表示當前鏈的默認策略,policy ACCEPT表示上圖中INPUT的鏈的默認動作爲ACCEPT,換句話說就是,默認接受通過INPUT關卡的所有請求,所以我們在配置INPUT鏈的具體規則時,應該將需要拒絕的請求配置到規則中,說白了就是"黑名單"機制,默認所有人都能通過,只有指定的人不能通過,當我們把INPUT鏈默認動作設置爲接受(ACCEPT),就表示所有人都能通過這個關卡,此時就應該在具體的規則中指定需要拒絕的請求,就表示只有指定的人不能通過這個關卡,這就是黑名單機制,但是,你一定發現了,上圖中所顯示出的規則,大部分都是接受請求(ACCEPT),並不是想象中的拒絕請求(DROP或者REJECT),這與我們所描述的黑名單機制不符啊,按照道理來說,默認動作爲接受,就應該在具體的規則中配置需要拒絕的人
packets表示當前鏈(上例爲INPUT鏈)默認策略匹配到的包的數量,0 packets表示默認策略匹配到0個包。
bytes表示當前鏈默認策略匹配到的所有包的大小總和。
其實,我們可以把packets與bytes稱作"計數器",上圖中的計數器記錄了默認策略匹配到的報文數量與總大小,"計數器"只會在使用-v選項時,纔會顯示出來。
當被匹配到的包達到一定數量時,計數器會自動將匹配到的包的大小轉換爲可讀性較高的單位,如下圖所示。
iptables詳解(2):iptables實際操作之規則查詢
如果你想要查看精確的計數值,而不是經過可讀性優化過的計數值,那麼你可以使用-x選項,表示顯示精確的計數值,示例如下。
iptables詳解(2):iptables實際操作之規則查詢
每張表中的每條鏈都有自己的計數器,鏈中的每個規則也都有自己的計數器,沒錯,就是每條規則對應的pkts字段與bytes字段的信息。

1.2.1 命令小結

iptables -t 表名 -L
查看對應表的所有規則,-t選項指定要操作的表,省略"-t 表名"時,默認表示操作filter表,-L表示列出規則,即查看規則。
iptable -t 表名 -L鏈名
查看指定表的指定鏈中的規則
iptables --line-numbers -t 表名 -L
表示查看錶的所有規則,並且顯示規則的序號,–line-numbers選項表示顯示規則的序號,注意,此選項爲長選項,不能與其他短選項合併,不過此選項可以簡寫爲–line,注意,簡寫後仍然是兩條橫槓,仍然是長選項
iptables -t FILTER -nvxL INPUT //-n不反解,顯示數字,-v詳細,-x詳細計數,-L鏈

1.3 iptables規則管理

首先,我們來回顧一下什麼是iptables的規則。
之前打過一個比方,每條"鏈"都是一個"關卡",每個通過這個"關卡"的報文都要匹配這個關卡上的規則,如果匹配,則對報文進行對應的處理,比如說,你我二人此刻就好像兩個"報文",你我二人此刻都要入關,可是城主有命,只有器宇軒昂之人才能入關,不符合此條件的人不能入關,於是守關將士按照城主制定的"規則",開始打量你我二人,最終,你順利入關了,而我已被拒之門外,因爲你符合"器宇軒昂"的標準,所以把你"放行"了,而我不符合標準,所以沒有被放行,其實,“器宇軒昂"就是一種"匹配條件”,“放行"就是一種"動作”,“匹配條件"與"動作"組成了規則
只不過,在iptables的世界中,最常用的匹配條件並不是"器宇軒昂”,而是報文的"源地址"、“目標地址”、“源端口”、"目標端口"等,在iptables的世界中,最常用的動作有ACCEPT(接受)、DROP(丟棄)、REJECT(拒絕),其中ACCEPT就與我們舉例中的"放行"類似,但是,我們剛纔提到的這些並不是全部的匹配條件與動作,只是最常用的一些罷了,具體的匹配條件與動作不是我們今天討論的重點,我們會在以後的文章中再做總結
好了,我們已經回顧了規則的概念,並且已經明白了,規則大致由兩個邏輯單元組成,匹配條件與動作,那麼多說無益,我們來動手定義一條規則,此處仍然以filter表中的INPUT鏈爲例,因爲filter表負責"過濾"功能,而所有發往本機的報文如果需要被過濾,首先會經過INPUT鏈(PREROUTING鏈沒有過濾功能),這與我們所比喻的"入關"場景非常相似,所以,使用filter表的INPUT鏈爲例,有助於我們進行理解。
首先,查看一下filter表中的INPUT鏈中的規則,查看規則的相關命令在前文已經總結了,此處不再贅述,如果你忘了,請回顧前文。
使用如下命令查看filter表INPUT鏈的規則,下圖中的規則爲centos6默認添加的規則
爲了準備一個從零開始的環境,以便我們進行實驗,使用iptables -F INPUT命令清空filter表INPUT鏈中的規則,後面我們會單獨對清除規則的相關命令進行總結,此處不用糾結此命令.
清空INPUT鏈以後,filter表中的INPUT鏈已經不存在任何的規則,但是可以看出,INPUT鏈的默認策略是ACCEPT,也就是說,INPUT鏈默認"放行"所有發往本機的報文,當沒有任何規則時,會接受所有報文,當報文沒有被任何規則匹配到時,也會默認放行報文
那麼此刻,我們就在另外一臺機器上,使用ping命令,向當前機器發送報文,如下圖所示,ping命令可以得到迴應,證明ping命令發送的報文已經正常的發送到了防火牆所在的主機,

1.3.1 增加規則

使用-I選項,指明將"規則"插入至哪個鏈中,-I表示insert,即插入的意思,所以-I INPUT表示將規則插入於INPUT鏈中,即添加規則之意。
使用-s選項,指明"匹配條件"中的"源地址",即如果報文的源地址屬於-s對應的地址,那麼報文則滿足匹配條件,-s爲source之意,表示源地址。
使用-j選項,指明當"匹配條件"被滿足時,所對應的動作,上例中指定的動作爲DROP,在上例中,當報文的源地址爲192.168.1.146時,報文則被DROP(丟棄)。
再次查看filter表中的INPUT鏈,發現規則已經被添加了,在iptables中,動作被稱之爲"target",所以,上圖中taget字段對應的動作爲DROP。
還記得我們在前文中說過的"計數器"嗎?此時,我們再次查看iptables中的規則,可以看到,已經有24個包被對應的規則匹配到,總計大小2016bytes。
現在INPUT鏈中已經存在了一條規則,它拒絕了所有來自192.168.1.146主機中的報文,如果此時,我們在這條規則之後再配置一條規則,後面這條規則規定,接受所有來自192.168.1.146主機中的報文,那麼,iptables是否會接受來自146主機的報文呢?我們動手試試
使用-A選項,表示在對應的鏈中"追加規則",-A爲append之意,所以,-A INPUT則表示在INPUT鏈中追加規則,而之前示例中使用的-I選項則表示在鏈中"插入規則",聰明如你一定明白了,它們的本意都是添加一條規則,只是-A表示在鏈的尾部追加規則,-I表示在鏈的首部插入規則而已。
使用-j選項,指定當前規則對應的動作爲ACCEPT。
執行完添加規則的命令後,再次查看INPUT鏈,發現規則已經成功"追加"至INPUT鏈的末尾,那麼現在,第一條規則指明瞭丟棄所有來自192.168.1.146的報文,第二條規則指明瞭接受所有來自192.168.1.146的報文,那麼結果到底是怎樣的呢?實踐出真知,在146主機上再次使用ping命令向156主機發送報文,發現仍然是ping不通的,看來第二條規則並沒有生效。
如果報文已經被前面的規則匹配到,iptables則會對報文執行對應的動作,即使後面的規則也能匹配到當前報文,很有可能也沒有機會再對報文執行相應的動作了,就以上圖爲例,報文先被第一條規則匹配到了,於是當前報文被"放行"了,因爲報文已經被放行了,所以,即使上圖中的第二條規則即使能夠匹配到剛纔"放行"的報文,也沒有機會再對剛纔的報文進行丟棄操作了。這就是iptables的工作機制
之前在總結查看命令時提到過,使用–line-number選項可以列出規則的序號,如下圖所示
iptables詳解(3):iptables規則管理
我們也可以在添加規則時,指定新增規則的編號,這樣我們就能在任意位置插入規則了,我們只要把剛纔的命令稍作修改即可,如下。
iptables詳解(3):iptables規則管理
仍然使用-I選項進行插入規則操作,-I INPUT 2表示在INPUT鏈中新增規則,新增的規則的編號爲2,好了,自己動手試試吧。
[root@node-101 ~]#iptables -t filter -A INPUT -p icmp -s 192.168.122.103 -j REJECT //-A默認添加在最後
添加規則後從103 ping 192.168.122.101不通,但是可以用ssh
[root@node-103 ~]#ssh 192.168.122.101
Last login: Fri Oct 18 11:04:17 2019 from 172.18.43.4
Waring …,if you not root,Please get out!
[root@node-101 ~]#iptables -t filter -vnxL INPUT --line
Chain INPUT (policy ACCEPT 229 packets, 17430 bytes)
num pkts bytes target prot opt in out source destination
1 74 6216 REJECT icmp – * * 192.168.122.103 0.0.0.0/0 reject-with icmp-port-unreachable
[root@node-101 ~]#iptables -S
-A INPUT -s 192.168.122.103/32 -p icmp -j REJECT --reject-with icmp-port-unreachable
可以查看當前的規則指令。

1.3.2 刪除規則

此刻,如果我們想要刪除filter表中INPUT中的一條規則,該怎麼做呢?
有兩種辦法
方法一:根據規則的編號去刪除規則
iptables --line -vnL INPUT //查看INPUT鏈。
比如像刪除第二條規則,可用iptables -t filter -D INPUT 3 //-t filter是默認值,可以不寫
刪除規則用-D,-D INPUT表示刪除INPUT鏈中的規則,-D INPUT 3表示刪除第三條規則。
方法二:根據具體的匹配條件與動作刪除規則
[root@node-101 ~]#iptables -S
-A INPUT -s 192.168.122.103/32 -p icmp -j REJECT //根據查詢到的指定,進行匹配刪除
[root@node-101 ~]#iptables -D INPUT -s 192.168.122.103 -p icmp -j REJECT
[root@node-101 ~]#iptables -vnxL INPUT
Chain INPUT (policy ACCEPT 102 packets, 7775 bytes)
pkts bytes target prot opt in out source destination
查看INPUT鏈規則已經沒有了。
而刪除指定表中某條鏈中的所有規則的命令,我們在一開始就使用到了,就是"iptables -t 表名 -F 鏈名"
-F選項爲flush之意,即沖刷指定的鏈,即刪除指定鏈中的所有規則,但是注意,此操作相當於刪除操作,在沒有保存iptables規則的情況下,請慎用。
其實,-F選項不僅僅能清空指定鏈上的規則,其實它還能清空整個表中所有鏈上的規則,不指定鏈名,只指定表名即可刪除表中的所有規則,命令如下
iptables -t 表名 -F
不過再次強調,在沒有保存iptables規則時,請勿隨便清空鏈或者表中的規則,除非你明白你在幹什麼。

1.3.3 修改規則

-R選項表示修改指定的鏈,使用-R 需要把原來定義規則的語句重新寫,跟定義一個新的規則一樣,只不過是把原來插入-I的選項,變成了-R,
後面要跟具體詳細的規則。-R其實相當於把原來的規則先刪掉,然後在相同的位置,添加新的完整的規則。
使用-R選項修改規則時,必須指明規則原本的匹配條件,那麼我們則可以理解爲,只能通過-R選項修改規則對應的動作了,所以我覺得,如果你想要修改某條規則,還不如先將這條規則刪除,然後在同樣位置再插入一條新規則
其實,我們還可以修改指定鏈的"默認策略"。iptables -P INPUT DROP //修改默認規則。默認時允許,現在改成拒絕。
但是強烈建議不要這麼做。因爲如果清空了規則,那麼遠程的ssh就再也連不上了,如果想要實現相同的效果,可以在最後一行
添加默認的拒絕規則,那麼以後每次添加規則用-I INPUT #N指定插入位置即可。

1.3.4 保存規則

在默認的情況下,我們對"防火牆"所做出的修改都是"臨時的",換句話說就是,當重啓iptables服務或者重啓服務器以後,我們平常添加的規則或者對規則所做出的修改都將消失,爲了防止這種情況的發生,我們需要將規則"保存"。
centos7與centos6中的情況稍微有些不同,我們先說centos6中怎樣保存iptables規則
centos6中,使用"service iptables save"命令即可保存規則,規則默認保存在/etc/sysconfig/iptables文件中,如果你剛剛安裝完centos6,在剛開始使用iptables時,會發現filter表中會有一些默認的規則,這些默認提供的規則
其實就保存在/etc/sysconfig/iptables中
當我們對規則進行了修改以後,如果想要修改永久生效,必須使用service iptables save保存規則,當然,如果你誤操作了規則,但是並沒有保存,那麼使用service iptables restart命令重啓iptables以後,規則會再次回到上次保存/etc/sysconfig/iptables文件時的模樣
centos7中,已經不再使用init風格的腳本啓動服務,而是使用unit文件,所以,在centos7中已經不能再使用類似service iptables start這樣的命令了,所以service iptables save也無法執行,同時,在centos7中,使用firewall替代了原來的iptables service,不過不用擔心,我們只要通過yum源安裝iptables與iptables-services即可(iptables一般會被默認安裝,但是iptables-services在centos7中一般不會被默認安裝),在centos7中安裝完iptables-services後,即可像centos6中一樣,通過service iptables save命令保存規則了,規則同樣保存在/etc/sysconfig/iptables文件中。

#配置好yum源以後安裝iptables-service
# yum install -y iptables-services
#停止firewalld
# systemctl stop firewalld
#禁止firewalld自動啓動
# systemctl disable firewalld
#啓動iptables
# systemctl start iptables
#將iptables設置爲開機自動啓動,以後即可通過iptables-service控制iptables服務
# systemctl enable iptables

還可以使用另一種方法保存iptables規則,就是使用iptables-save命令
使用iptables-save並不能保存當前的iptables規則,但是可以將當前的iptables規則以"保存後的格式"輸出到屏幕上。
所以,我們可以使用iptables-save命令,再配合重定向,將規則重定向到/etc/sysconfig/iptables文件中即可。
iptables-save > /etc/sysconfig/iptables
我們也可以將/etc/sysconfig/iptables中的規則重新載入爲當前的iptables規則,但是注意,未保存入/etc/sysconfig/iptables文件中的修改將會丟失或者被覆蓋。
使用iptables-restore命令可以從指定文件中重載規則,示例如下
iptables-restore < /etc/sysconfig/iptables
再次提醒:重載規則時,現有規則將會被覆蓋

1.3.5 命令小結

命令語法:iptables -t 表名 -A 鏈名 匹配條件 -j 動作
示例:iptables -t filter -A INPUT -s 192.168.1.146 -j DROP
命令語法:iptables -t 表名 -I 鏈名 匹配條件 -j 動作
示例:iptables -t filter -I INPUT -s 192.168.1.146 -j ACCEPT
命令語法:iptables -t 表名 -I 鏈名 規則序號 匹配條件 -j 動作
示例:iptables -t filter -I INPUT 5 -s 192.168.1.146 -j REJECT
命令語法:iptables -t 表名 -P 鏈名 動作
示例:iptables -t filter -P FORWARD ACCEPT
#刪除規則
命令語法:iptables -t 表名 -D 鏈名 規則序號
示例:iptables -t filter -D INPUT 3
命令語法:iptables -t 表名 -F 鏈名
示例:iptables -t filter -F INPUT
命令語法:iptables -t 表名 -F
示例:iptables -t filter -F
#修改規則
命令語法:iptables -t 表名 -R 鏈名 規則序號 規則原本的匹配條件 -j 動作
示例:iptables -t filter -R INPUT 3 -s 192.168.1.146 -j ACCEPT
命令語法:iptables -t 表名 -P 鏈名 動作
示例:iptables -t filter -P FORWARD ACCEPT
#保存規則
service iptables save
iptables-save > /etc/sysconfig/iptables
iptables-restore < /etc/sysconfig/iptables

1.4 iptables匹配條件

1.4.1 目標IP地址

除了可以通過-s選項指定源地址作爲匹配條件,我們還可以使用-d選項指定"目標地址"作爲匹配條件。
源地址表示報文從哪裏來,目標地址表示報文要到哪裏去。
除了127.0.0.1迴環地址以外,當前機器有兩個IP地址,IP如下。
iptables詳解(4):iptables匹配條件總結之一
假設,我們想要拒絕146主機發來的報文,但是我們只想拒絕146向156這個IP發送報文,並不想要防止146向101這個IP發送報文,我們就可以指定目標地址作爲匹配條件,示例如下。
iptables詳解(4):iptables匹配條件總結之一
上例表示只丟棄從146發往156這個IP的報文,但是146發往101這個IP的報文並不會被丟棄,如果我們不指定任何目標地址,則目標地址默認爲0.0.0.0/0,同理,如果我們不指定源地址,源地址默認爲0.0.0.0/0,0.0.0.0/0表示所有IP,示例如下。
iptables詳解(4):iptables匹配條件總結之一
上例表示,所有IP發送往101的報文都將被丟棄。
與-s選項一樣,-d選項也可以使用"歎號"進行取反,也能夠同時指定多個IP地址,使用"逗號"隔開即可。
但是請注意,不管是-s選項還是-d選項,取反操作與同時指定多個IP的操作不能同時使用。
需要明確的一點就是:當一條規則中有多個匹配條件時,這多個匹配條件之間,默認存在"與"的關係。
說白了就是,當一條規則中存在多個匹配條件時,報文必須同時滿足這些條件,纔算做被規則匹配。
我們除了能夠使用-s選項和-d選項匹配源IP與目標IP以外,還能夠匹配"源端口"與"目標端口"

1.4.2 協議類型

我們可以使用-p選項,指定需要匹配的報文的協議類型
假設,我們只想要拒絕來自203的tcp類型的請求,那麼可以進行如下設置

[root@node-101 ~]#iptables -t filter -I INPUT -s 172.18.43.4 -j ACCEPT //把自己的windows加入允許
iptables -t filter -A INPUT -p tcp -j REJECT   //拒絕所有的tcp協議連接
[root@node-102 ~]#ping 192.168.122.101          //能ping通
PING 192.168.122.101 (192.168.122.101) 56(84) bytes of data.
64 bytes from 192.168.122.101: icmp_seq=1 ttl=64 time=0.316 ms
[root@node-102 ~]#ssh 192.168.122.101
ssh: connect to host 192.168.122.101 port 22: Connection refused    //ssh連接失敗

那麼,-p選項都支持匹配哪些協議呢?我們總結一下
centos6中,-p選項支持如下協議類型
tcp,udp,udplite,icpm,esp,ah,sctp
udp-lite ,傳統的udp協議傳輸會對載荷(Payload)進行完整的校驗的,如果其中的一些位錯了,那麼整個數據包可能被
丟棄,但是udp-lite定義了是否需要對載荷進行校驗,或者校驗縮少位是由用戶控制,可以用於一些對應用層對輕微差錯不特別
敏感的情況,比如視頻直播。
esp:封裝安全載荷 stcp SCTP是一種面向消息的傳輸協議
tcp, udp, udplite, icmp, icmpv6,esp, ah, sctp, mh
當不使用-p指定協議類型時,默認表示所有類型的協議都會被匹配到,與使用-p all的效果相同

1.4.3 網卡接口

我們再來認識一個新的匹配條件,當本機有多個網卡時,我們可以使用 -i 選項去匹配報文是通過哪塊網卡流入本機的
假設想要拒絕由網卡eth1流入的ping請求報文,則可以進行如下設置

[root@node-101 ~]#iptables -t filter -A INPUT -i eth1 -p icmp -j REJECT
[root@node-102 ~]#ping 172.18.43.101
PING 172.18.43.101 (172.18.43.101) 56(84) bytes of data.
From 172.18.43.101 icmp_seq=1 Destination Port Unreachable    //172地址過來已經不通
[root@node-101 ~]#tcpdump -i eth1 -p icmp -vv     //對eth1進行抓包分析
172.18.43.103 > node-101.centos76.com: ICMP echo request, id 15237, seq 53, length 64
14:50:47.989193 IP (tos 0xc0, ttl 64, id 41757, offset 0, flags [none], proto ICMP (1), length 112)
node-101.centos76.com > 172.18.43.103: ICMP node-101.centos76.com protocol 1 port 45978 unreachable, length 92
IP (tos 0x0, ttl 64, id 16569, offset 0, flags [DF], proto ICMP (1), length 84)
#可以看到收到了報文,但是迴應的是unreachable,且每次迴應都是隨機端口。如果在102機器指定用192地址網卡ping呢?
[root@node-103 ~]#ping 172.18.43.101 -I eth0
PING 172.18.43.101 (172.18.43.101) from 192.168.122.103 eth0: 56(84) bytes of data.  //仍是不通。抓包無數據
[root@node-102 ~]#ping 192.168.122.101
PING 192.168.122.101 (192.168.122.101) 56(84) bytes of data.
64 bytes from 192.168.122.101: icmp_seq=1 ttl=64 time=0.284 ms
64 bytes from 192.168.122.101: icmp_seq=2 ttl=64 time=0.250 ms   //從eth0 192地址過來還是通的

以上設置還有個問題,由於eth1是訪問公網的ip,所以ping 公網也是不通。可以想辦法,自己能ping通別人,但是外部機器無法ping進來
既然-i選項是用於判斷報文是從哪個網卡流入的,那麼,-i選項只能用於上圖中的PREROUTING鏈、INPUT鏈、FORWARD鏈,這是-i選項的特殊性,
因爲它只是用於判斷報文是從哪個網卡流入的,所以只能"數據流入流向"的鏈中與FORWARD鏈中存在,而"數據發出流向"經過的鏈中,
是不可能使用-i選項的,OTPUT鏈與POSTROUTING鏈,他們都不能使用-i選項。
當主機有多塊網卡時,可以使用-o選項,匹配報文將由哪塊網卡流出,沒錯,-o選項與-i選項是相對的,-i選項用於匹配報文從哪個網卡流入,-o選項用於匹配報文將從哪個網卡流出。
聰明如你,一定想到了,-i選項只能用於PREROUTING鏈、INPUT鏈、FORWARD鏈,那麼-o選項只能用於FORWARD鏈、OUTPUT鏈、POSTROUTING鏈。
因爲-o選項是用於匹配報文將由哪個網卡"流出"的,所以與上圖中的"數據進入流向"中的鏈沒有任何緣分,所以,-o選項只能用於FORWARD鏈、OUTPUT鏈、POSTROUTING鏈中。
看來,FORWARD鏈屬於"中立國",它能同時使用-i選項與-o選項。

1.4.4 擴展匹配條件:

我們知道,sshd服務的默認端口爲22,當我們使用ssh工具遠程連接主機時,默認會連接服務端的22號端口,假設,我們現在想要使用iptables設置一條規則,拒絕來自192.168.1.146的ssh請求,
我們就可以拒絕146上的報文能夠發往本機的22號端口,這個時候,就需要用到"目標端口"選項。
使用選項–dport可以匹配報文的目標端口,–dport意爲destination-port,即表示目標端口。

[root@node-101 ~]#iptables -t filter -A INPUT -s 192.168.122.103 -p tcp -m tcp --dport 22 -j REJECT
[root@node-102 ~]#ssh 192.168.122.101
Last login: Fri Oct 18 14:19:25 2019 from 172.18.43.4
 Waring ...,if you not root,Please get out! 
[root@node-101 ~]#
[root@node-103 ~]#ssh 192.168.122.101
ssh: connect to host 192.168.122.101 port 22: Connection refused   //拒絕了103的ssh連接

注意,與之前的選項不同,–dport前有兩條"橫槓",而且,使用–dport選項時,必須事先指定了使用哪種協議,即必須先使用-p選項,示例如下
我們就使用了擴展匹配條件–dport,指定了匹配報文的目標端口,如果外來報文的目標端口爲本機的22號端口(ssh默認端口),則拒絕之,而在使用–dport之前,我們使用-m選項,指定了對應
的擴展模塊爲tcp
注意,-p tcp與 -m tcp並不衝突,-p用於匹配報文的協議,-m 用於指定擴展模塊的名稱,正好,這個擴展模塊也叫tcp。
當使用-p選項指定了報文的協議時,如果在沒有使用-m指定對應的擴展模塊名稱的情況下,使用了擴展匹配條件, iptables默認會調用與-p選項對應的協議名稱相同的模塊。
上例中,我們使用-p選項指定了協議名稱,使用擴展匹配條件–dport指定了目標端口,在使用擴展匹配條件的時候,如果沒有使用-m指定使用哪個擴展模塊,iptables會默認使用"-m 協議名",而協議名就是-p選項對應的協議名,上例中,-p 對應的值爲tcp,所以默認調用的擴展模塊就爲-m tcp,如果-p對應的值爲udp,那麼默認調用的擴展模塊就爲-m udp。
所以,上例中,其實"隱式"的指定了擴展模塊,只是沒有表現出來罷了
使用–sport可以判斷報文是否從指定的端口發出,即匹配報文的源端口是否與指定的端口一致,–sport表示source-port,即表示源端口之意
擴展匹配條件是可以取反的,同樣是使用"!"進行取反,比如 “! --dport 22”,表示目標端口不是22的報文將會被匹配到
藉助tcp擴展模塊的–sport或者–dport都可以指定一個連續的端口範圍,但是無法同時指定多個離散的、不連續的端口,如果想要同時指定多個離散的端口,需要藉助另一個擴展模塊,"multiport"模塊。
我們可以使用multiport模塊的–sports擴展條件同時指定多個離散的源端口。
我們可以使用multiport模塊的–dports擴展條件同時指定多個離散的目標端口。
"-m multiport --dports 22,36,80"表示使用了multiport擴展模塊的–dports擴展條件,以同時指定了多個離散的端口,每個端口之間用逗號隔開
其實,使用multiport模塊的–sports與–dpors時,也可以指定連續的端口範圍,並且能夠在指定連續的端口範圍的同時,指定離散的端口號

[root@node-101 ~]#iptables -t filter -A INPUT -p tcp -s 192.168.122.102 -m multiport --dports 22,23,80:88 -j REJECT 
[root@node-101 ~]#iptables -vnL INPUT 3 --line
3       12  2560 REJECT     tcp  --  *      *       192.168.122.102      0.0.0.0/0            multiport dports 22,23,80:88 reject-with icmp-port-unreachable
[root@node-102 ~]#ssh 192.168.122.101
ssh: connect to host 192.168.122.101 port 22: Connection refused  //ssh拒絕
[root@node-102 ~]#curl 192.168.122.101
curl: (7) Failed connect to 192.168.122.101:80; Connection refused //80拒絕
[root@node-102 ~]#telnet 192.168.122.101
Trying 192.168.122.101...
telnet: connect to address 192.168.122.101: Connection refused     //23拒絕
[root@node-103 ~]#telnet 192.168.122.101
Trying 192.168.122.101...
Connected to 192.168.122.101.
Escape character is '^]'.
Kernel 3.10.0-957.el7.x86_64 on an x86_64
node-101 login: 

上例中的命令表示拒絕來自192.168.1.146的tcp報文訪問當前主機的22號端口以及80到88之間的所有端口號,是不是很方便?有沒有很靈活?
不過需要注意,multiport擴展只能用於tcp協議與udp協議,即配合-p tcp或者-p udp使用。

1.4.5 小結

基礎用法

-s用於匹配報文的源地址,可以同時指定多個源地址,每個IP之間用逗號隔開,也可以指定爲一個網段。
#####示例如下

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之間用逗號隔開,也可以指定爲一個網段。
#####示例如下

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)。
#示例如下

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鏈中不能使用此選項

#示例如下
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鏈中不能使用此選項。

#示例如下
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協議報文的目標端口,可以使用冒號指定一個連續的端口範圍
#示例如下

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

常用的擴展匹配條件如下:
-p tcp -m multiport --sports 用於匹配報文的源端口,可以指定離散的多個端口號,端口之間用"逗號"隔開
-p udp -m multiport --dports 用於匹配報文的目標端口,可以指定離散的多個端口號,端口之間用"逗號"隔開
#示例如下

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

1.5 常用擴展模塊

1.5.1 iprange擴展模塊

之前我們已經總結過,在不使用任何擴展模塊的情況下,使用-s選項或者-d選項即可匹配報文的源地址與目標地址,
而且在指定IP地址時,可以同時指定多個IP地址,每個IP用"逗號"隔開,但是,-s選項與-d選項並不能一次性的指定一段連續的IP地址範圍,如果我們需要指定一段連續的IP地址範圍,可以使用iprange擴展模塊。
使用iprange擴展模塊可以指定"一段連續的IP地址範圍",用於匹配報文的源地址或者目標地址。
iprange擴展模塊中有兩個擴展匹配條件可以使用
–src-range
–dst-range
沒錯,見名知意,上述兩個選項分別用於匹配報文的源地址所在範圍與目標地址所在範圍。

iptables -t filter -A INPUT -m iprange --src-range 192.168.122.200-192.168.122.254 -j DROP

1.5.2 string擴展模塊

使用string擴展模塊,可以指定要匹配的字符串,如果報文中包含對應的字符串,則符合匹配條件。
比如,如果報文中包含字符"OOXX",我們就丟棄當前報文。
首先,我們在IP爲101的主機上啓動http服務,然後在默認的頁面目錄中添加兩個頁面,頁面中的內容分別爲"OOXX"和"Hello World",如下圖所示,在沒有配置任何規則時,103主機可以正常訪問146主機上的這兩個頁面。

[root@node-101 ~]#echo "hello world " > /var/www/html/index.html
[root@node-101 ~]#echo "abc OOXX string  " > /var/www/html/index2.html
[root@node-103 ~]#curl 192.168.122.101
hello world 
[root@node-103 ~]#curl 192.168.122.101/index2.html
abc OOXX string  
[root@node-103 ~]#iptables -t filter -A INPUT -m string --algo bm --string "OOXX" -j REJECT   //注意在103設置規則
[root@node-103 ~]#curl 192.168.122.101
hello world 
[root@node-103 ~]#curl 192.168.122.101/index2.html   //卡住了
curl: (56) Recv failure: Connection reset by peer    //黃花菜都涼了以後。。才報錯

那麼,我們想要達到的目的是,如果報文中包含"OOXX"字符,我們就拒絕報文進入本機,所以,我們可以在126上進行如下配置。
上圖中,’-m string’表示使用string模塊,’–algo bm’表示使用bm算法去匹配指定的字符串,’ --string “OOXX” '則表示我們想要匹配的字符串爲"OOXX"
設置完上圖中的規則後,由於index.html中包含"OOXX"字符串,所以,146的迴應報文無法通過126的INPUT鏈,所以無法獲取到頁面對應的內容。
那麼,我們來總結一下string模塊的常用選項
–algo:用於指定匹配算法,可選的算法有bm與kmp,此選項爲必須選項,我們不用糾結於選擇哪個算法,但是我們必須指定一個。
–string:用於指定需要匹配的字符串。

1.5.3 time擴展模塊

我們可以通過time擴展模塊,根據時間段區匹配報文,如果報文到達的時間在指定的時間範圍以內,則符合匹配條件。
比如,“我想要自我約束,下午13點到16:31不能看網頁”,多麼殘忍的規定,如果你想要這樣定義,可以嘗試使用如下規則

[root@node-103 ~]#iptables -t filter -A OUTPUT -p tcp -m multiport --dports 80,443 -m time --timestart 05:00:00 --timestop 08:31:00 -j REJECT 
[root@node-103 ~]#date
Fri Oct 18 16:29:55 CST 2019       //主意啊規則中定義的時間是UTC時間,所以要做時區轉換
[root@node-103 ~]#curl 192.168.122.101
curl: (7) Failed connect to 192.168.122.101:80; Connection refused
[root@node-103 ~]#date
Fri Oct 18 16:32:04 CST 2019       //16:32對應UTC時間的08:32
[root@node-103 ~]#curl 192.168.122.101
hello world 
-m time --monthdays 22,23  //每月的22,23號
-m time --weekdays 5 //每週五
-m --datestart 2019-10-18 --datestop 1029-10-30  

"-m time"表示使用time擴展模塊,–timestart選項用於指定起始時間,–timestop選項用於指定結束時間。控制不上網是作用在output鏈,
及不讓出去。

1.5.4 connlimit模塊

使用connlimit擴展模塊,可以限制每個IP地址同時鏈接到server端的鏈接數量,注意:我們不用指定IP,其默認就是針對"每個客戶端IP",即對單IP的併發連接數限制。
比如,我們想要限制,每個IP地址最多隻能佔用兩個ssh鏈接遠程到server端,我們則可以進行如下限制。

[root@node-101 ~]#iptables -t filter -A INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
[root@node-103 ~]#ssh 192.168.122.101
ssh: connect to host 192.168.122.101 port 22: Connection refused    //第三個連接,被拒絕

使用"-m connlimit"指定使用connlimit擴展,使用"–connlimit-above 2"表示限制每個IP的鏈接數量上限爲2,再配合-p tcp --dport 22,即表示限制每個客戶端IP的ssh併發鏈接數量不能高於2。
剛纔說過,–connlimit-above默認表示限制"每個IP"的鏈接數量,其實,我們還可以配合–connlimit-mask選項,去限制"某類網段"的鏈接數量,示例如下

1.5.5 limit擴展模塊

剛纔認識了connlimit模塊,現在來認識一下limit模塊。
connlimit模塊是對連接數量進行限制的,limit模塊是對"報文到達速率"進行限制的。
用大白話說就是,如果我想要限制單位時間內流入的包的數量,就能用limit模塊。
我們可以以秒爲單位進行限制,也可以以分鐘、小時、天作爲單位進行限制。
比如,限制每秒中最多流入3個包,或者限制每分鐘最多流入30個包,都可以。
那麼,我們來看一個最簡單的示例,假設,我們想要限制,外部主機對本機進行ping操作時,本機最多每6秒中放行一個ping包,那麼,我們可以進行如下設置(注意,只進行如下設置有可能無法實現限制功能,請看完後面的內容)

[root@node-101 ~]#iptables -t filter -A INPUT -p icmp -m limit --limit 10/minute -j ACCEPT

實測發現不管用,這是因爲該規則動作是ACCEPT,然後沒有被匹配到的會被默認的規則匹配,即允許放行。所以要在此規則後緊跟默認的拒絕規則。

root@node-101 ~]#iptables -t filter -A INPUT -p icmp -m limit --limit 10/minute -j ACCEPT 
[root@node-101 ~]#iptables -t filter  -A INPUT -p icmp -j REJECT 

兩條規則配合纔可以生效。另外還有指定默認初始值,即前多少個不做限制。如果通過一個機器的多個終端同時ping該主機,服務端則由的是按IP計算,由的終端可能會很久才能收到應答報文或者乾脆收不到。

1.5.6 命令總結

iprange模塊
包含的擴展匹配條件如下
–src-range:指定連續的源地址範圍
–dst-range:指定連續的目標地址範圍
#示例

iptables -t filter -I INPUT -m iprange --src-range 192.168.1.127-192.168.1.146 -j DROP
iptables -t filter -I OUTPUT -m iprange --dst-range 192.168.1.127-192.168.1.146 -j DROP
iptables -t filter -I INPUT -m iprange ! --src-range 192.168.1.127-192.168.1.146 -j DROP

string模塊
常用擴展匹配條件如下
–algo:指定對應的匹配算法,可用算法爲bm、kmp,此選項爲必需選項。
–string:指定需要匹配的字符串
#示例

iptables -t filter -I INPUT -p tcp --sport 80 -m string --algo bm --string "OOXX" -j REJECT
iptables -t filter -I INPUT -p tcp --sport 80 -m string --algo bm --string "OOXX" -j REJECT

time模塊
常用擴展匹配條件如下
–timestart:用於指定時間範圍的開始時間,不可取反
–timestop:用於指定時間範圍的結束時間,不可取反
–weekdays:用於指定"星期幾",可取反
–monthdays:用於指定"幾號",可取反
–datestart:用於指定日期範圍的開始日期,不可取反
–datestop:用於指定日期範圍的結束時間,不可取反
#示例

iptables -t filter -I OUTPUT -p tcp --dport 80 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 443 -m time --timestart 09:00:00 --timestop 19:00:00 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --weekdays 6,7 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --monthdays 22,23 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time ! --monthdays 22,23 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --timestart 09:00:00 --timestop 18:00:00 --weekdays 6,7 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --weekdays 5 --monthdays 22,23,24,25,26,27,28 -j REJECT
iptables -t filter -I OUTPUT -p tcp --dport 80  -m time --datestart 2017-12-24 --datestop 2017-12-27 -j REJECT

connlimit 模塊
常用的擴展匹配條件如下
–connlimit-above:單獨使用此選項時,表示限制每個IP的鏈接數量。
–connlimit-mask:此選項不能單獨使用,在使用–connlimit-above選項時,配合此選項,則可以針對"某類IP段內的一定數量的IP"進行連接數量的限制,如果不明白可以參考上文的詳細解釋。
#示例

iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 2 -j REJECT
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 20 --connlimit-mask 24 -j REJECT
iptables -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 10 --connlimit-mask 27 -j REJECT

limit模塊
常用的擴展匹配條件如下
–limit-burst:類比"令牌桶"算法,此選項用於指定令牌桶中令牌的最大數量,上文中已經詳細的描述了"令牌桶"的概念,方便回顧。
–limit:類比"令牌桶"算法,此選項用於指定令牌桶中生成新令牌的頻率,可用時間單位有second、minute 、hour、day。
#示例 #注意,如下兩條規則需配合使用,具體原因上文已經解釋過,忘記了可以回顧。

iptables -t filter -I INPUT -p icmp -m limit --limit-burst 3 --limit 10/minute -j ACCEPT
iptables -t filter -A INPUT -p icmp -j REJECT

1.6 iptables擴展匹配條件之’–tcp-flags’

見名知義,"–tcp-flags"指的就是tcp頭中的標誌位,看來,在使用iptables時,我們可以通過此擴展匹配條件,去匹配tcp報文的頭部的標識位,然後根據標識位的實際情況實現訪問控制的功能。
發起連接請求,tcp頭的標誌位中,只有SYN位被標識爲1,其他標誌位均爲0
服務端迴應剛纔的請求,將自己的tcp頭的SYN標誌位也設置爲1,同時將ACK標誌位也設置爲1
用於匹配報文tcp頭部的標誌位,“SYN,ACK,FIN,RST,URG,PSH SYN"是什麼意思呢?這串字符就是用於配置我們要匹配的標誌位的,
我們需要匹配報文tcp頭中的6個標誌位,這6個標誌位分別爲爲"SYN、ACK、FIN、RST、URG、PSH”,我們可以把這一部分理解成需要匹配的標誌位列表
–tcp-flags SYN,ACK,FIN,RST SYN 表示要檢查的標誌位爲SYN,ACK,FIN,RST四個,其中SYN必須爲1,餘下的必須爲0
–tcp-flags ALL ALL //全部位1
–tcp_flags ALL NONE //全部位0 .這兩種其實是錯誤,正常情況沒有這兩種情況,所有這兩種表示錯誤。
tcp擴展模塊還爲我們專門提供了一個選項,可以匹配上文中提到的"第一次握手",那就是–syn選項
使用"–syn"選項相當於使用"–tcp-flags SYN,RST,ACK,FIN SYN",也就是說,可以使用"–syn"選項去匹配tcp新建連接的請求報文。

小結

tcp擴展模塊常用的擴展匹配條件如下:
–sport
用於匹配tcp協議報文的源端口,可以使用冒號指定一個連續的端口範圍。
#示例

iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp --sport 22 -j REJECT
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp --sport 22:25 -j REJECT
iptables -t filter -I OUTPUT -d 192.168.1.146 -p tcp -m tcp ! --sport 22 -j ACCEPT

–dport
用於匹配tcp協議報文的目標端口,可以使用冒號指定一個連續的端口範圍
#示例

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

-tcp-flags
用於匹配報文的tcp頭的標誌位
#示例

iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN -j REJECT
iptables -t filter -I OUTPUT -p tcp -m tcp --sport 22 --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN,ACK -j REJECT
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --tcp-flags ALL SYN -j REJECT
iptables -t filter -I OUTPUT -p tcp -m tcp --sport 22 --tcp-flags ALL SYN,ACK -j REJECT

–syn
用於匹配tcp新建連接的請求報文,相當於使用"–tcp-flags SYN,RST,ACK,FIN SYN"
#示例
iptables -t filter -I INPUT -p tcp -m tcp --dport 22 --syn -j REJECT

1.7 iptables擴展之udp擴展與icmp擴展

1.7.1 udp擴展

我們先來說說udp擴展模塊,這個擴展模塊中能用的匹配條件比較少,只有兩個,就是–sport與–dport,即匹配報文的源端口與目標端口。
沒錯,tcp模塊中也有這兩個選項,名稱都一模一樣。
只不過udp擴展模塊的–sport與–dport是用於匹配UDP協議報文的源端口與目標端口,比如,放行samba服務的137與138這兩個UDP端口,示例如下
iptables詳解(7):iptables擴展之udp擴展與icmp擴展
前文說明過,當使用擴展匹配條件時,如果未指定擴展模塊,iptables會默認調用與"-p"對應的協議名稱相同的模塊,所以,當使用"-p udp"時,可以省略"-m udp",示例如下。
udp擴展中的–sport與–dport同樣支持指定一個連續的端口範圍
但是udp中的–sport與–dport也只能指定連續的端口範圍,並不能一次性指定多個離散的端口,沒錯,聰明如你一定想到,使用之前總結過的multiport擴展模塊,即可指定多個離散的UDP端口,

1.7.2 icmp擴展

最常用的tcp擴展、udp擴展已經總結完畢,現在聊聊icmp擴展,沒錯,看到icmp,你肯定就想到了ping命令,因爲ping命令使用的就是icmp協議。
ICMP協議的全稱爲Internet Control Message Protocol,翻譯爲互聯網控制報文協議,它主要用於探測網絡上的主機是否可用,目標是否可達,網絡是否通暢,路由是否可用等
我們平常使用ping命令ping某主機時,如果主機可達,對應主機會對我們的ping請求做出迴應(此處不考慮禁ping等情況),也就是說,我們發出ping請求,對方迴應ping請求,雖然ping請求報文與ping迴應報文都屬於ICMP類型的報文,但是如果在概念上細分的話,它們所屬的類型還是不同的,我們發出的ping請求屬於類型8的icmp報文,而對方主機的ping迴應報文則屬於類型0的icmp報文,
ping迴應報文,它的type爲0,code也爲0,從上圖可以看出,ping迴應報文屬於查詢類(query)的ICMP報文,從大類上分,ICMP報文還能分爲查詢類與錯誤類兩大類,目標不可達類的icmp報文則屬於錯誤類報文。
而我們發出的ping請求報文對應的type爲8,code爲0

[root@node-101 ~]#iptables -t filter -A INPUT -p icmp --icmp-type 8/0 -j REJECT 

使用"-m icmp"表示使用icmp擴展使用了"-p icmp",所以"-m icmp"可以省略,使用"–icmp-type"選項表示根據具體的type與code去匹配對應的icmp報文,而上圖中的"–icmp-type 8/0"表示icmp報文的type爲8,code爲0纔會被匹配到,也就是隻有ping請求類型的報文才能被匹配到,所以,別人對我們發起的ping請求將會被拒絕通過防火牆,而我們之所以能夠ping通別人,是因爲別人迴應我們的報文的icmp type爲0,code也爲0,所以無法被上述規則匹配到,所以我們可以看到別人迴應我們的信息
因爲type爲8的類型下只有一個code爲0的類型,所以我們可以省略對應的code
除了能夠使用對應type/code匹配到具體類型的icmp報文以外,我們還能用icmp報文的描述名稱去匹配對應類型的報文
使用的 --icmp-type "echo-request"與 --icmp-type 8/0的效果完全相同.

小結

udp擴展
常用的擴展匹配條件
–sport:匹配udp報文的源地址
–dport:匹配udp報文的目標地址
#示例

iptables -t filter -I INPUT -p udp -m udp --dport 137 -j ACCEPT
iptables -t filter -I INPUT -p udp -m udp --dport 137:157 -j ACCEPT

icmp擴展
常用的擴展匹配條件
–icmp-type:匹配icmp報文的具體類型
#示例

iptables -t filter -I INPUT -p icmp -m icmp --icmp-type 8/0 -j REJECT
iptables -t filter -I INPUT -p icmp --icmp-type 8 -j REJECT
iptables -t filter -I OUTPUT -p icmp -m icmp --icmp-type 0/0 -j REJECT
iptables -t filter -I OUTPUT -p icmp --icmp-type 0 -j REJECT
iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT

1.8 iptables擴展模塊之state擴展

從字面上理解,state可以譯爲狀態,但是我們也可以用一個高大上的詞去解釋它,state模塊可以讓iptables實現"連接追蹤"機制。
那麼,既然是"連接追蹤",則必然要有"連接"。
咱們就來聊聊什麼是連接吧,一說到連接,你可能會下意識的想到tcp連接,但是,對於state模塊而言的"連接"並不能與tcp的"連接"畫等號,在TCP/IP協議簇中,UDP和ICMP是沒有所謂的連接的,但是對於state模塊來說,tcp報文、udp報文、icmp報文都是有連接狀態的,我們可以這樣認爲,對於state模塊而言,只要兩臺機器在"你來我往"的通信,就算建立起了連接
對於state模塊的連接而言,“連接"其中的報文可以分爲5種狀態,報文狀態可以爲NEW、ESTABLISHED、RELATED、INVALID、UNTRACKED
NEW:連接中的第一個包,狀態就是NEW,我們可以理解爲新連接的第一個包的狀態爲NEW。
ESTABLISHED:我們可以把NEW狀態包後面的包的狀態理解爲ESTABLISHED,表示連接已建立。
RELATED:從字面上理解RELATED譯爲關係,但是這樣仍然不容易理解,我們舉個例子。
比如FTP服務,FTP服務端會建立兩個進程,一個命令進程,一個數據進程。
命令進程負責服務端與客戶端之間的命令傳輸(我們可以把這個傳輸過程理解成state中所謂的一個"連接”,暫稱爲"命令連接")。
數據進程負責服務端與客戶端之間的數據傳輸 ( 我們把這個過程暫稱爲"數據連接" )。
但是具體傳輸哪些數據,是由命令去控制的,所以,"數據連接"中的報文與"命令連接"是有"關係"的。
那麼,"數據連接"中的報文可能就是RELATED狀態,因爲這些報文與"命令連接"中的報文有關係。
(注:如果想要對ftp進行連接追蹤,需要單獨加載對應的內核模塊nf_conntrack_ftp,如果想要自動加載,可以配置/etc/sysconfig/iptables-config文件)
INVALID:如果一個包沒有辦法被識別,或者這個包沒有任何狀態,那麼這個包的狀態就是INVALID,我們可以主動屏蔽狀態爲INVALID的報文
UNTRACKED:報文的狀態爲untracked時,表示報文未被追蹤,當報文的狀態爲Untracked時通常表示無法找到相關的連接。
剛纔舉例中的問題即可使用state擴展模塊解決,我們只要放行狀態爲ESTABLISHED的報文即可,因爲如果報文的狀態爲ESTABLISHED,那麼報文肯定是之前發出的報文的迴應,如果你還不放心,可以將狀態爲RELATED或ESTABLISHED的報文都放行,這樣,就表示只有迴應我們的報文能夠通過防火牆,如果是別人主動發送過來的新的報文,則無法通過防火牆,示例如下

[root@node-101 ~]#iptables -t filter -S INPUT
-P INPUT ACCEPT
-A INPUT -s 172.18.43.4/32 -p tcp -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -j REJECT --reject-with icmp-port-unreachable

針對tcp連接,實現所有的外來訪問都被拒絕,主動訪問的除外。

1.9 自定義鏈

你可能會問,iptables的默認鏈就已經能夠滿足我們了,爲什麼還需要自定義鏈呢?
原因如下:
當默認鏈中的規則非常多時,不方便我們管理。
想象一下,如果INPUT鏈中存放了200條規則,這200條規則有針對httpd服務的,有針對sshd服務的,有針對私網IP的,有針對公網IP的,假如,我們突然想要修改針對httpd服務的相關規則,難道我們還要從頭看一遍這200條規則,找出哪些規則是針對httpd的嗎?這顯然不合理。
所以,iptables中,可以自定義鏈,通過自定義鏈即可解決上述問題。
假設,我們自定義一條鏈,鏈名叫IN_WEB,我們可以將所有針對80端口的入站規則都寫入到這條自定義鏈中,當以後想要修改針對web服務的入站規則時,就直接修改IN_WEB鏈中的規則就好了,即使默認鏈中有再多的規則,我們也不會害怕了,因爲我們知道,所有針對80端口的入站規則都存放在IN_WEB鏈中,同理,我們可以將針對sshd的出站規則放入到OUT_SSH自定義鏈中,將針對Nginx的入站規則放入到IN_NGINX自定義鏈中,這樣,我們就能想改哪裏改哪裏,再也不同擔心找不到規則在哪裏了
自定義鏈創建完成後,查看filter表中的鏈,如上圖所示,自定義鏈已經被創建,而且可以看到,這條自定義鏈的引用計數爲0 (0 references),也就是說,這條自定義鏈還沒有被任何默認鏈所引用,所以,即使IN_WEB中配置了規則,也不會生效,我們現在不用在意它,繼續聊我們的自定義鏈

root@node-101 ~]#iptables -t filter -N IN_WEB
[root@node-101 ~]#iptables -vnL IN_WEB 
Chain IN_WEB (0 references)
 pkts bytes target     prot opt in     out     source               destination 

自定義鏈好比自己寫的函數,創建自定義鏈好比聲明瞭函數,是不能直接使用的,如要使用必須先定義才行。賦予具體內容
自定義鏈也是需要賦予內容即規則。

[root@node-101 ~]#iptables -t filter -A IN_WEB -p tcp --dport 80 -j ACCEPT
[root@node-101 ~]#iptables -t filter -A IN_WEB -p tcp --dport 443 -j ACCEPT 
[root@node-101 ~]#iptables -vnL IN_WEB 
Chain IN_WEB (0 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:443

爲了舉例我們添加兩條規則給IN_WEB,接下來可以使用該自定義鏈IN_WEB

[root@node-101 ~]#iptables -t filter -A IN_WEB -p tcp --dport 80 -j ACCEPT   #定義IN_WEB第一條規則
[root@node-101 ~]#iptables -t filter -A IN_WEB -p tcp --dport 443 -j ACCEPT  #定義IN_WEB第二條規則
[root@node-101 ~]#iptables -t filter -A INPUT -s  192.168.122.103 -j IN_WEB  #使用自定義連IN_WEB
[root@node-101 ~]#iptabels -t filter -I  INPUT -s 172.18.43.4 -j ACCEPT      #把管理機ip加入允許
[root@node-101 ~]#iptables -t filter -A INPUT -j REJECT						 #決絕其他所有
[root@node-103 ~]#curl 192.168.122.101										 #101在允許規則,可以訪問
hello world 
[root@node-102 ~]#curl 192.168.122.101
curl: (7) Failed connect to 192.168.122.101:80; Connection refused           #101沒有在允許規則,所以被拒絕

過了一段時間,我們發現IN_WEB這個名字不太合適,我們想要將這條自定義鏈重命名,把名字改成WEB,可以嗎?必須能啊

[root@node-101 ~]#iptables -t filter  -E IN_WEB WEB
[root@node-101 ~]#iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-N WEB                                                 #已經改名
-A INPUT -s 172.18.43.4/32 -j ACCEPT
-A INPUT -s 192.168.122.103/32 -j WEB
-A INPUT -j REJECT --reject-with icmp-port-unreachable
-A WEB -p tcp -m tcp --dport 80 -j ACCEPT
-A WEB -p tcp -m tcp --dport 443 -j ACCEPT

使用"-X"選項可以刪除自定義鏈,但是刪除自定義鏈時,需要滿足兩個條件:
1、自定義鏈沒有被任何默認鏈引用,即自定義鏈的引用計數爲0。
2、自定義鏈中沒有任何規則,即自定義鏈爲空。

1.9.1 小結

創建自定義鏈 #示例:在filter表中創建IN_WEB自定義鏈
iptables -t filter -N IN_WEB
引用自定義鏈# 示例:在INPUT鏈中引用剛纔創建的自定義鏈
iptables -t filter -I INPUT -p tcp --dport 80 -j IN_WEB
重命名自定義鏈 #示例:將IN_WEB自定義鏈重命名爲WEB
iptables -E IN_WEB WEB #示例:刪除引用計數爲0並且不包含任何規則的WEB鏈
iptables -X WEB
刪除自定義鏈

1.10 iptables之網絡防火牆

我們一起來回顧一下之前的知識,在第一篇介紹iptables的文章中,我們就描述過防火牆的概念,我們說過,防火牆從邏輯上講,可以分爲主機防火牆與網絡防火牆。
主機防火牆:針對於單個主機進行防護。
網絡防火牆: 往往處於網絡入口或邊緣,針對於網絡入口進行防護,服務於防火牆背後的本地局域網
在前文的舉例中,iptables都是作爲主機防火牆的角色出現的,那麼,iptables怎樣作爲網絡防火牆呢?這就是我們今天要聊的話題。
回到剛纔的概念,網絡防火牆往往處於網絡的入口或者邊緣,那麼,如果想要使用iptables充當網絡防火牆,iptables所在的主機則需要處於網絡入口處
當外部網絡中的主機與網絡內部主機通訊時,不管是由外部主機發往內部主機的報文,還是由內部主機發往外部主機的報文,都需要經過iptables所在的主機,由iptables所在的主機進行"過濾並轉發",所以,防火牆主機的主要工作就是"過濾並轉發",
iptables的角色變爲"網絡防火牆"時,規則只能定義在FORWARD鏈中。

1.10.1 網絡防火牆實列

我已經準備了3臺主機,A、B、C。
假設A處於公網,172.18.43.101
B也有公網地址,172.18.43.102,同時有私網地址192.168.122.102
C,只是局域網地址192.168.122.103.
我們用主機A與B通過交換機連接,模擬互聯網直接通訊。而C與B也有單獨交換機連接,但是C只有私網地址。

主機 公網IP 私網IP
A 172.18.43.101
B 172.18.43.102 192.168.122.202
C 192.168.122.203

環境準備:

[root@node-101 ~]#ip link set eth0 down     #//A只允許外網172.18.43.0/16
[root@node-101 ~]#ip route del default via 172.18.0.1 dev eth1   #//刪除所有網關
[root@node-101 ~]#ip route  add 192.168.122.0/24 via 172.18.43.102 #//增加指向192.168.122.0/24網關
[root@node-101 ~]#ip route  add 192.168.122.0/24 via 172.18.43.102 #//增加指向192.168.122.0/24網關
[root@node-101 ~]#ping 192.168.122.103
PING 192.168.122.103 (192.168.122.103) 56(84) bytes of data.
[root@node-103 ~]#ip link set eth1 down     //C只允許內網192.168.122.0/24
[root@node-103 ~]#ping 172.18.43.101
connect: Network is unreachable
[root@node-103 ~]#ping 172.18.43.102
connect: Network is unreachable
[root@node-102 ~]#ip route del default via 192.168.122.1 dev eth0  #//刪除所有網關
[root@node-102 ~]#ip route del default via 172.18.0.1 dev eth1     #//刪除所有網關
[root@node-102 ~]#echo 1 > /proc/sys/net/ipv4/ip_forward            #//打開B機核心轉發
[root@node-102 ~]#cat /proc/sys/net/ipv4/ip_forward
1
[root@node-102 ~]#vim /usr/lib/sysctl.d/00-system.conf              #//想要永久生效則修改
net.ipv4.ip_forward = 1
[root@node-103 ~]#ip route add default via 192.168.122.102  #//給C增加默認網關,指向B
[root@node-103 ~]#ip route 
default via 192.168.122.102 dev eth0 
192.168.122.0/24 dev eth0 proto kernel scope link src 192.168.122.103 metric 100 
[root@node-103 ~]#ping 172.18.43.101
PING 172.18.43.101 (172.18.43.101) 56(84) bytes of data.
64 bytes from 172.18.43.101: icmp_seq=115 ttl=63 time=0.704 ms

此時已經可以訪問A,
通過在A抓包,可以明確看到是C機器在訪問

[root@node-101 ~]#tcpdump -i eth1 -p icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 262144 bytes
21:01:45.061883 IP 192.168.122.103 > node-101.centos76.com: ICMP echo request, id 16063, seq 21, length 64
[root@node-101 ~]#ping 192.168.122.103
PING 192.168.122.103 (192.168.122.103) 56(84) bytes of data.
64 bytes from 192.168.122.103: icmp_seq=1 ttl=63 time=0.512 ms		//實現雙向訪問。
[root@node-102 ~]#iptables -t filter -A FORWARD -j REJECT            //瞬間都掛了,AC不能互訪

另外配合其他選項可以實現端口轉發、源地址、目標地址的轉發

iptables -I FORWARD -s 192.168.122.0/24 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -d 1192.168.122.0/24 -p tcp --sport 80 -j ACCEPT
iptables -I FORWARD -s 192.168.122.0/24 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -d 192.168.122.0/24 -p tcp --sport 22 -j ACCEPT
#可以使用state擴展模塊,對上述規則進行優化,使用如下配置可以省略許多"迴應報文放行規則"。
iptables -A FORWARD -j REJECT
iptables -I FORWARD -s 192.168.122.0/24 -p tcp --dport 80 -j ACCEPT
iptables -I FORWARD -s 192.168.122.0/24 -p tcp --dport 22 -j ACCEPT
iptables -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT

一些注意點:
1、當測試網絡防火牆時,默認前提爲網絡已經正確配置。
2、當測試網絡防火牆時,如果出現問題,請先確定主機防火牆規則的配置沒有問題

1.11 iptables動作總結

之前的舉例中已經用到了一些常用動作,比如ACCEPT、DROP、REJECT等。
其實,"動作"與"匹配條件"一樣,也有"基礎"與"擴展"之分。
同樣,使用擴展動作也需要藉助擴展模塊,但是,擴展動作可以直接使用,不用像使用"擴展匹配條件"那樣指定特定的模塊。
之前用到的ACCEPT與DROP都屬於基礎動作。而REJECT則屬於擴展動作。

1.11.1動作REJECT

REJECT動作的常用選項爲–reject-with
使用–reject-with選項,可以設置提示信息,當對方被拒絕時,會提示對方爲什麼被拒絕。
可用值如下
icmp-net-unreachable
icmp-host-unreachable
icmp-port-unreachable,
icmp-proto-unreachable
icmp-net-prohibited
icmp-host-pro-hibited
icmp-admin-prohibited
當沒有明確設置–reject-with的值時,默認提示信息爲icmp-port-unreachable,即端口不可達之意
使用了–reject-with選項,將提示信息設置爲icmp-host-unreachable

1.11.2 動作LOG

使用LOG動作,可以將符合條件的報文的相關信息記錄到日誌中,但當前報文具體是被"接受",還是被"拒絕",都由後面的規則控制,換句話說,LOG動作只負責記錄匹配到的報文的相關信息,不負責對報文的其他處理,如果想要對報文進行進一步的處理,可以在之後設置具體規則,進行進一步的處理
在使用LOG動作時,匹配條件應該儘量寫的精確一些,匹配到的報文數量也會大幅度的減少,這樣冗餘的日誌信息就會變少,同時日後分析日誌時,日誌中的信息可用程度更高
我們已經瞭解到,LOG動作會將報文的相關信息記錄在/var/log/message文件中,當然,我們也可以將相關信息記錄在指定的文件中,以防止iptables的相關信息與其他日誌信息相混淆,修改/etc/rsyslog.conf文件(或者/etc/syslog.conf),在rsyslog配置文件中添加如下配置即可。
#vim /etc/rsyslog.conf
kern.warning /var/log/iptables.log
加入上述配置後,報文的相關信息將會被記錄到/var/log/iptables.log文件中。
完成上述配置後,重啓rsyslog服務(或者syslogd)
#service rsyslog restart
服務重啓後,配置即可生效,匹配到的報文的相關信息將被記錄到指定的文件中
LOG動作也有自己的選項,常用選項如下(先列出概念,後面有示例)
–log-level選項可以指定記錄日誌的日誌級別,可用級別有emerg,alert,crit,error,warning,notice,info,debug。
–log-prefix選項可以給記錄到的相關信息添加"標籤"之類的信息,以便區分各種記錄到的報文信息,方便在分析時進行過濾。
注:–log-prefix對應的值不能超過29個字符
除了ACCEPT、DROP、REJECT、LOG等動作,還有一些其他的常用動作,比如DNAT、SNAT等

1.11.3 SNAT

前文中,我們已經瞭解瞭如下動作

ACCEPT、DROP、REJECT、LOG

今天,我們來認識幾個新動作,它們是:

SNAT、DNAT、MASQUERADE、REDIRECT
NAT是Network Address Translation的縮寫,譯爲"網絡地址轉換",NAT說白了就是修改報文的IP地址,NAT功能通常會被集成到路由器、防火牆、或獨立的NAT設備中。

爲什麼要修改報文的IP地址呢?我們來描述一些場景,即可知道爲什麼有這方面的需求了。
1 SNAT
假設,網絡內部有10臺主機,它們有各自的IP地址,當網絡內部的主機與其他網絡中的主機通訊時,則會暴露自己的IP地址,如果我們想要隱藏這些主機的IP地址,該怎麼辦呢?可以這樣辦,如下。

當網絡內部的主機向網絡外部主機發送報文時,報文會經過防火牆或路由器,當報文經過防火牆或路由器時,將報文的源IP修改爲防火牆或者路由器的IP地址,當其他網絡中的主機收到這些報文時,顯示的源IP地址則是路由器或者防火牆的,而不是那10臺主機的IP地址,這樣,就起到隱藏網絡內部主機IP的作用,當網絡內部主機的報文經過路由器時,路由器會維護一張NAT表,表中記錄了報文來自於哪個內部主機的哪個進程(內部主機IP+端口),當報文經過路由器時,路由器會將報文的內部主機源IP替換爲路由器的IP地址,把源端口也映射爲某個端口,NAT表會把這種對應關係記錄下來。
於是,外部主機收到報文時,源IP與源端口顯示的都是路由的IP與端口,當外部網絡中的主機進行迴應時,外部主機將響應報文發送給路由器,路由器根據剛纔NAT表中的映射記錄,將響應報文中的目標IP與目標端口再改爲內部主機的IP與端口號,然後再將響應報文發送給內部網絡中的主機。整個過程中,外部主機都不知道內部主機的IP地址,內部主機還能與外部主機通訊,於是起到了隱藏網絡內主機IP的作用。
上述整個過程中,就用到了NAT功能,準確的說是用到了NAPT功能,NAPT是NAT的一種,全稱爲Network Address Port Translation,說白了就是映射報文IP地址的同時還會映射其端口號,就像剛纔描述的過程一樣。

剛纔描述的過程中,"IP地址的轉換"一共發生了兩次。

內部網絡的報文發送出去時,報文的源IP會被修改,也就是源地址轉換:Source Network Address Translation,縮寫爲SNAT。

外部網絡的報文響應時,響應報文的目標IP會再次被修改,也就是目標地址轉換:Destinationnetwork address translation,縮寫爲DNAT
但是,上述"整個過程"被稱爲SNAT,因爲"整個過程"的前半段使用了SNAT,如果上述"整個過程"的前半段使用了DNAT,則整個過程被稱爲DNAT,也就是說,整個過程被稱爲SNAT還是DNAT,取決於整個過程的前半段使用了SNAT還是DNAT。
實驗:
準備如下機器:
A 172.18.43.102/16 eth1,配置網卡,刪掉所有路由條目。安裝httpd充當web服務器。
B 172.18.43.103/16 eth1,192.168.122.103/24 刪掉所有路由條目。
C 192.168.122.104/24 企業內部主機。配置網關指向B的192.168.122.103
B機器開啓ip_forward轉發。
echo 1 > /proc/sys/net/ipv4/ip_forward
或者寫配置文件
[root@node-103 ~]#vim /etc/sysctl.conf
net.ipv4.ip_forward=1
//只要打開了核心轉發,其實此時B機器如能訪問互聯網,則會轉發A的請求,不會對數據包修改,原裝轉發給A,因爲是轉發,所以是私網地址,不會被互聯網機器路由,也就不能代理上網,
下面還要添加SDAT功能,把源地址修改成代理網關的IP,這樣的公網IP才能在互聯網路由。本次實驗只要保證BC同屬172.18.0.0/16即可。
在B配置SNAT後,無需給A添加路由。可實現C訪問A
打開B機器的SNAT功能
iptables -t nat -A POSTROUTING -s 192.168.122.0/24 -j SNAT --to-source 172.18.43.103
在POSTROUTING鏈上增加 源地址爲192.168.122.0/24 指定網關及172.18.43.103地址的snat規則。
當我們撥號網上時,每次分配的IP地址往往不同,不會長期分給我們一個固定的IP地址,如果這時,我們想要讓內網主機共享公網IP上網,就會很麻煩,因爲每次IP地址發生變化以後,我們都要重新配置SNAT規則,這樣顯示不是很人性化,我們通過MASQUERADE即可解決這個問題,MASQUERADE會動態的將源地址轉換爲可用的IP地址,其實與SNAT實現的功能完全一致,都是修改源地址,只不過SNAT需要指明將報文的源地址改爲哪個IP,而MASQUERADE則不用指定明確的IP,會動態的將報文的源地址修改爲指定網卡上可用的IP地址
通過外網網卡出去的報文在經過POSTROUTING鏈時,會自動將報文的源地址修改爲外網網卡上可用的IP地址,這時,即使外網網卡中的公網IP地址發生了改變,也能夠正常的、動態的將內部主機的報文的源IP映射爲對應的公網IP。
可以把MASQUERADE理解爲動態的、自動化的SNAT,如果沒有動態SNAT的需求,沒有必要使用MASQUERADE,因爲SNAT更加高效。
2 DNAT
公司有自己的局域網,網絡中有兩臺主機作爲服務器,主機1提供web服務,主機2提供數據庫服務,但是這兩臺服務器在局域網中使用私有IP地址,只能被局域網內的主機訪問,互聯網無法訪問到這兩臺服務器,整個公司只有一個可用的公網IP,怎樣通過這個公網IP訪問到內網中的這些服務呢?我們可以將這個公網IP配置到公司的某臺主機或路由器上,然後對外宣稱,這個IP地址對外提供web服務與數據庫服務,於是互聯網主機將請求報文發送給這公網 IP地址,也就是說,此時報文中的目標IP爲公網IP,當路由器收到報文後,將報文的目標地址改爲對應的私網地址,比如,如果報文的目標IP與端口號爲:公網IP+3306,我們就將報文的目標地址與端口改爲:主機2的私網IP+3306,同理,公網IP+80端口映射爲主機1的私網IP+80端口,當私網中的主機迴應對應請求報文時,再將回應報文的源地址從私網IP+端口號映射爲公網IP+端口號,再由路由器或公網主機發送給互聯網中的主機。

上述過程也牽扯到DNAT與SNAT,但是由於整個過程的前半段使用了DNAT,所以上述過程被稱爲DNAT
上述過程也牽扯到DNAT與SNAT,但是由於整個過程的前半段使用了DNAT,所以上述過程被稱爲DNAT
iptables -t nat -A PREROUTING -d 172.18.43.103 -p tcp --dport 80 -j DNAT --to-destination 192.168.122.105:8080
在PREROUTING鏈上 目標地址指向172.18.43.103的 tcp 80 端口的訪問都會被修改目標地址,轉發到192.168.122.105的8080/tcp
3 REDIRECT
使用REDIRECT動作可以在本機上進行端口映射

比如,將本機的80端口映射到本機的8080端口上

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

經過上述規則映射後,當別的機器訪問本機的80端口時,報文會被重定向到本機的8080端口上。

REDIRECT規則只能定義在PREROUTING鏈或者OUTPUT鏈中。

小結

開啓核心轉發:
SNAT相關
配置SNAT可以隱藏局域網地址,可以代理訪問互聯網,配置如下
iptables -t nat -A POSTROUTING -s 192.168.122.0/24 -j SNAT --to-source 172.18.43.103
iptables -t nat -A POSTROUTING -s 192.168.122.0/24 !-d 192.168.122.0/24 -j SNAT --to-source -j MASQUERADE
如果公網IP是撥號上網,不固定,則可以使用MASQUERADE進行SNAT操作,
DNAT相關
iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080

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