Чтобы завершить ответ @roaima, и на самом деле только потому, что вам нужны все мелкие детали, вот причина, по которой эти два правила ниже не могут совпадать в большинстве конфигураций:
--append INPUT --proto all --fragment --jump DROP
и
--append INPUT --proto icmp --match u32 ! --u32 "0x4&0x3fff=0x0" --jump DROP
--match u32 ! --u32 "0x4&0x3fff=0x0"
— это просто запутанный низкоуровневый -метод записи --fragment
, за исключением того, что он может включать в себя флаг MF в дополнение :смещение фрагмента (+ флаг MF )— это слово u32 в смещение 4 в IP-пакете (0x4
), в части младших битов(&0x3fff
):ненулевое значение эквивалентно наличию фрагмента (или объявлению дополнительных фрагментов ).
Но поскольку (по крайней мере)--match state
загружается модуль nf_conntrack
, для которого, в свою очередь, требуется модуль nf_defrag_ipv4
. Эта дефрагментация выполняется с PREROUTING
ловушкой приоритетом -400 , таким образом, не позволяя чему-либо после видеть фрагменты, а только заново собранный повторно собранный пакет. Более поздние ядра позволяют загружать таблицу raw
с более низким приоритетом :
.
# modinfo -p iptable_raw
raw_before_defrag:Enable raw table before defrag (bool)
что позволяет видеть эти пакеты, но только в необработанной таблице (, где явно нельзя использовать conntrack ).
Теперь, чтобы быть действительно тщательным, в отличие от моего предыдущего примера, по умолчанию Debian buster не будет использовать ip_tables
или какие-либо iptable_*
модули, потому что для iptables
Debian buster использует по умолчанию iptables-nft
, который представляет собой iptables, переведенный поверх nftables, но все же иногда использует iptables -расширения ' xt_*
модули.
ОБНОВЛЕНИЕ :Это по-прежнему позволит использовать и работать модуль u32
, но предотвратит попытку изменить правило через nft (, например, невозможно сохранить, а затем восстановить, и эмуляция на данный момент всегда будет выбирать приоритет -300 для цепочкиraw/PREROUTING
).
root@buster-amd64:~# update-alternatives --display iptables|head -3
iptables - auto mode
link best version is /usr/sbin/iptables-nft
link currently points to /usr/sbin/iptables-nft
# iptables -A INPUT -p udp --fragment -j DROP
# iptables -A INPUT -p icmp --match u32 ! --u32 "0x4&0x3fff=0x0" -j DROP
# iptables -S INPUT
-P INPUT ACCEPT
-A INPUT -p udp -f -j DROP
-A INPUT -p icmp -m u32 ! --u32 "0x4&0x3fff=0x0" -j DROP
# nft --debug=netlink list ruleset -a
ip filter INPUT 4
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000011 ]
[ payload load 2b @ network header + 6 => reg 1 ]
[ bitwise reg 1 = (reg=1 & 0x0000ff1f ) ^ 0x00000000 ]
[ cmp neq reg 1 0x00000000 ]
[ counter pkts 0 bytes 0 ]
[ immediate reg 0 drop ]
ip filter INPUT 5 4
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
[ match name u32 rev 0 ]
[ counter pkts 4 bytes 4096 ]
[ immediate reg 0 drop ]
table ip filter { # handle 5
chain INPUT { # handle 1
type filter hook input priority 0; policy accept;
meta l4proto udp ip frag-off & 8191 != 0 counter packets 0 bytes 0 drop # handle 4
meta l4proto icmp # u32 ! "0x4&0x3fff=0x0" counter packets 4 bytes 4096 drop # handle 5
}
chain FORWARD { # handle 2
type filter hook forward priority 0; policy accept;
}
chain OUTPUT { # handle 3
type filter hook output priority 0; policy accept;
}
}
Обратите внимание, что дескриптор правила #5 имеет комментарий перед u32
не потому, что он не работает, а потому, что он не может быть обработан собственным nft
.Дамп байт-кода не будет отображать фактическую проверку полезной нагрузки, которая хранится в другом месте, но будет вести себя так, как предполагалось, и счетчик будет увеличиваться при получении и удалении фактического фрагмента.
Похоже на ошибку ядра, которая была исправлена очень недавно и может быть включена в ядро 5.7.8. Простое решение — использовать более раннее ядро (>v5.7 ).
https://bugs.archlinux.org/task/66977
https://bugzilla.kernel.org/attachment.cgi?id=290037&action=diff