Iptables

為什麼 iptables(-nft) 中的 MSS 箝制似乎在 nftables 中無效?

  • October 11, 2021

我的 pppoe 客戶端自動iptables -t mangle -o "$PPP_IFACE" --insert FORWARD 1 -p tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:65495 -j TCPMSS --clamp-mss-to-pmtu/etc/ppp/ip-up.d. 但是,nftables 中的這條規則看起來像

table ip mangle {
   chain FORWARD {
       type filter hook forward priority mangle; policy accept;
       oifname "ppp0" meta l4proto tcp tcp flags & (syn|rst) == syn # tcpmss match 1400:65495 counter packets 714 bytes 42388 tcp option maxseg size set rt mtu
   }
}

為什麼 tcpmss 之後的內容被註釋了,而這條規則似乎什麼也沒做?

解釋

原生nftables在設計上不能使用xtables核心模組:每當使用xtables時,它就不再是原生的了,使用者態nft命令(或其 API)只處理原生nftablesxtables的使用是為兼容層保留的。因此,當通過nft顯示時,任何此類未知模組都會被註釋掉(但見下文)。

  • 目前版本iptables-nft還不能將iptables規則自動轉換為本地nftables規則(對於這種情況),或者沒有等效的本地nftables規則可以轉換為(例如:思考LED目標)。

這裡nft看到有一些xtables模組不能被通用翻譯引擎翻譯,因此認為這部分是禁區,並在不可翻譯的部分添加了註釋,但仍會翻譯它所知道的內容。可以通過以下方式看到對xtables模組的呼叫--debug=netlink

# nft -a --debug=netlink list ruleset
ip mangle FORWARD 2
 [ meta load oifname => reg 1 ]
 [ cmp eq reg 1 0x30707070 0x00000000 ]
 [ meta load l4proto => reg 1 ]
 [ cmp eq reg 1 0x00000006 ]
 [ match name tcp rev 0 ]
 [ match name tcpmss rev 0 ]
 [ counter pkts 0 bytes 0 ]
 [ target name TCPMSS rev 0 ]

table ip mangle { # handle 167
 chain FORWARD { # handle 1
     type filter hook forward priority mangle; policy accept;
     oifname "ppp0" meta l4proto tcp tcp flags & (syn|rst) == syn # tcpmss match 1400:65495 counter packets 0 bytes 0 tcp option maxseg size set rt mtu # handle 2
 }
}

match上圖:target表示xtables模組。由於nftables在這方面使用與iptables-translate大致相同的引擎,因此可能會-m tcpmss --mss 1400:65495出現問題,因為這是一個以註釋開頭且未在輸出中翻譯的引擎,而最後一部分已被翻譯。這裡nft顯示的只是為了顯示,不能作為實際的規則

實際規則是顯示的字節碼(加上xtables--debug=netlink特定數據的不可見部分),所以這個字節碼是這個規則正在做某事的證明。它對本機nftables沒有用。

本機nftables版本

例如,大多數 OP 的iptables規則都可以本地翻譯:

# iptables-translate -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
nft add rule ip mangle FORWARD tcp flags & (syn|rst) == syn counter tcp option maxseg size set rt mtu

雖然目前沒有可用於 的自動翻譯-m tcpmss --mss,但該功能可用:tcp option maxseg size可用作表達式(相當於 match -m tcpmss --mss)或 withset作為語句(相當於 target -j TCPMSS)。以下是此類翻譯的結果(並且可能在將來改進翻譯引擎後):

nft add rule ip mangle FORWARD 'oifname ppp0 tcp flags & (syn|rst) == syn tcp option maxseg size 1400-65495 counter tcp option maxseg size set rt mtu'

第二個值 65495 可能沒用(可以直接使用tcp option maxseg size >= 1400)。


筆記

nft並且iptables-nft在試圖濫用翻譯時可能會產生誤導。例如使用iptables v1.8.7 (nf_tables)nft v1.0.0,可以得到:

# iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
# nft list ruleset | tee /tmp/mss.nft
table ip mangle {
   chain FORWARD {
       type filter hook forward priority mangle; policy accept;
       meta l4proto tcp tcp flags & (syn|rst) == syn counter packets 0 bytes 0 tcp option maxseg size set rt mtu
   }
 }
# nft flush ruleset
# nft -f /tmp/mss.nft
# iptables-save 
# Table `mangle' is incompatible, use 'nft' tool.

這是因為雖然nft在顯示時能夠翻譯整個規則集,但最初的兼容規則集仍然在字節碼中包含一個xtables目標(如上所示:)[ target name TCPMSS rev 0 ]iptables-nft沒有表現得像iptables-translatenft的輸出隱藏了差異。再次通過該nft命令執行,結果是完整的原生nftablestcp option maxseg size set rt mtu而不是-j TCMPSS --clamp-mss-to-pmtu. 但是該iptables-save命令不再將結果辨識為iptables翻譯的程式碼,並且無法將其翻譯回iptables格式。

不要盲目地使用 nftables 轉儲iptables**規則以使用nftables重新載入它們,如果仍然需要iptables,這可能會在以後咬人。

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