Основная проблема, которая должна быть решена здесь, заключается в том, что мы не можем просто закрыть весь трафик с клиента после установления соединения, поскольку TCP является положительным протоколом подтверждения. Если сервер не получает данные от клиента, он будет повторно передавать и, в конечном итоге, отключиться. В дальнейшем я буду считать, что мы используем IPV4.
Итак, что мы хотим сделать, это разрешить установление соединения, а затем разрешать только подтверждения от клиента, то есть пакеты, которые не содержат полезной нагрузки TCP.
К сожалению, длина полезной нагрузки TCP явно не представлена в TCP header. Мы можем попытаться использовать общую длину в IP header, но это осложняется тем, что как заголовок IP, так и заголовок TCP включают поля переменной длины, поэтому существует много возможных общих длин, которые не имеют полезной нагрузки.
Поскольку параметры IP редко используются и обычно фильтруются, давайте упростим их, сначала удалив все пакеты, содержащие параметры в заголовке IP (если ваш брандмауэр еще не делает этого). Последствия этого будут рассмотрены на длине here.
Для этого мы отбросим весь трафик на наш сервер (здесь принято 10.2.3.4:1234), где длина заголовка IP (бит 4-7 байт 0 в заголовке IP) не равна 5:
iptables -A INPUT -p tcp -d 10.2.3.4 --dport 1234 \
-m u32 --u32 "0>>24&0xF=6:0xF" -j DROP
Это использует модуль iptables
u32
, чтобы захватить 4 байта из пакета, начиная с байта 0, сдвиг вправо его 24 бита, маскировать нижний полубайт, а затем отбросить этот пакет, если это находится в диапазоне 6-15. Обратите внимание: 5 - фактически минимальный размер IP-заголовка.
Ситуация с параметрами TCP несколько сложнее. При установлении соединений можно использовать множество различных опций, например , например., чтобы обсудить масштабирование окна. Однако, как только соединение установлено, единственное, о чем нам нужно беспокоиться, это временные метки TCP и выборочные значения. Итак, давайте пусть будет установлено соединение:
iptables -A INPUT -p tcp -d 10.2.3.4 --dport 1234 \
--tcp-flags SYN SYN -j ACCEPT
Обратите внимание, что можно послать полезную нагрузку в пакете SYN, поэтому здесь мы не полностью отвечает вашим требованиям. Большинство обычных реализаций TCP этого не сделают, хотя TCP fast open делает. Если вы хотите смягчить это, вы можете отказаться от пакетов SYN, которые являются фрагментами (которые могут быть собраны для чего-то очень большого) и ограничить общую длину нефрагментированных SYN-пакетов чем-то разумным, что позволило бы использовать обычные параметры в трехстороннее рукопожатие TCP. Обратите внимание, что указанное правило было добавлено в цепочку INPUT, которая была обработана после Повторная сборка фрагмента IP.
OK, поэтому мы можем установить TCP-соединение, а заголовки IP ограничены 5 словами (20 байтов).
Однако заголовки TCP могут содержать выборочные значения acks, tcp timestamps, both или both. Начнем с заголовков TCP без параметров. Ack без опций и никакой полезной нагрузки будет состоять из 5-го IP-заголовка, за которым следует 5-словный TCP-заголовок, за которым не следует никаких данных. Таким образом, общая длина в IP-заголовке будет равна 40. Если пакет был фрагментом, он мог бы скрыть полезную нагрузку в последующем фрагменте, но поскольку мы работаем с цепочкой INPUT, которая обрабатывается после повторной сборки фрагментации IP, мы не будем придется беспокоиться об этом.
iptables -A INPUT -p tcp -d 10.2.3.4 --dport 1234 \
-m u32 --u32 "32>>28=5 && 0&0xFFFF=40" -j ACCEPT
Заголовок IP-20 байт, и данные смещения полубайт в байте 12, поэтому принимать 4 байта, начиная с байта 32 = 20 + 12, то сдвиг откусывание вниз и сравнить его до пяти, а затем убедитесь, что общая длина в байтах 2 и 3 слова 0 IP-заголовка равна 40.
Если в TCP-заголовке есть отметки времени TCP, тогда в TCP будут добавлены дополнительные 12 байтов (3 слова) заголовок. Мы можем принять, что аналогичным образом:
iptables -A INPUT -p tcp -d 10.2.3.4 --dport 1234 \
-m u32 --u32 "32>>28=8 && 0&0xFFFF=52" -j ACCEPT
Я оставлю его в качестве упражнения для читателя, чтобы выработать другие комбинации. (Обратите внимание, что при работе с выборочной проверкой в нескольких случаях возможно наличие 1-4 выборочных блоков ack или 1-3 выборочных блоков с отметками времени.)
ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: На самом деле, я не пробовал это, поэтому извиняюсь, если есть опечатка или я что-то пропустил. Я считаю, что стратегия будет звуковой, и если есть какая-либо ошибка или упущение, сообщите мне, и я исправлю.