Настройка лимитов заказов по IP-адресу 1С-Битрикс
Одна IP-подсеть генерирует 50 заказов за 10 минут. Причина — массовый мошеннический вброс или баг на фронтенде с повторной отправкой формы. Лимиты по IP защищают базу данных от мусора и предотвращают финансовые потери. Мошеннические заказы обходятся магазину в серьёзные суммы: упаковка, доставка, возврат. Внедрение лимитов снижает возвраты по мошенническим заказам на 80% (по данным наших кейсов). За годы работы с Битрикс мы разработали готовое решение, которое ставится под ключ за 2-3 дня.
Почему лимиты по IP важны для интернет-магазина?
Мошенники используют автоматизированные скрипты для оформления заказов с подставными данными. Один IP может создать десятки заказов за минуту, засоряя систему и вызывая ложные списания товаров. Лимиты по IP — первая линия обороны, которая отсекает такие атаки до того, как они повлияют на складские остатки и финансовые операции.
Как работают лимиты заказов по IP?
Механизм прост: перед сохранением заказа проверяется количество заказов с этого IP за последние N минут. Если превышен порог — заказ отклоняется с понятным сообщением. Мы используем два уровня защиты: быстрый на nginx и детальный на PHP.
Лимиты на уровне PHP
Проверка в обработчике события перед сохранением заказа:
namespace Local\Fraud; class IpOrderLimiter { // Лимиты: [интервал в минутах => максимум заказов] private const LIMITS = [ 15 => 3, // не более 3 заказов за 15 минут 60 => 5, // не более 5 заказов за 1 час 1440 => 15, // не более 15 заказов за сутки ]; public static function check(string $ip): ?string { $conn = \Bitrix\Main\Application::getConnection(); $ipSafe = $conn->getSqlHelper()->forSql($ip); foreach (self::LIMITS as $minutes => $maxOrders) { $from = date('Y-m-d H:i:s', time() - $minutes * 60); $count = (int)$conn->query( "SELECT COUNT(*) cnt FROM b_sale_order WHERE CREATED_BY_IP = '{$ipSafe}' AND DATE_INSERT >= '{$from}'" )->fetch()['cnt']; if ($count >= $maxOrders) { return "Превышен лимит заказов с вашего IP. Попробуйте через " . self::cooldownMinutes($minutes, $maxOrders, $ip) . " минут."; } } return null; } private static function cooldownMinutes(int $windowMinutes, int $max, string $ip): int { $conn = \Bitrix\Main\Application::getConnection(); $ipSafe = $conn->getSqlHelper()->forSql($ip); $from = date('Y-m-d H:i:s', time() - $windowMinutes * 60); // Находим самый ранний из последних $max заказов $oldest = $conn->query( "SELECT MIN(DATE_INSERT) dt FROM ( SELECT DATE_INSERT FROM b_sale_order WHERE CREATED_BY_IP = '{$ipSafe}' AND DATE_INSERT >= '{$from}' ORDER BY DATE_INSERT ASC LIMIT {$max} ) sub" )->fetch()['dt']; if (!$oldest) return $windowMinutes; $oldestTs = strtotime($oldest); return max(1, (int)ceil(($oldestTs + $windowMinutes * 60 - time()) / 60)); } } Обработчик события:
AddEventHandler('sale', 'OnBeforeOrderFinalAction', function(\Bitrix\Sale\Order $order) { if ($order->getId() > 0) return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS); $ip = $_SERVER['REMOTE_ADDR'] ?? ''; $error = \Local\Fraud\IpOrderLimiter::check($ip); if ($error) { return new \Bitrix\Main\EventResult( \Bitrix\Main\EventResult::ERROR, new \Bitrix\Main\Error($error) ); } return new \Bitrix\Main\EventResult(\Bitrix\Main\EventResult::SUCCESS); }); Согласно документации Битрикс, событие OnBeforeOrderFinalAction вызывается перед финальным действием с заказом — идеальное место для превентивных проверок.
Лимиты на уровне nginx
Почему лимиты на уровне nginx эффективнее? Nginx обрабатывает лимиты до PHP, не тратя серверные ресурсы на выполнение скриптов. Для магазина с большим потоком заказов это снижает нагрузку на PHP на 70%. Кроме того, nginx не ждёт ответа от приложения — блокировка происходит на уровне ядра веб-сервера.
# /etc/nginx/conf.d/order-limit.conf # Зона для страницы оформления заказа limit_req_zone $binary_remote_addr zone=checkout:10m rate=2r/m; # Зона для AJAX-запросов создания заказа limit_req_zone $binary_remote_addr zone=order_ajax:10m rate=5r/m; server { # ... location = /order/ { limit_req zone=checkout burst=3 nodelay; limit_req_status 429; # ... } location ~ ^/local/ajax/(order|checkout) { limit_req zone=order_ajax burst=5 nodelay; limit_req_status 429; add_header Retry-After 60; # ... } } Белый список IP и логирование
Легитимные партнёры или внутренние IP не должны попадать под лимиты:
private static function isWhitelisted(string $ip): bool { $whitelist = [ '127.0.0.1', '::1', '10.0.0.0/8', // внутренняя сеть '192.168.0.0/16', ]; foreach ($whitelist as $cidr) { if (str_contains($cidr, '/')) { if (self::ipInCidr($ip, $cidr)) return true; } elseif ($ip === $cidr) { return true; } } return false; } private static function ipInCidr(string $ip, string $cidr): bool { [$subnet, $mask] = explode('/', $cidr); return (ip2long($ip) & ~((1 << (32 - (int)$mask)) - 1)) === ip2long($subnet); } Каждое срабатывание лимита логируется:
\Bitrix\Main\Diag\Debug::writeToFile( [ 'ip' => $ip, 'limit' => "{$count}/{$maxOrders} за {$minutes} мин", 'ua' => $_SERVER['HTTP_USER_AGENT'] ?? '', 'referer' => $_SERVER['HTTP_REFERER'] ?? '', ], 'IP limit triggered', '/local/logs/ip-limits.log' ); Агент раз в день парсит лог и отправляет отчёт: топ-10 IP по блокировкам, динамика за неделю.
Что делать при ложных срабатываниях лимитов?
Ложные срабатывания возникают, когда легитимные пользователи (например, из одной офисной сети) превышают лимиты. Решение — настроить белый список для корпоративных подсетей или увеличить лимиты для B2B-сценариев. В нашей практике достаточно скорректировать пороги в 80% случаев без изменения кода.
Сравнение подходов: PHP vs nginx
| Критерий | Лимиты на PHP | Лимиты на nginx |
|---|---|---|
| Нагрузка на сервер | Средняя (выполнение PHP, запросы к БД) | Минимальная (ядро nginx) |
| Гибкость логики | Высокая (белый список, кастомные интервалы) | Низкая (только частота запросов) |
| Скорость блокировки | После начала выполнения PHP | До обработки PHP |
| Рекомендация | Для детальной логики | Первый рубеж, снижение нагрузки |
Как внедрить лимиты заказов по IP: пошаговое руководство
- Аудит текущей архитектуры: выявить точки обработки заказов, определить используемые IP-адреса.
- Настройка лимитов на nginx: добавить
limit_req_zoneдля страниц оформления и AJAX-запросов, установить базовые пороги. - Разработка PHP-класса
IpOrderLimiter: реализовать проверку с гибкими временными окнами и белым списком. Для хранения конфигурации лимитов можно использовать HL-блок — это позволит менять пороги без деплоя. - Интеграция с событием
OnBeforeOrderFinalAction: подключить обработчик вinit.phpили кастомном модуле. - Логирование и мониторинг: настроить запись срабатываний и агент для ежедневной отправки отчёта.
- Тестирование: симулировать превышение лимита с разных IP, убедиться в корректной блокировке.
- Запуск и адаптация: наблюдать за логами первую неделю, при необходимости корректировать пороги.
Настройка лимитов для разных сценариев
| Сценарий магазина | Рекомендованные лимиты |
|---|---|
| Стандартный B2C | 3/15мин, 5/час, 15/сутки |
| B2B с крупными заказами | 5/15мин, 15/час, 50/сутки |
| Распродажа (временно) | 10/15мин, 30/час |
Лимиты хранятся в конфиге или опциях модуля — без деплоя меняются через административную часть.
Что входит в работу
- Аудит текущей архитектуры и выявление уязвимых мест.
- Разработка PHP-класса IpOrderLimiter с гибкими лимитами и белым списком.
- Настройка nginx для первого рубежа защиты.
- Интеграция с событием
OnBeforeOrderFinalAction. - Система логирования и агент отчётов.
- Документация и обучение администратора.
Для расчёта стоимости и сроков свяжитесь с нами — мы подготовим предложение под ваш проект.
У нас более 100 успешных внедрений защиты заказов в Битрикс. Сертифицированные специалисты с многолетним опытом. Получите консультацию по настройке лимитов для вашего магазина — свяжитесь с нами.







