IPTABLES блок User-Agent

Я получаю DDoS от Wordpress Pingback BOTNET, теперь я хочу заблокировать всех клиентов, которые содержат Wordpress там есть Useragents. Например:

WordPress/4.0; http://vk.lokos.net; verifying pingback from 107.158.239.82

Мне нужно заблокировать как HTTP-порт 80, так и HTTPS-порт 443. Как я могу это сделать?

3 ответа

Первое: вы не хотите делать это таким образом, как я опишу ниже.

Второе: очень похожая проблема решена здесь http://spamcleaner.org/en/misc/w00tw00t.html. Я передаю их решение на ваш конкретный вопрос. Есть iptables string модуль, который вы можете использовать, чтобы соответствовать агенту браузера. Однако iptables затем проверяет каждый пакет... мы можем оптимизировать это с помощью connmark модуль. Я не пробовал, поэтому мой ответ - только толчок в правильном направлении:

<other rules>
iptables -t mangle -A PREROUTING -m connmark --mark 0xBAD1 -j DROP
iptables -t mangle -A PREROUTING -m connmark --mark 0xBAD0 -j ACCEPT
iptables -t mangle -A PREROUTING -p tcp --dport 80 -m string --string "User-Agent: " -j CHECK_UAGENT
iptables -t mangle -A CHECK_UAGENT -m string --string "User-Agent: WordPress/4.0" -j CATCH
iptables -t mangle -A CHECK_UAGENT -j CONNMARK --set-xmark 0xBAD0
<otherrules>
iptables -t mangle -N CATCH 
iptables -t mangle -A CATCH -j LOG --log-level alert --log-prefix "WordPress attack "
iptables -t mangle -A CATCH -j CONNMARK --set-xmark 0xBAD1
iptables -t mangle -A CATCH -j DROP

Вот идея connmark Модуль и связанная цель пометят пакет, как вы пожелаете, и любые последующие пакеты в этом потоке соединения будут помечены аналогичным образом. Поэтому мы ищем пакеты, направленные к порту 80, и имеем строку "User Agent". Если у них есть нежелательный пользовательский агент, мы помечаем его как 0xBAD1. Мы тогда регистрируем это и понижаем это. В противном случае, как только мы увидим "User Agent", но не нежелательный, он попадет в белый список с 0xBAD0. Добавляя его в белый список, мы уменьшаем нагрузку на инспектор пакетов (это шаг оптимизации). В противном случае мы будем искать в каждом пакете каждого загруженного изображения - бессмысленная трата.

** Почему вышеупомянутое является плохой идеей ** Один: HTTPS не может быть декодирован на уровне фильтра пакетов. Два: потому что DDOS-атака с вышеупомянутым возможна. Соединение начинается, открывает соединение на вашем веб-сервере, а затем исчезает (с точки зрения вашего веб-сервера). Он будет ждать долгое время, прежде чем откажется от клиента, которому больше не разрешено пропускать больше пакетов. Между тем, больше попыток придет. В конце концов, HTTP исчерпает ресурсы, и запросы не будут проходить. (Одним из способов решения этой проблемы является использование recentмодуль. Более тщательный способ состоит в том, чтобы иметь процесс, отслеживающий лог-файл для "атаки WordPress", который запоминает удаленный IP-адрес и порт и либо принудительно закрывает соединение с помощью резака, либо перекрестно ссылается на это соединение с PID сервера, связанным с это и затем убивает этот процесс.)

Аналогичный вопрос был задан и получен ответ: используйте обратный прокси. Это лучший вариант, но требует большой перенастройки и, возможно, промежуточного сервера.

Вместо этого используйтеэтот способ. Используйте mod_rewrite (в Apache/*ngnx) для сопоставления строки User-Agent, установите переменную среды для ведения журнала и верните сообщение об ошибке 403. Это закрывает удаленную сторону. Теперь, чтобы сделать его более постоянным, создайте отдельный мониторинг процессов, который представляет собой log-файл для таких разорванных соединений, и добавьте удаленный ip в recent таблица, из которой iptables будет сбрасывать новые соединения в течение следующих 5 минут. Так...

# Apache config
RewriteCond %{HTTP_USER_AGENT}  ^WordPress/4\.0
RewriteRule - [L,R=403,E=WordPress]
LogFormat "%t\t%a\t%{remote}p\t%{User-Agent}i"
CustomLog wordpress wordpress.log env=WordPress

Пользовательский формат журнала облегчает декодирование нашего внешнего процесса. IPtables - это только одно правило:

iptables -A INPUT --syn -m recent --name WordPress --rcheck --seconds 300 -j DROP

и внешний процесс (работает как root) выглядит так:

#!perl 
open(STDIN,"tail -f /var/log/http/wordpress.log|")
while (<>) {
   my ($time,$ip,$port,$useragent)=split('\t');
   open(RECENT,"> /proc/net/xt_recent/WordPress")
   print RECENT "+$ip\n"
   close RECENT
}

Временная метка и строка user-agent просто так, чтобы вы могли убедиться, что все работает / не работает, как вы ожидаете. Я добавлю, что с модом переписать способ, у вас есть гораздо больше гибкости, что отклонить / запретить.

Выполнение следующих команд заблокирует эту конкретную атаку:

iptables -N Wordpress-PingVerify
iptables -I INPUT -p tcp --dport 80 -m string --to 70 --algo bm --string 'GET /' -j Wordpress-PingVerify
iptables -A Wordpress-PingVerify -p tcp --dport 80 -m string --to 80 --algo bm ! --string 'User-Agent: WordPress/' -j RETURN
iptables -A Wordpress-PingVerify -p tcp --dport 80 -m string --to 300 --algo bm --string 'verifying pingback from' -j DROP
iptables -A Wordpress-PingVerify -j RETURN

Приведенные выше правила предполагают, что атака направлена ​​на HTTP (порт 80).

В качестве альтернативы вы можете использовать эти правила для блокировки ВСЕХ запросов пингбека WordPress - это будет блокировать не только проверки пингбека, но и пингбэки:

iptables -N Wordpress-PingBacks
iptables -I INPUT -p tcp --dport 80 -m string --to 70 --algo bm --string 'GET /' -j Wordpress-PingBacks
iptables -A Wordpress-PingBacks -p tcp --dport 80 -m string --to 80 --algo bm ! --string 'User-Agent: WordPress/' -j RETURN
iptables -A Wordpress-PingBacks -p tcp --dport 80 -j DROP
iptables -A Wordpress-PingBacks -j RETURN

Источник: https://sysadminblog.net/2016/05/blocking-wordpress-pingback-verification-ddos/

Как упоминалось другими, в целом, используя-m stringПравила на вашем сервере не очень эффективны, поскольку они проверяют каждый пакет на наличие этой строки, что происходит медленно. Но это не все. Данные могут быть намеренно разбиты на отдельные пакеты (хакерами), чтобы сказать «Слово» в первом пакете и «нажать» во втором пакете. Так что это не поможет. Мало того, теперь у нас есть HTTP/3, который использует пакеты UDP... которые можно зашифровать.

Кроме того, настоящий DDoS имеет тенденцию происходить очень быстро, поэтому я думаю, что вам нужно как можно быстрее заблокировать IP-адреса, если вы думаете, что это действительно происходит.

Это означает, что вы хотите отправить IP-адресiptablesкак можно быстрее. В брандмауэре появился _новый интерфейс_¹, который позволяет добавлять до 65535 IP-адресов в отсортированную таблицу (очень быстрый поиск). Поскольку маловероятно, что у злоумышленника такое количество компьютеров, все будет работать как положено.

Сначала в настройках Apache2 вы фиксируете словоWordpressвUser-Agentзаголовок:

      RewriteEngine On

RewriteCond %{HTTP_USER_AGENT} Wordpress
RewriteRule !^/?scripts/ scripts/script-to-run.cgi [L]

Затем вscript-to-run.cgiвы используете так:

      #!/bin/bash
ipset add unwanted $REMOTE_ADDR -exist

Источник: Как запустить какой-либо код или команду в Apache2 при условии?

Затем вам нужно правило в вашем брандмауэре для проверки списка IP-адресов, оно выглядит так:

      iptables -A unwanted -m set --match-set unwanted src -j DROP

Примечание. Перед этим убедитесь, что ваши пользователи SSH не заблокированы, принимая трафик на порт 22. unwantedПравило – это безопасно, если все ваши пользователи имеют статический IP-адрес.

Однако при попытке выполнить команду вы, скорее всего, столкнетесь с проблемой. Он будет работать от имени пользователя Apache2, а не от имени пользователя root. Одним из простых решений является написание процесса на C++, которому можно предоставить root-права. Что-то вроде этого:

      int main(int argc, char *argv[])
{
    if(setuid(0) != 0) return 1; // could not become root?!
    if(argc != 2) return 1; // exactly one parameter: IP address
    std::string ip(argv[1]);
    if(ip.find(' ') != std::string::npos) return 1; // IP can't include spaces
    if(ip.find('\'') != std::string::npos) return 1; // IP can't include quotes
    std::string cmd("ipset add unwanted '");
    cmd += ip;
    cmd += "' -exist";
    return system(cmd.c_str());
}

Примечание. Это безопасно, поскольку позволяет только «добавлять» в конкретную таблицу «нежелательные». Предлагать все варианты, которые само по себе поддерживает, было бы небезопасно.

Скомпилировать с помощью:

      g++ safeipset.cpp -o safeipset

Скопировать результат в/usr/binи убедитесь, что он может стать root:

      sudo cp safeipset /usr/bin/.
sudo chmod u+s /usr/bin/safeipset

Используйте в своем CGI-скрипте вот так:

      #!/bin/bash
safeipset $REMOTE_ADDR

Таблице можно задать тайм-аут по умолчанию, чтобы заблокированные IP-адреса удалялись через определенный промежуток времени. Вы можете сначала протестировать без этого тайм-аута, чтобы увидеть, сколько IP-адресов будет добавлено.

Здесь вы устанавливаете время до 5 минут:

      ipset create unwanted hash:ip timeout 300

Пожалуйста, проверьтеman ipsetстраницу руководства для получения дополнительной информации.

¹ipsetбыл в Linux 2.4.x, выпущенном в 2001 году. Так что он не такой уж и новый, но уже давно никем не используется.

Другие вопросы по тегам