Задержка выполнения PHP-скрипта - PullRequest
7 голосов
/ 01 февраля 2009

Каков наилучший способ остановить ботов, злоумышленников и т. Д. От слишком быстрого выполнения сценариев php? Это нормально, если я использую функции usleep() или sleep(), чтобы просто какое-то время ничего не делать (непосредственно перед тем, как выполняется нужный код), или это просто глупо, и для этого есть лучшие способы?

Пример:

function login() {
 //enter login code here
}

function logout() {
 //enter logout code here
}

Если я просто поставлю, скажем, usleep(3000000) перед кодами входа и выхода, это нормально, или есть ли лучшие, более мудрые способы достижения того, чего я хочу достичь?

edit: Исходя из приведенных ниже предложений, usleep или sleep только заставляет процессор отключаться от текущего сценария, выполняемого текущим пользователем, или вызывает его отключение со всего сервиса? Т.е. если один пользователь + сценарий вызывает sleep / usleep, будут ли все одновременные пользователи + сценарии также задерживаться?

Ответы [ 4 ]

8 голосов
/ 01 февраля 2009

Способ работы большинства веб-серверов (например, Apache) - поддерживать набор рабочих потоков. Когда выполняется скрипт PHP, один поток запускает скрипт PHP.

Когда ваш сценарий выполняет sleep(100), выполнение сценария занимает 100 секунд. Это означает, что ваш рабочий поток связан на 100 секунд.

Проблема в том, что у вас очень ограниченное число рабочих потоков - скажем, у вас есть 10 потоков и 10 человек, которые входят в систему - теперь ваш веб-сервер не может обслуживать дальнейшие ответы.

Лучший способ ограничить скорость входа в систему (или другие действия) - это использовать какой-нибудь быстрый способ хранения в памяти ( memcached идеально подходит для этого), но для этого требуется запустить отдельный процесс и довольно сложно (вы можете сделать это, если вы запускаете что-то вроде 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 (что быстрее)

3 голосов
/ 01 февраля 2009

чтобы остановить ботов, злоумышленников и т. Д. от выполнения сценариев PHP слишком быстро?

Я бы сначала спросил, что вы действительно пытаетесь предотвратить? Если это атаки типа «отказ в обслуживании», то я должен сказать, что вы ничего не можете сделать, если вы ограничены тем, что можете добавить в сценарии PHP. Уровень техники намного выше того, от чего мы, программисты, можем защитить. Начните смотреть на инструменты sysadmin, разработанные для этой цели.

Или вы пытаетесь ограничить свой сервис, чтобы реальные люди могли получить к нему доступ, а боты - нет? Если это так, я бы посмотрел на некоторые техники "капчи".

Или вы пытаетесь запретить пользователям опрашивать ваш сайт каждую секунду в поисках нового контента? Если это так, я бы расследовал предоставление RSS-канала или какой-либо другой способ уведомить их, чтобы они не использовали вашу пропускную способность.

Или это что-то еще?

В общем, я бы сказал, что sleep () и usleep () не являются хорошим способом.

1 голос
/ 01 февраля 2009

Вы не хотите спать в своем php. Это значительно сократит число одновременных запросов, которые может обработать ваша подача, поскольку у вас будут открытые соединения, ожидающие открытия.

Большинство HTTP-серверов имеют функции, которые вы можете включить, чтобы избежать DoS-атак, но при этом вам не нужно просто отслеживать IP-адреса, которые вы видели слишком много раз за последнее время, и отправлять им 403 Forbidden с сообщением, просящим их подождать секунду.

Если по какой-то причине вы не можете рассчитывать на то, что REMOTE_ADDR зависит от пользователя (все за одним и тем же брандмауэром и т. Д.), Вы можете доказать проблему в форме входа в систему и заставить удаленный браузер выполнять расширенные вычисления (скажем, фактор номер), который вы можете быстро проверить на стороне сервера (с быстрым умножением).

1 голос
/ 01 февраля 2009

Ваш предложенный метод заставит ВСЕХ пользователей без необходимости ждать перед входом в систему.

Большинство серверов LAMP (и большинство маршрутизаторов / коммутаторов на самом деле) уже настроены на предотвращение атак типа «отказ в обслуживании». Они делают это, отклоняя несколько последовательных запросов с одного и того же IP-адреса.

...