為什麼 iptables(-nft) 中的 MSS 箝制似乎在 nftables 中無效?
我的 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核心 API 沿兼容層 API
iptables-nft
使用xtables核心模組(此處:xt_tcpmss
和xt_TCPMSS
),即使xtables最初旨在用於(舊核心 API)iptables。原生nftables在設計上不能使用xtables核心模組:每當使用xtables時,它就不再是原生的了,使用者態
nft
命令(或其 API)只處理原生nftables。xtables的使用是為兼容層保留的。因此,當通過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
在試圖濫用翻譯時可能會產生誤導。例如使用iptablesv1.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-translate
和nft
的輸出隱藏了差異。再次通過該nft
命令執行,結果是完整的原生nftables,tcp option maxseg size set rt mtu
而不是-j TCMPSS --clamp-mss-to-pmtu
. 但是該iptables-save
命令不再將結果辨識為iptables翻譯的程式碼,並且無法將其翻譯回iptables格式。不要盲目地使用 nftables 轉儲iptables**規則以使用nftables重新載入它們,如果仍然需要iptables,這可能會在以後咬人。