Network / iptables === ###### tags: `OS / Ubuntu / Network` ###### tags: `OS`, `Ubuntu`, `linux`, `command`, `network`, `iptables`, `iptables NAT` <br> [TOC] <br> ## `-t <table>` | 表(table) | 作用 | |-------------|------| | **filter**(預設) | 做防火牆的過濾判斷(如 DROP/ACCEPT) | | **nat** | 做 IP 位址轉換(如 SNAT, DNAT) | | **mangle** | 修改封包欄位(TTL, TOS, 路徑等) | | **raw** | 跳過連線追蹤(Connection Tracking) | | **security** | SELinux 相關的存取控制 | <br> ## iptables NAT 除錯教學(K8s: Flannel + Pod 無法出網) > by gpt-4o (2025/06/05) :::info :bulb: [QuickStart] **啟用 iptables LOG,觀察封包經過哪裡** ```bash= # 設置前先查看 monitor sudo iptables -t nat -L POSTROUTING -v -n --line-numbers # 設置 monitor sudo iptables -t nat -I POSTROUTING 1 -j LOG --log-prefix "NAT-POST: " # 查看 monitor sudo iptables -t nat -L POSTROUTING -v -n --line-numbers # 開 log 監聽 sudo journalctl -f | grep NAT-POST # 發 request 測試,查看 log 有無 91.189.91.38 curl -I http://91.189.91.38 # 查看 monitor sudo iptables -t nat -L POSTROUTING -v -n --line-numbers # 移除 monitor sudo iptables -t nat -D POSTROUTING 1 ``` ::: ### ✅ 一、觀察 NAT 規則 列出目前 NAT 表的 POSTROUTING 鏈(封包離開主機前的轉換規則): ``` sudo iptables -t nat -L POSTROUTING -v -n --line-numbers ``` 常見欄位: | 欄位 | 說明 | |------|------| | num | 規則編號 | | pkts | 被這條規則匹配的封包數量 | | target | MASQUERADE 表示 SNAT | | source/destination | 對應來源與目的 IP 範圍 | --- ### ✅ 二、加入 MASQUERADE SNAT 規則(讓 Pod 封包能出網) ``` sudo iptables -t nat -I POSTROUTING 1 -s 10.244.0.0/16 ! -d 10.244.0.0/16 -j MASQUERADE ``` - **意義**: - 在 `nat` 表中, - 插入(Insert)一條規則到 `POSTROUTING` 鏈(處理封包出站前), - 當來源是 Pod 網段(10.244.0.0/16),且目標不是 Pod 網段(! -d 10.244.0.0/16)時, - 將來源 IP MASQUERADE(動態轉換為主機 IP) - **參數**: - `-t nat` 指的是要操作 **NAT(Network Address Translation)表**,這個表用來修改封包的來源或目的 IP,例如: | 表(table) | 作用 | |-------------|------| | **filter**(預設) | 做防火牆的過濾判斷(如 DROP/ACCEPT) | | **nat** | 做 IP 位址轉換(如 SNAT, DNAT) ✅ | | **mangle** | 修改封包欄位(TTL, TOS, 路徑等) | | **raw** | 跳過連線追蹤(Connection Tracking) | | **security** | SELinux 相關的存取控制 | - `-I 1`:插入到 POSTROUTING 鏈的第一條(優先匹配) - `-s 10.244.0.0/16`:指定來源為 Pod IP(Flannel 預設) - `! -d 10.244.0.0/16`:排除 Pod-to-Pod 內部流量 - `-j MASQUERADE`:動態 SNAT,轉換成 Node 的 IP 出站 - masquerade [͵mæskəˋred] - n. 偽裝;化裝;欺騙 - vi. 化裝;冒充 --- ### ✅ 三、插入 LOG 規則觀察封包是否進入 NAT ``` sudo iptables -t nat -I POSTROUTING 1 -j LOG --log-prefix "NAT-POST: " ``` > 📌 建議插入在第一條以觀察所有封包是否經過 POSTROUTING 鏈。 --- ### ✅ 四、過濾 NAT 封包 log 系統 log 非常多,建議如下方式過濾出你要看的內容: ``` sudo journalctl -k -g 'NAT-POST' ``` 或用 `tail`: ``` sudo tail -f /var/log/kern.log | grep 'NAT-POST' ``` 範例輸出: ``` Jun 05 18:12:45 node kernel: NAT-POST: IN=cni0 OUT=eth0 SRC=10.244.0.3 DST=91.189.91.38 ... ``` 你可以從中看到: - `SRC=`:來源 IP,應是某個 Pod IP - `DST=`:目標 IP(如 archive.ubuntu.com 的實際 IP) --- ### ✅ 五、如何從 Pod 發出測試封包? 使用 `curl` 搭配 IP(不經過 DNS): ``` kubectl exec -it ubuntu-2204-net-tools-pod -- curl -I http://91.189.91.38 ``` 或: ``` kubectl exec -it <pod-name> -- ping -c 2 91.189.91.38 ``` > `91.189.91.38` 是 archive.ubuntu.com 的實體 IP,可用 `dig` 查出其他目標 IP 這些封包會觸發 `iptables` 的 POSTROUTING 鏈,若有成功觸發,`pkts/bytes` 會上升,`LOG` 也會輸出對應內容。 --- ### ✅ 六、刪除指定規則 查出規則編號: ``` sudo iptables -t nat -L POSTROUTING --line-numbers -v -n ``` 刪除(例如第 1 條): ``` sudo iptables -t nat -D POSTROUTING 1 ``` --- ### ✅ 七、檢查系統是否允許封包轉送(forward) ``` sysctl net.ipv4.ip_forward # 應輸出:net.ipv4.ip_forward = 1 ``` 如為 0,請執行: ``` sudo sysctl -w net.ipv4.ip_forward=1 ``` --- ### ✅ 八、觀察封包是否真的從 Node 出去(tcpdump) 在 Node 執行: ``` sudo tcpdump -i any host 91.189.91.38 ``` 從 Pod 發出 curl 時觀察是否有封包經過,若沒有,表示: - 封包卡在 Pod → bridge → Node 的某一環節 - 或沒有經過 SNAT,被網關擋掉 --- ### ✅ 九、建議測試流程總結 1. 插入 LOG 規則觀察封包是否進入 POSTROUTING 2. 從 Pod 發出 curl 請求(用 IP,排除 DNS 問題) 3. 用 `journalctl -g 'NAT-POST'` 觀察 log 是否出現封包紀錄 4. 若 `pkts=0` 且 log 無紀錄 → 封包未進入 NAT(可能 bridge 或 route 問題) --- 以上為常用的 `iptables NAT` 除錯操作整理,特別適用於 Kubernetes Flannel CNI 中的 Pod 無法出網情境。 <br> ## 討論 ### 解釋 `sudo iptables -D INPUT -j CILIUM_INPUT 2>/dev/null` - ### Question ``` sudo iptables -D INPUT -j CILIUM_INPUT 2>/dev/null ``` 這段指令怎麼解釋? - ### GPT-4 Turbo (2025/06/16) 這段指令 `sudo iptables -D INPUT -j CILIUM_INPUT 2>/dev/null` 是用來在 Linux 系統中操作 **iptables** 防火牆規則的。讓我們來一步步解釋: ### 1. **`sudo`**: * `sudo` 代表「SuperUser Do」,意思是以 **超級使用者(root)** 的身份執行後面的命令。這是因為操作防火牆通常需要更高的權限。 ### 2. **`iptables`**: * `iptables` 是一個用來設定和管理 Linux 防火牆的工具。它基於網路流量過濾規則,幫助管理進出系統的網路流量。 ### 3. **`-D INPUT`**: * `-D` 是 **刪除規則**(Delete)的意思,表示你要刪除一條現有的規則。 * `INPUT` 是指 **進來的網路流量**。因此,這條規則是針對處理進入系統的流量,且會刪除相關的規則。 ### 4. **`-j CILIUM_INPUT`**: * `-j` 代表「跳轉到(jump)」某個規則鏈。這意味著當流量進入該防火牆規則時,會轉到名為 `CILIUM_INPUT` 的自訂鏈(chain)進一步處理。 * `CILIUM_INPUT` 是某個特定的鏈名,這通常是在 **Cilium** 等網路管理工具中設置的規則鏈,用來進行流量管理、監控、或者處理。Cilium 是一個容器化環境下的網路和安全解決方案。 ### 5. **`2>/dev/null`**: * `2>` 是將 **標準錯誤輸出**(stderr)重定向到某個地方。 * `/dev/null` 是一個特殊設備,會丟棄所有寫入它的資料,這相當於「消聲處理」。換句話說,這一部分的作用是讓錯誤訊息不會顯示在終端機上,即便執行指令時出現錯誤也不會顯示出來。 ### 綜合解釋: 這條命令的意思是: * 以超級使用者身份執行 `iptables`。 * 刪除在 `INPUT` 鏈中,跳轉到 `CILIUM_INPUT` 鏈的規則。 * 如果有錯誤發生,將錯誤訊息丟到 `/dev/null`,也就是不顯示錯誤。 ### 使用場景: 這條指令通常用來 **移除** 與 Cilium 相關的防火牆規則,尤其是在需要清理或調整 Cilium 的網路設定時,這樣做可以保證不再通過 `CILIUM_INPUT` 鏈處理進來的流量。 <br> {%hackmd vaaMgNRPS4KGJDSFG0ZE0w %}