BunkerWeb — открытый обратный прокси на базе NGINX, который из коробки включает ModSecurity с набором правил OWASP Core Rule Set, ограничение частоты запросов, защиту от автоматизированных сканеров, автоматический выпуск сертификатов и интеграцию с CrowdSec. Его смысл в том, чтобы не собирать защитный контур из десятка отдельных модулей, а поставить перед приложением готовый узел, который настраивается переменными окружения. Ниже — установка, подключение сервиса, первичная настройка правил и разбор типичных проблем.

Как устроен BunkerWeb

В основе лежит NGINX, который принимает трафик на портах 80 и 443 и передаёт его приложению. Поверх работают модули: WAF на ModSecurity, антибот, лимиты запросов, проверка репутации адресов, кэширование и балансировка. Конфигурация хранится не в обычных файлах nginx, а в наборе параметров, которые планировщик собирает и рассылает экземплярам. В контейнерной поставке NGINX слушает внутри 8080 и 8443, поэтому наружу пробрасываются именно эти порты, а не 80 и 443 напрямую.

  • bunkerweb — сам прокси и WAF, принимает трафик и применяет правила.
  • bw-scheduler — хранит настройки, генерирует конфигурацию и перезагружает экземпляры.
  • bw-ui — веб-интерфейс с мастером первоначальной настройки и редактором сервисов.
  • bw-db — база MariaDB для настроек, пользователей и статистики.

Для небольшой инсталляции есть образ all-in-one: в нём уже собраны прокси, планировщик, интерфейс и SQLite. Он удобен для теста и домашнего стенда, но в продакшене лучше раздельные контейнеры: компоненты обновляются независимо.

Быстрый запуск в Docker

Ниже — ключевая часть compose-файла: прокси и планировщик, а база и интерфейс добавляются отдельными сервисами. Планировщику нужно знать имя экземпляра и диапазон адресов, с которых разрешено обращаться к внутреннему API. Этот диапазон должен совпадать с подсетью служебной сети, иначе планировщик не сможет отправить конфигурацию.

x-bw-env: &bw-env
  API_WHITELIST_IP: "127.0.0.0/8 10.20.30.0/24"
  DATABASE_URI: "mariadb+pymysql://bunkerweb:changeme@bw-db:3306/db"

services:
  bunkerweb:
    image: bunkerity/bunkerweb:1.6.17
    ports:
      - "80:8080/tcp"
      - "443:8443/tcp"
      - "443:8443/udp"
    environment: *bw-env
    networks: [bw-universe, bw-services]

  bw-scheduler:
    image: bunkerity/bunkerweb-scheduler:1.6.17
    environment:
      <<: *bw-env
      BUNKERWEB_INSTANCES: "bunkerweb"
      MULTISITE: "yes"
    networks: [bw-universe, bw-db]

Пароль к базе из примера обязательно замените на длинный случайный. Сеть bw-universe нужна для обмена конфигурацией, bw-services — для доступа к защищаемым приложениям, bw-db — для базы. Сервис bw-ui слушает порт 7000; публиковать его наружу не стоит — доступ к интерфейсу лучше ограничить файрволом или открывать через SSH-туннель.

Подключение приложения

Сервис описывается теми же параметрами, что и в файле variables.env: имя домена, режим обратного прокси и адрес бэкенда. Для нескольких сайтов включается MULTISITE, а параметры получают префикс с именем домена. Такой префикс — главная причина ошибок: без него настройка применится глобально и переопределит остальные сайты.

MULTISITE=yes
SERVER_NAME=app.example.com
app.example.com_USE_REVERSE_PROXY=yes
app.example.com_REVERSE_PROXY_URL=/
app.example.com_REVERSE_PROXY_HOST=http://app:3000

Контейнер приложения должен находиться в сети bw-services, иначе имя app не разрешится и вы получите 502. После правки конфигурации планировщик перезапускают, чтобы он пересобрал файлы и разослал их экземплярам.

HTTPS и сертификаты

Автоматический выпуск включается параметром AUTO_LETS_ENCRYPT=yes; для проверки домена нужен открытый 80-й порт и корректная A-запись. Если сайт стоит за CDN или балансировщиком, дополнительно настраивают Real IP, иначе в журналах будут адреса промежуточного узла, а лимиты начнут срабатывать для всех клиентов сразу. Проверить цепочку и срок действия проще двумя командами, чем через браузер.

curl -I https://app.example.com
openssl s_client -connect app.example.com:443 -servername app.example.com </dev/null | openssl x509 -noout -dates

Первая команда показывает код ответа и заголовки, вторая — даты выпуска и истечения сертификата.

Что включить в первую очередь

  • USE_MODSECURITY=yes и USE_MODSECURITY_CRS=yes — базовый WAF с набором правил.
  • USE_LIMIT_REQ=yes с разумной скоростью, например LIMIT_REQ_RATE=20r/s.
  • USE_BAD_BEHAVIOR=yes — временная блокировка клиентов, генерирующих много ошибок.
  • USE_CROWDSEC=yes, если рядом развёрнут CrowdSec с локальными сценариями.
  • LOG_LEVEL=info на время настройки, затем возврат к notice.

Начинать с максимального уровня паранойи не стоит: PL1 даёт меньше ложных срабатываний, а повышать его имеет смысл после того, как журнал неделю оставался чистым. Для чувствительных форм и API правила уточняют точечно, а не отключают WAF целиком.

Диагностика: баны и ложные срабатывания

Заблокированный адрес разблокируется утилитой bwcli, которая есть и в контейнере, и в Linux-установке. Перед снятием бана полезно понять причину: в журнале WAF видно идентификатор правила и итоговую оценку аномалии, а не только факт отказа.

docker exec bw-scheduler bwcli unban 203.0.113.10
docker logs --tail 200 bunkerweb | grep -i modsecurity
cat /var/log/bunkerweb/error.log | tail -50

Если правило срабатывает на легитимный запрос, помогает режим обнаружения: он пропускает трафик, но пишет события. После сбора статистики добавляют исключение для конкретного параметра или пути. Отключать правило 949110, которое выносит решение о блокировке, нельзя — это сломает подсчёт аномалий.

Ресурсы, обновление и резервное копирование

Для тестового стенда достаточно двух ядер и восьми гигабайт памяти, для продакшена с десятком сайтов закладывают четыре ядра и шестнадцать гигабайт.

Перед обновлением фиксируют тег образа, а не используют latest. Настройки и статистика лежат в томе bw-data (в compose он получает префикс проекта), конфигурация интерфейса — в bw-ui-data. Копию удобно снимать с остановленного планировщика, иначе дамп базы может оказаться несогласованным.

docker compose stop bw-scheduler
docker run --rm -v bw-data:/src -v "$PWD":/backup alpine tar czf /backup/bw-data.tgz -C /src .
docker compose up -d bw-scheduler

После обновления проверяют docker compose ps, журналы и тестовый запрос к каждому домену. Если новый образ ведёт себя иначе, возврат к прежнему тегу занимает минуту — при условии, что том с данными не мигрировал безвозвратно и совместим со старой версией.

Итог

BunkerWeb закрывает типовые задачи защиты веб-приложения без ручной сборки конфигурации NGINX: WAF, лимиты, HTTPS и веб-интерфейс уже включены. Разумный порядок внедрения — поднять стенд, пропустить через него реальный трафик в режиме обнаружения, настроить исключения и только потом включать блокировки. Тогда защита не превратится в источник отказов для пользователей.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте