Перейти к содержанию

waf: Высокопроизводительный WAF, построенный на стеке nginx-module-lua

Установка

Если вы еще не настроили подписку на RPM-репозиторий, зарегистрируйтесь. Затем вы можете перейти к следующим шагам.

CentOS/RHEL 7 или Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-waf

CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-waf

Чтобы использовать эту библиотеку Lua с NGINX, убедитесь, что nginx-module-lua установлен.

Этот документ описывает lua-resty-waf v0.11.1, выпущенный 9 мая 2017 года.


lua-resty-waf — это WAF обратного прокси, построенный с использованием стека OpenResty. Он использует Nginx Lua API для анализа информации о HTTP-запросах и обработки в соответствии с гибкой структурой правил. lua-resty-waf поставляется с набором правил, который имитирует ModSecurity CRS, а также с несколькими пользовательскими правилами, созданными в процессе начальной разработки и тестирования, и небольшим виртуальным набором патчей для возникающих угроз. Кроме того, lua-resty-waf поставляется с инструментами для автоматического перевода существующих правил ModSecurity, позволяя пользователям расширять реализацию lua-resty-waf без необходимости изучать новый синтаксис правил.

lua-resty-waf был изначально разработан Робертом Папроки для его магистерской диссертации в Университете Западных губернаторов.

./configure --with-pcre=/path/to/pcre/source --with-pcre-jit

Вы можете скачать исходный код PCRE с [сайта PCRE](http://www.pcre.org/). Также смотрите этот [блог-пост](https://www.cryptobells.com/building-openresty-with-pcre-jit/) для пошагового руководства по сборке OpenResty с библиотекой PCRE, поддерживающей JIT.

## Производительность

lua-resty-waf был разработан с учетом эффективности и масштабируемости. Он использует асинхронную модель обработки Nginx и эффективный дизайн, чтобы обрабатывать каждую транзакцию как можно быстрее. Нагрузочное тестирование показало, что развертывания, реализующие все предоставленные наборы правил, которые предназначены для имитации логики, стоящей за ModSecurity CRS, обрабатывают транзакции примерно за 300-500 микросекунд на запрос; это соответствует производительности, рекламируемой [WAF Cloudflare](https://www.cloudflare.com/waf). Тесты проводились на разумном аппаратном обеспечении (процессор E3-1230, 32 ГБ ОЗУ, 2 x 840 EVO в RAID 0), достигая примерно 15,000 запросов в секунду. Смотрите [этот блог-пост](http://www.cryptobells.com/freewaf-a-high-performance-scalable-open-web-firewall) для получения дополнительной информации.

Нагрузка lua-resty-waf почти исключительно зависит от ЦП. Объем памяти в виртуальной машине Lua (исключая постоянное хранилище, поддерживаемое `lua-shared-dict`) составляет примерно 2 МБ.

## make && sudo make install

Или установите через Luarocks:

### process_multipart_body

*По умолчанию* true

Включить обработку тел запросов multipart/form-data (если они присутствуют), используя модуль `lua-resty-upload`. В будущем lua-resty-waf может использовать эту обработку для более строгой проверки тел загрузок; на данный момент этот модуль выполняет только минимальные проверки целостности на теле запроса и не будет записывать событие, если тело запроса недействительно. Отключите эту опцию, если вам не нужна эта проверка или если ошибки в модуле upstream вызывают проблемы с HTTP-загрузками.

*Пример*:

```lua
location / {
    access_by_lua_block {
        -- отключить обработку запросов multipart/form-data
        -- обратите внимание, что тело запроса все равно будет отправлено на upstream
        waf:set_option("process_multipart_body", false)
    }
}

req_tid_header

По умолчанию: false

Установить HTTP-заголовок X-Lua-Resty-WAF-ID в upstream-запросе, со значением в качестве идентификатора транзакции. Этот идентификатор будет коррелировать с идентификатором транзакции, присутствующим в отладочных журналах (если установлен). Это может быть полезно для отслеживания запросов или отладки.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("req_tid_header", true)
    }
}

res_body_max_size

По умолчанию: 1048576 (1 МБ)

Определяет порог длины содержимого, выше которого тела ответов не будут обрабатываться. Этот размер тела ответа определяется заголовком Content-Length. Если этот заголовок отсутствует в ответе, тело ответа никогда не будет обработано.

Пример:

location / {
    access_by_lua_block {
        -- увеличить максимальный размер ответа до 2 МБ
        waf:set_option("res_body_max_size", 1024 * 1024 * 2)
    }
}
Обратите внимание, что по своей природе требуется буферизовать все тело ответа, чтобы правильно использовать ответ в качестве коллекции, поэтому значительно увеличивать это число не рекомендуется без обоснования (и достаточных ресурсов сервера).

res_body_mime_types

По умолчанию: "text/plain", "text/html"

Определяет MIME-типы, с которыми lua-resty-waf будет обрабатывать тело ответа. Это значение определяется заголовком Content-Type. Если этот заголовок отсутствует или тип ответа не входит в этот список, тело ответа не будет обработано. Установка этой опции добавит указанный MIME-тип к существующим значениям по умолчанию text/plain и text/html.

Пример:

location / {
    access_by_lua_block {
        -- mime-типы, которые будут обрабатываться, теперь text/plain, text/html и text/json
        waf:set_option("res_body_mime_types", "text/json")
    }
}

Несколько MIME-типов можно добавить, передав таблицу типов в set_option.

res_tid_header

По умолчанию: false

Установить HTTP-заголовок X-Lua-Resty-WAF-ID в downstream-ответе, со значением в качестве идентификатора транзакции. Этот идентификатор будет коррелировать с идентификатором транзакции, присутствующим в отладочных журналах (если установлен). Это может быть полезно для отслеживания запросов или отладки.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("res_tid_header", true)
    }
}

score_threshold

По умолчанию: 5

Устанавливает порог для оценки аномалий. Когда порог достигнут, lua-resty-waf будет отклонять запрос.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("score_threshold", 10)
    }
}

storage_backend

По умолчанию: dict

Определите движок для использования для постоянного хранения переменных. Текущие доступные варианты: dict (разделяемая память ngx_lua), memcached и redis.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("storage_backend", "memcached")
    }
}

storage_keepalive

По умолчанию: true

Включить или отключить TCP keepalive для соединений с удаленными хостами постоянного хранилища.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("storage_keepalive", false)
    }
}

storage_keepalive_timeout

По умолчанию: 10000

Настройте (в миллисекундах) тайм-аут для пула keepalive cosocket для удаленных хостов постоянного хранилища.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("storage_keepalive_timeout", 30000)
    }
}

storage_keepalive_pool_size

По умолчанию: 100

Настройте размер пула для пула keepalive cosocket для удаленных хостов постоянного хранилища.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("storage_keepalive_pool_size", 50)
    }
}

storage_memcached_host

По умолчанию: 127.0.0.1

Определите хост для использования при использовании memcached в качестве движка постоянного хранения переменных.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("storage_memcached_host", "10.10.10.10")
    }
}

storage_memcached_port

По умолчанию: 11211

Определите порт для использования при использовании memcached в качестве движка постоянного хранения переменных.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("storage_memcached_port", 11221)
    }
}

storage_redis_host

По умолчанию: 127.0.0.1

Определите хост для использования при использовании redis в качестве движка постоянного хранения переменных.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("storage_redis_host", "10.10.10.10")
    }
}

storage_redis_port

По умолчанию: 6379

Определите порт для использования при использовании redis в качестве движка постоянного хранения переменных.

Пример:

location / {
    access_by_lua_block {
        waf:set_option("storage_redis_port", 6397)
    }
}

storage_zone

По умолчанию: none

Определяет lua_shared_dict, который будет использоваться для хранения данных постоянного хранилища. Эта зона должна быть определена в блоке http{} конфигурации.

Пример:

http {
    -- определить разделяемую память 64M для хранения данных постоянного хранилища
    lua_shared_dict persistent_storage 64m;
}

location / {
    access_by_lua_block {
        waf:set_option("storage_zone", "persistent_storage")
    }
}

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

Ошибка при добавлении ключа в постоянное хранилище, увеличьте размер lua_shared_dict

Обработка фаз

lua-resty-waf разработан для работы на нескольких фазах жизненного цикла запроса. Правила могут обрабатываться на следующих фазах:

  • access: Информация о запросе, такая как URI, заголовки запроса, аргументы URI и тело запроса, доступны на этой фазе.
  • header_filter: Заголовки ответа и HTTP-статус доступны на этой фазе.
  • body_filter: Тело ответа доступно на этой фазе.
  • log: Журналы событий автоматически записываются по завершении этой фазы.

Эти фазы соответствуют соответствующим обработчикам lua Nginx (access_by_lua, header_filter_by_lua, body_filter_by_lua и log_by_lua, соответственно). Обратите внимание, что запуск lua-resty-waf в обработчике lua-фазы, не входящей в этот список, приведет к некорректному поведению. Все данные, доступные на более ранней фазе, доступны на более поздней фазе. То есть данные, доступные на фазе access, также доступны на фазах header_filter и body_filter, но не наоборот.

Включенные наборы правил

lua-resty-waf поставляется с рядом наборов правил, которые предназначены для имитации функциональности ModSecurity CRS. Для справки эти наборы правил перечислены здесь:

  • 11000_whitelist: Локальная политика белого списка
  • 20000_http_violation: Нарушение протокола HTTP
  • 21000_http_anomaly: Аномалии протокола HTTP
  • 35000_user_agent: Зловредные/подозрительные пользовательские агенты
  • 40000_generic_attack: Общие атаки
  • 41000_sqli: SQLi
  • 42000_xss: XSS
  • 90000_custom: Пользовательские правила/виртуальное патчирование
  • 99000_scoring: Обработка оценки аномалий

Определения правил

lua-resty-waf разбирает определения правил из JSON-объектов, хранящихся на диске. Правила сгруппированы по назначению и серьезности, определяемым как набор правил. Включенные наборы правил были созданы для имитации некоторой функциональности ModSecurity CRS, особенно определений base_rules. Кроме того, включенный скрипт modsec2lua-resty-waf.pl может использоваться для перевода дополнительных или пользовательских наборов правил в совместимый с lua-resty-waf JSON-объект.

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

Примечания

Pull Requests

Пожалуйста, направляйте все pull requests на ветку разработки или на ветку функции, если PR является значительным изменением. Коммиты в master должны поступать только в виде обновлений документации или других изменений, которые не влияют на сам модуль (и могут быть чисто объединены с разработкой).

Дорожная карта

  • Расширенный набор правил виртуального патча: Увеличить охват возникающих угроз.
  • Расширенное интеграционное/приемочное тестирование: Увеличить охват общих угроз и сценариев использования.
  • Расширенные переводы синтаксиса ModSecurity: Поддержка большего количества операторов, переменных и действий.
  • Общие профили приложений: Настроенные наборы правил для общих CMS/приложений.
  • Поддержка нескольких целей логирования сокетов/файлов: Вероятно, потребуется форк проекта lua-resty-logger-socket.

Ограничения

lua-resty-waf находится в процессе постоянной разработки и улучшения, и, как таковой, может быть ограничен в своей функциональности и производительности. Текущие известные ограничения можно найти в трекере проблем GitHub для этого репозитория.

См. также

GitHub

Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-waf.