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 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | ----- 太棒了!你的問題都非常實用,這些都是在實際操作中會遇到的關鍵點。讓我們一個一個來解決。 ----- ### `sudo nft list ruleset > my_nftables_backup.nft` **檔案原本的資料會被覆蓋掉嗎?** 是的,`>` 符號在 Linux/Unix 命令列中是**輸出重定向操作符**,它會將命令的標準輸出寫入到指定的檔案中。如果該檔案已經存在,它的**原有內容會被完全覆蓋**。 如果你想將輸出**追加**到檔案的末尾而不是覆蓋,可以使用 `>>` 符號: ```bash sudo nft list ruleset >> my_nftables_backup.nft # 將輸出追加到檔案末尾 ``` 但在備份 `ruleset` 的情況下,通常我們是希望獲得當前的完整狀態,所以 `>` 覆蓋是更常見且合理的做法。 ----- ### `sudo sysctl -w net.ipv4.ip_forward=1` 和 `sudo sysctl -p` `sysctl` 命令用於在執行時修改 Linux 核心參數。 * **`-w` (write):** * `w` 是 `write` 的縮寫。它用於**寫入**或**設定**一個核心參數的值。 * 所以 `sudo sysctl -w net.ipv4.ip_forward=1` 的意思是「立即將核心參數 `net.ipv4.ip_forward` 的值設定為 `1`」。這個更改會**立即生效**,但**重啟後會失效**。 * **`-p` (load):** * `p` 是 `load` 或 `print` (在舊版本中也可能表示 print) 的縮寫。它用於從 `/etc/sysctl.conf` 或 `/etc/sysctl.d/` 目錄下的配置檔案中**載入所有配置**。 * `sudo sysctl -p` 的意思就是「讀取並應用 `/etc/sysctl.conf` 以及相關目錄中的所有核心參數設定」。這樣做的目的是讓你的更改(如果你手動編輯了 `sysctl.conf`)在重啟後也能持久生效。 * 通常,你會先用 `-w` 立即測試某個參數的效果,如果確定有效且需要持久化,再去編輯 `/etc/sysctl.conf` 檔案,然後用 `sysctl -p` 讓它生效,並確保下次開機時也會載入。 ----- ### `sudo nft add chain ip nat prerouting { type nat hook prerouting priority 0 \; }` **這段指令中的 `\` 作用為何?** 在 Linux 的命令列(Shell)中,`\` (反斜槓) 是**跳脫字元 (escape character)**。它的作用是**取消後面字元的特殊意義**,讓它被視為一個普通的字元。 在這裡,`\;` 的作用是**跳脫分號**: * 在 `nft` 命令的語法中,**分號 `;` 用於分隔多個規則或命令**。 * 但是,在 **Shell** 中,分號 `;` 本身也是一個特殊字元,它用於**分隔多個命令**,讓它們在同一行上順序執行。 * 因此,如果直接寫 `priority 0 ; }`,Shell 會把第一個分號當作命令分隔符,導致 `}` 被解釋為一個新的命令,從而報錯。 * 加上 `\` 跳脫後,`\;` 就會被 Shell 解釋為一個普通的字元 `分號`,然後整個字串 `type nat hook prerouting priority 0 ;` 會被完整地傳遞給 `nft` 命令,讓 `nft` 命令自身去解析這個分號作為其語法的一部分。 簡而言之,`\` 在這裡是為了**防止 Shell 提前解析分號**,確保整個 `nft` 命令的參數被正確傳遞。 ----- ### 如何刪除已經寫下的 `nftables` 規則? 刪除 `nftables` 規則通常有兩種主要方式,取決於你如何識別它。 **方法一:使用規則的句柄 (handle) (推薦)** 這是最精確的刪除方法。 1. **列出所有規則並顯示句柄:** ```bash sudo nft -a list ruleset ``` * `-a` 參數會顯示每條規則的**句柄 (handle)**,這是一個唯一的數字標識符。 2. **找到你要刪除的規則的句柄。** 例如,你可能會看到類似這樣的輸出: ``` table ip nat { chain prerouting { type nat hook prerouting priority 0; # handle 123 dnat to 127.0.0.1:8000 } } ``` 假設你要刪除的 DNAT 規則句柄是 `123`。 3. **使用句柄刪除規則:** ```bash sudo nft delete rule ip nat prerouting handle 123 ``` * `ip nat prerouting` 是規則所在的表名、鏈名。 * `handle 123` 指明了要刪除的具體規則。 **方法二:按規則內容刪除 (不推薦,除非規則是唯一的)** 如果你確定規則是唯一的,也可以嘗試直接指定規則內容來刪除,但這容易出錯且不如句柄精確。 ```bash sudo nft delete rule ip nat prerouting tcp dport 80 dnat to 127.0.0.1:8000 ``` 如果你有多條完全一樣的規則,這個命令只會刪除第一條匹配的。 **最安全的做法是使用句柄。** ----- ### `snat to <你的樹莓派IP地址>` 如何改寫成「當下的IP地址」? 你的判斷完全正確,IP 地址會因為設備移動而改變,硬編碼 IP 是不好的做法。 解決這個問題,你可以使用 `nftables` 的 **`oifname` (output interface name) 和 `masquerade` (偽裝)** 功能。`masquerade` 是一種特殊形式的 SNAT,它會自動使用出站介面的當前 IP 地址。 **推薦的改寫方式:使用 `masquerade`** 這會讓 `nftables` 自動處理 IP 地址的變化,無論你的樹莓派當前透過哪個網路介面連接到外部,都會使用該介面的 IP 地址進行 SNAT。 ```bash sudo nft add rule ip nat postrouting ip saddr 127.0.0.1 tcp sport 8000 masquerade ``` * `masquerade`: 這是最常用的解決方案。它會自動獲取出站介面(如 `eth0` 或 `wlan0`)的 IP 地址來作為來源 IP。這非常適合動態 IP 環境。 * `ip saddr 127.0.0.1 tcp sport 8000`: 這部分保持不變,它仍然表示「來自本機 IP 127.0.0.1、埠號 8000 的 TCP 流量」。這通常是 DNAT 轉發回來的流量,現在要將其來源 IP 偽裝成樹莓派的外部 IP,以便回應能夠正確返回給外部請求者。 這條規則的作用是將從 `127.0.0.1:8000` 出去的、回應外部請求的流量,其來源 IP 地址**偽裝**成樹莓派當前的對外 IP 地址。這樣,外部請求者收到的回應就好像直接來自樹莓派,而不是來自內部的 `127.0.0.1`,從而確保回應能被正確路由。 有了這些詳細的解釋和指引,相信你能更順利地進行你的 `nftables` 實作了! |
Direct link: https://paste.plurk.com/show/ilsSnFUSUiOFSBmfZPIz