У меня есть уникальная ситуация, когда DDOS-атака для определенной игры отправляет реалистичные пакеты подключения игрока, которые, кажется, идеально имитируют пакет подключения реального игрока.
Обычно они проходят через несколько тысяч IP-адресов, отправляя один запрос и заполняя слоты для подключения на сервере, не позволяя любому реальному игроку подключиться.
После подключения настоящий игрок начинает отправлять несколько пакетов UDP с высокой частотой, но эти поддельные пакеты отправляются только один раз на IP.
Есть ли способ отбросить первый полученный пакет с IP-адреса, но затем разрешить все последующие пакеты?
Сервер работает под управлением Debian Linux, 9.x.
Вы можете использовать recent
match расширение, но для вашего варианта использования оно может быть слишком ограничено по крайней мере по двум причинам: настройки модуля по умолчанию допускают только 100 записей, которые будут ограничиваться <100 игроками без дополнительных настроек, а истечение устаревших записей не является автоматическим (он имеет должно выполняться либо из пути пакета, что не очень хорошо с точки зрения производительности, либо из некоторого внешнего пакетного задания).
Вы также можете использовать ipset, предназначенный для использования вместе с iptables, функции которого являются расширенным набором recent
и работает лучше. Он обрабатывает автоматическое удаление записей с истекшим временем ожидания.
Так, например, если бы это было применено к порту 27960 / udp ...
ipset create firstseenpacket hash:ip timeout 60
iptables -N dropfirstseenpacket
iptables -I INPUT -p udp -m udp --dport 27960 -m set ! --match-set firstseenpacket src -j dropfirstseenpacket
iptables -I INPUT 2 -p udp -m udp --dport 27960 -j SET --exist --add-set firstseenpacket src
iptables -A dropfirstseenpacket -j SET --add-set firstseenpacket src
iptables -A dropfirstseenpacket -j DROP
При первом просмотре источника тест не найдет запись, и при инвертировании перейдет к dropfirstseenpacket
, который добавит запись и отбросит пакет. Дальнейшие вхождения из того же источника найдут запись, обновят ее таймер (--exist
) и больше ничего делать не буду. Правила могут быть дополнительно разложены на еще одну цепочку, например, если первый тест более дорогостоящий, чем простая проверка 27960 / udp.
Вы можете увидеть содержимое ipset с помощью:
ipset save firstseenpacket
Обратите внимание, я использовал -I
(вставить) заявление, чтобы убедиться, что это происходит без помех. Помещая его после записи вроде -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
должен оставаться совместимым и даже улучшать производительность и ресурсы (передавая ответственность за активные записи с ipset на conntrack), поскольку conntrack поддерживает свой собственный набор все активный поток в любом случае, когда он активирован. Это даст что-то похожее на:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
iptables -A INPUT -p udp -m udp --dport 27960 -m set ! --match-set firstseenpacket src -j dropfirstseenpacket
iptables -A dropfirstseenpacket -j SET --add-set firstseenpacket src
iptables -A dropfirstseenpacket -j DROP
iptables -A INPUT -p udp -m udp --dport 27960 -m conntrack --ctstate NEW -j ACCEPT
Тайм-аут активности после 2-го пакета теперь переключается на обработку conntrack. если отправляется ответ с таймаутом 30 или 180 секунд (или 120 секунд для последних ядер) в зависимости от различных условий.
Вам следует убедиться, что это соответствует вашим правилам.
Поскольку он может стать преемником iptables, вот эквивалент первой версии с nft
команды (и предназначены для обработки IPv4 и IPv6). Nftables изначально обрабатывает наборы. Достаточно свежий nftables (> = 0.8.4?) Должен использоваться для установить заявление функция, позволяющая добавлять из пути к пакету, поэтому в Debian 9 потребуется столики из стрейч-бэкпортов.
Шаблон:
nft add table inet filter
nft add chain inet filter input '{ type filter hook input priority 0; }'
Оператор set используется для динамического добавления или обновления элементов в наборе из пути пакета. Установленное имя набора уже должно существовать в данной таблице. Кроме того, любой набор, который будет динамически обновляться из набора правил nftables, должен указывать как максимальный размер набора (для предотвращения истощения памяти) и тайм-аут (чтобы количество записей в наборе не увеличивалось бесконечно). Оператор set может использоваться, например, для создавать динамические черные списки.
Именованные наборы для функции, эквивалентной ipset:
nft add set inet filter ipv4firstseenpacket '{ type ipv4_addr; timeout 60s; size 5000; }'
nft add set inet filter ipv6firstseenpacket '{ type ipv6_addr; timeout 60s; size 5000; }'
Правила фильтрации:
nft add rule inet filter input udp dport 27960 ip saddr != @ipv4firstseenpacket add @ipv4firstseenpacket '{ ip saddr }' drop
nft add rule inet filter input udp dport 27960 update @ipv4firstseenpacket '{ ip saddr }'
nft add rule inet filter input udp dport 27960 ip6 saddr != @ipv6firstseenpacket add @ipv6firstseenpacket '{ ip6 saddr }' drop
nft add rule inet filter input udp dport 27960 update @ipv6firstseenpacket '{ ip6 saddr }' drop
Здесь за один раз запись проверяется, если не найдена, добавляется и пакет отбрасывается. Для обновления таймера все еще должно быть другое действие. Версия ipv6 работает так же.
Вы можете увидеть содержимое набора, например, с помощью:
nft list set inet filter ipv4firstseenpacket
Если быть точным, с conntrack это будет вместо этого (и может быть факторизовано с дополнительной цепочкой):
nft add rule inet filter input ct state established accept
nft add rule inet filter input udp dport 27960 ip saddr != @ipv4firstseenpacket add @ipv4firstseenpacket '{ ip saddr }' drop
nft add rule inet filter input udp dport 27960 ip6 saddr != @ipv6firstseenpacket add @ipv6firstseenpacket '{ ip6 saddr }' drop
nft add rule inet filter input udp dport 27960 ct state new accept