iptables知識點總結

一、參考鏈接和本次實驗地址

1.1、參考鏈接

感謝以下鏈接的博主或者相關人員。如有侵權,可以留言聯繫我刪除。
主要思想來自於馬哥教育內容;
重點翻譯man手冊爲主;
以下是參考或者部分摘抄的博文鏈接:
https://blog.csdn.net/dhrainer/article/details/83411391#comments
https://blog.csdn.net/dhRainer
https://blog.csdn.net/dhRainer/article/details/83411296
https://www.jianshu.com/p/b9843ac9450c
https://blog.csdn.net/chengxuyuanyonghu/article/details/51898002
http://blog.51cto.com/minux/1727684
https://blog.csdn.net/adamska0104/article/details/44916597
https://baike.baidu.com/item/防火牆/52767?fr=aladdin
http://blog.51cto.com/laokaddk/496983
http://lib.ru/SECURITY/ipfwadm/ipfwadm.txt_with-big-pictures.html
http://www.xos.nl/resources/ipfwadm/
http://blog.sina.com.cn/s/blog_4c86552f0102wyfc.html
https://www.cnblogs.com/549294286/p/5172435.html
http://blog.51cto.com/minux/1727684
https://lwn.net/Articles/267140/
http://www.zsythink.net/archives/1199/
http://blog.jobbole.com/89936/

1.2、單機實驗環境

雙網卡環境。eno16777736網卡是NAT出去的,可以上網,模擬的是外網網卡。ens37是僅主機模式,模擬的是內網網卡。(做NAT實驗,這個內網網卡有用到)
[root@gateway ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.16.0.10  netmask 255.255.0.0  broadcast 172.16.255.255
        inet6 fe80::20c:29ff:fe85:868d  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:85:86:8d  txqueuelen 1000  (Ethernet)
        RX packets 53844  bytes 5057774 (4.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 56703  bytes 12869995 (12.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens37: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.254  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::20c:29ff:fe85:8697  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:85:86:97  txqueuelen 1000  (Ethernet)
        RX packets 3684  bytes 539555 (526.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4959  bytes 441220 (430.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
[root@gateway ~]# ip addr show|sed -rn '/inet[[:space:]]+127/! s/^[[:space:]]+inet[[:space:]]+(.*)\/[[:digit:]]+[[:space:]]+.*$/\1/p'
172.16.0.10
192.168.10.254

Selinux是關閉的。本次講解是關閉firewalld,直接使用iptables。其實firewalld無法是做了一些自定義的鏈,引入的區域的概念。學會
iptables,能看懂,firewalld無法只是選項理解和區域概念的問題。後邊有時間會提供firewalld防火牆的專題。      

1.3、非單機實驗環境(主要是演示NAT實驗)

中轉服務器(路由服務器),雙網卡:
(僞)外網:eno16777736    ip爲:172.16.0.10
內網:ens37    ip爲:192.168.10.254

內網環境的模擬服務一臺:
內網:eno16777736    ip爲:192.168.10.4

外網服務器的模擬環境一臺:
(僞)外網:eno16777736    ip爲:172.16.0.120
內網:沒有,實際不同機房都會有內網接口。

二、防火牆概述和linux防火牆概述

2.1、防火牆概念引入和不同防火牆類型

摘自:https://baike.baidu.com/item/防火牆/52767?fr=aladdin

防火牆(Firewall),也稱防護牆,是由Check Point創立者Gil Shwed於1993年發明並引入國際互聯網(US5606668(A)1993-12-15)。防火牆是位於內部網和外部網之間的屏障,它按照系統管理員預先定義好的規則來控制數據包的進出。防火牆是系統的第一道防線,其作用是防止非法用戶的進入。
防火牆,簡單來理解就是一種隔離機制或者叫隔離工具。它主要工作在主機或網絡邊緣,對於進出主機或網絡的報文根據事先定義的檢查規則作匹配檢測,對於能夠被規則匹配到的報文作出相應的處理的組件。

根據防火牆所處的位置不同,可以分爲:主機防火牆和網絡防火牆。如下圖所示:
在這裏插入圖片描述

在這裏插入圖片描述

2.2、linux防火牆演變

參考:http://blog.51cto.com/laokaddk/496983

可以參考:
http://lib.ru/SECURITY/ipfwadm/ipfwadm.txt_with-big-pictures.html
http://www.xos.nl/resources/ipfwadm/

最早的防火牆實現框架是:ipfw,安裝軟件包應該是:ipfwadm。在linux內核1.2.x版本和2.0.x版本。
後面是:ipchains linux內核2.2.x之後,2.4.x之前。
接着是:netfilter(規則編寫組件是iptables) ,linux內核2.4.x之後,3.13之前。
後邊較新的內核版本:nftables,3.13版本之後。

CentOS 6和CnetOS7防火牆內核的實現都是netfiter,不過在CentOS6,iptables是一款防火牆策略編寫工具,在CentOS7,利用firewalld實現了策略編寫,不過它要去調用iptables編寫規則。所以可以理解,你使用CentOS6和CentOS7,其實弄懂iptables就行了。

三、iptables命令和匹配條件

3.1、iptables概述和iptables的五表五鏈

iptables的表的鏈以及規則的基本說明:

iptables/ip6tables ? administration tool for IPv4/IPv6 packet filtering and NAT。
iptables是IPv4/IPv6 的包過濾和網絡地址轉換的管理工具。

Iptables and ip6tables are used to set up, maintain, and inspect the tables of IPv4 and IPv6 packet filter rules in the Linux kernel. 
 Several different tables may be defined.  Each table contains a number of built-in chains and  may  also contain user-defined chains.
iptables用來發起,維護以及檢查linux內核中Ipv4包過濾規則表。(預設)定義了一些不同的表。每個表中可以包含一些內建的鏈,並且
可以包含用戶自定義的鏈。(這裏就不涉及ipv6了,所以ip6tables不註解)

Each  chain  is  a  list  of rules which can match a set of packets.  Each rule specifies what to do with a packet that matches.  
This is called a `target', which may be a jump to a user-defined chain in the same table.
每一條鏈上都有一系列的可以用來匹配一組數據包的規則。每條規則指定了能夠讓匹配的報文做什麼(比較常見的就是通過或者不通
過)。這個做什麼通常叫做"動作,目標(target)",這個target可以實現在一個表的內建鏈跳轉到一個用戶自定義的鏈,並去匹配自定義鏈
上的規則。

目標,處理動作(target):

A firewall rule specifies criteria for a packet and a target.  If the packet does not match, the next rule in the chain is  examined;  
if it does match, then the next rule is specified by the value of the target, which can be the name of a user-defined chain, one of the
 targets described in iptables-extensions(8), or one of the special values  ACCEPT,  DROP or RETURN.
防火牆規則指定了數據包和處理動作的準則。如果數據報文不匹配(鏈上某條具體的規則),然後會依次檢查鏈上接下來的規則;如果一
旦數據報文被鏈上的規則所匹配到,接下來會去檢查對應鏈上對應規則的處理動作,這個動作可以是一個用戶自定義鏈的名字。最終
的處理動作可能會是ACCEPT,DROP以及RETURAN還有高級擴展部分的中提到的target,詳情請參考(man 8 iptables-extensions,
這個是CentOS 7上,如果是CentOS 6,直接man 8 iptables就行)。

ACCEPT means to let the packet through.  DROP means to drop the packet on the floor.  RETURN means stop traversing this chain
and resume at the next rule in the previous (calling) chain.  If the end of a built-in chain is reached or a rule in  a built-in chain with 
target RETURN is matched, the target specified by the chain policy determines the fate of the packet.
ACCEPT動作表示讓數據包通過. DROP表示直接在數據包通過的入口處丟棄掉。RETURN表示停止當前鏈上規則的遍歷,返回到之前
調用鏈的地方,然後開始檢測之前鏈上的下一條規則。如果在內建鏈上,策略匹配已經達到了結束或者在內建鏈中匹配到RETURN,
那麼會去檢查指定鏈的默認策略來決定報文的"宿命"。

關於netfilter框架所在位置和數據報文和鏈的基本框架圖解如下圖所示:

這張圖引用自:https://blog.csdn.net/silent123go/article/details/52588518
在這裏插入圖片描述

在這裏插入圖片描述

通俗註解:
說了這麼多,大概意思就是如圖所示,爲了實現一些功能,有定義一些表,這些表,每一張都能實現一個大的功能,爲了實現這些表的功能,有事先定義一些函數,這些函數就是爲了來完成這些所謂的表的功能而設計的,它們之間可能是多個函數一起工作的,這些函數,在防火牆領域,被稱爲鉤子函數(hook function)。鉤子函數,默認一共定義了5個,分別爲prerouting,input,output,forward以及postrouting。而這些都只是內核中的功能接口,如果我們去調用這些鉤子函數,需要通過系統調用,調用這些功能接口,這樣未免讓使用成本和難度變得更大。所以後來就開發了一個可以用來在用戶空間完成策略編寫,然後由這個工具給我們去處理這些底層複雜的調用。這就是iptables的功能,在iptables中爲了讓鉤子函數的作用一目瞭然,有定義一些內建的與鉤子函數同名的全大寫字符。比如PREROUTING,INPUT,OUTPUT,FORWARD以及POSTROUTING,這些字符串分別對應同名的鉤子函數,它們統稱爲鏈,叫做對應名字的鏈,這些鏈是內建的,默認就存在的。我們如果要讓這些鏈或者說內核中鉤子函數更好的完成工作,我們要自己給鉤子函數定義一些策略,或者說給對應的鏈上編寫一些策略,每條策略可以理解爲檢測規則,數據報文經過這些規則,要去檢查是否可以通過。而編寫策略是我們在用戶空間使用iptables來編寫到對應的鏈上,iptables會幫我們交給對應的鉤子函數,數據報文最終還是由內核空間中的鉤子函數來完成策略檢測。這些策略可以分爲檢測和處理動作,可以從一個鉤子函數跳轉到另外一個鉤子函數。

除了內建鏈,我們可以自己定義新的鏈,這類鏈叫做用戶自定義鏈。在內建鏈或者自定義鏈中,會有很多條規則,即爲我們說的防火牆策略,這些策略都編寫在對應的鏈中。一旦數據報文經過對應鉤子函數的時候,鉤子函數會使用這些策略去匹配檢測數據報文,看它是否能夠通過,一條一條檢測,每一條規則,都有一個動作。數據報文不管來或者不來,這些內核中的鉤子函數總是會把這些策略放在那兒,就好像一直把這些策略勾着一樣。

預先定義了實現特定功能的表,完成複雜功能的5張表的名字分別爲:
raw
mangle
nat
filter
security
其中的security屬於加入沒多久的一張表(CentOS 6的iptables版本沒有這個security表,CentOS 7的iptables版本有引入這個),可以暫時不用理會。不過另外四張表中常用的也只有nat,filter。除了security外(這個主要是與selinux有關的mac安全過濾相關的一張表),另外四張表實現的功能和優先級分別爲(從上到下,優先級從高到低):
raw:主要功能是關閉nat表上啓用的連接追蹤機制;
mangle:主要功能是拆解報文,對報文進行修改,然後重新封裝起來;
nat:主要功能是實現網絡地址轉換,用於修改通信報文的源ip或目標ip,或者源端口或目標端口;
filter:主要功能實現報文過濾的,也是我們要了解的重點。

那麼這些對應的表與鉤子函數或者說與鏈之間的關係是怎樣的呢?

raw:PREROUTING,OUTPUT
mangle:PREROUTING,INPUT,FORWORD,OUTPUT,
nat:PREROUTING,[INPUT,]OUTPUT,POSTROUTIG  #CentOS 7才支持INPUT,CentOS 6 不支持INPUT
filter:INPUT,FORWORD,OUTPUT
security:INPUT, FORWARD, OUTPUT

其中如果只是涉及單主機的話,filter是用到最多的,而且也是最基礎的。可以說必須要掌握。對於多臺主機之間的應用,涉及轉發,路由之類的,nat和mangle可能會用的比較多,其中的nat應用特別廣泛。我們來簡單看看下面的圖解數據報文在這些表和鏈中間的銜接工作關係:

這張圖引用自:https://blog.csdn.net/silent123go/article/details/52588518
在這裏插入圖片描述

在這裏插入圖片描述

在這裏插入圖片描述

數據報文的流向,大概分爲:
(1) 從外部進來,流入主機內部;
(2) 從外部經過本機,由本機轉發;
(3) 從本機內部出來,即由本機流出;

報文到達本機後,會經過PREROUTING鏈後,然後路由後做判斷(只有路由後才能拆解報文頭的mac地址,看到內部封裝的網絡地址,判斷目標網絡地址是否是本機),如果報文的目標地址是本機,會通過INPUT鏈進入本機內部。通過PREROUTING鏈會發生一次路由。如果判斷目標地址不是本機,會嘗試讓本機進行報文的轉發(主機要開啓核心轉發功能才能做報文的轉發,這是個根本條件,默認的主機的核心轉發功能是關閉的),這個時候報文會通過FORWARD鏈。通過後,然後無法確認通過哪一個網絡接口發出,還要做一次路由,路由後會通過POSTROUTING鏈。對於主機內部的網絡報文,如果要出去,會通過OUTPUT,然後經過POSTROUTING出去。

3.2、iptables基礎命令語法結構

來看看固定形式的命令語法結構:

SYNOPSIS
       iptables [-t table] {-A|-C|-D} chain rule-specification
       ip6tables [-t table] {-A|-C|-D} chain rule-specification
       iptables [-t table] -I chain [rulenum] rule-specification
       iptables [-t table] -R chain rulenum rule-specification
       iptables [-t table] -D chain rulenum
       iptables [-t table] -S [chain [rulenum]]
       iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]
       iptables [-t table] -N chain
       iptables [-t table] -X [chain]
       iptables [-t table] -P chain target
       iptables [-t table] -E old-chain-name new-chain-name
       rule-specification = [matches...] [target]
       match = -m matchname [per-match-options]
       target = -j targetname [per-target-options]

-t 用來顯式指明操作或調用的的表是哪一張,默認是filter這個實現過濾功能的表。-t 後邊可選參數有:filter,nat,mangle,raw,security;

常用命令選項:
-A, --append chain rule-specification:表示向指定的鏈中追加一條策略;
-C, --check chain rule-specification:檢測鏈上是否有對應匹規則;
-D, --delete chain rule-specification或-D, --delete chain rulenum:刪除指定鏈的一條或多條規則,可以根據指定規則名來刪也可以根
據指定規則對應的編號來刪;
-I, --insert chain [rulenum] rule-specificatio:向給定鏈的指定位置(默認是第一條)插入指定的一條或多條規則;
-R, --replace chain rulenum rule-specification:替換給定鏈的給定規則;
-S, --list-rules [chain]:打印指定鏈所有規則或打印所有的鏈的所有規則;
-F, --flush [chain]:清空(刷新)指定鏈或所有的鏈;
-L, --list [chain]:查看指定鏈的所有規則;
-Z, --zero [chain [rulenum]]:置零所有鏈或指定鏈的或給定鏈的給定規則的數據包和字節統計信息。
-P, --policy chain target:設置指定鏈的默認策略爲給定的策略;
-N, --new-chain chain:自定義鏈;
-E, --rename-chain old-chain new-chain:重命名用戶自定義的鏈;
-X, --delete-chain [chain]:刪除用戶自定義的鏈;

常用參數選項:
[!] -p, --protocol protocol:指定協議;
[!] -s, --source address[/mask][,...]:檢查報文中的源IP地址是否符合此處指定的地址或範圍;
[!] -d, --destination address[/mask][,...]:檢查報文中的目標IP地址是否符合此處指定的地址或範圍;
-m, --match match:指定使用的擴展匹配項(模塊);擴展選項會在其他小結講解。
[!] -i, --in-interface name:數據報文流入的接口;只能應用於數據報文流入的環節,只能應用於PREROUTING, INPUT 和 FORWARD鏈;
[!] -o, --out-interface name:數據報文流出的接口;只能應用於數據報文流出的環節,只能應用於FORWARD, OUTPUT 和 POSTROUTING鏈;

其他選項:
-v, --verbose:查看詳細信息(-v使用多次,會顯示更加詳細的調試信息)
	-vv
	-vvv
-n, --numeric:以數字格式顯示地址和端口號;
-x, --exact:顯示技術結果的精確值;
--line-numbers:顯示規則的序號;

其中的chain部分,表示需要用戶自己指定的鏈名,可以是內建的鏈(PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING)
或者用戶自定義鏈;
rule-specification:表示規則指定部分。這部分由匹配和處理動作組成。匹配可以是基本條件匹配和擴展匹配
rulenum表示對應鏈的規則編號;

3.3、iptables基礎命令詳細說明

簡化後的命令格式爲:
iptables [-t tables] COMMAND chain [-m matchname [per-match-options]] -j target [per-target-options]

使用表說明:
-t table:CentOS 7後,內核默認支持使用5張表,分別是 filter、nat、mangle、raw、security
		如果沒有使用-t選項,默認操作的是filter表;(上文有介紹不同表的使用和區別)
iptables能識別的選項分爲下面三個部分:

(1) 命令選項
說明:下面這部分的選項用來表明想要執行的動作。大部分情況,下面的選項每次使用只能使用其中的一個。如果使用短選項,
除了-h,其他短選項字母都是大寫的英文字母,如果使用長選項,要把長選項表示的命令寫全,不能省略。

-A, --append chain rule-specification:
    向指定的鏈追加一條或多條規則。追加就是向鏈的規則列表的最後一條規則後面追加,如果鏈沒有規則,追加的就是第一條。因爲
鏈上規則默認是從上往下依次被檢測,所以規則的前後順序很關鍵。當指定源地址或目標地址,或者指定二者都指定時,如果地址被
解析成不止一個地址的時候,將會爲每個可能的地址組合添加一條規則(就是寫源地址和目標地址的時候要注意通配多個地址的情況);
	命令使用頻率:高

-C, --check chain rule-specification:
	檢測是否在對應鏈上存在指定的規則。iptables內部有個邏輯,下面-D選項也有用到,去尋找指定鏈上指定規則是否存在,然後返回
成功與否的狀態。-D會調用前邊這個判斷邏輯,然後繼續執行操作,而不是直接返回(要先查找是否指定鏈上是否存在要操作的規則)。
	命令使用頻率:不高

-D, --delete chain rule-specification
-D, --delete chain rulenum:
	從指定鏈上刪除一條或多條規則。默認在鏈上,規則會顯示規則名字和規則的序列編號,編號從1開始往後依次遞增。所以刪除鏈上
的規則有兩種情況,一個是直接指定規則名(上面的第一條語法),另外一個是直接指定規則所在的序號(上面的第二條語法)。規則的序號。
	可以通過後邊的其他選項或者叫輔助選項 --line-numbers查看。
	命令使用頻率:中等
	
-I, --insert chain [rulenum] rule-specification:
	向指定鏈的指定位置或默認位置(省略插入編號位置表示默認的1)插入一條或多條規則。指定位置插入規則後,此位置後邊的規則編
號依次向下平移插入規則的數量。
	命令使用頻率:高
	
-R, --replace chain rulenum rule-specification:
	在指定鏈上,使用指定的規則替換指定規則編號處的規則。如果待替換的規則中的源地址或目標地址中任意有一個地址被解析成多
個地址,此替換命令將會失敗。再次說明,規則是從第一條開始的,插入可以不指定規則編號,但是替換不可以,一定要顯式指明要被替換的規則的編號。
	命令使用頻率:中等
	
-L, --list [chain]:
	列出默認表或指定表的指定鏈或所有鏈的所有的規則。這個選項經常會配合-n選項一起使用,爲了避免長時間的DNS的反向解析查
詢(會被有些ip解析成對應的帶有字符的字符串格式,還有端口解析成對應的默認協議等,簡單來說就是DNS的反向解析,反向解析會
去查找DNS反向解析樹,是非常消耗資源和服務性能的)。此選項還可以配合-Z選項一起使用,就是列出後,會把鏈上規則的計數器
統計數據(匹配到的報文個數和匹配到的所有報文的大小之和)置爲零。如果配合後邊的輔助選項,比如常常配合一起使用的除了-n之外,還有-v,-vv,-vvv,-x等等,那麼輸出結果可能都會有所差異。
	命令使用頻率:高
	
-S, --list-rules [chain]:
	列出默認表或指定表的指定鏈或所有鏈的所有的規則。這個選項的輸出結果,在沒有指定鏈的情況下,和執行iptables-save命令的
結果一樣。
	命令使用頻率:不高

-F, --flush [chain]:
	清空指定鏈或所有鏈(沒有給出鏈名的情況)的所有規則。如果有給定表選項,會清空指定表,如果沒有情況的是默認的filter表。這個
命令要謹慎操作,這個命令的操作等價於一條一條的去刪除鏈上的所有的規則。
	命令使用頻率:中等

-Z, --zero [chain [rulenum]]:
	把報文個數計數和所有報文大小之和計數置爲0,重新開始計數。如果沒有給定鏈,會把默認表或指定表的所有鏈的統計數據置爲0
可以指定鏈或指定鏈的指定規則。可以配-L選項一起使用(上邊有提到過)。爲了測試效果,你可以在執行置零操作前,先看看統計數據。
	命令使用頻率:中等

-N, --new-chain chain:
創建一個新的用戶自定義的鏈。鏈的名字不能和已有target一樣。
	命令使用頻率:中等

-X, --delete-chain [chain]:
	刪除任意用戶自定義的鏈。如果不指定鏈的名字,會刪除指定表或默認表所有可以被刪除的自定義鏈。
要刪除用戶自定義鏈,這個鏈必須滿足:
	鏈沒有被引用;
	鏈上沒有規則(鏈必須爲空);
	一句話總結:僅能刪除 用戶自定義的 引用計數爲0的 空的 鏈
	命令使用頻率:不高

-P, --policy chain target:
設置對應鏈的默認策略爲給定的策略。而且設置的策略不能是內建的鏈名或用戶自定義鏈的名字。
常用的非擴展策略有:ACCEPT,REJECT,DROP,RETURN

-E, --rename-chain old-chain new-chain:
重命名用戶自定義的鏈的名字。在表看來,內部結構沒有變化,這個只是名字變化了。

-h
查看幫助信息。

(2) 參數(匹配條件)
[!] -p, --protocol protocol
	設置用於檢測報文時候的協議規則。可以指定的值有:tcp,udp,udplite,icmp,icmpv6,esp,ah,sctp,mh或者關鍵字all或者
數字值(特定數字有特定含義)。在配置文件/etc/protocols中指定的協議名是允許的。可以在指定協議的參數前邊使用!,表示取反的意思。指定數字 0 表示 all(匹配所有協議),all也是在-p選項省略時候的默認值。常用的值有:tcp,udp,icmp以及all
	參數使用頻率:高

[!] -s, --source address[/mask][,...]
	指定源地址。值address可以是一個網絡名,一個主機名,一個帶有子網掩碼(/mask)的網絡ip地址,或者是一個單獨的文本IP地址。
在規則被提交給內核前,這個主機名只會被解析一次。使用遠端主機(比如類似於讓遠程主機的DNS服務器去解析)去解析這個主機名
是不推薦的。掩碼錶示長格式(例如255.255.255.0)和短格式(24)。可以在參數選項前加上符號"!",取反。這個選項有另外一個等價表
示爲--src 如果指定多個地址,要特別注意。可以在使用-A追加的時候追加多個規則,或者在使用-D的時候刪除多個規則等。
	一句話概括:檢查報文中的源IP地址是否符合此處指定的地址或範圍;
	所有地址:0.0.0.0/0
	參數使用頻率:高

[!] -d, --destination address[/mask][,...]
	指定目標地址。和-s時候的用法和含義一樣。它的等價選項是--dst
	一句話概括:檢查報文中的目標IP地址是否符合此處指定的地址或範圍;
	參數使用頻率:高
	
-m, --match match
	指定要使用的匹配項,即測試特定屬性的擴展模塊(使用擴展模塊要使用這個選項明確指定擴展模塊名)。匹配集構成了調用目標的
條件。匹配首先根據命令行上的指定進行評估,然後以短路方式工作,即,如果一個擴展結果爲false,則評估將停止。
	參數使用頻率:高
	
[!] -i, --in-interface name
	數據報文流入的接口;只能應用於數據報文流入的環節,只能應用於PREROUTING,INPUT和FORWARD鏈;如果接口名字結尾
有個符號"+",表示匹配以name開頭的所有的地址。
	參數使用頻率:中等
	
[!] -o, --out-interface name
	數據報文流出的接口;只能應用於數據報文流出的環節,只能應用於FORWARD、OUTPUT和POSTROUTING鏈;如果接口名字結
尾有個符號"+"表示匹配以name開頭的所有地址。
	參數使用頻率:中等
	
(3) 其他選項(輔助選項)
-v, --verbose:
	信息信息。會顯示接口名字,規則選項以及TOS標誌。數據報文和所有數據報文的大小也會顯式。默認單位是K,M,G等,換算進度
是1000,可以使用-x選項顯式精確值。可以使用-v選項多次,顯示更加具體的調試信息。比如-vv或-vvv
	選項使用頻率:高
	
-n, --numeric:
	以數字格式顯示IP地址和端口號。默認程序會嘗試去顯示主機名,網絡名以及服務名。
	選項使用頻率:高
	
-x, --exact:
	數據報文個數和所有數據報文的字節統計大小會以更加精確的值顯示而不是換算過的帶上單位的值。這個選項只有配合-L時候纔有
意義的。
	選項使用頻率:中等
	
--line-numbers:
	在每條規則的開頭部分,顯示每條規則的序列好或編號。
	選項使用頻率:高
	
--modprobe=command
	當向鏈中添加或插入規則的時候,使用指定命令取加載任何所需的模塊。	      	
	選項使用頻率:不高

3.4、iptables基礎命令使用舉例

3.4.1、查看類

默認的firewalld服務時啓動的:
[root@gateway ~]# systemctl status firewalld.service
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2018-12-27 22:36:09 CST; 3h 2min ago
 Main PID: 3259 (firewalld)
   CGroup: /system.slice/firewalld.service
           └─3259 /usr/bin/python -Es /usr/sbin/firewalld --nofork --nopid

Dec 27 22:36:03 gateway systemd[1]: Starting firewalld - dynamic firewall daemon...
Dec 27 22:36:09 gateway systemd[1]: Started firewalld - dynamic firewall daemon.

先看一下默認firewalld啓動的情況下iptables策略表中的東西:
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  426 34200 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    1    52 INPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    1    52 INPUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    1    52 INPUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_IN_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_IN_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_OUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_OUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 420 packets, 62882 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  420 62882 OUTPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD_IN_ZONES (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 FWDI_public  all  --  ens37  *       0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 FWDI_public  all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 FWDI_public  all  --  +      *       0.0.0.0/0            0.0.0.0/0           [goto] 

Chain FORWARD_IN_ZONES_SOURCE (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD_OUT_ZONES (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 FWDO_public  all  --  *      ens37   0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 FWDO_public  all  --  *      eno16777736  0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 FWDO_public  all  --  *      +       0.0.0.0/0            0.0.0.0/0           [goto] 

Chain FORWARD_OUT_ZONES_SOURCE (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD_direct (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDI_public (3 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 FWDI_public_log  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FWDI_public_deny  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FWDI_public_allow  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FWDI_public_allow (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDI_public_deny (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDI_public_log (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDO_public (3 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 FWDO_public_log  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FWDO_public_deny  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FWDO_public_allow  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FWDO_public_allow (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDO_public_deny (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain FWDO_public_log (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT_ZONES (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 IN_public  all  --  ens37  *       0.0.0.0/0            0.0.0.0/0           [goto] 
    1    52 IN_public  all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 IN_public  all  --  +      *       0.0.0.0/0            0.0.0.0/0           [goto] 

Chain INPUT_ZONES_SOURCE (1 references)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT_direct (1 references)
 pkts bytes target     prot opt in     out     source               destination       
 
 省略很多內容。

iptables和firewalld的關係如下圖所示:(引用的互聯網的圖片。)
在這裏插入圖片描述

其實firewalld無非也是寫入的iptables策略,最終都是要被內核中的netfilter防火牆所處理。firewalld爲了實現區域的概念,有定義了很多iptables中的鏈(自定義鏈),比如:

FORWARD_IN_ZONES
FORWARD_IN_ZONES_SOURCE
FORWARD_OUT_ZONES
FORWARD_OUT_ZONES_SOURCE
FORWARD_direct
FWDI_public
FWDI_public_allow
FWDI_public_deny
FWDI_public_log
FWDO_public
FWDO_public_allow
FWDO_public_deny
FWDO_public_log
INPUT_ZONES
INPUT_ZONES_SOURCE
INPUT_direct
IN_public
IN_public_allow
IN_public_deny
IN_public_log
OUTPUT_direct

關閉firewalld服務後,iptables默認策略:(可以簡單印證每個表中所支持的鏈)

[root@gateway ~]# systemctl stop firewalld.service
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
[root@gateway ~]# 

[root@gateway ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
[root@gateway ~]# iptables -t mangle -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
[root@gateway ~]# iptables -t security -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
[root@gateway ~]# iptables -t raw -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination 

(1) 查看命令-L默認不帶附屬選項(爲了查看策略,我先把firewalld啓用,因爲有一些默認策略)

[root@gateway ~]# iptables -t filter -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere            
INPUT_direct  all  --  anywhere             anywhere            
INPUT_ZONES_SOURCE  all  --  anywhere             anywhere            
INPUT_ZONES  all  --  anywhere             anywhere            
ACCEPT     icmp --  anywhere             anywhere            
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere            
FORWARD_direct  all  --  anywhere             anywhere            
FORWARD_IN_ZONES_SOURCE  all  --  anywhere             anywhere            
FORWARD_IN_ZONES  all  --  anywhere             anywhere            
FORWARD_OUT_ZONES_SOURCE  all  --  anywhere             anywhere            
FORWARD_OUT_ZONES  all  --  anywhere             anywhere            
ACCEPT     icmp --  anywhere             anywhere            
REJECT     all  --  anywhere             anywhere             reject-with icmp-host-prohibited
......

(2) 加上以數字格式顯示ip和地址的選項-n

[root@gateway ~]# iptables -t filter -L -n 
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
INPUT_direct  all  --  0.0.0.0/0            0.0.0.0/0           
INPUT_ZONES_SOURCE  all  --  0.0.0.0/0            0.0.0.0/0           
INPUT_ZONES  all  --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           
REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0           
FORWARD_direct  all  --  0.0.0.0/0            0.0.0.0/0           
FORWARD_IN_ZONES_SOURCE  all  --  0.0.0.0/0            0.0.0.0/0           
FORWARD_IN_ZONES  all  --  0.0.0.0/0            0.0.0.0/0           
FORWARD_OUT_ZONES_SOURCE  all  --  0.0.0.0/0            0.0.0.0/0           
FORWARD_OUT_ZONES  all  --  0.0.0.0/0            0.0.0.0/0           
ACCEPT     icmp --  0.0.0.0/0            0.0.0.0/0           
REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited
......

(3) 加上-v輸出詳細信息

[root@gateway ~]# iptables -t filter -L -n -v
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  141 10344 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 INPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 INPUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 INPUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_IN_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_IN_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_OUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 FORWARD_OUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
    0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 109 packets, 19876 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  109 19876 OUTPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD_IN_ZONES (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 FWDI_public  all  --  ens37  *       0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 FWDI_public  all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0           [goto] 
    0     0 FWDI_public  all  --  +      *       0.0.0.0/0            0.0.0.0/0           [goto] 

(4) 顯示規則編號

[root@gateway ~]# iptables -t filter -L -n -v --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1      373 27964 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
2        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
3        0     0 INPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
4        0     0 INPUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
5        0     0 INPUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
6        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
7        0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
2        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
3        0     0 FORWARD_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
4        0     0 FORWARD_IN_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
5        0     0 FORWARD_IN_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
6        0     0 FORWARD_OUT_ZONES_SOURCE  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
7        0     0 FORWARD_OUT_ZONES  all  --  *      *       0.0.0.0/0            0.0.0.0/0           
8        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0           
9        0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 305 packets, 97800 bytes)
num   pkts bytes target     prot opt in     out     source               destination         
1      305 97800 OUTPUT_direct  all  --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD_IN_ZONES (1 references)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 FWDI_public  all  --  ens37  *       0.0.0.0/0            0.0.0.0/0           [goto] 
2        0     0 FWDI_public  all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0           [goto] 
3        0     0 FWDI_public  all  --  +      *       0.0.0.0/0            0.0.0.0/0           [goto] 

常見組合方式:

iptables -nvL  #注意如果把短選項組合在一起,-L命令選項不能出現在最開始,例如iptables -Lnv就會報錯
iptables -nvL --line-numbers

3.4.2、規則管理類

先關閉firewalld.service,然後去配置
(1) 允許原地址與我們系統ip在一個網絡內的tcp報文通過
進來:

[root@gateway ~]# iptables -t filter -A INPUT -s 172.16.0.0/16 -p tcp -d 172.16.0.10 -j ACCEPT```
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   22  1712 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 16 packets, 1504 bytes)
 pkts bytes target     prot opt in     out     source               destination  

出去:

[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  233 17932 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    4   544 ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16    

(2) 把INPUT、OUTPUT以及FORWARD鏈的默認策略設置爲DROP

#這裏要注意,我們把所有filter表默認鏈設置爲DROP後,這種修改是內存中實時生效的,而我們的ssh通常是遠程
#連接的,所以要注意遠程連接的問題,上面我們已經放行了我本地這個網段的權限。(這個是白名單機制,默認策略
#設置爲禁止,然後放行指定部分)
[root@gateway ~]# iptables -P INPUT DROP
[root@gateway ~]# iptables -P OUTPUT DROP
[root@gateway ~]# iptables -P FORWARD DROP
[root@gateway ~]# iptables -nvL
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  472 36528 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10         

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  195 19148 ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16   

(3) 能讓別人ping通我們的主機
添加前:
在這裏插入圖片描述

添加內容:

[root@gateway ~]# iptables -t filter -A INPUT -d 172.16.0.10 -p icmp -j ACCEPT
[root@gateway ~]# iptables -t filter -A OUTPUT -s 172.16.0.10 -p icmp -j ACCEPT
[root@gateway ~]# iptables -vnL
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  765 59696 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10         
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10         

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  428 40980 ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16       
    0     0 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0 

添加後:
在這裏插入圖片描述

(4) 只對主機所在網絡開放ssh連接,假設默認端口是22
爲了性能,我們把這條插入到第一條,後面把之前添加的開放整個網絡段的所有協議會刪掉。

[root@gateway ~]# iptables -t filter -I INPUT -s 172.16.0.0/16 -p tcp -d 172.16.0.10 --dport 22 -j ACCEPT
[root@gateway ~]# iptables -t filter -I OUTPUT -s 172.16.0.10 --sport 22 -p tcp -d 172.16.0.0/16 -j ACCEPT
iptables v1.4.21: unknown option "--sport"
Try `iptables -h' or 'iptables --help' for more information.
#這裏有個注意事項,因爲默認tcp是一個擴展模塊,可以被隱式調用,也可以被顯式調用,上面我們這種用法屬於隱式調用。
#-p tcp這個參數要在--dport 和--sport前面,因爲--dport和--sport都是-p tcp的子選項。

[root@gateway ~]# iptables -t filter -I OUTPUT -s 172.16.0.10 -p tcp --sport 22 -d 172.16.0.0/16 -j ACCEPT
[root@gateway ~]# iptables -nvL
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  330 26688 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10          tcp dpt:22
 1114 87353 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10         
    4   240 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10         

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   23  2044 ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16        tcp spt:22
  949  105K ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16       
    4   240 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0      

(5) 刪除之前開放的允許整個網段的tcp協議通過的

[root@gateway ~]# iptables -nvL
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  374 29772 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10          tcp dpt:22
 1114 87353 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10         
    4   240 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10         

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   68 15860 ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16        tcp spt:22
  949  105K ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16       
    4   240 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0  

[root@gateway ~]# iptables -t filter -D INPUT 2
[root@gateway ~]# iptables -t filter -D OUTPUT 2

[root@gateway ~]# iptables -nvL
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  731 57144 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10          tcp dpt:22
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10         

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  333 42888 ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16        tcp spt:22
    4   240 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0     

(6) 調整一下策略,讓默認策略允許,不過把入報文目標地址是本機,出報文,源地址是本機禁掉

先設置策略,然後再改默認策略。
[root@gateway ~]# iptables -t filter -A INPUT -d 172.16.0.10 -j REJECT
[root@gateway ~]# iptables -t filter -A OUTPUT -s 172.16.0.10 -j REJECT
[root@gateway ~]# iptables -nvL
Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  979 76308 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10          tcp dpt:22
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10         
    0     0 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  528 60076 ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16        tcp spt:22
    4   240 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0           
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable

[root@gateway ~]# iptables -t filter -P INPUT ACCEPT
[root@gateway ~]# iptables -t filter -P OUTPUT ACCEPT
[root@gateway ~]# iptables -t filter -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1122 87664 ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10          tcp dpt:22
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10         
    0     0 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  642 71560 ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16        tcp spt:22
    4   240 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0           
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable
  
#這樣一來,對於ssh協議和ping本機的icmp協議都可以分別被第一條和第二條鏈所匹配到,而且也允許出去。所以我們的遠程
#ssh會話沒有中斷,而且外部也可以ping通本機。  而且這樣做的好處是,之前ping本地會話不行,現在卻可以了:
[root@gateway ~]# ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.056 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.056 ms
^C
--- 127.0.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.056/0.056/0.056/0.000 ms

(7) 使用一下接口參數

[root@gateway ~]# iptables -t filter -A INPUT -i eno16777736
[root@gateway ~]# iptables -t filter -A OUTPUT -o eno16777736
[root@gateway ~]# iptables -t filter -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1446  112K ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10          tcp dpt:22
    4   240 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10         
    0     0 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable
    0     0            all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  903 95812 ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16        tcp spt:22
    8   480 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0           
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable
    0     0            all  --  *      eno16777736  0.0.0.0/0            0.0.0.0/0           
[root@gateway ~]# iptables -D INPUT 3 
[root@gateway ~]# iptables -D OUTPUT 3 

[root@gateway ~]# iptables -t filter -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1554  121K ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10          tcp dpt:22
    4   240 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10         
    0     0            all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  986  105K ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16        tcp spt:22
    8   480 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0           
    0     0            all  --  *      eno16777736  0.0.0.0/0            0.0.0.0/0           
[root@gateway ~]# ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.037 ms
^C
--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.037/0.037/0.037/0.000 ms

在這裏插入圖片描述

(8) 清空指定表或默認表上鍊的所有規則

[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 2 packets, 168 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 2979  229K ACCEPT     tcp  --  *      *       172.16.0.0/16        172.16.0.10          tcp dpt:22
    8   480 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10         
    0     0            all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0           

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 2 packets, 168 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 2401  167K ACCEPT     tcp  --  *      *       172.16.0.10          172.16.0.0/16        tcp spt:22
   12   720 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0           
    0     0            all  --  *      eno16777736  0.0.0.0/0            0.0.0.0/0           
[root@gateway ~]# iptables -F
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 5 packets, 356 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 4 packets, 400 bytes)
 pkts bytes target     prot opt in     out     source               destination     

(9) 調整一下策略,讓自己能ping通別人,別人不能ping通自己
之前規則有清空,先加一下ssh通過,以免斷開。

[root@gateway ~]# iptables -A INPUT -d 172.16.0.10 -p tcp --dport 22 -j ACCEPT
[root@gateway ~]# iptables -A OUTPUT -s 172.16.0.10 -p tcp --sport 22 -j ACCEPT
[root@gateway ~]# iptables -A INPUT -i eno16777736 -j REJECT
[root@gateway ~]# iptables -A OUTPUT -o eno16777736 -j REJECT
#這幾條代碼,前面都解釋過了,這裏不再贅述
[root@gateway ~]# iptables -vnL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  270 20736 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          tcp dpt:22
    0     0 REJECT     all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  127 11656 ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            tcp spt:22
    0     0 REJECT     all  --  *      eno16777736  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable
#放行icmp協議代碼
[root@gateway ~]# iptables -I OUTPUT 2 -s 172.16.0.10 -p icmp --icmp-type 8 -j ACCEPT
[root@gateway ~]# iptables -I INPUT 2 -d 172.16.0.10 -p icmp --icmp-type 0 -j ACCEPT
[root@gateway ~]# ping 114.114.114.114
PING 114.114.114.114 (114.114.114.114) 56(84) bytes of data.
64 bytes from 114.114.114.114: icmp_seq=1 ttl=128 time=22.3 ms
64 bytes from 114.114.114.114: icmp_seq=2 ttl=128 time=21.3 ms
^C
--- 114.114.114.114 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 21.392/21.854/22.317/0.485 ms
#這裏有些知識點,我這裏不特別說明。到下面講到擴展模塊的時候會重新提到tcp和udp以及icmp;

(10) 添加策略讓別人也能ping通(基於第9例)

[root@gateway ~]# iptables -I INPUT 3 -d 172.16.0.10 -p icmp --icmp-type 8 -j ACCEPT
[root@gateway ~]# iptables -I OUTPUT 3 -s 172.16.0.10 -p icmp --icmp-type 0 -j ACCEPT
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 3207  181K ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          tcp dpt:22
    2   168 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 0
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 8
    5   300 REJECT     all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 3449 2729K ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            tcp spt:22
    2   168 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 8
    0     0 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 0
36435 3060K REJECT     all  --  *      eno16777736  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

在這裏插入圖片描述

3.4.3、鏈管理類

(1) 自定義鏈

#在過濾表定義了一條名叫clearing的鏈。
[root@gateway ~]# iptables -N clearing
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 3353  192K ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          tcp dpt:22
    2   168 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 0
    4   240 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 8
    5   300 REJECT     all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 3573 2743K ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            tcp spt:22
    2   168 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 8
    4   240 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 0
36435 3060K REJECT     all  --  *      eno16777736  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain clearing (0 references)
 pkts bytes target     prot opt in     out     source               destination    
 

(2) 重命名自定義鏈和刪除自定義鏈

[root@gateway ~]# iptables -E clearing input_clean
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 3477  201K ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          tcp dpt:22
    2   168 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 0
    4   240 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 8
    5   300 REJECT     all  --  eno16777736 *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain FORWARD (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 3673 2755K ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            tcp spt:22
    2   168 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 8
    4   240 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 0
36435 3060K REJECT     all  --  *      eno16777736  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain input_clean (0 references)
 pkts bytes target     prot opt in     out     source               destination         
[root@gateway ~]# iptables -X input_clean

3.5、iptables的基本匹配條件

基本匹配條件就上上文中提到的PARAMETERS(參數)選項。基本匹配條件儘量要先寫。上文已經重點講解過了,這裏總結一下。

指定源地址:(核心)
[!] -s, --source address[/mask][,...]

指定目標地址:(核心)
[!] -d, --destination address[/mask][,...]

指定協議的:(核心)
[!] -p, --protocol protocol

指定輸入接口:
[!] -i, --in-interface name

指定輸出接口:
[!] -o, --out-interface name

跳轉target:
-j, --jump target

跳轉鏈:
-g, --goto chain

指定擴展模塊:(重點)
-m, --match match

3.6、iptables的常用擴展匹配條件

下面的擴展參考文檔:man 8 iptables-extensions
或者:
iptables -m extension_module_name --help
iptables 可以通過基本選項(-m或–match)來使用擴展的報文匹配模塊,簡稱擴展模塊。-m 後邊要加上擴展匹配
模塊的名字,這樣就表示顯式調用了這個模塊。在這個擴展模塊選項指定後,後邊可以使用各種額外的擴展模塊
所支持的命令行選項(具體支持什麼選項因模塊而異,下文中會詳細介紹)。在命令行可以指定多個擴展匹配模塊,
規則生效順序按照擴展模塊指定的先後順序。
擴展匹配模塊中按照用法又分爲隱式擴展和顯式擴展,所謂隱式擴展,比如常見的tcp,udp以及icmp,這類本身屬於協議,他們在使用的時候直接配合使用-p protocol_name,然後就好像調用-p protocol_name -m protocol_name一樣,這樣隱式調用也可以使用對應擴展模塊的子選項。比如:
tcp屬於可隱式調用模塊,支持這樣調用:

...... -p tcp [!] --sport port[:port] [!] --dport port[:port]  ......
...... -p tcp -m tcp [!] --sport port[:port] [!] --dport port[:port]  ......

3.6.1、隱式擴展之tcp

該模塊顯式指定或隱式指定後,後邊可以接着使用的選項以及含義簡析:

[!] --source-port,--sport port[:port]:
	指定源端口或源端口範圍。這個port的值可以是一個服務名或一個(整數)數值端口。如果是指定的服務名,iptables在插入策略的時
候會去映射服務名對應的端口值而後插入(參考/etc/services配置文件),雖然可以通過修改/etc/services配置去改默認協議或服務的標
準映射端口值,這樣修改後,iptables插入的時候確實可以做到插入修改後的值,不過不建議這樣做。
	指定端口範圍的語法是first:last。如果省略起始端口(first),默認會以0來替代;如果省略結束端口(last),默認會以65535來替代。
雖然手冊中寫到,如果first端口大於last的端口值,那麼會自行替換其實的端口,不過實際測試過程中,發現如果first的值大於last的
值,會報錯。--sport是--source-port的等價的別名,通常都是用--sport,因爲好記(要記住區別對待multiport擴展模塊的子選項
--sports)。這個要麼是單個指定值,要麼是一個範圍值,不支持離散值。

例如:
上面有提到port可以使用服務名:
-p tcp [-m tcp] --sport ssh  #插入後默認值是22,中括號[]內的內容可以省略,因爲這個模塊可以隱式調用;
-p tcp [-m tcp] --sport http:https  #插入後默認範圍是80:443,中括號[]內的內容可以省略,因爲這個模塊可以隱式調用;
-p tcp [-m tcp] --sport :2048  #插入後默認範圍是0:2048,中括號[]內的內容可以省略,因爲這個模塊可以隱式調用;
-p tcp [-m tcp] --sport 4000: #插入後默認範圍是4000:65535;
PS:示例演示我就不貼出了,上面我都實際測試過了的。

[!] --destination-port,--dport port[:port]:
	指定目標端口或端口範圍。取值和源端口含義一樣。這裏就不說明了,通常也適用等價含義的別名--dport。同時要強調一點,要
區別multiport擴展模塊的子選項--dports。這個要麼是單個指定值,要麼是一個範圍值,不支持離散值。

[!] --tcp-flags mask comp:
當給定TCP報文標誌位的時候的匹配。(Match when the TCP flags are as specified.)
選項的第一個參數mask是要檢查的TCP報文標誌位的列表,TCP報文一共可選的標誌位有SYN, ACK, FIN, RST, URG, PSH。
這裏可選的參數除了上面這6個標誌位,還可以使用ALL來代表所有標誌位,NONE來表示沒有標誌位。mask值的語法格式爲,
如果值是以逗號分開的。 comp也是一個以逗號分隔的參數列表,這個參數必須要設置(設置的意思就是非0)。我們來看看下面的示例:
-p tcp [-m tcp] ---tcp-flags SYN,ACK,FIN,RST SYN
這句含義是,要檢查的標誌位一共有4個,分別是SYN,ACK,FIN,RST且SYN的值必須爲1,其他三個ACK,FIN,RST必須爲0.
這個示例其實就是TCP通信建立會話的第一次握手,就是新發起連接請求。


[!] --syn:
	只匹配TCP報文中SYNC標誌爲被設置(值要爲1),且ACK,RST以及FIN標誌位被清除(值爲0)的報文。這種報文是用去TCP連接請求的
初始連接狀態(我們俗稱的TCP的第一次握手)。這種等價於上面的選項--tcp-flags SYN,ACK,FIN,RST SYN。如果要表示第一次握手,
通常會使用這種簡單的表示,而非上面那種複雜的表示法。

上面涉及TCP報文狀態情況的要了解一下
圖片引用自互聯網:
TCP報文首部圖解

含義摘抄地址:http://www.cnblogs.com/liquan2005/p/9113369.html

  TCP Header Format


    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |          Source Port          |       Destination Port        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                        Sequence Number                        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Acknowledgment Number                      |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |  Data |           |U|A|P|R|S|F|                               |
   | Offset| Reserved  |R|C|S|S|Y|I|            Window             |
   |       |           |G|K|H|T|N|N|                               |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |           Checksum            |         Urgent Pointer        |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                    Options                    |    Padding    |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |                             data                              |
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
●源、目標端口號字段:佔16比特。TCP協議通過使用"端口"來標識源端和目標端的應用進程。端口號可以使用0到65535之間的任何
數字。在收到服務請求時,操作系統動態地爲客戶端的應用程序分配端口號。在服務器端,每種服務在"衆所周知的端口"(Well-Know
 Port)爲用戶提供服務。
●順序號字段:佔32比特。用來標識從TCP源端向TCP目標端發送的數據字節流,它表示在這個報文段中的第一個數據字節。
●確認號字段:佔32比特。只有ACK標誌爲1時,確認號字段纔有效。它包含目標端所期望收到源端的下一個數據字節。
●頭部長度字段:佔4比特。給出頭部佔32比特的數目。沒有任何選項字段的TCP頭部長度爲20字節(5x32=160比特);最多可以有
60字節的TCP頭部。
●標誌位字段(U、A、P、R、S、F):佔6比特。各比特的含義如下:
    ◆URG:緊急指針(urgent pointer)有效。
    ◆ACK:確認序號有效。
    ◆PSH:接收方應該儘快將這個報文段交給應用層。
    ◆RST:重建連接。
    ◆SYN:發起一個連接。
    ◆FIN:釋放一個連接。
●窗口大小字段:佔16比特。此字段用來進行流量控制。單位爲字節數,這個值是本機期望一次接收的字節數。
●TCP校驗和字段:佔16比特。對整個TCP報文段,即TCP頭部和TCP數據進行校驗和計算,並由目標端進行驗證。
●緊急指針字段:佔16比特。它是一個偏移量,和序號字段中的值相加表示緊急數據最後一個字節的序號。
●選項字段:佔32比特。可能包括"窗口擴大因子"、"時間戳"等選項。

TCP三次握手和四次揮手簡單圖解

3.6.2、隱式擴展之udp

該模塊顯式指定或隱式指定後,後邊可以接着使用的選項以及含義簡析:

[!] --source-port,--sport port[:port]:
和TCP的選項含義一樣。這裏也是表示匹配udp報文的源端口;可以是端口範圍;

[!] --destination-port,--dport port[:port]:
和TCP的選項含義一樣,這裏也是表示匹配udp報文的目標端口;可以是端口範圍;

說明:學完之後要會放行本地的samba服務和dns服務中使用udp協議53號端口的部分。
samba涉及兩個服務,一個是smb.service,涉及的端口和協議分別是:137/udp,138/udp
另一個是nmb.service,涉及的端口和協議分別是:139/tcp,445/tcp

DNS比較複雜,從網上摘錄了一段比較經典的話:
https://www.cnblogs.com/549294286/p/5172435.html
DNS同時佔用UDP和TCP端口53是公認的,這種單個應用協議同時使用兩種傳輸協議的情況在TCP/IP棧也算是個另類。但很少有人知道DNS分別在什麼情況下使用這兩種協議。
如果用wireshark、sniffer或古老些的tcpdump抓包分析,會發現幾乎所有的情況都是在使用UDP,使用TCP的情況非常罕見,神祕兮兮。其實當解析器發出一個request後,返回的response中的tc刪節標誌比特位被置1時,說明反饋報文因爲超長而有刪節。這是因爲UDP的報文最大長度爲512字節。解析器發現後,將使用TCP重發request,TCP允許報文長度超過512字節。既然TCP能將data stream分成多個segment,它就能用更多的segment來傳送任意長度的數據。
另外一種情況是,當一個域的輔助域名服務器啓動時,將從該域的主域名服務器primary DNS server執行區域傳送。除此之外,輔域名服務器也會定時(一般時3小時)向PDS進行查詢以便了解SOA的數據是否有變動。如有變動,也會執行一次區域傳送。區域傳送將使用TCP而不是UDP,因爲傳送的數據量比一個request或response多得多。
DNS主要還是使用UDP,解析器還是服務端都必須自己處理重傳和超時。DNS往往需要跨越廣域網或互聯網,分組丟失率和往返時間的不確定性要更大些,這對於DNS客戶端來說是個考驗,好的重傳和超時檢測就顯得更重要了。
關於DNS,網上這兩篇博文有對DNS使用的協議端口進行比較剖析講解:
http://blog.sina.com.cn/s/blog_4c86552f0102wyfc.html
https://www.cnblogs.com/549294286/p/5172435.html

3.6.3、隱式擴展之icmp

該模塊顯式指定或隱式指定後,後邊可以接着使用的選項以及含義簡析:

下面這張圖是icmp類型、代碼以及含義對應表,圖片摘自互聯網:(下面設置時候有用到)
在這裏插入圖片描述

[!] --icmp-type {type[/code]|typename}:
指定ICMP協議的類型,可以使用數值表示也可以使用特定的類型名字表示。數值可能有type/code兩種形式,第一個type的數值表示類
型,第二個數值code表示該類型下特定狀態(可以理解爲有些大類型下可以分爲很多子類型),上面有一張表格有詳細介紹這個對應值
的含義。typename的可選值下面有列出來。
一般這裏的icmp類型常見的就兩種,一個是8,表示發起的icmp協議請求(echo-request),另外一個0,表示icmp協議響應的報文。
例如,前面小結有講到過的,要讓別人能ping通你,這樣的這一句話的含義是,首先ping通你,就是別人請求進來的icmp報文,
既然是進來的,就要設定echo-request允許。響應的icmp報文是服務器自己響應的,所以響應也要指定icmp協議的類型(echo-reply),即爲0.
iptables [-t filter] -A INPUT -d 172.16.0.10 -p icmp [-m icmp] --icmp-type 8[/0] -j ACCEPT
iptables [-t filter] -A OUTPUT -s 172.16.0.10 -p icmp [-m icmp] --icmp-type 0[/0] -j ACCEPT
或者
iptables [-t filter] -A INPUT -d 172.16.0.10 -p icmp [-m icmp] --icmp-type echo-request -j ACCEPT
iptables [-t filter] -A OUTPUT -s 172.16.0.10 -p icmp [-m icmp] --icmp-type echo-reply -j ACCEPT
或者
iptables [-t filter] -A INPUT -d 172.16.0.10 -p icmp [-m icmp] --icmp-type ping -j ACCEPT
iptables [-t filter] -A OUTPUT -s 172.16.0.10 -p icmp [-m icmp] --icmp-type pong -j ACCEPT


參考iptables -p icmp -h之後的結果:
icmp match options:
[!] --icmp-type typename	match icmp type
[!] --icmp-type type[/code]	(or numeric type or type/code)
Valid ICMP Types:
any
echo-reply (pong)
destination-unreachable
   network-unreachable
   host-unreachable
   protocol-unreachable
   port-unreachable
   fragmentation-needed
   source-route-failed
   network-unknown
   host-unknown
   network-prohibited
   host-prohibited
   TOS-network-unreachable
   TOS-host-unreachable
   communication-prohibited
   host-precedence-violation
   precedence-cutoff
source-quench
redirect
   network-redirect
   host-redirect
   TOS-network-redirect
   TOS-host-redirect
echo-request (ping)
router-advertisement
router-solicitation
time-exceeded (ttl-exceeded)
   ttl-zero-during-transit
   ttl-zero-during-reassembly
parameter-problem
   ip-header-bad
   required-option-missing
timestamp-request
timestamp-reply
address-mask-request
address-mask-reply

3.6.4、顯式擴展之multiport

這個擴展模塊用於匹配一組源端口或一組目標端口。單挑規則,15個端口是最大值。端口範圍(port:port)算兩個
端口。這個擴展模塊只能配合協議爲tcp,udp,udplite,dccp以及sctp一起使用。

[!] --source-ports,--sports port[,port|,port:port]...:
匹配是否源端口是給定的端口中的一部分。--sports是--source-ports等效的別名形式。多個離散的端口要使用逗號分隔符來分隔,一個
連續的端口範圍使用冒號來分分隔,離散端口和端口範圍可以一起結合使用。
例如:
-p tcp -m multiport --sports 80,443    #這個端口計數算兩個。能匹配80和443端口;
-p tcp -m multiport --sports 4000:20000 #這個端口算2個,能匹配4000到20000這個範圍內的端口,包括邊界;
-p tcp -m multiport --sports 53,80,443,4000:20000 #這個端口算5個,能匹配53,80,443這三個離散端口以及4000到20000的端口範圍,包括邊界。

[!] --destination-ports,--dports port[,port|,port:port]...:
匹配是否目標端口是給定端口中的一部分。用法、取值和--sports一樣。

[!] --ports port[,port|,port:port]...:
匹配是否源端口或目標端口是給定的端口中的一部分。用法、取值和--sports或--dports一樣。

示例:修改之前的單個端口的,讓22和80端口都能被正常訪問

[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  108  8708 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          tcp dpt:22
    2   120 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 8
   44  5361 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   16  1520 ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            tcp spt:22
    2   120 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 0
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable
[root@gateway ~]# iptables -R INPUT 1 -d 172.16.0.10 -p tcp -m multiport --dports 22,80 -j ACCEPT
[root@gateway ~]# iptables -R OUTPUT 1 -s 172.16.0.10 -p tcp -m multiport --sports 22,80 -j ACCEPT
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  131 10252 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          multiport dports 22,80
    2   120 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 8
   44  5361 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   15  1412 ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            multiport sports 22,80
    2   120 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 0
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable
    #可以測試一下服務器上的httpd是否可以訪問。測試就不截圖了。

3.6.5、顯式擴展之iprange

這個擴展匹配模塊用來匹配任意的IP地址範圍;

[!] --src-range from[-to]:
用指定的IP地址範圍來匹配源IP地址;

[!] --dst-range from[-to]:
用指定的IP地址範圍來匹配目標IP地址;

#只允許和我主機在一個網段內,源地址範圍在172.16.0.1~172.16.0.20內的主機可以訪問我的telnet服務

#修改前
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   31  2228 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          multiport dports 22,80
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 8
    0     0 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   22  3192 ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            multiport sports 22,80
    0     0 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 0
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable
#插入的策略
[root@gateway ~]# iptables -I INPUT 3 -d 172.16.0.10 -p tcp --dport 23 -m iprange --src-range 172.16.0.1-172.16.0.10 -j ACCEPT
[root@gateway ~]# iptables -I OUTPUT 3 -s 172.16.0.10 -p tcp --sport 23 -m iprange --dst-range 172.16.0.1-172.16.0.10 -j ACCEPT
#修改後
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  672 51740 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          multiport dports 22,80
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 8
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          tcp dpt:23 source IP range 172.16.0.1-172.16.0.10
    0     0 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  507 52068 ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            multiport sports 22,80
    0     0 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 0
    0     0 ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            tcp spt:23 destination IP range 172.16.0.1-172.16.0.10
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable

telnet服務要自己去安裝(telnet-server軟件包,telnet.socket),客戶端也是,我現在拿已經弄好的環境測試一下telnet登錄訪問。一臺客戶端是172.16.0.4,一臺客戶端是172.16.0.120.

允許訪問的測試過程:
[root@localhost ~]# ip addr list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:57:46:83 brd ff:ff:ff:ff:ff:ff
    inet 172.16.0.4/16 brd 172.16.255.255 scope global eno16777736
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe57:4683/64 scope link 
       valid_lft forever preferred_lft forever
[root@localhost ~]# telnet 172.16.0.10 23
Trying 172.16.0.10...
Connected to 172.16.0.10.
Escape character is '^]'.

Kernel 3.10.0-229.el7.x86_64 on an x86_64
gateway login: yanhui
Password: 
Last login: Sat Dec 29 19:11:21 from ::ffff:172.16.0.1
[yanhui@gateway ~]$ who am i
yanhui   pts/6        2018-12-29 19:31 (::ffff:172.16.0.4)
[yanhui@gateway ~]$ ip addr list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:85:86:8d brd ff:ff:ff:ff:ff:ff
    inet 172.16.0.10/16 brd 172.16.255.255 scope global eno16777736
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe85:868d/64 scope link 
       valid_lft forever preferred_lft forever
3: ens37: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:85:86:97 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.254/24 brd 192.168.10.255 scope global ens37
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fe85:8697/64 scope link 
       valid_lft forever preferred_lft forever
不允許訪問的測試過程:
[root@localhost ~]# telnet 172.16.0.10 23
Trying 172.16.0.10...
telnet: connect to address 172.16.0.10: Connection timed out

3.6.6、顯式擴展之time

如果報文抵達的時間/日期在指定的範圍內,則匹配。(This matches if the packet arrival time/date is within a given range.)所有下面的子選項都是可選的。默認使用UTC時間。

--datestart YYYY[-MM[-DD[Thh[:mm[:ss]]]]]
--datestop YYYY[-MM[-DD[Thh[:mm[:ss]]]]]:
僅僅匹配給定的時間範圍內,時間格式必須要加上ISO 8601 的"T"標記。有效的時間範圍爲:
1970-01-01T00:00:00 to 2038-01-19T04:17:07
如果省略--datestart或省略--datestop,則會使用默認的1970-01-01和2038-01-19。


--timestart hh:mm[:ss]
--timestop hh:mm[:ss]:
僅僅匹配給定的時間範圍內,與上面--datestart和--datestop區別是,這裏只能指定時間,不能指定日期。可以的時間範圍爲:
00:00:00 ~ 23:59:59。允許數值帶上前導0的形式,例如:上午6點半,可以寫成6:30或06:30。這些時間數值都被識別成10進制。

[!] --monthdays day[,day...]:
Only match on the given days of the month. Possible values are 1 to 31. Note that specifying 31 will of course not match on months
which do not have a 31st day; the same goes for 28- or 29-day February.
只匹配每月指定的日期。可以使用的值爲1到31.如果實際月份沒有31天,如果指定了31就不會被匹配。2月的29天或28天也滿足這種
定律。
  
[!] --weekdays day[,day...]:
Only match on the given weekdays. Possible values are Mon, Tue, Wed, Thu, Fri, Sat, Sun, or values from 1 to 7, respectively. You
may also use two-character variants (Mo, Tu, etc.).
值匹配給定的星期。可以設置的值Mon,Tue,Wed,Thu,Fri,Sat,Sun或1到7的值。也可以使用兩個字符的縮寫表示星期。
星期一:1或Mo或Mon
星期二:2或Tu或Tue
星期三:3或We或Wed
星期四:4或Th或Thu
星期五:5或Fr或Fri
星期六:6或Sa或Sat
星期天:7或Su或Sun

--contiguous:
When --timestop is smaller than --timestart value, match this as a single time period instead distinct intervals
如果--timestop的參數值小於--timestart的值,將其匹配爲單個時間段,而不是不同的間隔。請參考下面文檔中自己附帶的實例。

這裏文檔中有個示例:
Matching across days might not do what is expected.  For instance,
	-m time --weekdays Mo --timestart 23:00  --timestop 01:00 Will match Monday, for one hour from midnight to 1 a.m., and then
again for another hour from 23:00 onwards.  If this is unwanted,  e.g.  if  you  would  like 'match for two hours from Monday 23:00
onwards' you need to also specify the --contiguous option in the example above.

跨天匹配可能無法達到預期的效果。例如,
-m time --weekdays Mo --timestart 23:00 --timestop 01:00
上面示例匹配的是週一的午夜(0點)到凌晨1點這一小時,以及週一的23點往前一小時。如果不是預期的,可能你只能想匹配從
週一的23:00往後推2小時,可以在上面示例選項中加上--contiguous:
-m time --weekdays Mo --timestart 23:00 --timestop 01:00 --contiguous

--kerneltz:
Use the kernel timezone instead of UTC to determine whether a packet meets the time regulations.
使用內核時區而不是通過UTC來決定是否一個報文滿足時間規則。

示例:在前邊telnet服務訪問控制的基礎上,再加一條規則,只有正常工作日(週一到週五)的上班期間(9:00~17:30)
才能訪問。

[root@gateway ~]# iptables -R INPUT 3 -d 172.16.0.10 -p tcp --dport 23 -m iprange --src-range 172.16.0.1-172.16.0.10 -m time --timestart 9:00:00 --timestop 17:30 --weekdays 1,2,3,4,5 --kerneltz -j ACCEPT
[root@gateway ~]# iptables -R OUTPUT 3 -s 172.16.0.10 -p tcp --sport 23 -m iprange --dst-range 172.16.0.1-172.16.0.10 -m time --timestart 9:00:00 --timestop 17:30 --weekdays 1,2,3,4,5 --kerneltz -j ACCEPT

[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1471  113K ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          multiport dports 22,80
    0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            172.16.0.10          icmptype 8
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          tcp dpt:23 source IP range 172.16.0.1-172.16.0.10 TIME from 09:00:00 to 17:30:00 on Mon,Tue,Wed,Thu,Fri
    7   420 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
 1108  104K ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            multiport sports 22,80
    0     0 ACCEPT     icmp --  *      *       172.16.0.10          0.0.0.0/0            icmptype 0
    0     0 ACCEPT     tcp  --  *      *       172.16.0.10          0.0.0.0/0            tcp spt:23 destination IP range 172.16.0.1-172.16.0.10 TIME from 09:00:00 to 17:30:00 on Mon,Tue,Wed,Thu,Fri
   23  1816 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable
#測試過程略,可以臨時調整提供服務器的服務器上的日期和時間自行測試,我已驗證。

3.6.7、顯式擴展之string

This modules matches a given string by using some pattern matching strategy. It requires a linux kernel >= 2.6.14.
這個模塊可以通過使用一些模式匹配策略來匹配給定的字符串。需要使用環境的linux內核版本高於或者等於2.6.14;

--algo {bm|kmp}
	Select the pattern matching strategy. (bm = Boyer-Moore, kmp = Knuth-Pratt-Morris)
	選擇模式匹配策略。
	PS:bm和kmp相差都不太,對於我們使用來講不需要特別深入研究。可以理解爲不同的實現算法。

--from offset:
	Set the offset from which it starts looking for any matching. If not passed, default is 0.
	設置查找指定模式開始的偏移量。如果沒有指定,默認是0.表示從頭開始搜尋。
	PS:簡單來說就是查找默認從第一個字符開始,如果指定其實偏移量後,會從offset個字符開始。
	
--to offset:
Set the offset up to which should be scanned. That is, byte offset-1 (counting from 0) is the last one that is scanned.  
If not passed, default is the packet size.
指定結束偏移量。默認是整個報文的大小。

[!] --string pattern:
Matches the given pattern.
匹配給定的模式.

[!] --hex-string pattern:
Matches the given pattern in hex notation
匹配給定的16進制標記的模式。

 默認示例:
 Examples:

	# The string pattern can be used for simple text characters.
	iptables -A INPUT -p tcp --dport 80 -m string --algo bm --string 'GET /index.html' -j LOG

	# The hex string pattern can be used for non-printable characters, like |0D 0A| or |0D0A|.
	iptables -p udp --dport 53 -m string --algo bm --from 40 --to 57 --hex-string '|03|www|09|netfilter|03|org|00|'

3.6.8、顯式擴展之connlimit

這個模塊允許你限制每個客戶端IP地址(或客戶端地址塊)到服務器的並行連接數量。

--connlimit-upto n:
Match if the number of existing connections is below or equal n.
匹配現有連接數量是否小於或等於n。

--connlimit-above n:
Match if the number of existing connections is above n
匹配現有連接數量是否大於n。

--connlimit-mask prefix_length:
Group hosts using the prefix length. For IPv4, this must be a number between (including) 0 and 32. For IPv6, between 0 and 128. 
If not specified, the maximum prefix length for the applicable protocol is used.
使用前綴長度對主機進行分組。對於IPv4,這個前綴長度值只是是0到32之前的。對於IPv6而言,只能指定0到128之間的。如果沒有
指定,會使用適用協議最大長度的前綴。

--connlimit-saddr:
Apply the limit onto the source group. This is the default if --connlimit-daddr is not specified.
如果使用前綴長度對主機分組,對於源組應用限制。如果沒有使用--connlimit-daddr選項,該參數就是默認的。

--connlimit-daddr:
Apply the limit onto the destination group.
對於目標組進行限制。

示例說明:
可以部署一個mysql或mariadb服務器。然後做連接併發限制。例如:

iptables -I INPUT 2 -d 172.16.0.10 -s 172.16.0.0/26 -p tcp --dport 3306 -m connlimit --connlimit-upto 2 -j ACCEPT

3.6.9、顯式擴展之limit

瞭解這個擴展模塊的作用和原理,要先了解令牌通算法。請參考:
https://baike.baidu.com/item/令牌桶算法/6597000?fr=aladdin

This module matches at a limited rate using a token bucket filter. A rule using this extension will match until
this limit is reached.It can be used in combination with the LOG target to give limited logging
通過令牌桶過濾器來限制匹配的速率。

--limit rate[/second|/minute|/hour|/day]:
Maximum average matching rate: specified as a number, with an optional `/second', `/minute', `/hour', or `/day' suffix; 
the default is 3/hour.
匹配限制的最大速率。可選後綴有/second表示每秒;/minute表示每分;/hour表示每小時,/day表示每天。
默認值是:每小時3。

--limit-burst number:
Maximum initial number of packets to match: this number gets recharged by one every time the limit specified above is not 
reached, up to this number; the default is 5.
最多可以收集多少個令牌。默認值是5.

示例:

iptables -I INPUT 1 -d 172.16.0.10 -p icmp --icmp-type 8 -m limit --list-burst 5 --limit 20/minute -j ACCPET
iptables -I OUPUT 1 -s 172.16.0.10 -p icmp --icmp-type 0 -j ACCEPT

#限制http的新建連接併發。
iptables -I INPUT 4 -d 172.16.-.10 -p tcp --dport 80 -m tcp --syn -m limit --limit-burst 1000 -limit 800/second -j AACEPT

3.6.10、顯式擴展之state

The “state” extension is a subset of the “conntrack” module. “state” allows access to the connection
tracking state for this packet.
state擴展模塊是conntrack擴展模塊的子集(子模塊)。state允許去訪問報文的連接追蹤狀態。

[!] --state state:
Where state is a comma separated list of the connection states to match. Only a subset of the states unterstood by "conntrack" 
are recognized: INVALID, ESTABLISHED, NEW, RELATED or UNTRACKED.
指定要匹配的追蹤狀態的值,多個值組成的參數列表要使用逗號分隔。
這裏指定的狀態要能被conntrack擴展模塊所識別,在state模塊中可以使用的狀態有:INVALID,ESTABLISHED,NEW,RELATED以及
UNTRACKED。其中每個狀態的含義如下:(這裏的連接千萬不要和tcp的連接混用,這裏的是針對不止tcp協議的,還針對udp,icmp等)

INVALID
	The packet is associated with no known connection.
	報文和未知連接有關係。簡單來說就是異常報文或異常連接,無法識別的連接;
	
ESTABLISHED
	The packet is associated with a connection which has seen packets in both directions.
	已建立的連接。

NEW    
	The packet has started a new connection or otherwise associated with a connection which has not seen packets 
in both directions.
新連接請求。

RELATED
	The packet is starting a new connection, but is associated with an existing connection, such as an FTP data transfer or 
 an ICMP error.
相關聯的連接,當前連接是一個新請求,但附屬於某個已存在的連接;

UNTRACKED
	The packet is not tracked at all, which happens if you explicitly untrack it by using -j CT --notrack in the raw table.
	未追蹤的連接,無法被追蹤。如果在raw表中使用-j ct --notrack顯式地取消跟蹤,就會發生這種情況。

關於連接追蹤,引用一段網上博文其他的話:
http://blog.51cto.com/minux/1727684
iptables/netfilter具有追蹤連接狀態功能,用於描述各會話連接之間的關係型。一般爲四層協議:TCP,UDP,ICMP等;

爲什麼要追蹤連接狀態呢?iptables/netfilter默認規則爲拒絕的情況下,當用戶訪問一個iptables/netfilter允許的服務(端口)的時候,服務器如果想要回復客戶端則還需要爲其設定一個放行的規則(如果有多個就要多個規則),然而這樣每一個服務或應用都手動配置一條規則,規則表會非常多,而且處理效益不高,這是多餘的。當防火牆允許客戶端向服務器通信時,則認爲此連接一定是負荷規則的,與之相對的通信都應該具備可靠性,可以對其他放行。這樣就可以實現一條規則放行所有可信的通信,而不用多條規則。

iptables/netfilter的狀態追蹤由state模塊,state模塊底層依賴於nf_conntrack(2.6內核之前叫做ip_conntrack),nf_conntrack是內核功能,負責具體的連接追蹤的實施。可以通過模塊(lsmod)查看等命令來確認nf_conntrack是否有加載。

nf_conntrack是有限制的,其根據內部算法,會在內核空間所持有的內存區域中記錄各個所追蹤的連接的狀態,並將其映射到/proc/net/nf_conntrack文件中。nf_conntrack連接追蹤的限制由/proc/sys/net/nf_conntrack_max文件控制。

涉及幾個比較重要的文件和目錄:

目錄:
	/proc/sys/net
	/proc/net

文本文件:
	追蹤到的連接:/proc/net/nf_conntrack
	調整可記錄的連接數量最大值:/proc/sys/net/nf_conntrack_max
	超時時長:/proc/sys/net/netfilter/*timeout*

讓我們來簡單看看一個使用案例,對於ftp的主動模式和被動模式的應用可能會用到這個連接追蹤功能。默認有個內核模塊叫nf_conntrack_ftp沒有導入,我們需要導入一下。linux有幾個與模塊管理相關的命令。

lsmod命令:顯示linux內核的狀態信息(被裝載的模塊),這個命令取得原始快照數據是/proc/modules的內容;
modinfo命令:顯示linux內核的模塊的說明信息
	modinfo	[-F field] [-k kernel] [modulename|filename...]
		-F field:僅顯示指定字段的信息;
		-n:顯示文件路徑;
modprobe命令:(動態)裝載或卸載linux內核模塊
	modprobe [-r] module_name
		模塊的動態狀態:modprobe module_name
		動態的卸載:modprobe -r module_name
depmod:內核模塊依賴關係文件的生成工具

另外一組比較不好用的模塊的裝載和卸載工具(主要有時候裝載模塊有依賴關係,要手動解決依賴關係,即先手動掛載依賴的模塊,
而且還要裝載的時候還要指定模塊文件全路徑,具體應用請參考下面實際的例子):
	insmod:裝載指定模塊路徑下指定的模塊;
		insmod [filename] [module options...]
			filename:模塊文件的文件路徑;
	rmmod:卸載指定的模塊(不需要指定全路徑);
		rmmod [module_name]	
								
比如我們想要動態裝載或卸載與ftp相關的內核的連接追蹤模塊:

a) 查看nf_conntrack_ftp模塊是否狀態
[root@gateway ~]# lsmod |grep 'nf_conntrack_ftp'
#沒有結果就表示此模塊並沒有被裝載。

b) 查看nf_conntrack_ftp模塊說明信息
[root@gateway ~]# modinfo nf_conntrack_ftp
filename:       /lib/modules/3.10.0-229.el7.x86_64/kernel/net/netfilter/nf_conntrack_ftp.ko
alias:          nfct-helper-ftp
alias:          ip_conntrack_ftp
description:    ftp connection tracking helper
author:         Rusty Russell <[email protected]>
license:        GPL
rhelversion:    7.1
srcversion:     13050F0A1E370983C87DEA6
depends:        nf_conntrack
intree:         Y
vermagic:       3.10.0-229.el7.x86_64 SMP mod_unload modversions 
signer:         CentOS Linux kernel signing key
sig_key:        A6:2A:0E:1D:6A:6E:48:4E:9B:FD:73:68:AF:34:08:10:48:E5:35:E5
sig_hashalgo:   sha256
parm:           ports:array of ushort
parm:           loose:bool
#此過程可以瞭解模塊文件的絕對路徑以及默認掛載所依賴的模塊。如果使用insmod命令裝載就要考慮這兩個點,如果使用modprobe
不需要過度關心這兩個點。

c) 使用傳統命令(insmod/rmmod)實現模塊的裝載和卸載
裝載:
[root@gateway ~]# insmod /lib/modules/3.10.0-229.el7.x86_64/kernel/net/netfilter/nf_conntrack_ftp.ko 
[root@gateway ~]# lsmod |grep 'nf_conntrack_ftp'
nf_conntrack_ftp       18638  0 
nf_conntrack          105702  3 xt_connlimit,nf_conntrack_ftp,nf_conntrack_ipv4

卸載:
[root@gateway ~]# rmmod nf_conntrack_ftp
[root@gateway ~]# lsmod |grep 'nf_conntrack_ftp'

d) 使用高效命令(modprobe)實現模塊的狀態和卸載
裝載:
[root@gateway ~]# lsmod |grep 'nf_conntrack_ftp'
[root@gateway ~]# modprobe nf_conntrack_ftp
[root@gateway ~]# lsmod |grep 'nf_conntrack_ftp'
nf_conntrack_ftp       18638  0 
nf_conntrack          105702  3 xt_connlimit,nf_conntrack_ftp,nf_conntrack_ipv4

卸載:
[root@gateway ~]# modprobe -r nf_conntrack_ftp 
[root@gateway ~]# lsmod |grep 'nf_conntrack_ftp'

現在先簡單的調整一下防火牆:

#先清空規則
[root@gateway ~]# iptables -F

#加入一些常見服務的端口
[root@gateway ~]# iptables -A INPUT -d 172.16.0.10 -p tcp -m multiport --dports 20:23,80,139,443,445,8080,10020:10540,13721 -m state --state NEW -j ACCEPT
[root@gateway ~]# iptables -I INPUT 1 -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@gateway ~]# iptables -I INPUT 3 -d 172.16.0.10 -j REJECT

#INPUT鏈進來,第一條規則,對於ESTABLISHED和RELATED的狀態,都允許。這樣ftp的主動模式是在命令連接的基礎上,主動
去連接客戶端的,這種主動連接的發起是服務端,這樣的數據連接與命令連接有關係,可以理解爲RELATED狀態的報文。
# 對於tcp協議的本機端口20到23(20默認ftp數據端口,21默認的ssh協議端口,23默認的telnet服務端口),80(默認的http協議的端口)
#139,445這兩個是和samba相關的。443是https協議的端口。8080,10020到10540以及13721我是添加了給測試用的,測試服務使用
#非默認端口

[root@gateway ~]# iptables -A OUTPUT -s 172.16.0.10 -m state --state ESTABLISHED -j ACCEPT
[root@gateway ~]# iptables -A OUTPUT -s 172.16.0.10 -p udp -m multiport --dports 123,323 -m state --state NEW -j ACCEPT
[root@gateway ~]# iptables -A OUTPUT -s 172.16.0.10 -j REJECT
#對於從本機出去的報文,狀態是ESTABLISHED允許。
#對於端口是123,323,協議是udp,這兩個是與本機與外界時間服務器同步相關的,狀態是NEW就是新發起的。


[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  920 72157 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          multiport dports 20:23,80,139,443,445,8080,10020:10540,13721 state NEW
    0     0 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
  417 58728 ACCEPT     all  --  *      *       172.16.0.10          0.0.0.0/0            state ESTABLISHED
    0     0 ACCEPT     udp  --  *      *       172.16.0.10          0.0.0.0/0            multiport dports 123,323 state NEW
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable

服務端啓動vsftpd,然後客戶端去連接並測試上傳數據:

vsftpd的按照下面配置,讓匿名用戶可以寫和上傳:
anonymous_enable=YES
anon_upload_enable=YES
anon_mkdir_write_enable=YES
anon_mkdir_write_enable=YES
connect_from_port_20=YES
port_enable=YES
pasv_enable=YES
pasv_min_port=10020
pasv_max_port=10540
並在匿名用戶家目錄創建一個目錄,可以讓匿名用戶可寫:
[root@gateway ~]# mkdir -pv /var/ftp/pub/uploads
mkdir: created directory ‘/var/ftp/pub/uploads’
[root@gateway ~]# setfacl -m u:ftp:rwx /var/ftp/pub/uploads
[root@gateway ~]# getfacl -p /var/ftp/pub/uploads
# file: /var/ftp/pub/uploads
# owner: root
# group: root
user::rwx
user:ftp:rwx
group::r-x
mask::rwx
other::r-x

[root@gateway ~]# systemctl start vsftpd.service
[root@gateway ~]# ss -tnl
State      Recv-Q Send-Q                                 Local Address:Port                                   Peer Address:Port 
LISTEN     0      128                                                *:22                                                *:*     
LISTEN     0      100                                        127.0.0.1:25                                                *:*     
LISTEN     0      128                                               :::80                                               :::*     
LISTEN     0      32                                                :::21                                               :::*     
LISTEN     0      128                                               :::22                                               :::*     
LISTEN     0      128                                               :::23                                               :::*     
LISTEN     0      100                                              ::1:25                                               :::*    

客戶端測試(默認被動模式):
[root@localhost ~]# ftp 172.16.0.10 21
Connected to 172.16.0.10 (172.16.0.10).
220 (vsFTPd 3.0.2)
Name (172.16.0.10:root): ftp
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
227 Entering Passive Mode (172,16,0,10,39,182).
150 Here comes the directory listing.
drwxr-xr-x    3 0        0              20 Dec 29 10:28 pub
226 Directory send OK.
ftp> cd pub
250 Directory successfully changed.
ftp> ls
227 Entering Passive Mode (172,16,0,10,39,200).
150 Here comes the directory listing.
drwxrwxr-x    2 0        0               6 Dec 29 10:28 uploads
226 Directory send OK.
ftp> cd uploads
250 Directory successfully changed.
ftp> lcd /etc/
Local directory now /etc
ftp> put issue
local: issue remote: issue
227 Entering Passive Mode (172,16,0,10,40,227).  #這裏使用的是被動模式了
150 Ok to send data.
226 Transfer complete.
23 bytes sent in 0.000132 secs (174.24 Kbytes/sec)
ftp> ls
227 Entering Passive Mode (172,16,0,10,40,251).
150 Here comes the directory listing.
-rw-------    1 14       50             23 Dec 29 10:29 issue
226 Directory send OK.
後續步驟略。
#ftp涉及的東西很複雜,而且主動模式和被動模式不是涉獵的這麼簡單,我一直抓包分析都沒有完全弄懂。
#希望後面有專門閱讀過源碼的人指定一番,特別是涉及到開啓防火牆情況下,ftp主動模式傳輸數據通過
#的,並且能以抓包結果證明。(我線上一直都是用的被動模式,ftp主動模式在防火牆開啓情況下,我一直
#沒有調試通過,而且windows的cmd命令工具貌似不給力。)

3.7、處理動作

3.7.1、常用簡單的target

(1) ACCEPT
這個ACCEPT原文註解是:ACCEPT means to let the packet through. ACCEPT意味着讓報文通過;

(2) DROP
DROP means to drop the packet on the floor.DROP以爲在入口或門口就把這個報文給刪掉了。

(3) RETURN
RETURN means stop traversing this chain and resume at the next rule in the previous (calling) chain.
RETURN意味着停止遍歷當前鏈的規則並且繼續之前鏈(之前鏈有調用其他鏈)的下一下規則。
簡單來說在遍歷A鏈規則的時候有調用B鏈,然後遍歷B鏈規則的時候使用RETURN可以返回掉A鏈,並繼續開始
執行匹配A鏈上的規則。

3.7.2、常用擴展的target

(1) REJECT
This is used to send back an error packet in response to the matched packet: otherwise it is equivalent to DROP so it is a terminating TARGET,ending rule traversal.This target is only valid in the INPUT, FORWARD and OUTPUT chains, and user-defined chains which are only called from those chains.The following option controls
the nature of the error packet returned:
REJECT與DROP的區別就是,同樣都是拒絕,DROP就是不給對方迴應,REJECT就是給別人一個錯誤說明。
這個錯誤說明可以自己控制,建議有些場景要使用REJECT。(比如你喜歡一個女孩,你給她送一束花。DROP就
表示這個女孩收到後,什麼都不說;而REJECT就是收到後,告訴你"老孃"已經名花有主了或者說告知你,你是一個好人,我不配你之類的云云)。
REJECT這個target只能用於INPUT,FORWARD,OUTPUT以及調用這三個鏈的用戶自定義的鏈。下面的選項控制返回錯誤數據包的類型。

–reject-with type
The type given can be icmp-net-unreachable, icmp-host-unreachable, icmp-port-unreachable, icmp-proto-unreachable, icmp-net-prohibited, icmp-host-prohibited,or icmp-admin- prohibited (), which return the appropriate ICMP error message (icmp-port-unreachable is the default). The option tcp-reset can be used on rules which only match the TCP protocol: this causes a TCP RST packet to be sent back. This is mainly useful for blocking ident (113/tcp) probes which frequently occur when sending mail to broken mail hosts (which won’t accept your mail otherwise).
(
) Using icmp-admin-prohibited with kernels that do not support it will result in a plain DROP instead of REJECT
上面這一大段話,重點就說明了兩個:
(1) 默認不指定REJECT返回錯誤類型就是 icmp-port-unreachable;
(2) 支持的錯誤類型有:
icmp-net-unreachable
icmp-host-unreachable
icmp-port-unreachable
icmp-proto-unreachable
icmp-net-prohibited
icmp-host-prohibited
icmp-admin- prohibited

(2) LOG
Turn on kernel logging of matching packets.When this option is set for a rule, the Linux kernel will print some
information on all matching packets (like most IP/IPv6 header fields) via the kernel log (where it can be read
with dmesg(1) or read in the syslog).
This is a “non-terminating target”, i.e. rule traversal continues at the next rule. So if you want to LOG the packets
you refuse, use two separate rules with the same matching criteria, first using target LOG then DROP (or REJECT).
打開內核記錄匹配報文日誌的功能。當這個選項被作爲一個規則設置的時候或規則中調用這個LOG的時候,linux的內核會打印一些關於所有匹配報文的信息(像大多數的IP首部字段信息等),默認記錄在內核日誌/var/log/messages中,可以使用syslog和dmesg等程序去做日誌查看(也可以直接是用文本編輯器查看messages日誌)。
這個LOG不是一個終止的target,它只是對於被此規則所匹配到的報文記錄到相應的內核日誌中,然後報文會接着遍歷對應鏈上接下來的規則。如果要想使用內核日誌記錄被拒絕的數據報文的信息,可以使用兩聊獨立的規則,第一條用來記錄日誌,第二條來指定被匹配到後的處理目標動作爲DROP或REJECT。

支持的選項:

-log-level level:
Level of logging, which can be (system-specific) numeric or a mnemonic. Possible  values  are  (in  decreasing
order of priority): emerg, alert, crit, error, warning, notice, info or debug.
記錄的日誌級別。可以使用的值:
emerg,alert,crit,error,warning,notice,info以及debug。
PS:生產環境,建議記錄warning或者notice即可。

--log-prefix prefix:
Prefix  log messages with the specified prefix; up to 29 letters long, and useful for distinguishing messages in
the logs.
可以給記錄的日誌加上前綴信息,最長支持29個字符長度。加前綴的作用可以用來區別不同的日誌記錄。

--log-tcp-sequence:
Log TCP sequence numbers. This is a security risk if the log is readable by users.

--log-tcp-options:
Log options from the TCP packet header.
記錄TCP報文首部的選項信息。

--log-ip-options:
Log options from the IP/IPv6 packet header.
記錄IP報文首部的選項信息。

--log-uid:
Log the userid of the process which generated the packet.
記錄產生數據報文的用戶進程的id信息。

3.8、CentOS 6 和CentOS 7管理、保存和載入防火牆規則區別

保存和載入規則:
保存:iptables-save > /PATH/TO/SOME_RULE_FILE
重載:iptabls-restore < /PATH/FROM/SOME_RULE_FILE
-n, --noflush:不清除原有規則
-t, --test:僅分析生成規則集,但不提交
比如:

#先查看策略
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   26  2080 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          multiport dports 20:23,80,139,443,445,8080,10020:10540,13721 state NEW
    0     0 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   23  2180 ACCEPT     all  --  *      *       172.16.0.10          0.0.0.0/0            state ESTABLISHED
    0     0 ACCEPT     udp  --  *      *       172.16.0.10          0.0.0.0/0            multiport dports 123,323 state NEW
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable
 
#把策略備份   
[root@gateway ~]# iptables-save >/tmp/iptables.back1
#清空策略
[root@gateway ~]# iptables -F
#確認策略
[root@gateway ~]# iptables -vnL
Chain INPUT (policy ACCEPT 21 packets, 1640 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 18 packets, 1532 bytes)
 pkts bytes target     prot opt in     out     source               destination     

#載入策略
[root@gateway ~]# iptables-restore </tmp/iptables.back1 

#確認
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   26  2080 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
    0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            172.16.0.10          multiport dports 20:23,80,139,443,445,8080,10020:10540,13721 state NEW
    0     0 REJECT     all  --  *      *       0.0.0.0/0            172.16.0.10          reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   23  2180 ACCEPT     all  --  *      *       172.16.0.10          0.0.0.0/0            state ESTABLISHED
    0     0 ACCEPT     udp  --  *      *       172.16.0.10          0.0.0.0/0            multiport dports 123,323 state NEW
    0     0 REJECT     all  --  *      *       172.16.0.10          0.0.0.0/0            reject-with icmp-port-unreachable 
CentOS 6:
	保存規則:
		service iptables save
		保存規則於/etc/sysconfig/iptables文件,覆蓋保存;
		重載規則:
			service iptables restart
		默認重載/etc/sysconfig/iptables文件中的規則 
	
		配置文件:/etc/sysconfig/iptables-config
		
CentOS 7:
	(1) 自定義Unit File,進行iptables-restore;
	(2) firewalld服務;
	(3) 自定義腳本;

四、主機防火牆、網絡防火牆和NAT

4.1、主機防火牆和網絡防火牆以及實驗環境圖解

簡單梳理一下防火牆的netfilter框架的流程:
四表五鏈(CentOS 6.x),五表五鏈(CentOS 7.x),按照從高到低的應用的優先順序依次爲:raw,mangle,nat,filter。這裏沒有給出security,是因爲應用的不多,而且是爲了selinux新增的一個表,selinux本身大部分公司都不會去用,所以這裏沒有給出來。

filter表示實現的功能是過濾,也是真正意義上的防火牆的核心意義之所在,只有它纔算得上是防火牆,其他幾個表實現的功能都已經是額外的其他功能了。這幾個額外的功能是我們內核中用來實現操縱通信報文的其他幾個功能,比如nat用來實現網絡地址轉換(源地址轉換或目標地址轉換都是可行的),mangle理解爲做報文修改用的,除了地址轉換、端口轉換以外的報文首部的其他報文的信息的修改,都可以在mangle中實現,在mangle中應用比較多的是實際上是一種防火牆打標的功能,可以把任何報文經過防火牆之後,給它加一標記,分分類,通常用來做分類器,比如訪問目標端口是TCP的80的給它標記爲1,訪問目標端口是TCP的21的標記爲2的給,將來可以基於分類標識符來實現做報文識別而不要再基於所謂的端口和地址了。raw表所提供的主要功能主要是關閉nat表所打開的連接追蹤功能,如果某些功能,我們不打算去追蹤,只是做地址轉換,而且轉換後只有出去的報文沒有回來的報文,此時,我們就不需要去做追蹤。

進出本地netfilter框架的協議報文大概可以分爲三個流程:
(1)進入本機
先經過PREROUTING,然後是INPUT

(2)經由本機轉發的
先經過PREROUTING,然後是FORWARD,其次是POSTROUTING

(3)經由本機發出的
先是OUTPUT,然後是POSTROUTING
弄清上面三個協議報文的流程非常重要,因爲我們寫規則的時候要弄清楚誰是源,誰是目標以及規則添加該添加在何處。對於一個主機來講,接口網卡可能有多個。任何時候,剛剛到達本機還沒有進行路由之前的都要先經過PREROUTING處理,無論是經過OUTPUT還是FORWARD之後將要離開本機,還未路由決定經過哪一個網卡出去的,都會經過POSTROUTING處理。也就是所,報文的流向和網卡的前後左右,和網卡的數量沒有關係,任何時候從一個網卡進來,也有可能從同一個網卡出去,我們要注意的都只是報文的流向,即我們上面強調的協議報文的流程。

剛剛進來,還未進入本機的是PREROUTING,快要出去,的經過是POSTROUTING。進入本機後,有三個比較核心的鏈,分別是INPUT,FORWARD以及OUTPUT,這些位置也是我們通常做報文深入控制的位置,不管怎麼講,這些鏈路上的控制無非是上文中提到的三個流程或者流向。

對於一臺主機來講,如果我們用來做單機防火牆,我們只需要管兩個流程:
進入本機的和從本機發出的。對於這種情況,如果要阻斷某些應用或服務,我們有兩種方式,第一,直接在報文進入的入口處進行阻斷,即在INPUT鏈上設置。第二,可以讓報文進來,不然它出去,就是在報文的出口處進行阻斷,即在OUTPUT鏈上設置。這兩種方式,前一種比較高效,一般寫規則的時候,我們會有一種習慣。如果是別人訪問自己的,我們先寫在INPUT鏈上寫策略,如果是自己訪問別人的,我們先在OUTPUT鏈上寫規則。邏輯是:先去規劃請求報文,再去規劃響應報文。

對於過濾來講,filter表上實現的鏈有INPUT,FORWARD以及OUTPUT;
對於網絡地址來講,nat表上實現的鏈有PREROUTING,INPUT(CentOS6上沒有,CentOS7上引入的),OUTPUT以及POSTROUTING。如果主機既要實現單機防火牆,也要實現網絡防火牆,就涉及上面的三個流程的,而且作爲網絡防火牆,要打開主機上的核心轉發功能,對於路由條目,要先能實現主機自我學習,還要配合上對應的軟件實現。通常來講,如果是要做專業的網絡防火或者是路由功能,建議購買專業的硬件,如果只是簡單的實現網絡報文控制,可以把主機作爲防火牆或路由器。

所謂網關,任何非本地網絡通信的報文都要經由網關設備來做轉發。這個網關設備可能是一個硬件的路由器。
非本機主機通信,要把網絡報文交給下一跳主機。TCP/IP通信有個前提,跨網絡通信,報文必須要經過路由設備路由來完成把報文從一個網絡轉交給另外一個網絡。這個網關可能也有連接到N個下一跳的網關,當報文抵達此網關時候,要把下一跳交給哪一個網關,是經由路由決策的。網關設備會有對應的路由條目。當報文抵達網關的時候,網關會先判斷報文是不是就是請求我們本地網絡的。如果對方訪問報文的目標地址根本不是本地而是遠程主機。根據報文的目標地址,去路由條目中選一個合適的路由條目來決定下一跳網關是誰,先找路由條目中的主機路由,如果沒有主機路由,再找網絡路由,網絡路由網絡匹配最小的優先被選擇。這些都是基本的判斷,其實路由決策過程遠不止如此。
如果上面決策都沒有符合的,會把網絡報文交給默認網關。對於本地通信和跨網絡通信還涉及一個子網掩碼,會把請求報文的目標ip和所在網絡的子網掩碼做與運行,然後把本地網絡的子網掩碼與請求報文的目標ip做一個與運行,對二者結果進行比較,如果相同就表示是本地通信,如果不同就是跨網絡通信,跨網絡通信就涉及到網關和路由了。

基本過程,如下圖所示:
在這裏插入圖片描述

非單機實驗環境圖解:
在這裏插入圖片描述

X主機(只有內網):

[root@localhost ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.4  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::20c:29ff:fe64:344  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:64:03:44  txqueuelen 1000  (Ethernet)
        RX packets 487  bytes 44189 (43.1 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 278  bytes 33283 (32.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 152  bytes 11680 (11.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 152  bytes 11680 (11.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        
#純內網主機,其默認的網關指向的是C主機的內網網卡接口   
[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.10.254  0.0.0.0         UG    100    0        0 eno16777736
192.168.10.0    0.0.0.0         255.255.255.0   U     100    0        0 eno16777736        

C主機(內外網,路由主機):

#路由主機,eno16777736接口是外網接口,ens37接口是內網接口,也是內網主機的默認網關指向
[root@gateway ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.16.0.10  netmask 255.255.0.0  broadcast 172.16.255.255
        inet6 fe80::20c:29ff:fe85:868d  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:85:86:8d  txqueuelen 1000  (Ethernet)
        RX packets 693  bytes 64962 (63.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 618  bytes 81256 (79.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens37: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.254  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::20c:29ff:fe85:8697  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:85:86:97  txqueuelen 1000  (Ethernet)
        RX packets 258  bytes 32050 (31.2 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 458  bytes 40547 (39.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Y主機(有外網環境):

#Y主機是和C主機外網在一個網絡中的主機,正常情況,應該是Y主機屬於額外一個網絡。C主機到Y主機可以經過層層路由抵達,
#反之亦然,這裏爲了方便所以就直接把Y主機配置的和C主機外網互通(如果不這樣做,要額外添加路由條目,使得C所在網絡能
#抵達Y所在網絡)。
[root@localhost ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.16.0.120  netmask 255.255.0.0  broadcast 172.16.255.255
        inet6 fe80::20c:29ff:fe4d:d522  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:4d:d5:22  txqueuelen 1000  (Ethernet)
        RX packets 102  bytes 10334 (10.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 112  bytes 11529 (11.2 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

實驗步驟:
(1) 先清空三臺主機的防火牆,做簡單的icmp協議測試(如果默認的firewalld服務有啓動,先關掉它)

iptables -F可以清空filter表的三條鏈INPUT,FORWARD以及OUTPUT上的策略。
systemctl stop firewalld.service #關掉firewalld服務

路由主機ping一下外網主機和內網主機:

默認的核心轉發功能沒有開啓的。
[root@gateway ~]# cat /proc/sys/net/ipv4/ip_forward
0
[root@gateway ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.16.0.10  netmask 255.255.0.0  broadcast 172.16.255.255
        inet6 fe80::20c:29ff:fe85:868d  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:85:86:8d  txqueuelen 1000  (Ethernet)
        RX packets 1092  bytes 101367 (98.9 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 960  bytes 125270 (122.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens37: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.254  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::20c:29ff:fe85:8697  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:85:86:97  txqueuelen 1000  (Ethernet)
        RX packets 408  bytes 53843 (52.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 734  bytes 63455 (61.9 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
 
 #ping測試OK
[root@gateway ~]# ping 172.16.0.120
PING 172.16.0.120 (172.16.0.120) 56(84) bytes of data.
64 bytes from 172.16.0.120: icmp_seq=1 ttl=64 time=1.28 ms
^C
--- 172.16.0.120 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 1.285/1.285/1.285/0.000 ms
[root@gateway ~]# ping 192.168.10.4
PING 192.168.10.4 (192.168.10.4) 56(84) bytes of data.
64 bytes from 192.168.10.4: icmp_seq=1 ttl=64 time=64.9 ms
^C
--- 192.168.10.4 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 64.978/64.978/64.978/0.000 ms  

內網主機ping一下路由主機的內網和外網接口ip以及另外一臺有外網的主機:
[root@localhost ~]# ping 192.168.10.254
PING 192.168.10.254 (192.168.10.254) 56(84) bytes of data.
64 bytes from 192.168.10.254: icmp_seq=1 ttl=64 time=0.394 ms
64 bytes from 192.168.10.254: icmp_seq=2 ttl=64 time=0.449 ms
^C
--- 192.168.10.254 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.394/0.421/0.449/0.034 ms
#這裏ping路由主機的外網網卡也通了,並不是實現了轉發。因爲內網主機的網關指向的是192.168.10.254,而172.16.0.10只是這個網關
#所在主機的另外一塊不同的網卡而已,在內網中,當報文請求網關的其他接口的時候,也會正常返回請求的報文。
[root@localhost ~]# ping 172.16.0.10
PING 172.16.0.10 (172.16.0.10) 56(84) bytes of data.
64 bytes from 172.16.0.10: icmp_seq=1 ttl=64 time=0.349 ms
^C
--- 172.16.0.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.349/0.349/0.349/0.000 ms

#ping另外一臺是ping不同的,默認情況
[root@localhost ~]# ping 172.16.0.120
PING 172.16.0.120 (172.16.0.120) 56(84) bytes of data.
^C
--- 172.16.0.120 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2000ms

外網主機ping一下路由主機的內外網以及只有內網環境的主機:
[root@localhost ~]# ping 172.16.0.10
PING 172.16.0.10 (172.16.0.10) 56(84) bytes of data.
64 bytes from 172.16.0.10: icmp_seq=1 ttl=64 time=0.362 ms
^C
--- 172.16.0.10 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.362/0.362/0.362/0.000 ms
#ping路由的內網接口不同。
[root@localhost ~]# ping 192.168.10.254
PING 192.168.10.254 (192.168.10.254) 56(84) bytes of data.
^C
--- 192.168.10.254 ping statistics ---
5 packets transmitted, 0 received, 100% packet loss, time 4000ms      

#ping另外一臺只有內網的主機不通
[root@localhost ~]# ping 192.168.10.4
PING 192.168.10.4 (192.168.10.4) 56(84) bytes of data.
^C
--- 192.168.10.4 ping statistics ---
2 packets transmitted, 0 received, 100% packet loss, time 999ms

(2) 現在要實現192.168.10.4主機能ping通172.16.0.120,抓包分析

在主機192.168.10.4上啓動ping 172.16.0.120:
[root@localhost ~]# ping 172.16.0.120
PING 172.16.0.120 (172.16.0.120) 56(84) bytes of data.
......#這裏默認是ping不通的

雙網卡主機抓包,抓內網接口的icmp協議的包:
[root@gateway ~]# tcpdump -i ens37 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens37, link-type EN10MB (Ethernet), capture size 262144 bytes
00:39:43.257467 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 88, length 64
00:39:44.257556 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 89, length 64
00:39:45.257587 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 90, length 64
00:39:46.257644 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 91, length 64
00:39:47.257679 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 92, length 64
^C
5 packets captured
5 packets received by filter
0 packets dropped by kernel
#這裏被我中斷了,這臺主機會收到192.168.10.4到172.16.0.120的ping請求的報文。爲啥不同還要看外網接口的回包情況。

雙網卡主機抓包,抓外網接口的icmp協議的包:
[root@gateway ~]# tcpdump -i eno16777736 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
#默認情況這裏沒有報文,因爲核心轉發沒有啓用的緣故,所以當主機接收到從192.168.10.4到172.16.0.120的報文的時候,不會處理。
#因爲已經跨網絡通信了。

開啓核心轉發:
[root@gateway ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
[root@gateway ~]# cat /proc/sys/net/ipv4/ip_forward
1
開啓核心轉發後抓包效果:
[root@gateway ~]# tcpdump -i ens37 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens37, link-type EN10MB (Ethernet), capture size 262144 bytes
00:43:19.331513 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 304, length 64
00:43:20.331656 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 305, length 64
00:43:21.331724 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 306, length 64
00:43:22.331749 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 307, length 64
00:43:23.331812 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 308, length 64
00:43:24.331752 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 309, length 64

[root@gateway ~]# tcpdump -i eno16777736 -nn icmp #外網接口有抓到報文情況了。
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
00:43:24.331811 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 309, length 64
00:43:24.333248 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4431, seq 309, length 64
00:43:25.332019 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 310, length 64
00:43:25.334025 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4431, seq 310, length 64
00:43:26.332994 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 311, length 64
00:43:26.335054 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4431, seq 311, length 64
00:43:27.333038 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 312, length 64

抓包一下172.16.0.120外網主機外網接口的icmp協議報文情況:
[root@localhost ~]# tcpdump -i eno16777736 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
00:46:00.351971 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 465, length 64
00:46:00.352026 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4431, seq 465, length 64
00:46:01.351916 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 466, length 64
00:46:01.351963 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4431, seq 466, length 64
00:46:02.352061 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4431, seq 467, length 64
00:46:02.352116 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4431, seq 467, length 64

#看一下172.16.0.120的默認網關
[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.0.2      0.0.0.0         UG    100    0        0 eno16777736
172.16.0.0      0.0.0.0         255.255.0.0     U     100    0        0 eno16777736
#由於默認的網關指向的是172.16.0.2,當收到192.168.10.4的報文,從路由主機轉過來之後,主機172.16.0.120有回包,不過默認是把
報文回給默認的網關了,現在如果要想192.168.10.4主機能正常收到請求,要先讓172.16.0.120的默認回包會給172.16.0.10接口。

在外網主機上加一條網絡路由,讓到達192.168.10.0/24網絡的報文的下一跳指向172.16.0.10,即路由主機的外網接口
命令:route add -net 192.168.10.0/24 gw 172.16.0.10
執行:
[root@localhost ~]# route add -net 192.168.10.0/24 gw 172.16.0.10
[root@localhost ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.16.0.2      0.0.0.0         UG    100    0        0 eno16777736
172.16.0.0      0.0.0.0         255.255.0.0     U     100    0        0 eno16777736
192.168.10.0    172.16.0.10     255.255.255.0   UG    0      0        0 eno16777736

然後再去看內網主機對172.16.0.120的ping請求就通了:
[root@localhost ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.4  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::20c:29ff:fe64:344  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:64:03:44  txqueuelen 1000  (Ethernet)
        RX packets 1581  bytes 135576 (132.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 1385  bytes 160595 (156.8 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 300  bytes 23012 (22.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 300  bytes 23012 (22.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@localhost ~]# ping 172.16.0.120
PING 172.16.0.120 (172.16.0.120) 56(84) bytes of data.
64 bytes from 172.16.0.120: icmp_seq=1 ttl=63 time=3.96 ms
64 bytes from 172.16.0.120: icmp_seq=2 ttl=63 time=0.904 ms
^C
--- 172.16.0.120 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 0.904/2.434/3.965/1.531 ms

此時路由主機外網網卡抓包即有請求報文,也有響應報文:
[root@gateway ~]# tcpdump -i eno16777736 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
00:59:13.562763 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4813, seq 1, length 64
00:59:13.563408 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4813, seq 1, length 64
00:59:14.565239 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4813, seq 2, length 64
00:59:14.565611 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4813, seq 2, length 64
00:59:15.566337 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4813, seq 3, length 64
00:59:15.566784 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4813, seq 3, length 64
00:59:16.568321 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4813, seq 4, length 64
00:59:16.568691 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4813, seq 4, length 64
00:59:17.570339 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4813, seq 5, length 64
00:59:17.570730 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4813, seq 5, length 64
00:59:18.572441 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 4813, seq 6, length 64
00:59:18.572907 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 4813, seq 6, length 64
^C

4.2、NAT概述

引用百科:
https://baike.baidu.com/item/nat/320024?fr=aladdin

NAT(Network Address Translation,網絡地址轉換)是1994年提出的。當在專用網內部的一些主機本來已經分配到了本地IP地址(即僅在本專用網內使用的專用地址),但現在又想和因特網上的主機通信(並不需要加密)時,可使用NAT方法。
這種方法需要在專用網連接到因特網的路由器上安裝NAT軟件。裝有NAT軟件的路由器叫做NAT路由器,它至少有一個有效的外部全球IP地址。這樣,所有使用本地地址的主機在和外界通信時,都要在NAT路由器上將其本地地址轉換成全球IP地址,才能和因特網連接。
另外,這種通過使用少量的公有IP 地址代表較多的私有IP 地址的方式,將有助於減緩可用的IP地址空間的枯竭。在RFC 2663中有對NAT的說明。

NAT的主要功能早期是用來隱藏主機的。任何內網主機之間進行通信,純網關設備僅僅是將報文實現跨網絡間轉發的,純網關設備不會修改報文的源ip和目標ip。當本地客戶端請求互聯網的時候,如果地址沒有實現轉換,就會
暴露客戶的ip信息,下次你上網的時候,別人會利用你這個暴露的信息善加利用後,攻擊你內部的主機。這樣
本不是我們的本意,我們的本意就是爲了訪問互聯網,而且大部分的終端用戶都沒有安全意思,他們使用的
用於請求互聯網的終端設備大部分都沒有做安全或者開啓防火牆,所以爲了上網而不得不把自己處於這樣一個
尷尬的處境是我們本不想遇見的。
現在我們的NAT就可以實現這樣的功能。都知道,如果本地客戶端跨網絡訪問互聯網,都要經過一個叫做網關的
設備,如果對於經過網關的設備,我們把都請求報文的源地址給它修改成網關設備的外網接口的地址,這樣就可
做到隱藏客戶端主機信息的目的。而網關設備,我們可以做到安全加強。

我們今天這裏介紹的主要是兩個,一個是SNAT,一個是DNAT,分別是源網絡地址轉換以及目標網絡地址轉換。
在瞭解NAT前,我們先來看看路由的簡單圖解:
在這裏插入圖片描述

因爲本人網絡知識水平有限,也只能理解到這種程度,後續如果學術提升,會過來補充不足。

4.3、SNAT

SNAT圖解:
在這裏插入圖片描述

This target is only valid in the nat table, in the POSTROUTING and INPUT chains, and user-defined chains which are only called from those chains. It specifies that the source address of the packet should be modified (and all future packets in this connection will also be mangled), and rules should cease being examined. It takes the following options:
SNAT這個target只有在nat表中使用纔有效。在nat 的POSTROUTING以及INPUT鏈(當然包括從這兩個鏈上調用的其他用戶的自定義鏈。這個target指定應該去修改報文的源地址。(因爲修改源地址的關係,這個鏈接中將來所有的報文都將被破壞),並且應該停止規則的檢查。

以下是它選項以及含義:

--to-source [ipaddr[-ipaddr]][:port[-port]]
	which can specify a single new source IP address, an inclusive range of IP addresses. Optionally a port range, if the rule also
specifies one of the following protocols: tcp, udp, dccp or sctp.  If no port range is specified, then source ports below 512 will be
mapped to other ports below 512: those between 512  and 1023 inclusive will be mapped to ports below 1024, and other ports will
be mapped to 1024 or above. Where possible, no port alteration will occur.  In Kernels up to 2.6.10, you can add several --to-source
options. For those kernels, if you specify more than one source address, either via an address range or multiple --to-source
options,  a  simple  round-robin  (one after another in cycle) takes place between these addresses.  Later Kernels (>= 2.6.11-rc1)
don't have the ability to NAT to multiple ranges anymore.
指定單個新的源IP地址,也可以是一個地址範圍。如果規則也指定了一下協議:tcp,udp,dccp或者sctp,可以使用端口範圍。
如果沒有指定端口範圍,端口有3個邊界值。對於源端口是512以下的會被映射成512以下的其他端口;對於在512到1023幷包括1023
邊界的這個範圍內的端口,講會被映射成1024以下的端口;對於其他端口,講會被映射成1024以及1024以上的端口。
如果可能的話,不會有端口被轉換。
對於linux的2.6.10內核以前,可以使用--to-source選項指定不止一個源地址。可以指定一個地址範圍或者使用多次--to-source多次來
指定多個源地址。如果有多個源地址(不管是什麼形式給出的),默認情況,每匹配一個報文,做源地址轉換,要被轉換成的源地址的
值按照依次輪循的方式從這個指定的多個源地址中去取得。
在2.6.11-rc1版本的內核之後,再也沒有能力處理多個地址範圍的能力(這裏這句話我不太懂,我手冊查看的是CentOS 7版本的
iptables,CentOS 7上內核版本是3.10,是大於2.6.11的。我理解這裏的意思應該是之前內核版本可以使用多次--to-source選項,比如
--to-source=172.16.0.10 --to-source=172.16.0.11或--to-source=172.16.0.0/24。而2.6.11-rc1內核版本之後,不支持多個--to-source選
項,只能使用--to-source=netaddress/prefix這種形式來表示多個地址)。

--random
	If option --random is used then port mapping will be randomized (kernel >= 2.6.21).
如果--random選項被使用,端口映射將會隨機。(應用於2.6.21以及之後的內核版本)。
額外說明:
上文中有提到,做源地址轉換,可以指定單個要轉換成的源地址,也可以指定一個地址範圍,一個地址範圍就對應有多個地址。
對於多個地址,默認策略是輪循。每當一個報文被匹配後,去這個多個可選的源地址中取一個地址作爲要被報文要被轉換的源
地址,然後下一個報文過來並且符合匹配條件,然後會依次輪循去取指定的可選的其他源地址。如果配合--random選項後,會
隨機從指定的可選的多個源地址中選擇一個。


 --persistent
	Gives a client the same source-/destination-address for each connection.  This supersedes the SAME target. Support for
	 persistent mappings is  available  from	2.6.29-rc2.Kernels prior to 2.6.36-rc1 don't have the ability to SNAT in the INPUT chain.
	IPv6 support available since Linux kernels >= 3.7.
對於每一個來自於同一個客戶端的連接,指定要轉換的源地址或目標地址是固定的。它的作用會覆蓋--random的效果。

實例:
在這裏插入圖片描述

實驗說明。這裏使用192.168.10.4來模擬內網環境。然後雙網卡主機(192.168.10.254模擬路由的內網接口,
172.16.0.10模擬路由的外網接口)模擬路由設備,使用172.16.0.120來模擬互聯網上的外網主機。
現在要求,從內網主機上網(這裏就模擬請求172.16.0.120,icmp協議和http協議訪問)。然後再172.16.0.120上抓
包看到對應請求報文的源地址應該是172.16.0.10.這樣能簡單模擬SNAT應用。

192.168.10.4主機的網關指向的是192.168.10.254接口。由於172.16.0.10和172.16.0.120都指向網關172.16.0.2.
而且它們是同一個網段,可以理解爲從172.16.0.120向172.16.0.10的響應報文不會跨網絡,也就是說不會涉及
172.16.0.2這個網關設備。現實生活中,web主機和路由主機外網幾乎不可能在一個網段。

(1) 確認網關服務器的核心轉發有開啓
[root@gateway ~]# cat /proc/sys/net/ipv4/ip_forward
1

(2) 清空nat表的規則,還有過濾表的一併清空了,方便後邊測試使用
[root@gateway ~]# iptables -F
[root@gateway ~]# iptables -t nat -F
[root@gateway ~]# iptables -nvL
Chain INPUT (policy ACCEPT 53 packets, 4521 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 44 packets, 3998 bytes)
 pkts bytes target     prot opt in     out     source               destination         
[root@gateway ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination  

(3) 網關主機上添加防火牆規則
#這裏做SNAT一定要在路由後做才比較合適。如果報文剛剛抵達主機,直接在路由前做了,如果請求報文剛好
訪問的是本機,那麼修改源地址後,這樣會繞一大圈。所以是路由後,選定了要從哪個接口出去,然後再做源地址
修改比較合適。所以要在nat表的POSTROUTING鏈上做,上面有提到的nat表的的INPUT鏈也行,不過用的比較少。
通過INPUT鏈,也是路由後的報文了。

#這裏在中轉服務器的nat表的POSTROUTING鏈上添加了一條規則。凡是源地址是192.16.10.0/24這個網絡的,請求目標主機
是任意主機,以及請求報文協議是任意協議的報文,統一做SNAT,然後修改請求報文後的源地址爲172.16.0.10(網關主機的外網
接口地址)。這裏因爲網關接口只有一個外網地址,所以這裏不涉及--to-source的參數爲多個源地址。所以另外兩個選項--random和
--persistent沒有作用。


[root@gateway ~]# iptables -t nat -A POSTROUTING -s 192.168.10.0/24 -j SNAT --to-source=172.16.0.10
[root@gateway ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 SNAT       all  --  *      *       192.168.10.0/24      0.0.0.0/0            to:172.16.0.10

(4) 在內網主機192.168.10.4主機請求172.16.0.120提供的web服務
[root@localhost ~]# curl http://172.16.0.120
<h1>172.16.0.120 server</h1>

(5) 在172.16.0.120主機上抓取tcp協議的80的報文的數據包
[root@localhost ~]# tcpdump -i eno16777736 -nn tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
15:31:12.451262 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [S], seq 1675037329, win 14600, options [mss 1460,sackOK,TS val 143300578 ecr 0,nop,wscale 6], length 0
15:31:12.451335 IP 172.16.0.120.80 > 172.16.0.10.58940: Flags [S.], seq 165137782, ack 1675037330, win 14480, options [mss 1460,sackOK,TS val 143312619 ecr 143300578,nop,wscale 6], length 0
15:31:12.457888 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 143300583 ecr 143312619], length 0
15:31:12.458061 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [P.], seq 1:77, ack 1, win 229, options [nop,nop,TS val 143300584 ecr 143312619], length 76: HTTP: GET / HTTP/1.1
15:31:12.458098 IP 172.16.0.120.80 > 172.16.0.10.58940: Flags [.], ack 77, win 227, options [nop,nop,TS val 143312625 ecr 143300584], length 0
15:31:12.458825 IP 172.16.0.120.80 > 172.16.0.10.58940: Flags [P.], seq 1:271, ack 77, win 227, options [nop,nop,TS val 143312627 ecr 143300584], length 270: HTTP: HTTP/1.1 200 OK
15:31:12.462762 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [.], ack 271, win 245, options [nop,nop,TS val 143300589 ecr 143312627], length 0
15:31:12.462801 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [F.], seq 77, ack 271, win 245, options [nop,nop,TS val 143300590 ecr 143312627], length 0
15:31:12.462960 IP 172.16.0.120.80 > 172.16.0.10.58940: Flags [F.], seq 271, ack 78, win 227, options [nop,nop,TS val 143312631 ecr 143300590], length 0
15:31:12.465995 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [.], ack 272, win 245, options [nop,nop,TS val 143300592 ecr 143312631], length 0
註解壽命:
請求報文源地址是172.16.0.10,源端口是58940,目標地址是172.16.0.120,目標端口是80.在外網主機看來,請求報文的源地址已經
是中轉服務器的外網地址,源地址已經做了轉換。
響應報文源地址是172.16.0.120,源端口是80,目標地址是172.16.0.10,目標端口是58940.這裏是我剛好讓中轉服務器的外網接口和
外網設備172.16.0.120在同一個網段,實際生活中。內部主機請求的外網與官關設備外網接口地址不在一個網絡內。那麼這個外網設
就要經過層層路由或者路由中繼包請求報文轉交給對應172.16.0.120所在網絡內的路由。(這就是我們上問引入路由概念的時候的說
到過的。)


(6) 在192.168.10.4主機上抓取tcp協議的80的報文的數據包
[root@localhost ~]# tcpdump -i eno16777736 -nn tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 65535 bytes
23:31:21.538381 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [S], seq 1675037329, win 14600, options [mss 1460,sackOK,TS val 143300578 ecr 0,nop,wscale 6], length 0
23:31:21.542391 IP 172.16.0.120.80 > 192.168.10.4.58940: Flags [S.], seq 165137782, ack 1675037330, win 14480, options [mss 1460,sackOK,TS val 143312619 ecr 143300578,nop,wscale 6], length 0
23:31:21.542740 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 143300583 ecr 143312619], length 0
23:31:21.544243 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [P.], seq 1:77, ack 1, win 229, options [nop,nop,TS val 143300584 ecr 143312619], length 76
23:31:21.548095 IP 172.16.0.120.80 > 192.168.10.4.58940: Flags [.], ack 77, win 227, options [nop,nop,TS val 143312625 ecr 143300584], length 0
23:31:21.549260 IP 172.16.0.120.80 > 192.168.10.4.58940: Flags [P.], seq 1:271, ack 77, win 227, options [nop,nop,TS val 143312627 ecr 143300584], length 270
23:31:21.549299 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [.], ack 271, win 245, options [nop,nop,TS val 143300589 ecr 143312627], length 0
23:31:21.550056 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [F.], seq 77, ack 271, win 245, options [nop,nop,TS val 143300590 ecr 143312627], length 0
23:31:21.552296 IP 172.16.0.120.80 > 192.168.10.4.58940: Flags [F.], seq 271, ack 78, win 227, options [nop,nop,TS val 143312631 ecr 143300590], length 0
23:31:21.552357 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [.], ack 272, win 245, options [nop,nop,TS val 143300592 ecr 143312631], length 0
註解說明:
請求報文源地址是192.168.10.4,源端口是隨機端口58940,目標地址是172.16.0.120,目標端口是80;
響應報文源地址是172.168.10.4,,源端口是80,目標地址是192.168.10.4,目標端口是58940.
因爲這臺主機是內網主機,發起請求的時候,上面的源ip,源端口,目標ip,目標端口都是正常的。



(7) 在中轉服務器的內外網接口上抓取tcp協議的80的報文的數據包
內網接口:
[root@gateway ~]# tcpdump -i ens37 -nn tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens37, link-type EN10MB (Ethernet), capture size 262144 bytes
15:31:12.446798 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [S], seq 1675037329, win 14600, options [mss 1460,sackOK,TS val 143300578 ecr 0,nop,wscale 6], length 0
15:31:12.449705 IP 172.16.0.120.80 > 192.168.10.4.58940: Flags [S.], seq 165137782, ack 1675037330, win 14480, options [mss 1460,sackOK,TS val 143312619 ecr 143300578,nop,wscale 6], length 0
15:31:12.452460 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 143300583 ecr 143312619], length 0
15:31:12.452658 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [P.], seq 1:77, ack 1, win 229, options [nop,nop,TS val 143300584 ecr 143312619], length 76: HTTP: GET / HTTP/1.1
15:31:12.455071 IP 172.16.0.120.80 > 192.168.10.4.58940: Flags [.], ack 77, win 227, options [nop,nop,TS val 143312625 ecr 143300584], length 0
15:31:12.456843 IP 172.16.0.120.80 > 192.168.10.4.58940: Flags [P.], seq 1:271, ack 77, win 227, options [nop,nop,TS val 143312627 ecr 143300584], length 270: HTTP: HTTP/1.1 200 OK
15:31:12.458805 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [.], ack 271, win 245, options [nop,nop,TS val 143300589 ecr 143312627], length 0
15:31:12.458948 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [F.], seq 77, ack 271, win 245, options [nop,nop,TS val 143300590 ecr 143312627], length 0
15:31:12.459942 IP 172.16.0.120.80 > 192.168.10.4.58940: Flags [F.], seq 271, ack 78, win 227, options [nop,nop,TS val 143312631 ecr 143300590], length 0
15:31:12.461385 IP 192.168.10.4.58940 > 172.16.0.120.80: Flags [.], ack 272, win 245, options [nop,nop,TS val 143300592 ecr 143312631], length 0
內網接口抓包,請求報文的源地址沒有轉換,也就是說內核中抵達192.168.10.254網絡接口後,報文還未提交給172.16.0.10網卡
接口的報文發送隊列中。(應該在中轉或叫路由服務器上的外網網卡抓包的結果,請求報文的源地址已經轉換過了)。


外網接口:
[root@gateway ~]# tcpdump -i eno16777736 -nn tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
15:31:12.446889 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [S], seq 1675037329, win 14600, options [mss 1460,sackOK,TS val 143300578 ecr 0,nop,wscale 6], length 0
15:31:12.449623 IP 172.16.0.120.80 > 172.16.0.10.58940: Flags [S.], seq 165137782, ack 1675037330, win 14480, options [mss 1460,sackOK,TS val 143312619 ecr 143300578,nop,wscale 6], length 0
15:31:12.452555 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 143300583 ecr 143312619], length 0
15:31:12.452674 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [P.], seq 1:77, ack 1, win 229, options [nop,nop,TS val 143300584 ecr 143312619], length 76: HTTP: GET / HTTP/1.1
15:31:12.455017 IP 172.16.0.120.80 > 172.16.0.10.58940: Flags [.], ack 77, win 227, options [nop,nop,TS val 143312625 ecr 143300584], length 0
15:31:12.456821 IP 172.16.0.120.80 > 172.16.0.10.58940: Flags [P.], seq 1:271, ack 77, win 227, options [nop,nop,TS val 143312627 ecr 143300584], length 270: HTTP: HTTP/1.1 200 OK
15:31:12.458851 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [.], ack 271, win 245, options [nop,nop,TS val 143300589 ecr 143312627], length 0
15:31:12.458979 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [F.], seq 77, ack 271, win 245, options [nop,nop,TS val 143300590 ecr 143312627], length 0
15:31:12.459918 IP 172.16.0.120.80 > 172.16.0.10.58940: Flags [F.], seq 271, ack 78, win 227, options [nop,nop,TS val 143312631 ecr 143300590], length 0
15:31:12.461398 IP 172.16.0.10.58940 > 172.16.0.120.80: Flags [.], ack 272, win 245, options [nop,nop,TS val 143300592 ecr 143312631], length 0
#外網接口,請求報文的源地址也已經轉換過了。

上面測試的是tcp協議的報文,對於icmp協議的報文應該也有做源地址轉換。因爲向中轉服務器的nat表的POSTROUTING鏈上添加規則的時候,並沒有指明協議,默認通配的協議是all表示匹配所有的協議。

(1) 192.168.10.4主機上請求172.16.0.120的icmp結果
[root@localhost ~]# ping 172.16.0.120
PING 172.16.0.120 (172.16.0.120) 56(84) bytes of data.
64 bytes from 172.16.0.120: icmp_seq=1 ttl=63 time=7.29 ms
^C
--- 172.16.0.120 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 7.293/7.293/7.293/0.000 ms

(2) 192.168.10.4主機上抓取icmp協議的報文
[root@localhost ~]# tcpdump -i eno16777736 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 65535 bytes
23:49:46.819267 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 12239, seq 1, length 64
23:49:46.826512 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 12239, seq 1, length 64

(3) 172.16.0.120主機上抓取icmp協議的報文
[root@localhost ~]# tcpdump -i eno16777736 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
15:49:37.764089 IP 172.16.0.10 > 172.16.0.120: ICMP echo request, id 12239, seq 1, length 64
15:49:37.764144 IP 172.16.0.120 > 172.16.0.10: ICMP echo reply, id 12239, seq 1, length 64

(4) 路由主機的內網和外網接口抓取icmp協議的報文
內網:
[root@gateway ~]# tcpdump -i ens37 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens37, link-type EN10MB (Ethernet), capture size 262144 bytes
15:49:37.762027 IP 192.168.10.4 > 172.16.0.120: ICMP echo request, id 12239, seq 1, length 64
15:49:37.768037 IP 172.16.0.120 > 192.168.10.4: ICMP echo reply, id 12239, seq 1, length 64

外網:
[root@gateway ~]# tcpdump -i eno16777736 -nn icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
15:49:37.762175 IP 172.16.0.10 > 172.16.0.120: ICMP echo request, id 12239, seq 1, length 64
15:49:37.767957 IP 172.16.0.120 > 172.16.0.10: ICMP echo reply, id 12239, seq 1, length 64

4.4、DNAT

在這裏插入圖片描述

This target is only valid in the nat table, in the PREROUTING and OUTPUT chains, and user-defined chains which are only called from those chains. It specifies that the destination address of the packet should be modified (and all future packets in this connection will also be mangled), and rules should cease being examined. It takes the following options:
和SNAT適用的表和鏈一樣。這裏是主要是修改報文的目標地址。
想象一下,爲啥DNAT要在PREROUTING鏈或OUTPUT鏈上。比如INPUT或POSTROUTING爲啥不行?
DNAT主要引用是爲了隱藏提供服務器的主機的信息。比如我內網有個主機,有啓動一個web服務器。就以
192.168.10.4爲例,上面啓動一個httpd服務,監聽在80端口。中轉服務器是172.16.0.10(模擬外網網卡),它
的內網網卡是192.168.10.254。現在有個172.16.0.120(模擬的外網)的外網主機。假設172.16.0.120要想請求
192.168.10.4的web服務,我們之前說的報文轉發可以實現。現在有個要求,172.16.0.120直接對外宣稱,我
這裏有個web服務,因爲涉及到域名,域名要解析到這個外網上。現在172.16.0.120請求172.16.0.10的web
服務,假設默認的80端口。現在請求報文的源ip是172.16.0.120,源端口隨機。請求報文的目標端口是
172.16.0.10,目標端口是80.實際172.16.0.10上面用戶空間並沒有進程向內核註冊使用80這個端口,所以當
請求報文抵達172.16.0.10後,DNAT的作用就是把請求報文的目標ip和端口轉給成內網的ip和對應實際提供服務
進程註冊使用的端口,這裏即爲192.168.10.4和80.
假設在報文進入本機,還沒有做路由,假設路由後再去做DNAT,這樣請求報文的MAC封裝已經被拆解,會看到
報文的目標地址就是本機(比如中轉服務器的172.16.0.10),此報文就會直接流經INPUT進入本機,這樣就並沒有
實現把報文轉發給192.16.10.4的主機。如果是路由前,報文還沒有拆解MAC封裝,修改了請求報文的目標IP和
端口。這樣一當路由後,發現請求報文目標地址不是本機,會通過FORWARD鏈把請求報文路由給對應的其他路由或主機。


--to-destination [ipaddr[-ipaddr]][:port[-port]]
which can specify a single new destination IP address, an inclusive range of IP addresses. Optionally a port range, if the rule also specifies one of the following protocols: tcp, udp, dccp or sctp.  If no port range is specified, then the destination port will never be modified. If no IP address is specified then only the destination port will be modified.  In Kernels up to 2.6.10 you can add several --to-destination options. For those kernels, if you specify more than one  destination  address,  either via an address range or multiple --to-destination options, a simple round-robin (one after another in cycle) load balancing takes place between these addresses.  Later Kernels (>= 2.6.11-rc1) don't have the ability to NAT to multiple ranges anymore.

--random
If option --random is used then port mapping will be randomized (kernel >= 2.6.22).

--persistent
Gives a client the same source-/destination-address for each connection.  This supersedes the SAME target. Support for persistent mappings is  available  from 2.6.29-rc2.IPv6 support available since Linux kernels >= 3.7.

實例:
在這裏插入圖片描述

說明:還是上面這套環境。現在內網192.168.10.4上有啓動一個web服務。現在有一個路由服務器,有兩塊網卡,
假設模擬的內網網卡是192.168.10.254,也是內網192.168.10.4主機所在內網環境的默認網關。模擬的外網網卡
是172.16.0.10。現在把192.168.10.4主機上的web服務提供對外。比如要讓172.16.0.120訪問。

實現就是,讓172.16.0.120去訪問172.16.0.10,然後轉給把請求報文的目標地址和端口轉成192.168.10.4主機。
想象一種場景,假設內網一臺主機上即有一個web服務,又有一個ftp服務,還有一個samba服務,現在要web服務
壓力逐漸加大,要把ftp和samba服務從一臺主機剝離出來。然後這個時候只有一臺主機有外網網卡,怎麼辦。
DNAT可以實現。把請求報文來自於互聯網的任意地址,請求172.16.0.10的某個端口A,目標地址轉成192.168.10.4,目標端口是80(這個是web服務),請求172.16.0.10的某個端口B,目標地址轉成192.168.10.5,
目標端口是21(這個主機是ftp服務)等等。

(1) 清空中轉服務的所有iptables策略,包括filter表以及nat表
[root@gateway ~]# iptables -t filter -F
[root@gateway ~]# iptables -t nat -F
[root@gateway ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 4 packets, 808 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
[root@gateway ~]# 

(2) 中轉服務添加防火牆策略
#向中轉服務器的nat表的PREROUTING鏈上添加規則,對於請求報文,請求目標地址爲172.16.0.10,協議爲tcp協議,請求端口是80
的報文,然後把它們的報文的目標地址和端口轉換成192.168.10.4和80
[root@gateway ~]# iptables -t nat -A PREROUTING -d 172.16.0.10 -p tcp --dport 80 -j DNAT --to-destination 192.168.10.4:80
[root@gateway ~]# iptables -t nat -nvL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 DNAT       tcp  --  *      *       0.0.0.0/0            172.16.0.10          tcp dpt:80 to:192.168.10.4:80

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination   

(3) 在172.16.0.120外網主機請求172.16.0.10的80(假設中轉服務器對外宣稱了我這裏可以提供web服務)
[root@localhost ~]# curl http://172.16.0.10
<h1>192.168.10.4</h1>
中轉服務自己其實並沒有監聽80端口:
[root@gateway ~]# ifconfig
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.16.0.10  netmask 255.255.0.0  broadcast 172.16.255.255
        inet6 fe80::20c:29ff:fe85:868d  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:85:86:8d  txqueuelen 1000  (Ethernet)
        RX packets 30571  bytes 3022570 (2.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 27684  bytes 3455777 (3.2 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens37: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.254  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::20c:29ff:fe85:8697  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:85:86:97  txqueuelen 1000  (Ethernet)
        RX packets 5356  bytes 755293 (737.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 6526  bytes 554510 (541.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@gateway ~]# ss -tnl
State      Recv-Q Send-Q                                                                                      Local Address:Port                                                                                        Peer Address:Port 
LISTEN     0      128                                                                                                     *:22                                                                                                     *:*     
LISTEN     0      100                                                                                             127.0.0.1:25                                                                                                     *:*     
LISTEN     0      128                                                                                                    :::22                                                                                                    :::*     
LISTEN     0      100                                                                                                   ::1:25                                                                                                    :::*   

(4) 在172.16.0.120主機上抓包的結果
[root@localhost ~]# tcpdump -i eno16777736 -nn tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
16:25:37.224996 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [S], seq 2414794746, win 14600, options [mss 1460,sackOK,TS val 146577392 ecr 0,nop,wscale 6], length 0
16:25:37.229355 IP 172.16.0.10.80 > 172.16.0.120.32965: Flags [S.], seq 4199406913, ack 2414794747, win 14480, options [mss 1460,sackOK,TS val 146565400 ecr 146577392,nop,wscale 6], length 0
16:25:37.229444 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 146577397 ecr 146565400], length 0
16:25:37.230998 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [P.], seq 1:76, ack 1, win 229, options [nop,nop,TS val 146577399 ecr 146565400], length 75: HTTP: GET / HTTP/1.1
16:25:37.236641 IP 172.16.0.10.80 > 172.16.0.120.32965: Flags [.], ack 76, win 227, options [nop,nop,TS val 146565408 ecr 146577399], length 0
16:25:37.237801 IP 172.16.0.10.80 > 172.16.0.120.32965: Flags [P.], seq 1:264, ack 76, win 227, options [nop,nop,TS val 146565409 ecr 146577399], length 263: HTTP: HTTP/1.1 200 OK
16:25:37.237831 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [.], ack 264, win 245, options [nop,nop,TS val 146577406 ecr 146565409], length 0
16:25:37.239273 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [F.], seq 76, ack 264, win 245, options [nop,nop,TS val 146577407 ecr 146565409], length 0
16:25:37.244770 IP 172.16.0.10.80 > 172.16.0.120.32965: Flags [F.], seq 264, ack 77, win 227, options [nop,nop,TS val 146565417 ecr 146577407], length 0
16:25:37.244808 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [.], ack 265, win 245, options [nop,nop,TS val 146577413 ecr 146565417], length 0
#這個結果沒得說。172.16.0.10的80並不是作爲監聽註冊使用的。

(5) 中轉服務器的內網網卡和外網網卡抓包結果
內網:
[root@gateway ~]# tcpdump -i ens37 -nn tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on ens37, link-type EN10MB (Ethernet), capture size 262144 bytes
16:25:37.228276 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [S], seq 2414794746, win 14600, options [mss 1460,sackOK,TS val 146577392 ecr 0,nop,wscale 6], length 0
16:25:37.231881 IP 192.168.10.4.80 > 172.16.0.120.32965: Flags [S.], seq 4199406913, ack 2414794747, win 14480, options [mss 1460,sackOK,TS val 146565400 ecr 146577392,nop,wscale 6], length 0
16:25:37.232633 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 146577397 ecr 146565400], length 0
16:25:37.236502 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [P.], seq 1:76, ack 1, win 229, options [nop,nop,TS val 146577399 ecr 146565400], length 75: HTTP: GET / HTTP/1.1
16:25:37.239354 IP 192.168.10.4.80 > 172.16.0.120.32965: Flags [.], ack 76, win 227, options [nop,nop,TS val 146565408 ecr 146577399], length 0
16:25:37.239661 IP 192.168.10.4.80 > 172.16.0.120.32965: Flags [P.], seq 1:264, ack 76, win 227, options [nop,nop,TS val 146565409 ecr 146577399], length 263: HTTP: HTTP/1.1 200 OK
16:25:37.241902 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [.], ack 264, win 245, options [nop,nop,TS val 146577406 ecr 146565409], length 0
16:25:37.242394 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [F.], seq 76, ack 264, win 245, options [nop,nop,TS val 146577407 ecr 146565409], length 0
16:25:37.246349 IP 192.168.10.4.80 > 172.16.0.120.32965: Flags [F.], seq 264, ack 77, win 227, options [nop,nop,TS val 146565417 ecr 146577407], length 0
16:25:37.249762 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [.], ack 265, win 245, options [nop,nop,TS val 146577413 ecr 146565417], length 0
#內網接口收到請求報文後,還沒有做目標地址轉換。這個能被防火牆策略那條所匹配到。所以路由前就應該把地址給修改了。所以
通過外網網卡抓包的結果,目標地址應該被修改了。

外網:
[root@gateway ~]# tcpdump -i eno16777736 -nn tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 262144 bytes
16:25:37.228197 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [S], seq 2414794746, win 14600, options [mss 1460,sackOK,TS val 146577392 ecr 0,nop,wscale 6], length 0
16:25:37.231995 IP 172.16.0.10.80 > 172.16.0.120.32965: Flags [S.], seq 4199406913, ack 2414794747, win 14480, options [mss 1460,sackOK,TS val 146565400 ecr 146577392,nop,wscale 6], length 0
16:25:37.232601 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 146577397 ecr 146565400], length 0
16:25:37.236389 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [P.], seq 1:76, ack 1, win 229, options [nop,nop,TS val 146577399 ecr 146565400], length 75: HTTP: GET / HTTP/1.1
16:25:37.239385 IP 172.16.0.10.80 > 172.16.0.120.32965: Flags [.], ack 76, win 227, options [nop,nop,TS val 146565408 ecr 146577399], length 0
16:25:37.239680 IP 172.16.0.10.80 > 172.16.0.120.32965: Flags [P.], seq 1:264, ack 76, win 227, options [nop,nop,TS val 146565409 ecr 146577399], length 263: HTTP: HTTP/1.1 200 OK
16:25:37.241872 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [.], ack 264, win 245, options [nop,nop,TS val 146577406 ecr 146565409], length 0
16:25:37.242371 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [F.], seq 76, ack 264, win 245, options [nop,nop,TS val 146577407 ecr 146565409], length 0
16:25:37.246391 IP 172.16.0.10.80 > 172.16.0.120.32965: Flags [F.], seq 264, ack 77, win 227, options [nop,nop,TS val 146565417 ecr 146577407], length 0
16:25:37.249723 IP 172.16.0.120.32965 > 172.16.0.10.80: Flags [.], ack 265, win 245, options [nop,nop,TS val 146577413 ecr 146565417], length 0
#外網網卡的請求報文的目標地址已經被修改了。


(6) 192.168.10.4內網主機抓包結果
[root@localhost ~]# tcpdump -i eno16777736 -nn tcp port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eno16777736, link-type EN10MB (Ethernet), capture size 65535 bytes
00:25:46.359591 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [S], seq 2414794746, win 14600, options [mss 1460,sackOK,TS val 146577392 ecr 0,nop,wscale 6], length 0
00:25:46.359765 IP 192.168.10.4.80 > 172.16.0.120.32965: Flags [S.], seq 4199406913, ack 2414794747, win 14480, options [mss 1460,sackOK,TS val 146565400 ecr 146577392,nop,wscale 6], length 0
00:25:46.363311 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [.], ack 1, win 229, options [nop,nop,TS val 146577397 ecr 146565400], length 0
00:25:46.367658 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [P.], seq 1:76, ack 1, win 229, options [nop,nop,TS val 146577399 ecr 146565400], length 75
00:25:46.367884 IP 192.168.10.4.80 > 172.16.0.120.32965: Flags [.], ack 76, win 227, options [nop,nop,TS val 146565408 ecr 146577399], length 0
00:25:46.369185 IP 192.168.10.4.80 > 172.16.0.120.32965: Flags [P.], seq 1:264, ack 76, win 227, options [nop,nop,TS val 146565409 ecr 146577399], length 263
00:25:46.376568 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [.], ack 264, win 245, options [nop,nop,TS val 146577406 ecr 146565409], length 0
00:25:46.376594 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [F.], seq 76, ack 264, win 245, options [nop,nop,TS val 146577407 ecr 146565409], length 0
00:25:46.376795 IP 192.168.10.4.80 > 172.16.0.120.32965: Flags [F.], seq 264, ack 77, win 227, options [nop,nop,TS val 146565417 ecr 146577407], length 0
00:25:46.380816 IP 172.16.0.120.32965 > 192.168.10.4.80: Flags [.], ack 265, win 245, options [nop,nop,TS val 146577413 ecr 146565417], length 0
#這裏請求報文能看到真實請求地址是172.16.0.120.迴應的時候也是從192.168.10.4迴應給172.16.0.120.因爲報文的源地址和目標地址
不在一個網絡,所以跨網絡通信,會去找192.168.10.4的路由條目。而192.168.10.4的網關指向的是192.168.10.254.所以報文就這樣
給到了中轉服務器。

擴展:
如果我現在要配合nat和filter的功能。比如192.168.10.4的web服務器要禁止源地址爲172.168.0.23訪問,因爲它總是攻擊我。這個時候既要做DNAT,又要做filter。

iptables -A FORWARD -s 172.16.0.23 -p tcp --dport 80 -d 192.168.10.4 -j REJECT
#上面這個-d參數指定的是192.168.10.4,這個是內網地址。這個很關鍵。因爲DNAT是在PREROUTING上應用,是在路由前就已經
把請求報文的目標地址從172.16.0.10改成192.168.10.4.然後路由拆解了MAC部分,然後去判斷報文的目標地址是否是本機來決定
是通過INPUT還是FORWARD,這個是過濾的功能,現在判斷的結果是目標地址是192.168.10.4,要通過FORWARD鏈,所以在filter表
的FORWARD鏈上的規則的目標地址應該是192.168.10.4而非172.16.0.10。

4.5、MASQUERADE

This target is only valid in the nat table, in the POSTROUTING chain. It should only be used with dynamically assigned IP (dialup) connections: if you have a static IP address, you should use the SNAT target. Masquerading is equivalent to specifying a mapping to the IP address of the interface the packet is going out, but also has the effect that connections are forgotten when the interface goes down. This is the correct behavior when the next dialup is unlikely to have the same interface address (and hence any established connections are lost anyway).
此target僅僅是在nat表的POSTROUTING鏈上才能使用。它只能應用於動態分配的IP(撥號上網)的連接:如果你
有固定的靜態的IP地址,你應該使用SNAT作爲你規則的target。簡單來說,現在有些公司是買的一個固定ip地址,
有些公司是撥號上網後動態分配的外網ip地址,外網ip會隨時變化,使用SNAT無法指定–to-source的值,所以要
使用MASQUERADE這個target。
MASQUERADE比SNAT更消耗性能,因爲每一條報文過來,它都要實現去檢測實際的源地址。

--to-ports port[-port]
	This  specifies a range of source ports to use, overriding the default SNAT source port-selection heuristics (see above).  This is only valid if the rule also specifies one of the following protocols: tcp, udp, dccp or sctp.

--random
Randomize source port mapping If option --random is used then port mapping will be randomized (kernel >= 2.6.21).
IPv6 support available since Linux kernels >= 3.7.

上面選項沒有什麼好說的。因爲外網ip不固定,所以--to-source在這個target不存在。如果要修改端口可以使用--to-ports。

4.6、REDIRECT

This target is only valid in the nat table, in the PREROUTING and OUTPUT chains, and user-defined chains which are only called from those chains. It redirects the packet to the machine itself by changing the destination IP to the primary address of the incoming interface (locally-generated packets are mapped to the localhost address, 127.0.0.1 for IPv4 and ::1 for IPv6).
這個target也是隻在nat表的PREROUTING鏈以及OUTPUT鏈上才能使用。這個是與單機做端口轉發有關的。
比如我本機有個非特權用戶啓動運行的web站點,默認肯定不能註冊使用80這個特權端口。比如註冊使用的
是8080,此時。如果我們對外提供服務器,要向瀏覽器不指定端口,就想要使用80這個默認端口,就可以通過
這個REDIRECT來實現。

--to-ports port[-port]
This specifies a destination port or range of ports to use: without this, the destination port is never altered.  This is only valid if the rule  also  specifies one of the following protocols: tcp, udp, dccp or sctp.

--random
If option --random is used then port mapping will be randomized (kernel >= 2.6.22).
IPv6 support available starting Linux kernels >= 3.7.

實例:

把請求報文來自於任何互聯網地址,然後請求的目標地址是192.168.10.4而且目標端口是80,給它轉交給8080.實際監聽的是
8080,然後80並沒有在用戶空間使用一個進程註冊監聽使用。
[root@localhost ~]#  iptables -t nat -A PREROUTING -d 192.168.10.4 -p tcp --dport 80 -j REDIRECT --to-ports 8080
#上面這條規則在192.168.10.4這臺內網主機執行。假設就是在之前做實驗的基礎上。然後使用網關服務器去訪問這個80和8080.
#如果不配置此條策略,默認只能請求http://192.168.10.4:8080

#下面結果顯示此內網機器,默認並沒有監聽在80端口。
eno16777736: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.10.4  netmask 255.255.255.0  broadcast 192.168.10.255
        inet6 fe80::20c:29ff:fe64:344  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:64:03:44  txqueuelen 1000  (Ethernet)
        RX packets 6323  bytes 594502 (580.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 4118  bytes 536285 (523.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 0  (Local Loopback)
        RX packets 8730  bytes 661548 (646.0 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 8730  bytes 661548 (646.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@localhost ~]# ss -tnl
State      Recv-Q Send-Q                                 Local Address:Port                                   Peer Address:Port 
LISTEN     0      50                                                 *:139                                               *:*     
LISTEN     0      128                                                *:111                                               *:*     
LISTEN     0      128                                                *:22                                                *:*     
LISTEN     0      100                                        127.0.0.1:25                                                *:*     
LISTEN     0      50                                                 *:445                                               *:*     
LISTEN     0      50                                                :::139                                              :::*     
LISTEN     0      128                                               :::111                                              :::*     
LISTEN     0      128                                               :::8080                                             :::*     
LISTEN     0      32                                                :::21                                               :::*     
LISTEN     0      128                                               :::22                                               :::*     
LISTEN     0      128                                               :::23                                               :::*     
LISTEN     0      100                                              ::1:25                                               :::*     
LISTEN     0      50                                                :::445                                              :::*  


#測試
[root@gateway ~]# curl http://192.168.10.4:8080
<h1>192.168.10.4</h1>
[root@gateway ~]# curl http://192.168.10.4:80
<h1>192.168.10.4</h1>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章