Задержка выполнения PHP-скрипта
-
20-08-2019 - |
Вопрос
Каков наилучший способ остановить ботов, злоумышленников и т.д.из-за слишком быстрого выполнения php-скриптов?Это нормально, если я использую usleep()
или sleep()
функции, чтобы просто "ничего" не делать некоторое время (непосредственно перед выполнением нужного кода), или это просто глупо, и для этого есть лучшие способы?
Пример:
function login() {
//enter login code here
}
function logout() {
//enter logout code here
}
Если я просто положу, скажем, usleep(3000000)
перед кодами входа и выхода из системы, это нормально, или есть лучшие, более мудрые способы достижения того, чего я хочу достичь?
Редактировать: Основываясь на приведенных ниже предложениях, делает ли тогда usleep
или sleep
вызывает только отключение процессора от текущего скрипта, выполняемого текущим пользователем, или это приводит к отключению процессора от всей службы?т. е.Если один пользователь + скрипт вызывает sleep
/usleep
, будут ли все одновременные пользователи + скрипты тоже отложены?
Решение
Способ работы большинства веб-серверов (например, Apache) заключается в поддержании коллекции рабочих потоков.Когда выполняется PHP-скрипт, один поток запускает PHP-скрипт.
Когда ваш сценарий выполняет sleep(100)
, выполнение скрипта занимает 100 секунд..Это означает, что ваш рабочий поток связан на 100 секунд.
Проблема в том, что у вас очень ограниченное число рабочих потоков - скажем, у вас есть 10 потоков и 10 человек входят в систему - теперь ваш веб-сервер не может обслуживать какие-либо дальнейшие ответы..
Лучший способ ограничить скорость входа в систему (или других действий) - это использовать какое-нибудь быстрое хранилище в памяти (кэшированный в памяти идеально подходит для этого), но это требует запуска отдельного процесса и довольно сложно (вы могли бы сделать это, если бы запустили что-то вроде Facebook ..).
Проще говоря, у вас могла бы быть таблица базы данных, в которой хранится user_id
или ip_address
, first_failed
и failure_counter
.
Каждый раз, когда вы получаете неудачный вход в систему, вы (в псевдокоде) должны делать:
if (first_failed in last hour) and (failure_counter > threshold):
return error_403("Too many authentication failures, please wait")
elseif first_failed in last hour:
increment failure_counter
else:
reset first_failed to current time
increment failure_counter
Возможно, не самый эффективный, и есть способы получше, но это должно довольно хорошо остановить грубое принуждение.Использование memcached в основном то же самое, но база данных заменяется memcached (что быстрее)
Другие советы
чтобы остановить ботов, злоумышленников и т.д.из-за слишком быстрого выполнения php-скриптов?
Я бы сначала спросил, что вы на самом деле пытаетесь предотвратить?Если это атаки типа "отказ в обслуживании", то я должен был бы сказать, что вы ничего не можете сделать, если вы ограничены тем, что вы можете добавлять в PHP-скрипты.Уровень техники намного превосходит то, от чего мы, программисты, можем защититься.Начните изучать инструменты системного администратора, предназначенные для этой цели.
Или вы пытаетесь ограничить свой сервис, чтобы реальные люди могли получить к нему доступ, а боты - нет?Если это так, я бы рассмотрел некоторые методы "captcha".
Или вы пытаетесь запретить пользователям ежесекундно опрашивать ваш сайт в поисках нового контента?Если это так, я бы изучил возможность предоставления RSS-канала или какого-либо другого способа уведомления их, чтобы они не поглощали вашу пропускную способность.
Или это что-то другое?
В общем, я бы сказал, что ни sleep(), ни usleep() не являются хорошим способом.
Предлагаемый вами метод заставит ВСЕХ пользователей без необходимости ждать перед входом в систему.
Большинство серверов LAMP (и, собственно, большинство маршрутизаторов / коммутаторов) уже настроены для предотвращения атак типа "Отказ в обслуживании".Они делают это, отклоняя несколько последовательных запросов с одного и того же IP-адреса.
Вы же не хотите переводить свой php в спящий режим.Это значительно сократит количество одновременных запросов, которые может обрабатывать ваша служба, поскольку у вас будут открытые соединения в ожидании.
Большинство HTTP-серверов имеют функции, которые вы можете включить, чтобы избежать DoS-атак, но в противном случае вам следует просто отслеживать IP-адреса, которые вы видели слишком много раз в последнее время, и отправлять им 403 Forbidden с сообщением, в котором их просят подождать секунду.
Если по какой-то причине вы не можете рассчитывать на то, что REMOTE_ADDR зависит от пользователя (все находятся за одним и тем же брандмауэром и т.д.), вы могли бы создать проблему в форме входа и заставить удаленный браузер выполнить расширенное вычисление (скажем, умножить число), которое вы можете быстро проверить на стороне сервера (с быстрым умножением).