iptables 的五表五鏈

概述

iptables 是一個配置 Linux 內核防火牆的命令行工具,它基於內核的包過濾框架(packet filtering framework) netfilter, 主要用於管理數據包過濾和 NAT 規則。

iptables 與協議棧內有包過濾功能的 hook 交 互來完成工作。這些內核 hook 構成了 netfilter 框架。每個進入網絡系統的包(接收或發送)在經過協議棧時都會觸發這些 hook, 程序可以通過註冊 hook 函數的方式在一些關鍵路徑上處理網絡流量iptables 相關的內核模塊在這些 hook 點註冊了處理函數,因此可以通過配置 iptables 規則來使得網絡流量符合防火牆規則。

理解 iptables 是學習 DockerKubernetes 等開源項目中網絡功能實現的基礎。

規則

規則 就是網絡管理員預定義的條件,一般的定義爲 如果數據包頭符合當前條件,處理這個數據包,反之執行下一個判斷條件, 規則 存儲在內核空間的過濾表中,這些規則分別指定了 源地址目的地址傳輸協議(如 TCP、UDP、ICMP)和 服務類型(如 HTTP、FTP 和 SMTP)等, 當數據包與 規則 匹配時,內核會執行具體的 行爲

配置防火牆的主要工作就是添加、修改和刪除規則

行爲

rcwD7r

5 鏈

 是數據包傳播的路徑,每一個  中可以有 N 個 規則 (N>= 0)。當數據包到達一個  時,iptables 就會從鏈中第一個規則開始檢測, 如果數據包滿足規則所定義的條件,系統會執行具體的 行爲,否則 iptables 繼續檢查下一個規則。 如果數據包不符合鏈中任一個規則,iptables 就會根據該鏈預先定義的默認策略來處理數據包。

uKHGtO

5 表

表有 N 個鏈,鏈有 N 個規則。

大部分場景僅需使用 Filter 表 和 NAT 表

Raw 表

Raw 表用於在 連接跟蹤、NAT 和路由表處理之前 對數據包進行處理,包含 2 種內置鏈:

因爲優先級最高,所以如果使用了 Raw 表,那麼在 Raw 表處理完後, 將跳過 NAT 表和 ip_conntrack 處理, 也就是避免了 連接跟蹤、NAT 和路由表前置 處理。

Filter 表

Filter 是 iptables 的默認表,用於過濾數據包,如果沒有定義表的情況下將使用 Filter 表,包含 3 種內置鏈:

在 Filter 表中只允許對數據包進行接受,丟棄的操作,而無法對數據包進行更改。

NAT 表

NAT 用於實現網絡地址轉換,包含 3 種內置鏈:

Mangle 表

Mangle 用於對指定數據包報頭進行修改、標記或重定向,包含 5 種內置鏈:

Security 表

Security 用於給包打上 SELinux 標記,以此影響 SELinux 或其他可以解讀 SELinux 安全上下文的系統處理包的行爲。這些標記可以基於單個包,也可以基於連接。

表和鏈關係圖

表和鏈關係圖

表的檢測優先級

Raw -> Mangle -> Nat -> Filter

任何一個數據包必然經過 5 個鏈中的其中一個

常用命令

查看類

# 查看所有防火牆規則
$ iptables --list

# 示例輸出如下
Chain DOCKER (8 references)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             172.27.0.2           tcp dpt:10010
ACCEPT     tcp  --  anywhere             172.22.0.2           tcp dpt:http
ACCEPT     tcp  --  anywhere             172.29.0.4           tcp dpt:memcached
ACCEPT     tcp  --  anywhere             172.17.0.2           tcp dpt:redis
ACCEPT     tcp  --  anywhere             172.17.0.2           tcp dpt:nginx
ACCEPT     tcp  --  anywhere             172.17.0.4           tcp dpt:8080
ACCEPT     tcp  --  anywhere             172.17.0.5           tcp dpt:mysql
ACCEPT     tcp  --  anywhere             172.17.0.5           tcp dpt:http

# 查看 mangle 表規則
$ iptables -t mangle --list

# 查看 nat 表規則
$ iptables -t nat --list

oorWFm

操作類

# 查看說明

$ iptables --help

# 查看命令
iptables -L:查看規則鏈

# 規則管理命令
iptables -A:在規則鏈的末尾加入新規則
iptables -D:刪除某個規則
iptables -I:在規則鏈的頭部加入新規則
iptables -R:替換規則鏈中的規則

# 鏈管理命令
iptables -F:清空規則鏈
iptables -Z:清空規則鏈中的數據包計算器和字節計數器
iptables -N:創建新的用戶自定義規則鏈
iptables -P:設置規則鏈中的默認策略

# 通用匹配參數
-t
    對指定的表 table 進行操作
    如果不指定此選項,默認的是 filter 表

-p 協議
    指定規則的協議,如 tcp, udp, icmp 等,可以使用all來指定所有協議
    如果不指定 -p 參數,默認的是 all 值

-s 源地址
    指定數據包的源地址
    參數可以使IP地址、網絡地址、主機名
    例如:-s 192.168.1.101 指定IP地址
    例如:-s 192.168.1.10/24 指定網絡地址

-d 目的地址
    指定數據包的目的地址,規則和 -s 類似

-j 執行目標
    指定規則匹配時如何處理數據包
    可能的值是ACCEPT, DROP, QUEUE, RETURN 等

-i 輸入接口
    指定要處理來自哪個接口的數據包,這些數據包將進入 INPUT, FORWARD, PREROUTE 鏈
    例如:-i eth0指定了要處理經由eth0進入的數據包
    如果不指定 -i參數,那麼將處理進入所有接口的數據包
    如果指定 ! -i eth0,那麼將處理所有經由eth0以外的接口進入的數據包
    如果指定 -i eth+,那麼將處理所有經由eth開頭的接口進入的數據包

-o 輸出
    指定了數據包由哪個接口輸出,這些數據包將進入 FORWARD, OUTPUT, POSTROUTING鏈
    如果不指定-o選項,那麼所有接口都可以作爲輸出接口
    如果指定 ! -o eth0,那麼將從eth0以外的接口輸出
    如果指定 -i eth+,那麼將僅從eth開頭的接口輸出
  
# 擴展參數
-sport 源端口
    針對 -p tcp 或者 -p udp,默認情況下,將匹配所有端口
    可以指定端口號或者端口名稱、端口範圍,例如 –sport 22, –sport ssh,–sport 22:100 
    從性能上講,使用端口號更好, /etc/services 文件描述了映射關係

-dport 目的端口
    規則和 –sport 類似

-tcp-flags TCP 標誌
    針對 -p tcp
    可以指定由逗號分隔的多個參數
    取值範圍:SYN, ACK, FIN, RST, URG, PSH, ALL, NONE

-icmp-type ICMP 標誌
    針對 -p icmp
    icmp-type 0 表示 Echo Reply
    icmp-type 8 表示 Echo

命令選項輸入順序

iptables -t 表名 <-A/I/D/R> 規則鏈名 [規則號] <-i/o 網卡名> -p 協議名 <-s 源IP/源子網> --sport 源端口 <-d 目標IP/目標子網> --dport 目標端口 -j 動作

示例

以下命令在生產環境中謹慎使用

查看已添加的 iptables 規則

$ iptables -L -n -v

Chain INPUT (policy DROP 48106 packets, 2690K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 5075  589K ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
 191K   90M ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22
1499K  133M ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:80
4364K 6351M ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED
 6256  327K ACCEPT     icmp --  *      *       0.0.0.0/0            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 3382K packets, 1819M bytes)
 pkts bytes target     prot opt in     out     source               destination         
 5075  589K ACCEPT     all  --  *      lo      0.0.0.0/0            0.0.0.0/0

清空當前的所有規則和計數

$ iptables -F  # 清空所有的防火牆規則
$ iptables -X  # 刪除用戶自定義的空鏈
$ iptables -Z  # 清空計數

設置默認規則

$ iptables -P INPUT DROP    # 配置默認的不讓進
$ iptables -P FORWARD DROP  # 默認的不允許轉發
$ iptables -P OUTPUT ACCEPT # 默認的可以出去

開放指定端口

$ iptables -A INPUT -s 127.0.0.1 -d 127.0.0.1 -j ACCEPT               # 允許本地迴環接口(即運行本機訪問本機)
$ iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT    # 允許已建立的或相關連的通行
$ iptables -A OUTPUT -j ACCEPT                                        # 允許所有本機向外的訪問
$ iptables -A INPUT -p tcp --dport 22 -j ACCEPT                       # 允許訪問22端口
$ iptables -A INPUT -p tcp --dport 80 -j ACCEPT                       # 允許訪問80端口
$ iptables -A INPUT -p tcp --dport 21 -j ACCEPT                       # 允許ftp服務的21端口
$ iptables -A INPUT -p tcp --dport 20 -j ACCEPT                       # 允許FTP服務的20端口
$ iptables -A INPUT -j reject                                         # 禁止其他未允許的規則訪問
$ iptables -A FORWARD -j REJECT                                       # 禁止其他未允許的規則訪問

白名單

$ iptables -A INPUT -p all -s 192.168.1.0/24 -j ACCEPT            # 允許機房內網機器可以訪問
$ iptables -A INPUT -p all -s 192.168.140.0/24 -j ACCEPT          # 允許機房內網機器可以訪問
$ iptables -A INPUT -p tcp -s 183.121.3.7 --dport 3380 -j ACCEPT  # 允許 183.121.3.7 訪問本機的 3380 端口

黑名單

iptables -I INPUT -s 123.45.6.7 -j DROP       # 屏蔽單個 IP
iptables -I INPUT -s 123.0.0.0/8 -j DROP      # 屏蔽 IP 網段 從 123.0.0.1  到 123.255.255.254
iptables -I INPUT -s 124.45.0.0/16 -j DROP    # 屏蔽 IP 網段 從 123.45.0.1 到 123.45.255.254
iptables -I INPUT -s 123.45.6.0/24 -j DROP    # 屏蔽 IP 網段 從 123.45.6.1 到 123.45.6.254

防止 SYN 洪水攻擊

$ iptables -A INPUT -p tcp --syn -m limit --limit 5/second -j ACCEPT

小結

撰寫本文過程中,筆者發現中文內容幾乎說的都是 四表五鏈,不知是作者刻意跳過 Security 表,還是抄襲導致的同質化太嚴重。 雖然 Security 表不是常用功能,但是我們不能忽略其存在。

Reference

引用鏈接

[1] Traversing of tables and chains: https://www.frozentux.net/iptables-tutorial/iptables-tutorial.html#TRAVERSINGOFTABLES
[2] iptables(8) - Linux man page: https://linux.die.net/man/8/iptables
[3] iptables: https://wiki.archlinuxcn.org/wiki/Iptables
[4] iptables 詳解: https://lixiangyun.gitbook.io/iptables_doc_zh_cn/
[5] iptables command: https://wangchujiang.com/linux-command/c/iptables.html
[6] 深入理解 iptables 和 netfilter 架構: https://arthurchiao.art/blog/deep-dive-into-iptables-and-netfilter-arch-zh/

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/D0FqiY5pPE9pJ-6AFMbZWQ