Сервер представляет собой стандартный стек LAMP, настроенный через cpanel в CentOS 5.9.
У нас есть один файл, назовите его bad.php, на одном из наших доменов, к которому поставщик услуг по ошибке обращается примерно 10 раз в секунду. Файл больше не существует, и мы хотим заблокировать эти запросы наиболее эффективным способом. В настоящее время мы возвращаем 410 простых ответов, но это все еще связано с связыванием потоков apache, отправкой заголовков и т. Д.
В идеале я хочу просто отбросить запросы, не отправляя никакого ответа. Блокировка по IP не является вариантом, потому что нам нужно разрешить этим IP-адресам законный доступ к другим файлам. (И нет, мы не можем просто попросить их остановиться.) У нас также нет внешнего брандмауэра для работы (арендованный сервер, настраиваемый внешний брандмауэр оплачивается дополнительно).
Я считаю, что лучшим вариантом было бы такое правило iptables:
iptables -I INPUT -p tcp --dport 80 --destination [ip address] -m string \
--algo kmp --string "bad\.php" -j DROP
Два вопроса:
Сначала я попробовал это правило (с IP-адресом домена вместо IP-адреса), но это не дало результата. Это было самое первое правило, показанное с помощью iptables -L, поэтому его не следует отменять более ранним правилом:
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP tcp -- anywhere [ip address] tcp dpt:http STRING match "bad\.php" ALGO name kmp TO 65535
Я где-то напортачил? Я в большой степени новичок в iptables.
Второй вопрос: есть ли предостережения по этому поводу? Возникнут ли значительные накладные расходы, если строка iptables будет соответствовать каждому запросу (по сравнению с apache RewriteRule с R = 410, как мы сейчас используем)? Мне лучше просто жить с этим? Или есть вариант получше? (Возможно, mod_security?) Сервер нигде не напрягается, так что это не необходимость, а просто оптимизация.
Редактировать в ответ на Саураба Барджатию:
Вот все, что я вижу из tcpdump, когда делаю запрос на файл bad.php:
20:21:09.740217 IP [clientIP].62790 > [serverIP].http: S 3454863895:3454863895(0) win 8192 <mss 1460,nop,wscale 2,nop,nop,sackOK>
20:21:09.740243 IP [serverIP].http > [clientIP].62790: S 4112555138:4112555138(0) ack 3454863896 win 5840 <mss 1460,nop,nop,sackOK,nop,wscale 7>
20:21:09.838595 IP [clientIP].62790 > [serverIP].http: . ack 1 win 16425
20:21:09.838606 IP [clientIP].62790 > [serverIP].http: . 1:1461(1460) ack 1 win 16425
20:21:09.838622 IP [serverIP].http > [clientIP].62790: . ack 1461 win 69
20:21:09.838632 IP [clientIP].62790 > [serverIP].http: P 1461:1476(15) ack 1 win 16425
20:21:09.838638 IP [serverIP].http > [clientIP].62790: . ack 1476 win 69
Очевидно, фактической строки URL-адреса здесь нет. Насколько я понимаю, iptables жестяная банка фильтр для строк URL-адресов, поэтому, по-видимому, я проверяю не то.
Предполагается, что правило iptables будет использовать больше ЦП, чем конфигурация apache. Но, тем не менее, использование iptables для блокировки входящих запросов интересно. Поскольку запросы не заархивированы и обычно находятся в одном пакете, я не вижу никаких возражений против вашей логики.
Чтобы понять, почему текущее правило не работает, у меня есть два предложения: