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 году. Так что он не такой уж и новый, но уже давно никем не используется.