聊聊Iptables 的五表五鏈,你學會了嗎?

2023.04.05

聊聊Iptables 的五表五鏈,你學會了嗎?

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

概述

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

圖片

圖片來源: https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg

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

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

規則

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

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

行為

動作

描述

接受

接收數據包

降低

丟棄數據包,進行完此動作後,將直接中斷檢測過程,不再檢測其它規則

重定向

將封包重新導向到另一個端口(PNAT),進行完此動作後,繼續比對其它規則,這個功能可以用來實現透明代理或用來保護應用服務器

SNAT

源地址轉換

DNAT

目的地址轉換

化裝舞會

IP偽裝(NAT),用於ADSL

日誌

日誌記錄

塞馬克

添加SEMARK 標記以供網域內強制訪問控制(MAC)

隊列

將數據包傳遞到用戶空間

拒絕

攔截數據包,並返回數據包通知對方

返回

防火牆停止執行當前鏈中的後續規則,並返回到調用鏈中繼續檢測

5鏈

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

名稱

描述

輸入

處理接收的數據包

輸出

處理髮送的數據包

向前

處理轉發的數據包,常用於 ​​网络隔离​​​, ​​NAT​​​, ​​负载均衡​

預路由

修改到達且還未轉發的數據包,常用於 ​​DNAT​​​, ​​端口映射​​​, ​​源地址转换​

郵寄

修改發送前的的數據包,常用於 ​​SNAT​

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 用於給包打上SELinux 標記,以此影響SELinux 或其他可以解讀SELinux 安全上下文的系統處理包的行為。這些標記可以基於單個包,也可以基於連接。

表和鏈關係圖

圖片

表和鏈關係圖

表的檢測優先級

Raw -> Mangle -> Nat -> 過濾器

圖片

圖片來源: https://www.frozentux.net/iptables-tutorial/images/tables_traverse.jpg

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

• 一個數據包進入網卡時,首先進入 PREROUTING 鏈,內核根據數據包目的IP 判斷是否需要轉發

• 如果數據包是進入本機的,它就會沿著圖向下移動,到達 INPUT​ 鏈,數據包到了INPUT鏈後,任何進程都會收到它,本機上程序可以發送數據包,這些數據包會經過 OUTPUT​ 鏈,然後到達 POSTROUTING 鏈輸出

• 如果數據包是轉發出去的,且內核允許轉發,數據包會經過 FORWARD​ 鏈,然後到達 POSTROUTING 鏈輸出

常用命令

查看類

# 查看所有防火墙规则
$ 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
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.

字段名稱

描述

目標

規則行為

利潤

協議

選擇

選項

來源

源IP 地址

目的地

目的IP 地址

操作類

# 查看说明

$ 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
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50。
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.

命令選項輸入順序

iptables -t 表名 <-A/I/D/R> 规则链名 [规则号] <-i/o 网卡名> -p 协议名 <-s 源IP/源子网> --sport 源端口 <-d 目标IP/目标子网> --dport 目标端口 -j 动作
  • 1.

示例

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

查看已添加的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
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

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

$ iptables -F  # 清空所有的防火墙规则
$ iptables -X  # 删除用户自定义的空链
$ iptables -Z  # 清空计数
  • 1.
  • 2.
  • 3.

設置默認規則

$ iptables -P INPUT DROP    # 配置默认的不让进
$ iptables -P FORWARD DROP  # 默认的不允许转发
$ iptables -P OUTPUT ACCEPT # 默认的可以出去
  • 1.
  • 2.
  • 3.

開放指定端口

$ 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                                       # 禁止其他未允许的规则访问
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

白名單

$ 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 端口
  • 1.
  • 2.
  • 3.

黑名單

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
  • 1.
  • 2.
  • 3.
  • 4.

防止SYN 洪水攻擊

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

小結

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

參考

  • • 遍歷表和鏈[1]
  • • iptables(8) - Linux 手冊頁 [2]
  • • iptables[3]
  • • iptables詳解[4]
  • • iptables 命令[5]
  • • 深入理解iptables 和netfilter 架構[6]
  • • iptables 基礎知識與命令速查

引用鏈接

[1] 表和鏈的遍歷: 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命令: https://wangchujiang.com/linux-command/c/iptables.html

[6]​ 深入理解iptables 和netfilter 架構: https://arthurchiao.art/blog/deep-dive-into-iptables-and-netfilter-arch-zh/