Linux防火牆之你必須知道的iptables

一、iptables簡介

  在介紹 iptables 之前,我們首先需要了解一下防火牆分類

  從邏輯上分類:

分 類 說 明
主機防火牆 針對單個主機進行防護
網絡防火牆 處於網絡入口或邊緣,針對網絡入口進行防護,服務於防火牆背後的本地局域網

  從物理上分類:

分 類 說 明
硬件防火牆 通過硬件和軟件的組合實現,性能高,成本高
軟件防火牆 應用軟件處理邏輯運行於通用硬件平臺之上的防火牆,性能低,成本低

  接下來就可以介紹iptables啦!其實iptables並不是真正意義上的防火牆,可以理解爲一個管理工具,用戶通過 iptables 將安全設定執行到對應的"安全框架"中,這個"安全框架"纔是真正的防火牆,這個框架叫做netfilter
  netfilter/iptables (簡稱爲iptables) 組成 Linux 平臺下的包過濾防火牆,可用於添加、編輯和除去規則,完成封包過濾、封包重定向和網絡地址轉換(NAT)等功能。這些規則是在做信息包過濾決定時,防火牆所遵循和組成的規則。這些規則存儲在專用的信息包過濾表 (table) 中, 而這些表集成在 Linux 內核中。在信息包過濾表中, 規則被分組放在鏈(chain) 中。

二、iptables之四表五鏈

  從上面我們瞭解到,防火牆是遵循管理員預先設定的規則行動。而規則一般的定義爲:“我要對哪些包,在什麼時候,進行哪些操作”。其中:

  • 哪些包:指定了源地址、目的地址、傳輸協議(如:TCP、UDP 和 ICMP)和服務類型(如:HTTP、FTP 和 SMTP)等;
  • 在什麼時候:即前面所提到鏈(chain);
  • 進行哪些操作:比如ACCEPT、DROP和REJECT等操作。

1、鏈(chain)

  上述的那些規則,一般都是多條,將多條規則串到一個鏈條上的時候,就形成了 “”。在 iptables 中包含5條鏈,每條鏈對應着不同的時候:

說 明
PREROUTING 數據包進入路由表之前
INPUT 通過路由表後目的地爲本機
FORWARDING 通過路由表後, 目的地不爲本機
OUTPUT 由本機產生, 向外轉發
POSTROUTIONG 發送到網卡接口之前

  那麼報文的流向是怎麼樣的呢?報文目的主機不同,流向也是不同的:

報 文 流 向
到本機某進程的報文 PREROUTING → INPUT
由本機轉發的報文 PREROUTING → FORWARDING → POSTROUTIONG
由本機某進程發出的報文 OUTPUT → POSTROUTIONG

  結合下面這張圖,可以更好地理解報文流經防火牆的過程:
在這裏插入圖片描述


2、表(table)

  前面瞭解到,鏈上有多條規則,那麼這些規則是不是可以合併呢?當然是可以的!我們把功能相同的一些規則合併,這些具有相同功能的規則的集合就叫做 “表(table)”。在 iptables 中包含4種表,每種表對應着不同的功能:

說 明
filter 表 一般的過濾功能
nat 表 網絡地址轉換功能
mangle 表 拆解報文,作出修改,並重新封裝的功能
raw 表 關閉nat表上啓用的連接追蹤機制

3、四表五鏈之間的關係

  在認識表和鏈之後,再來了解一下它們之間的關係。之前說,表是鏈上的一些具有相同功能規則的集合,那麼是不是所有的表都存在於每一條鏈上呢?答案是否定的!

PREROUTING raw表、mangle表、nat表
INPUT mangle表、filter表(CentOS7中還有nat表)
FORWARD mangle表、filter表
OUTPUT raw表、mangle表、nat表、filter表
POSTROUTING mangle表、nat表

  在實際的使用過程中,我們通常是通過"表"作爲入口,對規則進行操作的,所以這裏需要列出"表"與"鏈"的關係:

raw表 PREROUTING、OUTPUT
mangle表 PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING
nat表 PREROUTING、FORWARD、POSTROUTING(CentOS7中還有INPUT)
filter表 INPUT、FORWARD、OUTPUT

  需要注意的一點,當數據包經過一條"鏈"時,會將當前鏈的所有規則都匹配一遍,但匹配的時候要遵循一定的順序。那麼哪個"表"中的規則會放在"鏈"的最前面優先匹配呢?這就存在一個優先級的問題!
  當4張表同處於一條"鏈"時,執行優先級是這樣的(由高而低):raw → mangle → nat → filter

三、iptables基本用法

  現在我們都知道,匹配條件和處理動作共同組成了規則。如果滿足匹配條件,就執行對應的動作;如果不滿足,就判斷下一條規則。那麼該如何對規則進行管理呢?基本語法格式:iptables [ -t 表名 ] [ 命令選項 ] [ 鏈名 ] [ 匹配條件 ] [ -j 處理動作 ]

1、命令選項

選 項 說 明
-A 在指定鏈尾部添加規則
-I 在指定鏈指定位置添加規則,默認在首部添加
-R 修改、替換指定鏈的某一條規則
-D 刪除指定鏈的某一條規則
-F 清空指定鏈或所有鏈的規則
-L/S 列出指定鏈或所有鏈的規則
-N 創建用戶自定義鏈
-X 刪除指定的用戶自定義鏈
-P 爲指定鏈設置默認規則策略,對自定義鏈無效
-E 更改自定義鏈的名稱
-Z 將指定鏈或所有連的計數器清零
-n 解析IP地址,IP地址和端口號以數字形式顯示
-v 列出詳細信息
–line-numbers 顯示規則序號

2、匹配條件

  匹配條件分爲基礎匹配條件擴展匹配條件。其中,基本匹配條件可以直接使用,而再使用擴展匹配條件前需要指定依賴擴展的模塊纔行。這裏我們先了解基本匹配條件。

匹配條件 說 明
-p tcp/udp/icmp/all 匹配協議
-s addr1[,addr2] 匹配源地址(可指定多個離散的IP地址)
-d add1[,addr2] 匹配目的地址(可指定多個離散的IP地址)
–sport port1[:port2] 匹配源端口(可指定一個連續的端口範圍)
–dport port1[:port2] 匹配目的端口(可指定一個連續的端口範圍)
-o interface 匹配出口網卡(只適用FORWARD、POSTROUTING和OUTPUT)
-i interface 匹配入口網卡(只適用FORWARD、POSTROUTING和INPUT)

3、處理動作

條 件 說 明
ACCEPT 允許數據包通過
DROP 直接丟棄數據包,不給任何迴應信息,這時數據發送端只有請求超時時纔會有反應
REJECT 拒絕數據包通過,這時會給數據發送端發送一個拒絕響應信息
SNAT 源地址轉換
MASQUERADS SNAT的一種的形式,適用於動態的、臨時會變的 ip 上
DNAT 目標地址轉換
REDIRECT 在本機做端口映射
LOG 在 /var/log/messages 文件記錄日誌信息,然後將數據包傳遞給下一條規則

4、規則配置實例

兩臺服務器進行演示:
  服務器A:localhost   192.168.140.137
  服務器B:localhost123  192.168.140.128

  ① 首先清空服務器A防火牆規則;

[root@localhost ~]# iptables -F    //清空規則
[root@localhost ~]# iptables -nvL    //查看已經沒有任何規則
Chain INPUT (policy ACCEPT 19 packets, 1381 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 9 packets, 872 bytes)
 pkts bytes target     prot opt in     out     source               destination
 #清空規則後,可以看到INPUT、FORWORD、OUTPUT默認策略都是ACCEPT,也就是說默認當前所有發往本機的報文都將放行。
------------------------
[root@localhost123 ~]# ping 192.168.140.137    //當前服務器A上沒有任何規則,可以ping通
PING 192.168.140.137 (192.168.140.137) 56(84) bytes of data.
64 bytes from 192.168.140.137: icmp_seq=1 ttl=64 time=1.05 ms
64 bytes from 192.168.140.137: icmp_seq=2 ttl=64 time=0.255 ms
64 bytes from 192.168.140.137: icmp_seq=3 ttl=64 time=0.315 ms

  ② 增加規則;

[root@localhost ~]# iptables -t filter -I INPUT -s 192.168.140.128 -j REJECT    //新增規則:拒絕來自192.168.140.128的所有報文
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 24 packets, 1536 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  *      *       192.168.140.128      0.0.0.0/0           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 13 packets, 1144 bytes)
 pkts bytes target     prot opt in     out     source               destination
 
#下面對-v選項的各字段含義進行解釋:

#pkts:對應規則匹配到的報文的個數
#bytes:對應匹配到的報文包的大小總和
#target:規則對應的target,往往表示規則對應的"動作",即規則匹配成功後需要採取的措施
#prot:表示規則對應的協議,是否只針對某些協議應用此規則
#opt:表示規則對應的選項
#in:表示數據包由哪個接口(網卡)流入,我們可以設置通過哪塊網卡流入的報文需要匹配當前規則
#out:表示數據包由哪個接口(網卡)流出,我們可以設置通過哪塊網卡流出的報文需要匹配當前規則
#source:表示規則對應的源頭地址,可以是一個IP,也可以是一個網段
#destination:表示規則對應的目標地址。可以是一個IP,也可以是一個網段

------------------------
[root@localhost123 ~]# ping 192.168.140.137    //無法ping通
PING 192.168.140.137 (192.168.140.137) 56(84) bytes of data.
From 192.168.140.137 icmp_seq=1 Destination Port Unreachable
From 192.168.140.137 icmp_seq=2 Destination Port Unreachable
From 192.168.140.137 icmp_seq=3 Destination Port Unreachable
------------------------
[root@localhost ~]# iptables -nvL    //再次查看,pkts和bytes中已有包
Chain INPUT (policy ACCEPT 31 packets, 2578 bytes)
 pkts bytes target     prot opt in     out     source               destination
    5   420 REJECT     all  --  *      *       192.168.140.128      0.0.0.0/0           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 21 packets, 2272 bytes)
 pkts bytes target     prot opt in     out     source               destination
[root@localhost ~]# iptables -t filter -I INPUT -s 192.168.140.128 -j ACCEPT    //新增規則:允許來自192.168.140.128的所有報文通過
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 6 packets, 384 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  *      *       192.168.140.128      0.0.0.0/0
    5   420 REJECT     all  --  *      *       192.168.140.128      0.0.0.0/0           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 3 packets, 328 bytes)
 pkts bytes target     prot opt in     out     source               destination
------------------------
[root@localhost123 ~]# ping 192.168.140.137    //可以ping通
PING 192.168.140.137 (192.168.140.137) 56(84) bytes of data.
64 bytes from 192.168.140.137: icmp_seq=1 ttl=64 time=0.302 ms
64 bytes from 192.168.140.137: icmp_seq=2 ttl=64 time=0.267 ms
64 bytes from 192.168.140.137: icmp_seq=3 ttl=64 time=0.246 ms
#在這裏就存在一個規則順序問題:如果報文被前面的規則匹配到並執行對應動作,即使後面的規則也能匹配到當前報文,但已經沒有機會再對報文執行相應的動作了。

  ③ 刪除規則;

#方式一:
[root@localhost ~]# iptables -t filter -D INPUT 1
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 26 packets, 1760 bytes)
 pkts bytes target     prot opt in     out     source               destination
    5   420 REJECT     all  --  *      *       192.168.140.128      0.0.0.0/0           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 16 packets, 1440 bytes)
 pkts bytes target     prot opt in     out     source               destination
 
#方式二:
[root@localhost ~]# iptables -D INPUT -s 192.168.140.128 -j REJECT
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 6 packets, 384 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 3 packets, 312 bytes)
 pkts bytes target     prot opt in     out     source               destination

  ④ 修改規則;

[root@localhost ~]# iptables -t filter -I INPUT -s 192.168.140.128 -j ACCEPT    //新增規則:允許來自192.168.140.128的所有報文通過
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 32 packets, 2048 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  *      *       192.168.140.128      0.0.0.0/0

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

Chain OUTPUT (policy ACCEPT 16 packets, 1472 bytes)
 pkts bytes target     prot opt in     out     source               destination
[root@localhost ~]# iptables -t filter -R INPUT 1 -s 192.168.140.128 -j DROP    //修改規則:丟棄來自192.168.140.128的所有報文
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 6 packets, 384 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 DROP       all  --  *      *       192.168.140.128      0.0.0.0/0

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

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

#除了修改鏈已存在的規則之外,還能修改鏈的默認規則
[root@localhost ~]# iptables -t filter -P INPUT DROP
[root@localhost ~]# iptables -nvL    //可以看到INPUT鏈的默認規則已改變爲DROP
Chain INPUT (policy `DROP` 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
   61  3928 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22

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

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

  ⑤ 保存規則;

#之前的操作中所有的規則的配置都是臨時的,當重啓服務或服務器後,規則就會消失,如果想永久保存,就要執行一些命令
#CentOS6與CentOS7中的情況稍微有些不同

#CentOS6中使用service iptables save命令即可保存規則,規則默認保存在/etc/sysconfig/iptables文件中
[root@localhost ~]# service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]
[root@localhost ~]# cat /etc/sysconfig/iptables
# Generated by iptables-save v1.4.7 on Mon May 25 20:22:04 2020
*filter
:INPUT ACCEPT [77:5333]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [46:4368]
-A INPUT -s 192.168.140.128/32 -j DROP
COMMIT
# Completed on Mon May 25 20:22:04 2020

#CentOS7中已經不能使用類似service iptables start這樣的命令,並且使用firewall代替iptables service
#可以通過yum源安裝iptables和iptables-services(其中iptables一般會被默認安裝,但iptables-services一般不會被默認安裝)
#安裝完成後即可像CentOS6中一樣通過service iptables save命令保存規則

#CentOS7中配置iptables-services步驟:
[root@localhost etc]# yum install iptables-services -y    //配置好yum源後安裝iptables-service
[root@localhost ~]# systemctl stop firewalld    //停止firewalld
[root@localhost ~]# systemctl disable firewalld    //禁止Firewalld自動啓動
Removed symlink /etc/systemd/system/multi-user.target.wants/firewalld.service.
Removed symlink /etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service.
[root@localhost ~]# systemctl start iptables    //啓動iptables
[root@localhost ~]# systemctl enable iptables    //將iptables設置爲開機自動啓動,以後即可通過iptables-service控制iptables服務
Created symlink from /etc/systemd/system/basic.target.wants/iptables.service to /usr/lib/systemd/system/iptables.service.

#還可以通過另一種通用方法保存規則,那就是使用iptables-save命令
#但iptables-save並不保存當前的規則,但是可以將當前的規則以"保存後的格式(也就是上面的文件內容格式)"輸出到屏幕上
#利用這一點,相信大家已經想到了,配合重定向到/etc/sysconfig/iptables文件中即可
[root@localhost ~]# iptables-save > /etc/sysconfig/iptables

#我們也可以將/etc/sysconfig/iptables中的規則重新載入爲當前iptables規則。
#但需要注意的是,未保存到/etc/sysconfig/iptables文件中的規則會被覆蓋或丟失
[root@localhost ~]# iptables-restore < /etc/sysconfig/iptables

5、擴展匹配條件

  擴展匹配條件又可分爲顯式擴展隱式擴展。其中,顯式擴展是必須使用 -m 選項指明要調用的擴展模塊;隱式擴展是在使用 -p 選項指明瞭特定的協議時,如果這個擴展匹配條件所依賴的擴展模塊名正好與 -p 對應的協議名稱相同,那麼則可省略 -m 選項。這麼說可能大家不太明白,那麼我們繼續向下看。

① tcp擴展模塊

  tcp擴展模塊可以用來指定單個或者一個連續的端口範圍,當需要指定一個連續的端口範圍時,使用 起始端口號:末尾端口號 這樣的格式。需要注意的是,在指定端口號之前,必須先指定使用的協議(即使用-p選項)。

匹配條件 說 明
--sport port1[:prot2] 匹配源端口
--dport port1[:prot2] 匹配目的端口

  舉一個栗子,可以直觀看到隱式擴展的省略形式。拒絕shh工具遠程連接主機;

#sshd服務默認使用22端口,tcp協議
[root@localhost ~]# iptables -t filter -I INPUT -p tcp -m tcp --dport 22 -j REJECT
#-p指定的tcp協議與-m使用的tcp模塊名稱相同,所以可以省略-m選項
[root@localhost ~]# iptables -t filter -I INPUT -p tcp --dport 22 -j REJECT

  如果想指定一段連續的端口範圍,如果想匹配目的端口爲22、23和24三個端口,可以使用:--dport 22:24

  同時擴展匹配條件可以取反,比如:! --dport 22表示目標端口不是22的報文將會被匹配到。

② multiport擴展模塊
  multiport擴展模塊用來指定多個離散的、不連續的端口,每個端口之間用逗號隔開。

匹配條件 說 明
--sport port1[,prot2] 匹配源端口
--dport port1[,prot2] 匹配目的端口

  同樣是上面的栗子,如果想匹配目的端口爲22、23和24三個端口,當然範圍比較小,可以使用multiport模塊來指定多個離散的端口,就像這樣:-m multiport -dport 22,23,24

③ iprange擴展模塊
  在使用-s和-d選項指定源地址和目標地址時只能指定一個或多個離散的、不連續的IP地址。而iprange擴展模塊可以用來指定一段連續的IP地址範圍,使用 起始IP地址-末尾IP地址 這樣的格式。

匹配條件 說 明
--src-range 源地址範圍
--dst-range 目標地址範圍

  也很簡單,如果想匹配目的地址爲192.168.140.128到192.168.140.137之間,則可以使用:-m iprange --dst-range 192.168.140.128-192.168.140.137

④ string擴展模塊
  string擴展模塊用來指定需要匹配的字符串,如果報文中包含對應的字符串,則符合匹配條件。

匹配條件 說 明
--algo 指定匹配算法,可選的算法有 bm 與 kmp,此選項爲必須選項,不用糾結於選擇哪個算法,但是必須指定一個
--string 指定需要匹配的字符串

  如果我們想匹配包含字符串"XXOO"的報文,就可以這樣:-m string --algo bm --string "XXOO"

⑤ time擴展模塊
  time擴展模塊用來根據時間段區匹配報文,如果報文到達的時間在指定的時間範圍以內,則符合匹配條件。

匹配條件 說 明
--timestart 時:分:秒 指定起始時間,比如 23:21:54 表示23時21分54秒
--timestop 時:分:秒 指定結束時間
--weekdays 指定星期幾,可以用1~7表示,也可以用縮寫Mon, Tue, Wed, Thu, Fri, Sat, Sun表示
--datestart 年-月-日 指定起始日期
--datestop 年-月-日 指定結束日期
--monthdays 指定每個月的哪一天

  如果我們要匹配每週六、日的早上8點到下午1點,就可以這樣:-m time --timestart 08:00:00 --timestop 13:00:00 --weekdays 6,7

  其中,只有–monthdays與–weekdays可以使用" ! "取反,其他選項都不行哦。

⑥ connlimit擴展模塊
  connlimit擴展模塊用於限制每個IP地址同時鏈接到服務端的鏈接數量。如果不指定IP,則默認針對每個IP地址進行限制。

匹配條件 說 明
--connlimit-above 限制鏈接數量上限
--connlimit-mask 用於指定某類網段,與–connlimit-above配合使用,限制某類網段的鏈接數量

  這裏就需要先自行了解一些相關網絡知識,接下來就來了解這個栗子。我們對一個C類網絡中,同時最多隻能有5個ssh客戶端連接到當前服務器。在這裏就需要大家明白爲什麼–connlimit-mask後所跟的參數是24呢?mask是掩碼的意思,24轉換成點分十進制爲255.255.255.0,所以表示某個C類網段。

[root@localhost ~]# iptables -t filter -I INPUT -p tcp --dport 22 -m connlimit --connlimit-above 5 --connlimit-mask 24 -j ACCEPT

⑦ limit擴展模塊
  limit擴展模塊用於對報文到達速率進行限制的,即限制單位時間內流入的包的數量,單位可以是秒、分鐘、小時和天。

匹配條件 說 明
--limit 限制單位時間內流入數據包的數量,單位可以是秒、分鐘、小時和天
--limit-burst 設置令牌桶大小,默認爲5

  說到這裏,就會有疑問,什麼是令牌桶呢?大家可以這樣理解:假如我們是這樣設置的:-m limit --limit-burst 4 --limit 6/min。桶裏首先會放置4枚令牌,並且這個桶最多也只能放置4枚令牌,所有報文想通過關卡必須持有桶中的令牌。桶也有一個神奇的功能:每6秒會產生一個令牌。如果桶中的令牌有所消耗,那麼新產生的令牌就會存放在桶中,反之如果桶中令牌是滿的,那麼新產生的令牌就會溢出木桶(被丟棄)。

#首先在IP爲192.168.140.137的服務器上設置如下規則
[root@localhost ~]# iptables -t filter -I INPUT -p icmp -m limit --limit-burst 4 --limit 10/min -j ACCEPT
[root@localhost ~]# iptables -t filter -A INPUT -p icmp REJECT    //默認規則是通行,所以設置該條攔截沒有令牌的報文
#在另一臺服務器上對192.168.140.137主機執行ping命令
[root@localhost123 ~]# ping 192.168.140.137
PING 192.168.140.137 (192.168.140.137) 56(84) bytes of data.                          
64 bytes from 192.168.140.137: icmp_seq=1 ttl=64 time=0.157 ms    //放行               0 秒
64 bytes from 192.168.140.137: icmp_seq=2 ttl=64 time=0.274 ms    //放行               1 秒
64 bytes from 192.168.140.137: icmp_seq=3 ttl=64 time=0.317 ms    //放行               2 秒
64 bytes from 192.168.140.137: icmp_seq=4 ttl=64 time=0.504 ms    //放行               3 秒
From 192.168.140.137 icmp_seq=5 Destination Port Unreachable      //桶中已無令牌,拒絕  4 秒
From 192.168.140.137 icmp_seq=6 Destination Port Unreachable      //桶中已無令牌,拒絕  5 秒
64 bytes from 192.168.140.137: icmp_seq=7 ttl=64 time=0.230 ms    //產生新令牌,放行    6 秒
From 192.168.140.137 icmp_seq=8 Destination Port Unreachable      //桶中已無令牌,拒絕  7 秒
From 192.168.140.137 icmp_seq=9 Destination Port Unreachable      //桶中已無令牌,拒絕  8 秒
From 192.168.140.137 icmp_seq=10 Destination Port Unreachable     //桶中已無令牌,拒絕  9 秒
From 192.168.140.137 icmp_seq=11 Destination Port Unreachable     //桶中已無令牌,拒絕  10秒
From 192.168.140.137 icmp_seq=12 Destination Port Unreachable     //桶中已無令牌,拒絕  11秒
64 bytes from 192.168.140.137: icmp_seq=13 ttl=64 time=0.493 ms   //產生新令牌,放行    12秒
From 192.168.140.137 icmp_seq=14 Destination Port Unreachable     //桶中已無令牌,拒絕  13秒
From 192.168.140.137 icmp_seq=15 Destination Port Unreachable     //桶中已無令牌,拒絕  14秒
...省略部分內容

⑧ tcp模塊之–tcp-flags
  --tcp-flags模塊是tcp擴展模塊中的一個選項,它可以根據tcp頭部標誌位匹配報文,tcp包頭中的標誌位有6個:SYN,ACK,FIN,RST,URG,PSH。請同學務必瞭解相關tcp網絡知識!!

匹配條件 說 明
--tcp-flags 匹配tcp頭部標誌位

  如何匹配呢?舉個栗子:-m tcp --tcp-flags SYN,ACK,FIN,RST,URG,PSH SYN。我們可以看到後面的參數是兩部分。
  第一部分SYN,ACK,FIN,RST,URG,PSH,表示在該條規則中我們需要匹配tcp頭部的6個標誌位,所以可以理解爲需要匹配的標誌位。
  第二部分SYN,表示在第一部分的標誌位列表中,SYN標誌位必須爲1,其他標誌位必須爲0。所以可以理解爲在第一部分的標誌位列表中,哪些標誌位必須爲1。

  上述的栗子還可以這樣寫:-m tcp --tcp-flags ALL SYN,也就是說可以用ALL表示那六個標誌位。

  –syn 選項相當於--tcp-flags SYN,RST,ACK,FIN SYN,所以我們可以用"–syn"選項匹配tcp連接的"第一次握手"。

⑨ state擴展模塊
  state擴展模塊可以一個非常實用的模塊,可以基於連接追蹤機制匹配報文。什麼是鏈接追蹤呢?不論什麼協議,客戶端第一次訪問時,服務器就會去內核內存中的追蹤表查看他之前是否來過,查不到就證明是第一次來,記錄入追蹤表,如果查到以前來過,就不檢查規則直接允許訪問,這就叫做連接追蹤機制。
  其中共有5中狀態:NEW         新建連接請求的數據包,第一次連接
            ESTABLISHED   NEW狀態連接的回包,已建立的連接
            INVALID      無法識別或沒有任何狀態的數據包
            RELATED      當前數據包是一個新請求,但附屬於某個已相關聯的連接
            UNTRACKED     一種特殊狀態,管理員在raw表中爲連接設置NOTRACK規則後的狀態。

匹配條件 說 明
--state 基於連接追蹤機制匹配報文

  舉個栗子,如何放行迴應之前發出的報文?

#放行RELATED,ESTABLISHED兩個狀態的報文即可
[root@localhost ~]# iptables -t filter -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

⑩ udp擴展模塊
  udp擴展模塊和tcp擴展模塊大同小異,區別就是,udp擴展模塊是用於匹配UDP協議報文的,並且只有兩個選項。

匹配條件 說 明
--sport port1[:prot2] 匹配源端口
--dport port1[:prot2] 匹配目的端口

  看到上面選項參數的格式,大家肯定明白這兩個選項可以指定單個或者一個連續的端口範圍。那麼是不是還能用multiport擴展模塊指定多個離散的UDP端口呢?答案是肯定的!這裏不做過多描述。
⑪ icmp擴展模塊
  icmp協議(Internet Control Message Protocol)譯爲"互聯網控制報文協議"。它主要用於探測網絡上的主機是否可用、目標是否可達、網絡是否暢通和路由是否可用等,我們最常用的ping命令就使用的是icmp協議。
  icmp報文從概念上可以分爲多種type,而不同的type又可以分爲多種code去應用具體的場景(具體看下圖)。我們可以通過type/code或icmp報文的描述名稱(英文)去匹配到具體的icmp報文

  如果我們想拒絕別的主機的ping請求,但不影響本機向別的主機發起ping請求,就可以通過這兩種方法去設置:
    iptables -t filter -I INPUT -p icmp --icmp-type 8/0 -j REJECT
    iptables -t filter -I INPUT -p icmp --icmp-type "echo-request" -j REJECT
  ping請求的type爲8,code爲0,所以別的主機發送的icmp報文將會被匹配到,但是爲什麼我們還能ping別人呢?這是因爲本機的包發出並不經過INPUT鏈,並且當別的主機應答時,ping應答的type爲0,code爲0,所以並不會收到影響。

四、iptables之黑白名單機制

  前面講到,報文在經過iptables的鏈時會一一匹配鏈中的規則,如果匹配到則執行相應的動作。那麼當一條報文沒有被iptables中的規則所匹配時,就會執行鏈的默認策略(動作),這個默認策略通常設置爲ACCEPT或DROP。
  黑白名單也就是利用這種機制來實現的。可以這樣來理解:
  黑名單就是將默認策略設置爲ACCEPT(把所有人當成好人,允許進入),鏈中的規則對應動作爲DROP或REJECT(拒絕壞人進入)。也就是說只有匹配到規則的報文才會被拒絕,沒有被規則匹配到的報文都會被默認允許。
  白名單則是將默認策略設置爲DROP(把所有人當成壞人,拒絕進入),鏈中的規則對應動作爲ACCEPT(允許好人進入)。同理只有匹配到規則的報文才會被允許,沒有被規則匹配到的報文都會被默認拒絕。
  相對而言,白名單似乎安全性更高!具體如何實現呢?舉個栗子:使用白名單機制,只放行ssh遠程連接的相關報文。

[root@localhost ~]# iptables -t filter -I INPUT -p tcp --dport 22 -j ACCEPT    //放行ssh遠程連接的相關報文
[root@localhost ~]# iptables -P INPUT DROP    //修改INPUT鏈默認策略爲DROP
[root@localhost ~]# iptables -nL
Chain INPUT (policy `DROP`)    //默認策略修改成功
target     prot opt source               destination
ACCEPT     tcp  --  0.0.0.0/0            0.0.0.0/0           tcp dpt:22

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
#此時如果手誤執行了iptables -F,那麼ssh工具還能遠程連接到服務器上嗎?試試便知。
[root@localhost ~]# iptables -F
[root@localhost ~]#
──────────────────────────────────────────────────────────────────────────────────────────────────────────

Session stopped
    - Press <return> to exit tab
    - Press R to restart session
    - Press S to save terminal output to file

Network error: Software caused connection abort

  所以說,要注意的是,默認策略設置爲DROP這種做法不好!因爲如果不小心清空了防火牆規則,那將導致所有數據包都無法進入,如果機器不在身邊,管理員自己也就束手無策了!
  可以以這種方式代替,我們仍然保持鏈的默認策略爲ACCEPT,然後將“拒絕所有”這條規則放在鏈的尾部,將“放行規則”放在前面。這樣做既可以實現白名單機制,又可以保證在規則被清空時不會被默認策略爲DROP所影響。

五、iptables之網絡防火牆

1、forward轉發

  之前我們所說到的防火牆分類中講到,防火牆從邏輯上可以分爲主機防火牆與網絡防火牆,主機防火牆是針對於單個主機進行防護,而網絡防火牆處於網絡入口或邊緣,針對網絡入口進行防護,服務於防火牆背後的本地局域網。
  上文的栗子中,iptables都是以主機防火牆的角色出現的。我們只用到了INPUT鏈和OUTPUT鏈,因爲擁有"過濾功能"的鏈只有三條:INPUT、FORWARD、OUTPUT,當報文發往本機時,只能通過INPUT鏈和OUTPUT鏈進行過濾。而當iptables作爲網絡防火牆時,它的職責就變成了 過濾並轉發 ,而想要轉發,報文則只會經過它們中的FORWARD鏈。所以,iptables的角色變爲"網絡防火牆"時,規則只能定義在FORWARD鏈中。

  下面就實現網絡防火牆功能進行實驗演示。

演示環境

主機A 主機B 主機C
主機名 localhost01 localhost02 localhost03
IP eth0:192.168.140.129 eth0:192.168.140.130
eth1:192.168.38.130 eth1:192.168.38.131
GETEWAY 192.168.140.137 192.168.140.1,192.168.38.1 192.168.38.130
網卡模式 NAT eth0:NAT,eth1:僅主機 僅主機

在這裏插入圖片描述
環境準備

#主機B作爲192.168.38.0/24的網絡防火牆,所以將主機C的網關指向主機B的eth1(內網)網卡IP
[root@localhost03 ~]# vim /etc/sysconfig/network-scripts/ifcfg-eth1
...省略部分內容
GETEWAY=192.168.38.130    //添加該條信息

#配置路由,將主機A訪問192.168.38.0/24網絡時的網關指向主機B的eth0(公網)網卡IP
[root@localhost01 ~]# route add -net 192.168.38.0/24 gw 192.168.140.130
[root@localhost01 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.38.0    192.168.140.130 255.255.255.0   UG    0      0        0 eth0
192.168.140.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0
0.0.0.0         192.168.140.2   0.0.0.0         UG    0      0        0 eth0

演示過程

#使用主機A向主機C發起ping請求
[root@localhost01 ~]# ping 192.168.38.131
PING 192.168.38.131 (192.168.38.131) 56(84) bytes of data.
^C
--- 192.168.38.131 ping statistics ---
296 packets transmitted, 0 received, 100% packet loss, time 295778ms
#可以看到主機A無法ping通主機C

#使用主機A向主機B發起ping請求
[root@localhost01 ~]# ping -c 4 192.168.140.130
PING 192.168.140.130 (192.168.140.130) 56(84) bytes of data.
64 bytes from 192.168.140.130: icmp_seq=1 ttl=64 time=0.143 ms
64 bytes from 192.168.140.130: icmp_seq=2 ttl=64 time=0.504 ms
64 bytes from 192.168.140.130: icmp_seq=3 ttl=64 time=0.438 ms
64 bytes from 192.168.140.130: icmp_seq=4 ttl=64 time=0.384 ms

--- 192.168.140.130 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 0.143/0.367/0.504/0.136 ms
#可以看到主機A可以ping通主機B內網IP

#那麼192.168.38.130和192.168.38.131都屬於一個網段,按道理都可以ping通,那麼爲什麼ping主機C不通呢?
#主機A根據路由表的信息,將發往192.168.38.0/24網段的報文通通下跳給了192.168.140.130(主機B的外網網卡IP)
#當ping主機B的內網地址時,主機B發現自己便是目標主機,所以就回應了報文,這很好理解
#當ping主機C時,報文下跳到主機B時,主機B發現目標主機與自己是同一網段,這時就需要將這條報文轉發給主機C
#但是在默認情況下,linux主機並不會轉發報文,所以主機C沒有收到報文,自然不會迴應

#如何打開轉發功能呢?很簡單!

#臨時生效
#方法一:
#查看/proc/sys/net/ipv4/ip_forward文件,如果文件中內容爲0,表示當前主機不支持轉發
[root@localhost02 ~]# cat /proc/sys/net/ipv4/ip_forward
0
#反之,如果文件中內容爲1,表示當前主機支持轉發。所以我們只需要修改該值爲1即可。
[root@localhost02 ~]# echo 1 >> /proc/sys/net/ipv4/ip_forward
[root@localhost02 ~]# cat /proc/sys/net/ipv4/ip_forward
1
#方法二:
#使用sysctl命令
[root@localhost02 ~]# sysctl -w net.ipv4.ip_forward=0
net.ipv4.ip_forward = 0
[root@localhost02 ~]# cat /proc/sys/net/ipv4/ip_forward
0
[root@localhost02 ~]# sysctl -w net.ipv4.ip_forward=1
net.ipv4.ip_forward = 1
[root@localhost02 ~]# cat /proc/sys/net/ipv4/ip_forward
1


#永久生效
#CentOS6 配置/etc/sysctl.conf文件
#CentOS7 配置/usr/lib/sysctl.d/00-system.conf文件
#添加(或修改)配置項  net.ipv4.ip_forward = 1 即可

#此時再使用主機A向主機C發起ping請求,可以ping通
[root@localhost01 ~]# ping -c 4 192.168.38.131
PING 192.168.38.131 (192.168.38.131) 56(84) bytes of data.
64 bytes from 192.168.38.131: icmp_seq=1 ttl=64 time=0.214 ms
64 bytes from 192.168.38.131: icmp_seq=2 ttl=64 time=0.313 ms
64 bytes from 192.168.38.131: icmp_seq=3 ttl=64 time=0.493 ms
64 bytes from 192.168.38.131: icmp_seq=4 ttl=64 time=0.275 ms

--- 192.168.38.131 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 0.214/0.323/0.493/0.106 ms

2、規則配置實例

  iptables上文講到,iptables作爲網絡防火牆時,職責就變成了 過濾並轉發 。而我們都知道 filter 表實現過濾,FORWARD鏈進行轉發,所以就需要在filter表的FORWARD鏈中配置規則,從而達到網絡防火牆的功能。

#實例目標:使主機A能訪問主機C的web服務

#查看主機B的防火牆規則
[root@localhost02 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
#這裏我們使用白名單機制,在主機B的iptables的FORWARD鏈末端添加一條默認拒絕的規則
[root@localhost02 ~]# iptables -t filter -A FORWARD -j REJECT

#打開主機C的httpd服務
[root@localhost01 ~]# service httpd start

#剛剛添加了默認拒絕的規則,主機A肯定無法訪問主機C的web服務,現在我們在FORWARD鏈中添加一條允許外部主機A訪問內部主機C的web服務的規則
[root@localhost02 ~]# iptables -t filter -I FORWARD -s 192.168.140.0/24 -p tcp --dport 80 -j ACCEPT
[root@localhost02 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
`ACCEPT     tcp  --  192.168.140.0/24     0.0.0.0/0            tcp dpt:80`
REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

#使用主機A訪問主機C的web服務
[root@localhost01 ~]# curl 192.168.38.131
[root@localhost01 ~]#
#可以看到無法訪問主機C的web服務,這是爲什麼呢?
#這是因爲:主機B只放行了外部主機訪問80端口的請求,但並沒有放行內部主機的迴應報文,所以沒有反應

#知道了原因,我們需要在主機B添加一條允許迴應報文通行的規則
[root@localhost02 ~]# iptables -t filter -I FORWARD -d 192.168.140.0/24 -p tcp --sport 80 -j ACCEPT
[root@localhost02 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
`ACCEPT     tcp  --  0.0.0.0/0            192.168.140.0/24     tcp spt:80`
ACCEPT     tcp  --  192.168.140.0/24     0.0.0.0/0            tcp dpt:80
REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

#再次測試是否可以訪問主機B的web服務
[root@localhost01 ~]# curl 192.168.38.131
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"><html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
                <title>Apache HTTP Server Test Page powered by CentOS</title>
                <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    <!-- Bootstrap -->
    <link href="/noindex/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" href="noindex/css/open-sans.css" type="text/css" />

<style type="text/css"><!--
...省略部分內容
#測試成功

#在這裏我們需要注意的是,在iptables作爲網絡防火牆,配置規則時往往需要考慮“雙向性”。同時我們可以對上述實例規則配置進行優化
#使用--state模塊,無論是由內向外,還是由外向內,只要是響應報文,我們統統放行
[root@localhost02 ~]# iptables -t filter -I FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
[root@localhost02 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
`ACCEPT     all  --  0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED`
ACCEPT     tcp  --  0.0.0.0/0            192.168.140.0/24     tcp spt:80
ACCEPT     tcp  --  192.168.140.0/24     0.0.0.0/0            tcp dpt:80
REJECT     all  --  0.0.0.0/0            0.0.0.0/0            reject-with icmp-port-unreachable

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
#這樣,即使後面有更多的服務需要對規則進行配置,迴應報文都可以被上述這條規則所處理,而我們只需要考慮請求方即可

六、iptables之自定義鏈

  之前我們在定義規則時一直是在iptables中的默認鏈上定義的,當默認鏈中的規則非常多時,並不便與我們管理,那麼就可以通過自定義鏈來解決問題。我們需要知道的是,自定義鏈並不能直接使用,而是需要被默認鏈引用纔可以發揮自己的功能。下面大家從一個栗子來了解自定義鏈吧!

#創建一條自定義鏈對入站的web服務相關報文進行過濾
[root@localhost ~]# iptables -t filter -N IN_WEB    //-N選項用來創建自定義鏈
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 18 packets, 1152 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 9 packets, 856 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain IN_WEB (0 references)    //創建成功
 pkts bytes target     prot opt in     out     source               destination
#在自定義鏈中配置規則:拒絕源地址爲192.168.38.0/24的網絡訪問web服務
[root@localhost ~]# iptables -t filter -I IN_WEB -s 192.168.38.0/24 -j REJECT
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 13 packets, 808 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 8 packets, 784 bytes)
 pkts bytes target     prot opt in     out     source               destination

Chain IN_WEB (0 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  *      *       192.168.38.0/24      0.0.0.0/0           reject-with icmp-port-unreachable
    
#現在自定義鏈中雖然有規則,但是無法匹配報文,因爲我們還沒有在任何默認鏈中引用它
#即爲web服務的入站規則所創建,那麼毋庸置疑需要用INPUT鏈去引用它
[root@localhost ~]# iptables -I INPUT -p tcp --dport 80 -j IN_WEB
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 6 packets, 384 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 IN_WEB     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:80

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

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

Chain IN_WEB (`1 references`)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  *      *       192.168.38.0/24      0.0.0.0/0           reject-with icmp-port-unreachable
#上述這條規則表示:訪問本機80端口的tcp報文會由自定義鏈"IN_WEB"中的規則進行處理。
#之前講到-j選項後面指定處理動作,在這裏變成了自定義鏈,這種情況就表示當前匹配到的報文交由對應的自定義鏈處理,具體得取決於自定義鏈中的規則
#同時也可以看到,IN_WEB鏈高亮字體,表示引用次數,這裏已經變成1了呢

#過一段時間,如果我們覺得這個名字不夠帥,想改一個,怎麼辦呢?
[root@localhost ~]# iptables -E IN_WEB COOL_CHAIN    //-E選項用來重命名自定義鏈
[root@localhost ~]# iptables -nvL
Chain INPUT (policy ACCEPT 6 packets, 384 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 COOL_CHAIN  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:80

Chain FORWARD (policy ACCEPT 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

Chain COOL_CHAIN (1 references)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  *      *       192.168.38.0/24      0.0.0.0/0           reject-with icmp-port-unreachable
#可以看到,引用自定義鏈處的名稱自動會發生修改

#現在我們來探討如何刪除自定義鏈
#想要刪除自定義鏈,需要滿足兩個條件:
#    ① 自定義鏈沒有被任何默認鏈引用,也就是說引用計數爲0
#    ② 自定義鏈中沒有任何規則,也就是說自定義鏈爲空
#現在我們來看看不滿足條件的情況是什麼樣的
[root@localhost ~]# iptables -X COOL_CHAIN
iptables: Too many links.    //提示你太多鏈接哦!不滿足條件①的哦!
[root@localhost ~]# iptables -D INPUT 1    //刪除引用
[root@localhost02 ~]# iptables -X COOL_CHAIN
iptables: Directory not empty.    //提示你鏈不爲空哦!不滿足條件②的哦!
[root@localhost ~]# iptables -F COOL_CHAIN    
[root@localhost ~]# iptables -X COOL_CHAIN    //再次嘗試刪除自定義鏈
[root@localhost ~]# iptables -nvL    //刪除成功
Chain INPUT (policy ACCEPT 32 packets, 2144 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 19 packets, 1704 bytes)
 pkts bytes target     prot opt in     out     source               destination

七、iptables之處理動作詳解

  之前我們只瞭解到一些處理動作的基礎知識,其實處理動作也有自己的選項。

1、REJECT

  REJECT動作的常用選項爲–reject-with,可以設置提示信息,當對方被拒絕時,會提示對方爲什麼被拒絕。有這些可用的值:

選 項 描 述
icmp-net-unreachable 網絡不可達
icmp-host-unreachable 主機不可達
icmp-port-unreachable 端口不可達,默認值
icmp-proto-unreachable 協議不可達
icmp-net-prohibited 網絡被禁止
icmp-host-pro-hibited
icmp-admin-prohibited

  給大家舉個栗子:

演示環境

主機A 主機B
主機名 localhost01 localhost02
IP eth0:192.168.140.130 eth1:192.168.140.131

演示過程

#在主機A上設置規則:拒絕來自主機B的報文,不使用任何選項
[root@localhost01 ~]# iptables -t filter -I INPUT -s 192.168.140.131 -j REJECT
[root@localhost01 ~]# iptables -nL    
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  192.168.140.131      0.0.0.0/0            reject-with icmp-port-unreachable

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

[root@localhost02 ~]# ping -c 4 192.168.140.130    //可以看到,當沒有明確設置--reject-with的值時,默認提示信息爲icmp-port-unreachable
PING 192.168.140.130 (192.168.140.130) 56(84) bytes of data.
From 192.168.140.130 icmp_seq=1 Destination Port Unreachable
From 192.168.140.130 icmp_seq=2 Destination Port Unreachable
From 192.168.140.130 icmp_seq=3 Destination Port Unreachable
From 192.168.140.130 icmp_seq=4 Destination Port Unreachable

--- 192.168.140.130 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3001ms

[root@localhost01 ~]# iptables -t filter -D INPUT 1    //刪除規則

#在主機A上設置規則:拒絕來自主機B的報文,設置提示信息爲"網絡不可達"
[root@localhost01 ~]# iptables -t filter -I INPUT -s 192.168.140.131 -j REJECT --reject-with icmp-net-unreachable
[root@localhost01 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
REJECT     all  --  192.168.140.131      0.0.0.0/0            reject-with icmp-net-unreachable

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

[root@localhost02 ~]# ping -c 4 192.168.140.130    //提示信息已經變爲icmp-Net-Unreachable
PING 192.168.140.130 (192.168.140.130) 56(84) bytes of data.
From 192.168.140.130 icmp_seq=1 Destination Net Unreachable
From 192.168.140.130 icmp_seq=2 Destination Net Unreachable
From 192.168.140.130 icmp_seq=3 Destination Net Unreachable
From 192.168.140.130 icmp_seq=4 Destination Net Unreachable

--- 192.168.140.130 ping statistics ---
4 packets transmitted, 0 received, +4 errors, 100% packet loss, time 3000ms

2、LOG

  LOG動作可以將匹配到的報文的相關信息記錄到日誌(/var/log/messages文件)中,但不對報文做任何處理。舉個栗子:

演示環境

主機A 主機B
主機名 localhost01 localhost02
IP eth0:192.168.140.130 eth1:192.168.140.131

演示過程

#在主機A上設置規則:將B主機發往本機的報文的相關信息記錄在日誌中
[root@localhost01 ~]# iptables -t filter -I INPUT -s 192.168.140.131 -j LOG
[root@localhost01 ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
LOG        all  --  192.168.140.131      0.0.0.0/0            LOG flags 0 level 4

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

[root@localhost02 ~]# ping -c 1 192.168.140.130    //向主機A發送ping包

[root@localhost01 ~]# cat /var/log/messages    //對應報文的相關信息已經被記錄在日誌中
Jun 15 11:13:57 localhost kernel: IN=ens33 OUT= MAC=00:0c:29:50:a7:c5:00:0c:29:62:76:53:08:00 SRC=192.168.140.131 DST=192.168.140.130 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=20711 DF PROTO=ICMP TYPE=8 CODE=0 ID=8168 SEQ=1

  當然,我們也可以將相關信息記錄在指定的文件中,如果企業有專門的日誌服務器,這些日誌就可以分類管理。

#在/etc/rsyslog.conf文件中進行配置即可
[root@localhost01 ~]# vi /etc/rsyslog.conf
...省略部分內容
kern.warning /var/log/ping.log
[root@localhost ~]# systemctl restart rsyslog    //完成配置後需要重啓服務纔可生效

[root@localhost ~]# ping -c 1 192.168.140.130    //再次向主機A發送ping包

[root@localhost ~]# cat /var/log/ping.log
2020-06-15T11:24:40.801886+08:00 localhost kernel: IN=ens33 OUT= MAC=00:0c:29:50:a7:c5:00:0c:29:62:76:53:08:00 SRC=192.168.140.131 DST=192.168.140.130 LEN=84 TOS=0x00 PREC=0x00 TTL=64 ID=37823 DF PROTO=ICMP TYPE=8 CODE=0 ID=8171 SEQ=1

  LOG動作也有一些選項,常用的有這些:

選 項 描 述
–log-level 指定記錄日誌的日誌級別,可用級別有emerg、alert、crit、error、warning、notice、info、debug
–log-prefix 給所記錄的信息添加"標籤",以便區分各種所記錄的報文的信息,對應的值不能超過29個字符

  對這兩個選項不做過多描述。需要提一點,在使用LOG動作時,如果匹配條件很廣泛,那麼匹配到的報文就越多,記錄的信息就會很複雜,當你查看時便會摸不着頭腦。所以說,匹配條件儘可能精確一些,這樣日誌中的信息冗餘就會更少,分析起來效率更高呢!

3、NAT

  NAT(Network Address Translation),譯爲"網絡地址轉換"。通俗來說,也就是修改報文的IP地址,通常NAT功能會被集成到路由器、防火牆、或獨立的NAT設備中。
  那麼修改報文的IP地址該應用於哪些實際場景呢?比如公司的局域網裏每個員工的機器都是私有IP,只能在局域網內的互相訪問,公網無法訪問到這些私有IP,整個公司只有一個可用的公網IP,那麼如何與公網的服務器交互呢?又比如內網的主機訪問其他網絡中的主機時,會暴露自己的IP地址,那麼如何隱藏這些主機的IP地址呢?
  我們只需要在路由器上配置公網IP,在私網主機訪問公網服務時,報文經過路由器時,報文中的私網IP和端口號就會換成公網IP和端口號。這樣內網主機可以共享公網IP訪問互聯網了,與此同時,外部主機收到報文時,源地址和源端口顯示的都是公網IP和端口,當外部主機迴應時,路由器會根據NAT表的映射記錄,將回應報文的目標IP和目標端口換成內部主機的IP和端口,然後再將回應報文發給內網中對應的主機。

  其實整個過程實際有兩次地址轉換:
  ①內部主機的報文發送出去時,報文的源IP和端口發生了改變,也就是源地址轉換(SNAT)。
在這裏插入圖片描述
  ②外部主機迴應報文後,響應報文的目標IP和端口發生了改變,也就是目標地址轉換(DNAT)。
在這裏插入圖片描述
  上述過程被稱爲SNAT,那大家肯定會有疑問,整個過程SNAT和DNAT都有,爲什麼叫SNAT呢?其實這個取決於整個過程的上半段使用的是什麼


  接下來舉個栗子,看看規則應該如何配置吧!

演示環境

主機A(外網主機) 主機B(防火牆) 主機C(公司web服務器)
主機名 localhost01 localhost02 localhost03
IP eth0:192.168.140.129 eth0:192.168.140.130(公網)
eth1:192.168.38.130(私網) eth1:192.168.38.131
GETEWAY 192.168.140.137 192.168.140.1,192.168.38.1 192.168.38.130
網卡模式 NAT eth0:NAT,eth1:僅主機 僅主機

  作爲防火牆的主機負責對報文的修改與轉發,所以,需要開啓核心轉發功能。

演示過程

#SNAT 將來自於192.168.38.0/24網段(內網)的報文的源地址改爲公司的公網IP地址
[root@localhost02 ~]# iptables -t nat -I POSTROUTING -s 192.168.38.0/24 -j SNAT --to-source 192.168.140.130
[root@localhost02 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       all  --  192.168.38.0/24      0.0.0.0/0            to:192.168.140.130
---------------------------------------------------------------------------------
#DNAT 將訪問公網IP的80端口的報文的目標地址改爲公司web服務器的IP的80端口
[root@localhost02 ~]# iptables -t nat -I PREROUTING -d 192.168.140.130 -p tcp --dport 80 -j DNAT --to-destination 192.168.38.131:80
[root@localhost02 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       tcp  --  0.0.0.0/0            192.168.140.130      tcp dpt:80 to:192.168.38.131:80

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
SNAT       all  --  192.168.38.0/24      0.0.0.0/0            to:192.168.140.130

4、MASQUERADE

  MASQUERADE與NAT很類似,它會動態地將源地址轉換爲可用的IP地址。當我們使用撥號上網,那麼每次會分配不同的IP地址。如果這種情況下想讓內網主機共享公網IP上網,那麼每次都要重新配置SNAT規則,這樣無疑是很麻煩的!這時就可以通過MASQUERADE解決,它不需要指明確定的IP,會動態地將報文的源地址修改爲指定網卡上可用的IP地址。舉個栗子:

[root@localhost02 ~]# iptables -t nat -I POSTROUTING -s 192.168.38.131 -o ens33 -j MASQUERADE
[root@localhost01 ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  192.168.38.131      0.0.0.0/0

5、REDIRECT

  REDIRECT動作可以在本機上進行端口映射。經過映射,當別的機器訪問本機的特定端口時,報文會被重定向到本機的指定端口上。REDIRECT動作只能定義在PREROUTING鏈和OUTPUT鏈中。舉個栗子:

#將本機的80端口映射到本機的8080端口上
[root@localhost ~]# iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080
[root@localhost ~]# iptables -t nat -nL
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
REDIRECT   tcp  --  0.0.0.0/0            0.0.0.0/0            tcp dpt:80 redir ports 8080

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
#設置完成後,當其他機器訪問本機的80端口時,報文會被重定向到本機的8080端口上

八、結束語

  一些敘述可能不太準確,但是希望可以幫助到大家!如果其中有錯誤,還希望能及時告知我!謝謝大家!

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