# 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 對) 。