Firewall

如何通過終端在 Nftables 中使用定義的變數(不在腳本中)

  • May 27, 2020

我想在互動式shell中執行這兩個命令,一個接一個(作為root並載入“過濾器”表和“輸入”鏈):

nft define lala=1.2.3.4
nft add rule ip filter input ip saddr \$lala accept

你可以看到我逃脫了“ $ " to avoid shell expansion. But I get this error message “Unkown identifier ’lala’”. If I don’t escape the " $ ”,我得到這個錯誤消息:“語法錯誤,意外的接受”。如果我寫*$* $lala,我得到這個錯誤消息:“語法錯誤,未接受的接受,期望字元串”,並且顯示了這個錯誤的規則:添加規則 ip 過濾器輸入 ip saddr $ 接受。

那麼,在互動式 shell 中使用 Nft 變數的正確語法是什麼。在 Nft 腳本中做同樣的事情效果很好(不用擔心轉義)。

非常感謝

nft 使用者空間命令使用的符號變數由該命令解析為它們的值。該nft命令將變數解析為其分配的值以組合最終結果。然後nft命令使用netlink API與核心通信並向它發送新規則以添加。核心從來沒有看到lala=1.2.3.4也沒有任何符號變數的概念。

因此,如果您將nft命令拆分為兩個呼叫,則會發生以下情況:

  • 第一個nft命令定義了一個符號變數供其以後使用。但是什麼都不做。它甚至不必與核心通信,因為不需要更改規則集。(實際上它確實進行了通信,但發送“無”,就像使用命令一樣nft '')。在命令結束時,符號的定義失去,沒有被使用。
  • 該命令的第二次呼叫nft需要解析$lala符號,但找不到定義:nft因錯誤而停止。

所以這必須在一次 nft呼叫中完成,所以第二個語句仍然知道符號變數。有多種方法可以做到這一點。我在 shell 下面的範例中留下了nft不應輸入的提示。

-i, --interactive

從互動式 readline CLI 讀取輸入。您可以使用quit退出,或使用 EOF 標記,通常是 CTRL-D。

# nft -i
nft> define lala=1.2.3.4
nft> add rule ip filter input ip saddr $lala accept
nft> quit
  • 一次nft呼叫中的兩個命令。
# nft 'define lala=1.2.3.4; add rule ip filter input ip saddr $lala accept'

請注意所需的額外內容;,因為在此上下文中nft接收一行參數,但應將它們拆分為兩個邏輯命令。它也nft有自己的解析器,它不關心命令是作為單個命令參數還是多個單獨的參數接收的。在這裡,所有內容都包含在一對中,''以避免;$字元的外殼問題。

  • 然後nft可以選擇從文件中讀取。從文件讀取時,所有輸入都是同一nft命令上下文的一部分。

-f, --file filename

從文件名讀取輸入。如果文件名是 -,從標準輸入讀取。

nft 腳本必須啟動#!/usr/sbin/nft -f

因此,使用名為test.nft具有此內容的文​​件:

define lala=1.2.3.4
add rule ip filter input ip saddr $lala accept

然後可以使用它:

# nft -f test.nft

下面的變體以“ nftables語言”執行腳本。文件test.nft內容為:

#!/usr/sbin/nft -f
define lala=1.2.3.4
add rule ip filter input ip saddr $lala accept

然後:

# chmod a+rx test.nft
# ./test.nft

這也有效:

# nft -f - <<'EOF'
> define lala=1.2.3.4
> add rule ip filter input ip saddr $lala accept
> EOF

對於之前的每個命令,生成的規則集都是相同的(假設表和鍊是之前創建的):

# nft list chain ip filter input
table ip filter {
   chain input {
       type filter hook input priority filter; policy accept;
       ip saddr 1.2.3.4 accept
   }
}

將不再有任何$lala留下的痕跡:核心從未收到$lala,但只有1.2.3.4這就是它所返回的。

引用自:https://serverfault.com/questions/1018300