# nftables 基本觀念筆記 ## nftables 的基本結構 ``` nftables └── Table <表>(對應於某個協定族,如 ip、ip6、inet) ├── Chain <鏈>(包含規則的容器) │ ├── type <鏈類型>(base chain 或 regular chain) │ ├── hook <掛勾點>(prerouting、input、output、forward、postrouting) │ ├── priority <優先順序> │ ├── policy <預設策略>(accept/drop) │ ├── Rule <規則> │ │ ├── 條件式(match 條件,如 src ip、port、protocol) │ │ ├── 動作(accept、drop、dnat、snat、log) │ └── ... │ ├── Chain <其他鏈> │ ├── Rule <規則> │ └── ... │ ├── Set <集合>(儲存 IP、port 或其他值) │ ├── type <資料類型> │ ├── elements = { <值1>, <值2>, ... } │ └── ... │ ├── Map <映射>(key 對應 value) │ ├── type <key 類型> : <value 類型> │ ├── elements = { <key1> : <value1>, <key2> : <value2> } │ └── ... │ └── 其他物件(如 counter、meter、quota) ``` ### Rule (規則) * 描述「**該對具有什麼特徵的封包做什麼事**」的基本單位 。 * 由 **expression (表達式)** (指定封包的特徵) 和 **statement (語句)** (指定要執行的動作) 組成 。 * 範例:`ip saddr 1.1.1.1 ip daddr 2.2.2.2 tcp sport 111 tcp dport 222 accept` 。 * **Expression (表達式)**:測試封包是否符合特定的欄位或元數據 。多個表達式從左到右線性評估,所有表達式都匹配時,規則才匹配 。 * **Statement (語句)**:定義匹配封包後要執行的動作,例如計數 (`counter`)、記錄 (`log`)、接受 (`accept`)、丟棄 (`drop`) 或跳轉到另一個鏈 (`jump <chain-name>`) 。 ### Chain (鏈) * **Rule 的集合**,具有 `chain {...}` 形式的區塊。 * 分為兩種主要類型: * **Base Chain (基礎鏈)** :**會處理流經 Linux TCP/IP 堆疊的封包**,需要指定 `type`、`hook` 和 `priority` 。 * **Type (類型)** : * `filter`: 標準鏈類型,用於過濾 。 * `nat`: 用於執行網路位址轉換 (NAT),基於 conntrack 條目 。 * `route`: 如果封包在這種鏈中被接受且 IP header 相關部分已更改,則執行新的路由查找,可用於策略路由 。 * **Hook (掛鉤點)** :指定在封包處理的哪個階段進行過濾 。不同的協定族支援不同的 hook 點 。IPv4/IPv6 常見的 hook 點包括: * `prerouting`: 進入系統後,路由決策前 。 * `input`: 送往本地系統的封包 。 * `forward`: 轉發到其他主機的封包 。 * `output`: 本地進程發送的封包 。 * `postrouting`: 離開系統前 。 * `ingress`: 進入系統的最早階段 (Linux kernel 5.10+,僅適用於 inet 族) 。 * **Priority (優先順序)** :如果同一個 hook 點有多個鏈,則按照 priority 從小到大依序執行 。某些數值有預定義的名稱,例如 `raw` (-300), `mangle` (-150), `dstnat` (-100), `filter` (0), `security` (50), `srcnat` (100) 。 * **Regular Chain (常規鏈)** :**不直接掛鉤到 Netfilter hook**,本身不處理任何流量。可以被 base chain 中的規則使用 `jump` 或 `goto` 語句跳轉到此鏈。主要用於組織規則,提高可讀性 。 ### Table (表) * **Chain 和其他物件 (如 set 和 map) 的集合** 。 * 一個 table 屬於一個特定的**協定族 (address family)**,例如 `ip` (IPv4), `ip6` (IPv6), `inet` (同時支援 IPv4 和 IPv6), `arp`, `netdev` 等 。 * 使用 `table <協定族> <表名> { ... }` 的形式定義 。 * 一個 table 中可以包含多個 chain 。 ### 資料結構 * **Set (集合)** :用於定義**一組具有相同類型的元素** (例如 IPv4 位址、port 號) 。可以使用 `@<集合名>` 在規則中引用集合,使得一個規則可以應用於多個元素 。 * 使用 `set <集合名> { type <資料類型>; elements = { ... }; }` 創建 。 * 可以使用 `nft add element` 添加元素 。 * **Map (映射)** :用於建立 **key-value 的對應關係** 。例如,可以將 IP 位址映射到 conntrack mark 。可以使用 `map @<映射名>` 在規則中引用映射 。 * 使用 `map <映射名> { type <key 類型> : <value 類型>; elements = { <key1> : <value1>, ... }; }` 創建 。 * 可以使用 `nft add element` 添加元素 (key-value 對) 。