Я хотел бы добавить правило, отбрасывающее IPv4
пакет с любым IP option
следующим за заголовком. Я понимаю, что IHL
поле (длина заголовка Интернета) в заголовке содержит количество 32-битных слов в заголовке IPv4, включая опции. Таким образом, я понимаю, что правило должно получить длину пакета+опции из IHL
поля и сравнить с 20 (длина заголовка IPv4 без опций), и если она больше 20, отбросить пакет.
Существует ли специальный iptables
модуль, позволяющий проверять IP
заголовок и оценивать его (выполнять арифметические операции)?
решение1
iptables
включает в себя u32
метод match, который позволяет выполнять некоторые побитовые (но не произвольные арифметические) операции, сравнения диапазонов и некоторые указательные косвенные обращения к полезной нагрузке пакета для соответствия условиям:
U32 проверяет, имеют ли величины до 4 байтов, извлеченные из пакета, указанные значения. Спецификация того, что извлекать, достаточно общая, чтобы найти данные с заданными смещениями из заголовков или полезных нагрузок TCP.
Он имеет свою собственную грамматику подъязыка, поэтому следует изучить грамматику и примеры в руководстве.
МГП— размер заголовка IP (в 32-битных фрагментах, а не в байтах) и является частью первых 32 бит в заголовке (4 бита для версии со значением 0x04 для IPv4, за которыми следуют 4 бита для IHL) и , поэтому, если нет опции, этот размер должен быть минимальным: 20 (байт) / 4 (байт на 32-битные слова), поэтому IHL = 5 (32-битные слова). Я не буду обрабатывать недопустимые случаи, когда IHL < 5, стек IPv4 уже должен был позаботиться об этом.
Это означает:
- взять первые 32 бита значения
- замаскировать его для части МГП
- сдвиньте его на 24 бита
- сравнить равенство с 5 (инвертировать результат с
!
соответствующим совпадением)
Итак, чтобы отбросить такой входящий пакет с помощьюiptables:
iptables -A INPUT -m u32 ! --u32 '0 & 0x0F000000 >> 24 = 5' -j DROP
без инверсии (вместо этого соответствует 6 или больше):
iptables -A INPUT -m u32 --u32 '0 & 0x0F000000 >> 24 = 6:0xF' -j DROP
В руководстве есть похожий пример, где данные сдвигаются на 24 бита, а затем умножаются на 4 (то есть сдвигаются только на 22 бита), чтобы получить байты, а не 32-битные слова (потому что указатели, u32
используемые позже, используют 8-битные адреса), чтобы извлечь начало полезной нагрузки уровня 4 и продолжить дальнейшие операции:
... 0 >> 22 & 0x3C @ 0 >> 24 = 0"
Первый 0 означает чтение байтов 0-3, >>22 означает сдвиг на 22 бита вправо. Сдвиг на 24 бита даст первый байт, поэтому только 22 бита — это в четыре раза больше плюс еще несколько бит. Затем &3C удаляет два дополнительных бита справа и первые четыре бита первого байта. Например, если IHL=5, то заголовок IP имеет длину 20 (4 x 5) байт.
[...]
даю показания в пользу ОП:
iptables -A INPUT -m u32 ! --u32 '0 >> 22 & 0x3C = 20' -j DROP
без инверсии (и не заботясь о том факте, что первое следующее возможное значение не 21, а 24, и не заботясь о точном максимальном значении, пока заданное значение больше):
iptables -A INPUT -m u32 --u32 '0 >> 22 & 0x3C = 21:0xFF' -j DROP
Первый метод можно упростить следующим образом:
- взять первые 32 бита значения
- замаскировать его для части МГП
- сравнить равенство с (5<<24), т.е. сравнить с 0x05000000 (то же самое)
давая:
iptables -A INPUT -m u32 ! --u32 '0 & 0x0F000000 = 0x05000000' -j DROP
или:
iptables -A INPUT -m u32 --u32 '0 & 0x0F000000 = 0x06000000:0x0F000000' -j DROP
или даже:
- взять первые 32 бита значения
- сравните значение с диапазоном от 0x45000000 до 0x45FFFFFF для ОК (IPv4всегданачинается с 4, и любое значение после части IHL следует игнорировать) или между 0x46000000 и 0x4FFFFFFF, если не ОК.
давая:
iptables -A INPUT -m u32 ! --u32 '0 = 0x45000000:0x45FFFFFF' -j DROP
или:
iptables -A INPUT -m u32 --u32 '0 = 0x46000000:0x4FFFFFFF' -j DROP
Сделайте свой выбор.