Блокировка по ip адресу на PHP
В этой статье рассмотрен простейший php-скрипт, который имеет два уровня защиты сайта: предупреждение спамера о том, что ему не поздоровится, если он еще раз наспамит и полная блокировка доступа к сайту по ip. Единственным минусом блокировки по ipявляется то, что спамер может пользоваться бесплатным и общедоступным прокси-сервером, и если забаннить сервер с этим ip, то к вашему сайту не смогут получить доступ и те, кто использует его исключительно в мирных целях. Поэтому прежде чем банить смотрите, кто есть кто через сервис whois.
А вот и сам php-код простейшего скрипта для блокировки пользователя по ip:
/* http://wm-help.net/ */ /* Сообщение при банне ip */ define("bann_message", "Для вашего IP: %ip% доступ к сайту закрыт."); /* Предупреждение о возможности банна по ip */ define("wrong_message", "Вы предупреждены администратором данного сайта о возможной блокировке вашего IP: %ip% в случае дальнейшего нарушения правил."); /* массив с ip и типом блокировки. в ключе массива IP, в значении тип блокировки */ $bann_array = array( "195.66.203.247"=>"bann", // реальный плохой IP "220.94.220.60"=>"bann", // реальный плохой IP //"127.0.0.1"=>"wrong" // Test ); /* Функция для почти 100% определения IP адреса посетителя. */ /* Перебирает все возможные переменные с IP. */ function _ip() < if(isset($HTTP_SERVER_VARS)) < if(isset($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"])) < $realip = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"]; >elseif(isset($HTTP_SERVER_VARS["HTTP_CLIENT_IP"])) < $realip = $HTTP_SERVER_VARS["HTTP_CLIENT_IP"]; >else< $realip = $HTTP_SERVER_VARS["REMOTE_ADDR"]; > >else< if(getenv( 'HTTP_X_FORWARDED_FOR' ) ) < $realip = getenv( 'HTTP_X_FORWARDED_FOR' ); >elseif ( getenv( 'HTTP_CLIENT_IP' ) ) < $realip = getenv( 'HTTP_CLIENT_IP' ); >else < $realip = getenv( 'REMOTE_ADDR' ); > > return $realip; > /* Определяет, что делать с владельцем того или иного ip адреса */ function bann_on_not_to_bann() < global $bann_array; // получаем массив с ip адресами $user_ip = _ip(); // получаем ip /* разбираем массив на ключ и значение */ foreach($bann_array as $ip=>$type) < if ($ip == $user_ip) // проверяем < switch($type) // если ip совпал то смотрим что делать < case "wrong": // предупреждение < echo str_replace("%ip%", $user_ip, wrong_message); // выводим предупреждение break; // выход из switch > case "bann": // блокировка < die(str_replace("%ip%", $user_ip, bann_message)); // Сообщение о том, что доступ закрыт + завершение работы php // break не требуется т.к. дальше уже ничего не выполняется > > > > > /* проверяем владельца ip и блокируемпредупреждаем если это спамер */ bann_on_not_to_bann(); ?>
Для того, чтобы использовать данный скрипт блокировки ipадресов создайте php-файл ip_bann.php и поместите в него весь код скрипта, который вы видите выше. Затем в самом начале основного скрипта, обычно это index.php допишите строчку:
include ‘ip_bann.php’;
Так же этот php-скрипт можно использовать для блокировки ip непосредственно в скриптах отвечающих за добавление сообщений пользователей на ваш сайт, а не повсеместно, данный вариант иногда бывает даже лучше.
Рекомендуем почитать
- Грамотная работа с файлами: исключительная блокировка файлов
- Тонкая настройка MySQL
- Форматирование телефонных номеров на PHP
- Всеобъемлющая история шаблонов
- Системы голосований на РНР
- 21 ошибка программиста PHP
- Скрипт гостевой книги на PHP
Вычисляем потенциальных «злых» ботов и блокируем их по IP
Доброго дня! В статье расскажу как можно пользователям обычного хостинга отловить IP адреса генерирующие излишнюю нагрузку на сайт и затем блокировать их при помощи средств хостинга, будет «чуть-чуть» php кода, несколько скриншотов.
Вводные данные:
- Сайт созданный на CMS WordPress
- Хостинг Бегет (это не реклама, но скрины админки будут именно этого хостинг провайдера)
- WordPress сайт запущен где то в начале 2000 и имеет большое количество статей и материалов
- Версия PHP 7.2
- WP имеет последнюю версию
- С некоторых пор сайт начал генерировать высокую нагрузку на MySQL по данным хостинга. Каждый день это значение превышало 120% от нормы на учётную запись
- По данным Яндекс. Метрика сайт посещает 100-200 человек в сутки
- Очищены таблицы БД от накопившегося мусора
- Отключены не нужные плагины, убраны участки устаревшего кода
То как выглядела примерная нагрузка по базам данных хостинга

В топе находится сайт о котором идёт речь, чуть ниже другие сайты которые имеют ту же cms и примерно такую же посещаемость, но создают меньше нагрузки.
- Было предпринято много попыток с вариантами кеширования данных, проводились наблюдения в течении нескольких недель (благо хостинг за это время мне ни разу не написал что я такой плохой и меня отключат)
- Был анализ и поиск медленных запросов, затем была немного изменена структура БД и тип таблиц
- Для анализа в первую очередь использовался встроенный AWStats (он кстати помог вычислить самый злой IP адрес по объему трафика
- Метрика — метрика даёт информацию только о людях, а не о ботах
- Были попытки использовать плагины для WP, которые умеют фильтровать и блокировать посетителей даже по стране нахождения и по различным комбинациям
- Совсем радикальный способ оказался закрыть сайт на сутки с пометкой «Мы на техническом обслуживании» — это было так же сделано при помощи знаменитого плагина. В этом случае нагрузка ожидаем упала, но не до 0-левых значений, так как идеология WP базируется на хуках и плагины начинают свою активность при наступлении какого — либо «хука», а до наступления «хука» могут быть уже сделаны запросы к БД
- Вычислить IP адреса которые делают много запросов за короткий промежуток времени.
- Зафиксировать количество обращений к сайту
- На основе количества обращений блокировать доступ к сайту
- Блокировать при помощи записи «Deny from» в файле .htaccess
- Другие варианты, вроде iptables и правил для Nginx не рассматривая, ибо пишу про хостинг
-
Создаём таблицы для накопления данных
CREATE TABLE `wp_visiters_bot` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `ip` VARCHAR(300) NULL DEFAULT NULL, `browser` VARCHAR(500) NULL DEFAULT NULL, `cnt` INT(11) NULL DEFAULT NULL, `request` TEXT NULL, `input` TEXT NULL, `data_update` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE INDEX `ip` (`ip`) ) COMMENT='Кандидаты для блокировки' COLLATE='utf8_general_ci' ENGINE=InnoDB AUTO_INCREMENT=1;
CREATE TABLE `wp_visiters_bot_blocked` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `ip` VARCHAR(300) NOT NULL, `data_update` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE INDEX `ip` (`ip`) ) COMMENT='Список уже заблокированных' COLLATE='utf8_general_ci' ENGINE=InnoDB AUTO_INCREMENT=59;
CREATE TABLE `wp_visiters_bot_history` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `ip` VARCHAR(300) NULL DEFAULT NULL, `browser` VARCHAR(500) NULL DEFAULT NULL, `cnt` INT(11) NULL DEFAULT NULL, `data_update` DATETIME NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `data_add` DATETIME NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`), UNIQUE INDEX `ip` (`ip`) ) COMMENT='История всех запросов для дебага' COLLATE='utf8_general_ci' ENGINE=InnoDB AUTO_INCREMENT=1;
Код файла, для записи IP адресов
global $wpdb; /** * Вернёт конкретный IP адрес посетителя * @return boolean */ function coderun_get_user_ip() < $client_ip = ''; $address_headers = array( 'HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_X_CLUSTER_CLIENT_IP', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR', ); foreach ($address_headers as $header) < if (array_key_exists($header, $_SERVER)) < $address_chain = explode(',', $_SERVER[$header]); $client_ip = trim($address_chain[0]); break; >> if (!$client_ip) < return ''; >if ('0.0.0.0' === $client_ip || '::' === $client_ip || $client_ip == 'unknown') < return ''; >return $client_ip; > $ip = esc_sql(coderun_get_user_ip()); // IP адрес посетителя if (empty($ip))/ Нет IP, ну и идите лесом. header('Content-type: application/json;'); die('Big big bolt. '); > $browser = esc_sql($_SERVER['HTTP_USER_AGENT']); //Данные для анализа браузера $request = esc_sql(wp_json_encode($_REQUEST)); //Последний запрос который был к сайту $input = esc_sql(file_get_contents('php://input')); //Тело запроса, если было $cnt = 1; //Запрос в основную таблицу с временными кондидатами на блокировку $query = ','','','','$input') ON DUPLICATE KEY UPDATE cnt=cnt+1,request=VALUES(request),input=VALUES(input),browser=VALUES(browser) EOT; //Запрос для истории $query2 = ','','') ON DUPLICATE KEY UPDATE cnt=cnt+1,browser=VALUES(browser) EOT; $wpdb->query($query); $wpdb->query($query2);

Дальше просто, скопировали «вредный» IP, открыли файл .htaccess и добавили в конец файла
Order allow,deny Allow from all # start_auto_deny_list Deny from 94.242.55.248 # end_auto_deny_list
Всё, теперь 94.242.55.248 — не имеет доступа к сайту и не генерирует нагрузку на БД
Но каждый раз так руками копировать не очень праведное занятие, да и к тому же код задумывался как автономный
Добавим файл, который будет исполняться по CRON каждые 30 минут:
Код файла модифицирующий .htaccess
require('wp-load.php'); global $wpdb; $limit_cnt = 70; //Лимит запросов по которым отбирать $deny_table = $wpdb->get_results("SELECT * FROM wp_visiters_bot WHERE cnt>"); $new_blocked = []; $exclude_ip = [ '87.236.16.70'//адрес хостинга ]; foreach ($deny_table as $result) < if (in_array($result->ip, $exclude_ip)) < continue; >$wpdb->insert('wp_visiters_bot_blocked', ['ip' => $result->ip], ['%s']); > $deny_table_blocked = $wpdb->get_results("SELECT * FROM wp_visiters_bot_blocked"); foreach ($deny_table_blocked as $blocked) < $new_blocked[] = $blocked->ip; > //Очистка таблицы $wpdb->query("DELETE FROM wp_visiters_bot"); //echo '';print_r($new_blocked);echo ''; $file = '.htaccess'; $start_searche_tag = 'start_auto_deny_list'; $end_searche_tag = 'end_auto_deny_list'; $handle = @fopen($file, "r"); if ($handle) < $replace_string = '';//Тест для вставки в файл .htaccess $target_content = false; //Флаг нужного нам участка кода while (($buffer = fgets($handle, 4096)) !== false) < if (stripos($buffer, 'start_auto_deny_list') !== false) < $target_content = true; continue; >if (stripos($buffer, 'end_auto_deny_list') !== false) < $target_content = false; continue; >if ($target_content) < $replace_string .= $buffer; >> if (!feof($handle)) < echo "Ошибка: fgets() неожиданно потерпел неудачу\n"; >fclose($handle); > //Текущий файл .htaccess $content = file_get_contents($file); $content = str_replace($replace_string, '', $content); //Очищаем все блокировки в файле .htaccess file_put_contents($file, $content); //Запись новых блокировок $str = "# " . PHP_EOL; foreach ($new_blocked as $key => $value) < $str .= "Deny from " . PHP_EOL; > file_put_contents($file, str_replace("# ", $str, file_get_contents($file)));
Код файла достаточно прост и примитивен и главная его идея в том что бы взять кандидатов на блокировку и вписать правила блокирвоки в файл .htaccess между комментариями
# start_auto_deny_list и # end_auto_deny_listТеперь «вредные» ip блокируются сами собой, а файл .htaccess выглядит примерно так:
# BEGIN WordPressRewriteEngine On RewriteBase / RewriteRule ^index\.php$ - [L] RewriteCond % !-f RewriteCond % !-d RewriteRule . /index.php [L] # END WordPress Order allow,deny Allow from all # start_auto_deny_list Deny from 94.242.55.248 Deny from 207.46.13.122 Deny from 66.249.64.164 Deny from 54.209.162.70 Deny from 40.77.167.86 Deny from 54.146.43.69 Deny from 207.46.13.168 . ниже другие адреса # end_auto_deny_listВ итоге после начала действия такого кода можно увидеть результат в хостинг панели:
PS: Материал авторский, хоть его часть я и публиковал на своём сайте но на Habre получилась более расширенная версия.
Как заблокировать ip посетителя сайта php
Есть много способов защитить свой сайт от неблагоприятных посетителей, например спаммеров. Самый простой способ, который помогает в 90% случаев – блокировка IP.
В PHP это далается так:
Для начала нужно определить IP посетителя:
Далее нужно задать переменную, в которой будут храниться заблокированные IP-адреса:
$ban = array(‘111.111.111.111′,’222.222.222.222’);
$count = count($ban);Теперь надо запустить цикл, чтобы всё заработало.
Примерно такой код должен у вас получиться:
Фильтрация IP-адресов
Примеры как запретить доступ к сайту по IP-адресам в PHP и htaccess.
Определение IP-адреса
В PHP IP-адрес клиента доступен в переменной $_SERVER[‘REMOTE_ADDR’] , но не всегда она содержит истинный т.к. клиент может использовать прокси. Для определение истинного адреса можно использовать функцию.
function getIp($default = '') < if (!empty($_SERVER['HTTP_CLIENT_IP'])) < $value = $_SERVER['HTTP_CLIENT_IP']; >elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) < $value = $_SERVER['HTTP_X_FORWARDED_FOR']; >elseif (!empty($_SERVER['REMOTE_ADDR'])) < $value = $_SERVER['REMOTE_ADDR']; >else < return $default; >return $value; >Фильтрация по списку
$black_list = array( '192.168.0.0', '192.168.255.255', '172.16.0.0', '172.31.255.255', ); if (in_array($_SERVER['REMOTE_ADDR'], $black_list))В .htaccess применяется конструкция Order, Allow, Deny . Адреса перечисляются через пробел или отдельными строками.
Order Allow,Deny Allow from all Deny from 192.168.0.0 192.168.255.255 172.16.0.0 172.31.255.255Order Allow,Deny Allow from all Deny from 192.168.0.0 Deny from 192.168.255.255 Deny from 172.16.0.0 Deny from 172.31.255.255Фильтрация по диапазону
$black_list = array( array('192.168.0.0', '192.168.255.255'), array('172.16.0.0', '172.31.255.255'), ); $ip = @ip2long($_SERVER['REMOTE_ADDR']); foreach($black_list as $ips) < if ($ip >= @ip2long($ips[0]) && $ip >В htaccess диапазон блокируемых IP задаётся в виде бесклассовой адресации (CIDR). Для его формирования можно использовать сервис ip2cidr.com
Order Allow,Deny Allow from all Deny from 192.168.0.0/16 Deny from 172.16.0.0/12Фильтрация по маске
$black_list = array( '192.168.0.*', '172.16.*.*' ); foreach($black_list as $ips) < if (preg_match('/' . $ips . '/', $_SERVER['REMOTE_ADDR'])) < exit() >>В .htaccess нельзя задать маску вида 192.168.0.* , но можно не указывать последние части адреса – будет заблокирован весь диапазон.
Order Allow,Deny Allow from all Deny from 192.168. Deny from 172.16.

