聊聊Iptables 的五表五鏈,你學會了嗎?
聊聊Iptables 的五表五鏈,你學會了嗎?
概述
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 就會根據該鏈預先定義的默認策略來處理數據包。
名稱 | 描述 |
輸入 | 處理接收的數據包 |
輸出 | 處理髮送的數據包 |
向前 | 處理轉發的數據包,常用於 |
預路由 | 修改到達且還未轉發的數據包,常用於 |
郵寄 | 修改發送前的的數據包,常用於 |
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/