Linux

阻止過時的 tcp 選項

  • August 9, 2021

在 Linux 上,我想丟棄所有包含任何過時 tcp 選項的數據包。過時的選項是指所有那些 tcp 選項種類編號高於 8 的選項。我該如何使用nftables?

例如,如果有一種方法可以檢查 tcp 數據包是否具有 nftables 中給定數字類型的選項,那將起作用。如果 nftables 不支持這個,我可以使用tc或其他標準的 linux 實用程序來做到這一點嗎?

nftables中的許多關鍵字只代表一個常數。tcp 選項就是這種情況(更新:但僅從nftables 0.9.8 開始)。

這是 tcp 選項的摘錄:

擴展標題表達式

擴展標頭表達式是指來自可變大小協議標頭的數據,例如 IPv6 擴展標頭和 TCP 選項。

$$ … $$ tcp 選項

{eol | noop | 最大賽格 | 視窗 | 允許麻袋| 高解析度照片| CLIPARTO 麻袋 | 麻袋0 | 麻袋1 | 麻袋2 | 麻袋3 | 時間戳} tcp_option_field

TCP 選項

$$ … $$ 布爾規範

以下表達式支持布爾比較:

$$ … $$

# match if TCP timestamp option is present
filter input tcp option timestamp exists

這裡eol代表 0,nop代表 1,…timestamp代表 8,等等。

更新從 0.9.8 版開始,可以指定任意數值而不是關鍵字:

  • 添加原始 tcp 選項匹配支持

… tcp 選項@42,16,4

您可以在其中指定@kind,offset,length

  • 允許檢查是否存在任何 tcp 選項

… tcp 選項 42 存在

所以有了這種規則:

nft add table t
nft add chain t c '{ type filter hook input priority 0; policy accept; }'
nft add rule t c tcp option 8 exists drop
nft add rule t c tcp option 9 exists drop
nft add rule t c tcp option 10 exists drop
[...]
nft add rule t c tcp option 254 exists drop

可以過濾所有值為 8 的規則(包括在內以稍後顯示 8 表示timestamp)或更高(選項值在 8 位欄位上)。

已知值(僅此處timestamp)與關鍵字一起顯示,否則它們保持為數字:

# nft -a --debug=netlink list ruleset
ip t c 2
 [ exthdr load tcpopt 1b @ 8 + 0 present => reg 1 ]
 [ cmp eq reg 1 0x00000001 ]
 [ immediate reg 0 drop ]

ip t c 3 2
 [ exthdr load tcpopt 1b @ 9 + 0 present => reg 1 ]
 [ cmp eq reg 1 0x00000001 ]
 [ immediate reg 0 drop ]

ip t c 4 3
 [ exthdr load tcpopt 1b @ 10 + 0 present => reg 1 ]
 [ cmp eq reg 1 0x00000001 ]
 [ immediate reg 0 drop ]

ip t c 5 4
 [ exthdr load tcpopt 1b @ 254 + 0 present => reg 1 ]
 [ cmp eq reg 1 0x00000001 ]
 [ immediate reg 0 drop ]

table ip t { # handle 21
   chain c { # handle 1
       type filter hook input priority filter; policy accept;
       tcp option timestamp exists drop # handle 2
       tcp option 9 exists drop # handle 3
       tcp option 10 exists drop # handle 4
       tcp option 254 exists drop # handle 5
   }
}

我沒有找到將其分解為集合或映射的方法,也沒有與選項值進行比較,這會簡化這一點,因為整個tcp option foo語法必須使用,而不僅僅是tcp option,據我所知,這會導致無用特點:

  • 檢查選項 timestamp 是否意味著kind 8的 kind 值為… 8。(如果存在則始終為 true,因此等價於tcp option timestamp exists):
nft add rule t c tcp option timestamp kind == 8
  • 或檢查選項時間戳是否意味著種類 8的種類值大於 8(始終為假):
nft add rule t c 'tcp option timestamp kind > 8'

考慮到tcp 選項是選項列表的一部分,我可以理解實現並不是那麼容易,因為它必須遍歷所有現有選項才能選擇一個。當兩個可以匹配時會選擇哪個?


注意:8 個以上的選項值得保留。例如tcp option kind 30用於MPTCP,它最近被添加到主流 Linux 中,而 tcp options kind 6 (echo) 和 7 (echo reply) 已過時。

引用自:https://unix.stackexchange.com/questions/663858