nftset-access: Блокировка IP с нулевой задержкой с использованием наборов nftables ядра Linux
Требуется план Pro (или выше) подписки GetPageSpeed NGINX Extras.
Установка
Вы можете установить этот модуль в любом дистрибутиве на базе RHEL, включая, но не ограничиваясь:
- RedHat Enterprise Linux 7, 8, 9 и 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 и Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-nftset-access
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 nginx-module-nftset-access
Включите модуль, добавив следующее в начале файла /etc/nginx/nginx.conf:
load_module modules/ngx_http_nftset_access.so;
Этот документ описывает nginx-module-nftset-access v3.0.0, выпущенный 14 февраля 2026 года.
Корпоративный контроль доступа на основе IP для NGINX с использованием наборов nftables Linux. Блокируйте угрозы, ограничивайте злоумышленников, бросайте вызов ботам и защищайте свою инфраструктуру.
⚠️ Коммерческое программное обеспечение Это закрытый премиум модуль, доступный исключительно через GetPageSpeed Repository.
Требование к плану: Требуется план Pro подписки GetPageSpeed NGINX Extras.
✨ Возможности
Основные функции
| Функция | Описание |
|---|---|
| Черный/Белый список | Разрешить или запретить на основе членства в наборе nftables |
| Несколько наборов | Проверка по нескольким наборам nft в одной директиве |
| Живые обновления | Изменение наборов nft без перезагрузки NGINX |
| Пользовательские коды состояния | Возвращать любой HTTP статус при блокировке |
| Поддержка CIDR | Используйте интервальные наборы для диапазонов сети (например, 192.168.1.0/24) |
Функции производительности
| Функция | Описание |
|---|---|
| Сессии на поток | Контексты libnftables, локальные для потока, устраняют конкуренцию за блокировки |
| Кэш LRU | Кэш в общей памяти с настраиваемым временем жизни |
| Коэффициенты попадания в кэш | Обычно более 95% коэффициент попадания снижает вызовы ядра |
Функции безопасности
| Функция | Описание |
|---|---|
| Ограничение скорости | Ограничение запросов на IP с настраиваемыми окнами |
| Авто-блокировка | Автоматически добавлять нарушителей лимита скорости в черный список |
| JS Challenge | Задача на выполнение останавливает автоматизированные боты |
| Ловушки-хонейпоты | Авто-блокировка IP, попадающих на ловушки URL |
| Тайм-аут входа | Авто-истечение записей черного списка |
Операционные функции
| Функция | Описание |
|---|---|
| Режим пробного запуска | Тестирование конфигурации без блокировки |
| Fail-open/close | Управление поведением при ошибках набора nft |
| Метрики Prometheus | Нативная конечная точка /metrics для Grafana |
| JSON статистика | Подробный API статистики |
| Переменные NGINX | $nftset_result и $nftset_matched_set |
🚀 Быстрый старт
1. Создайте наборы nftables
## Создайте таблицу (если не существует)
sudo nft add table ip filter
## Создайте черный список с поддержкой тайм-аутов
sudo nft add set ip filter bad_guys '{ type ipv4_addr; flags timeout; timeout 1d; }'
## Создайте список блокировки по лимиту скорости
sudo nft add set ip filter ratelimited '{ type ipv4_addr; flags timeout; timeout 30m; }'
## Создайте список ловушек-хонейпотов
sudo nft add set ip filter honeypot '{ type ipv4_addr; flags timeout; timeout 1d; }'
## Создайте белый список с поддержкой CIDR
sudo nft add set ip filter trusted '{ type ipv4_addr; flags interval; }'
sudo nft add element ip filter trusted '{ 10.0.0.0/8, 192.168.0.0/16 }'
2. Настройте NGINX
load_module modules/ngx_http_nftset_access_module.so;
http {
server {
listen 80;
# Блокировать известные плохие IP (формат: table:setname)
nftset_blacklist filter:bad_guys;
# Ограничение скорости: 100 запросов в минуту
nftset_ratelimit rate=100 window=60s autoban=filter:ratelimited;
# Ваш контент
location / {
root /var/www/html;
}
# Ловушка-хонейпот - по умолчанию возвращает 404
location /wp-admin.php {
nftset_autoadd filter:honeypot timeout=86400;
}
# Конечная точка метрик
location /metrics {
nftset_metrics;
allow 127.0.0.1;
deny all;
}
}
}
3. Протестируйте и перезагрузите
sudo nginx -t && sudo nginx -s reload
📦 Установка
Этот модуль доступен исключительно через GetPageSpeed Premium Repository.
Шаг 1: Подпишитесь на репозиторий GetPageSpeed
Посетите GetPageSpeed Repository Subscription, чтобы получить доступ.
Шаг 2: Установите репозиторий
## RHEL/CentOS/Rocky/Alma Linux 8+
sudo dnf install https://extras.getpagespeed.com/release-latest.rpm
Шаг 3: Установите модуль
sudo dnf install nginx-module-nftset-access
Шаг 4: Включите модуль
Добавьте в /etc/nginx/nginx.conf перед любыми блоками http {}:
load_module modules/ngx_http_nftset_access_module.so;
Шаг 5: Перезагрузите NGINX
sudo nginx -t && sudo systemctl reload nginx
📖 Справочник по конфигурации
Формат спецификации набора
Все директивы, которые ссылаются на наборы nftables, используют формат: table:setname
table— Имя таблицы nftables (например,filter,firewalld)setname— Имя набора в этой таблице
Семейство IP (ip для IPv4, ip6 для IPv6) автоопределяется по IP-адресу клиента.
Примеры:
nftset_blacklist filter:blocklist; # IPv4 клиент → ip filter blocklist
# IPv6 клиент → ip6 filter blocklist
nftset_whitelist filter:trusted;
nftset_autoadd filter:honeypot timeout=3600;
Контроль доступа
nftset_blacklist table:set1 [table:set2 ...]
Контекст: http, server
По умолчанию: —
Блокирует запросы, если IP клиента появляется в любом из перечисленных наборов nft. Несколько наборов проверяются по порядку, пока не будет найдено совпадение.
## Один набор
nftset_blacklist filter:bad_guys;
## Несколько наборов (логика ИЛИ - заблокировано, если в ЛЮБОМ наборе)
nftset_blacklist filter:spammers filter:hackers filter:tor_exits;
## Отключить
nftset_blacklist off;
nftset_whitelist table:set1 [table:set2 ...]
Контекст: http, server
По умолчанию: —
Разрешает запросы только если IP клиента появляется хотя бы в одном из перечисленных наборов nft. Все остальные IP отклоняются.
## Разрешить только доверенные IP
nftset_whitelist filter:trusted_partners filter:office_ips;
Важно: IP в белом списке обходят все ограничения модуля, включая:
- Ограничение скорости (nftset_ratelimit)
- JavaScript-вызовы (nftset_challenge)
Это полезно для IP администраторов, которые не должны подлежать ограничениям по скорости или вызовам:
## IP администраторов обходят ограничения по скорости и вызовы
nftset_whitelist filter:admin_ips;
nftset_ratelimit rate=100 window=1m autoban=filter:ratelimited ban_time=1800;
nftset_challenge on;
nftset_status code
Контекст: http, server
По умолчанию: 403
HTTP код состояния, возвращаемый при блокировке запроса.
nftset_status 403; # Запрещено (по умолчанию)
nftset_status 444; # Закрыть соединение без ответа (специальный NGINX)
nftset_status 429; # Слишком много запросов
nftset_status 503; # Сервис недоступен
Кэширование и производительность
nftset_cache_ttl time
Контекст: http, server
По умолчанию: 60s
Как долго кэшировать результаты поиска наборов nft. Кэшированные результаты избегают повторных вызовов ядра для одного и того же IP.
nftset_cache_ttl 30s; # 30 секунд
nftset_cache_ttl 5m; # 5 минут
nftset_cache_ttl 1h; # 1 час
Примечание по отладке: Если вы удаляете IP из набора nft, но модуль все еще сообщает, что он "совпадает", это связано с кэшированием. Кэшированный результат истечет после установленного TTL. Для немедленного эффекта во время тестирования вы можете временно установить nftset_cache_ttl 0;, чтобы отключить кэширование (не рекомендуется для производства из-за влияния на производительность).
Влияние на производительность:
- Более высокий TTL = лучшая производительность, но медленнее отражает изменения в наборах nft
- Более низкий TTL = более быстрая реакция на изменения в наборах nft, но больше вызовов ядра
- Рекомендуется: 30s до 5m для большинства случаев использования
nftset_fail_open on|off
Контекст: http, server
По умолчанию: off
Управляет поведением, когда поиск набора nft не удался (например, набор не существует).
nftset_fail_open off; # Запретить при ошибке (безопасно, по умолчанию)
nftset_fail_open on; # Разрешить при ошибке (доступно, но рискованно)
nftset_dryrun on|off
Контекст: http, server
По умолчанию: off
Когда включено, регистрирует, что было бы заблокировано, но на самом деле не блокирует. Идеально для тестирования новых правил в производстве.
nftset_dryrun on; # Логировать, но не блокировать
Проверьте логи на наличие сообщений, таких как:
nftset: DRYRUN would block 1.2.3.4 (matched: filter:bad_guys)
Важно: При использовании переменных $nftset_result и $nftset_matched_set в режиме пробного запуска эти значения отражают состояние на момент обработки запроса, а не текущее состояние набора nft. Если вы позже проверите набор nft вручную и не найдете IP, возможные причины включают:
- Истечение тайм-аута: IP был добавлен с тайм-аутом (например,
timeout 1d) и с тех пор истек - Задержка кэша: Модуль кэширует результаты поиска (по умолчанию 60s). Запись, удаленная из набора nft, может все еще отображаться как "совпадающая", пока кэш не истечет
- Ручное удаление: Кто-то или что-то (fail2ban, скрипты) удалило запись
Это ожидаемое поведение — пробный запуск показывает вам именно то, что увидит производство во время запроса.
Ограничение скорости
nftset_ratelimit параметры
Контекст: http, server
По умолчанию: —
Ограничивает запросы на IP в пределах временного окна. Может автоматически добавлять нарушителей в набор nft.
Параметры:
| Параметр | Обязательный | Описание |
|---|---|---|
rate=N |
Да | Максимальное количество запросов за окно |
window=TIME |
Нет | Временное окно (по умолчанию: 60s) |
autoban=TABLE:SET |
Нет | набор nft для добавления нарушителей |
ban_time=N |
Нет | Секунды до авто-истечения (по умолчанию: 3600) |
Примеры:
## Основной: 100 запросов в минуту
nftset_ratelimit rate=100;
## С настраиваемым окном: 1000 запросов в час
nftset_ratelimit rate=1000 window=1h;
## С авто-блокировкой: Добавить нарушителей в набор nft на 30 минут
nftset_ratelimit rate=60 window=1m autoban=filter:ratelimited ban_time=1800;
## Строгая защита API
nftset_ratelimit rate=10 window=1s autoban=filter:api_abusers ban_time=3600;
Как это работает:
1. Каждый IP получает счетчик запросов и время начала окна
2. Счетчик увеличивается при каждом запросе
3. Когда окно истекает, счетчик сбрасывается
4. Если счетчик превышает rate, возвращается 429 Too Many Requests
5. Если установлен autoban, IP добавляется в указанный набор nft
Примечание: Состояние ограничения скорости хранится в общей памяти и сохраняется при перезапусках рабочих процессов.
JavaScript Challenge
nftset_challenge on|off
Контекст: http, server
По умолчанию: off
Включает режим вызова JavaScript. Браузеры должны решить задачу на выполнение, чтобы получить доступ к сайту. Эффективно против автоматизированных ботов и скрейперов.
nftset_challenge on;
Как это работает:
1. Первый запрос получает страницу вызова (HTTP 503)
2. Браузер выполняет JavaScript, который решает задачу хеширования
3. Решение сохраняется в куки (_nftset_verified)
4. Последующие запросы с действительными куки проходят
5. Куки истекают через 24 часа
nftset_challenge_difficulty level
Контекст: http, server
По умолчанию: 2
Управляет сложностью вызова (1-8). Чем выше = дольше время решения.
| Уровень | Приблизительное время решения |
|---|---|
| 1 | ~100ms |
| 2 | ~500ms (по умолчанию) |
| 3 | ~1 секунда |
| 4 | ~2 секунды |
| 5 | ~5 секунд |
| 6+ | ~10+ секунд |
nftset_challenge on;
nftset_challenge_difficulty 3; # ~1 секунда времени решения
Особенности страницы вызова: - Современный, адаптивный дизайн - Анимированный индикатор загрузки - Обратная связь о прогрессе - Авто-перенаправление при успехе - Без внешних зависимостей
Авто-добавление ловушки-хонейпота
nftset_autoadd table:setname [table:setname2 ...] [timeout=seconds] [status=code]
Контекст: server, location
По умолчанию: —
Автоматически добавляет IP клиента в указанные наборы nft, когда доступ к местоположению осуществляется и возвращается HTTP код состояния. Идеально для ловушек-хонейпотов.
Параметры:
| Параметр | Обязательный | Описание |
|---|---|---|
| table:setname | Да | Целевой набор nft (можно указать несколько) |
timeout=N |
Нет | Тайм-аут записи в секундах |
status=N |
Нет | HTTP код состояния для возврата (по умолчанию: 404) |
Примеры:
## Основной: Добавить в набор хонейпота и вернуть 404 (по умолчанию)
location /config.php {
nftset_autoadd filter:honeypot;
}
## С тайм-аутом: Авто-истечение через 24 часа
location /wp-admin.php {
nftset_autoadd filter:scanners timeout=86400;
}
## Вернуть 403 Запрещено вместо 404
location /admin.php {
nftset_autoadd filter:honeypot timeout=86400 status=403;
}
## Добавить в несколько наборов (IPv4 и IPv6)
location /trap {
nftset_autoadd filter:honeypot4 filter:honeypot6 timeout=86400;
}
Общие пути ловушек-хонейпотов:
## Ловушки WordPress - вернуть 404, чтобы выглядеть как отсутствующий файл
location ~ ^/(wp-admin\.php|wp-login\.php|xmlrpc\.php)$ {
nftset_autoadd filter:honeypot timeout=86400;
}
## Ловушки конфигурационных файлов - вернуть 403, чтобы смоделировать запрещенный доступ
location ~ ^/(\.env|config\.php|phpinfo\.php)$ {
nftset_autoadd filter:honeypot timeout=86400 status=403;
}
## Ловушки оболочки/эксплойтов - серьезные, блокировать на 1 неделю
location ~ ^/(shell|cmd|eval|exec)\.php$ {
nftset_autoadd filter:malicious timeout=604800 status=403;
}
Примечание: Когда IP автоматически добавляется, модуль немедленно возвращает указанный HTTP код состояния (по умолчанию 404), предотвращая дальнейшую обработку запроса. Также отключается поддержка keep-alive соединения, чтобы предотвратить дальнейшие запросы по тому же соединению.
Наблюдаемость
nftset_stats
Контекст: location
По умолчанию: —
Включает конечную точку статистики в формате JSON.
location = /_stats {
nftset_stats;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Смотрите JSON Stats API для формата ответа.
nftset_metrics
Контекст: location
По умолчанию: —
Включает конечную точку метрик Prometheus.
location = /metrics {
nftset_metrics;
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
}
Смотрите Prometheus Metrics для доступных метрик.
📝 Переменные NGINX
Модуль предоставляет две переменные для использования в логировании, заголовках или условных операторах.
$nftset_result
Решение о доступе, принятое для этого запроса.
| Значение | Описание |
|---|---|
allow |
Запрос разрешен |
deny |
Запрос заблокирован |
dryrun |
Было бы заблокировано (режим пробного запуска) |
ratelimited |
Превышен лимит скорости |
challenged |
Страница вызова обслужена |
$nftset_matched_set
Имя набора nft, который совпал (если есть), в формате table:setname. Пусто, если совпадений нет.
Примечание: Эта переменная отражает состояние совпадения в момент запроса, а не текущее состояние набора nft. Если вы позже проверите набор nft вручную и не найдете IP: - Запись могла истечь (наборы nft поддерживают тайм-ауты для каждой записи) - Кэш модуля (по умолчанию 60s) может показывать недавно удаленную запись как все еще совпадающую - Что-то могло удалить запись после обработки запроса
Примеры использования
Пользовательский журнал доступа:
log_format security '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'nftset_result="$nftset_result" '
'matched_set="$nftset_matched_set"';
access_log /var/log/nginx/security.log security;
Добавить заголовки для отладки:
add_header X-NFTSet-Result $nftset_result always;
add_header X-NFTSet-Matched $nftset_matched_set always;
Условное логирование:
## Логировать только заблокированные запросы
map $nftset_result $loggable {
"deny" 1;
default 0;
}
access_log /var/log/nginx/blocked.log combined if=$loggable;
📊 Метрики Prometheus
Конечная точка /metrics возвращает метрики в формате экспозиции Prometheus.
Доступные метрики
## HELP nginx_nftset_requests_total Всего обработанных запросов
## TYPE nginx_nftset_requests_total counter
nginx_nftset_requests_total{result="checked"} 1234567
nginx_nftset_requests_total{result="allowed"} 1234000
nginx_nftset_requests_total{result="blocked"} 500
nginx_nftset_requests_total{result="error"} 67
## HELP nginx_nftset_cache_total Операции кэша
## TYPE nginx_nftset_cache_total counter
nginx_nftset_cache_total{result="hit"} 1200000
nginx_nftset_cache_total{result="miss"} 34567
## HELP nginx_nftset_cache_entries Текущие записи кэша
## TYPE nginx_nftset_cache_entries gauge
nginx_nftset_cache_entries 5432
## HELP nginx_nftset_autoadd_total Операции авто-добавления
## TYPE nginx_nftset_autoadd_total counter
nginx_nftset_autoadd_total{result="success"} 42
nginx_nftset_autoadd_total{result="failed"} 3
## HELP nginx_nftset_ratelimit_total События ограничения скорости
## TYPE nginx_nftset_ratelimit_total counter
nginx_nftset_ratelimit_total{action="triggered"} 156
nginx_nftset_ratelimit_total{action="autobanned"} 23
## HELP nginx_nftset_challenge_total События вызова
## TYPE nginx_nftset_challenge_total counter
nginx_nftset_challenge_total{result="issued"} 1000
nginx_nftset_challenge_total{result="passed"} 950
nginx_nftset_challenge_total{result="failed"} 50
## HELP nginx_nftset_uptime_seconds Время работы модуля
## TYPE nginx_nftset_uptime_seconds gauge
nginx_nftset_uptime_seconds 86400
Запросы для панели Grafana
Частота запросов по результату:
rate(nginx_nftset_requests_total[5m])
Частота блокировок:
rate(nginx_nftset_requests_total{result="blocked"}[5m])
Коэффициент попадания в кэш:
rate(nginx_nftset_cache_total{result="hit"}[5m]) /
(rate(nginx_nftset_cache_total{result="hit"}[5m]) + rate(nginx_nftset_cache_total{result="miss"}[5m]))
События ограничения скорости в минуту:
rate(nginx_nftset_ratelimit_total{action="triggered"}[1m]) * 60
📈 JSON Stats API
Конечная точка /_stats возвращает подробную статистику в формате JSON.
Формат ответа
{
"version": "3.0.0",
"uptime_seconds": 86400,
"requests": {
"checked": 1234567,
"allowed": 1234000,
"blocked": 500,
"errors": 67
},
"cache": {
"hits": 1200000,
"misses": 34567,
"entries": 5432,
"hit_rate": 97.20
},
"autoadd": {
"success": 42,
"failed": 3
},
"ratelimit": {
"triggered": 156,
"autobanned": 23
},
"challenge": {
"issued": 1000,
"passed": 950,
"failed": 50
}
}
Описания полей
| Поле | Описание |
|---|---|
version |
Версия модуля |
uptime_seconds |
Секунды с момента загрузки модуля |
requests.checked |
Всего обработанных запросов |
requests.allowed |
Запросы, которые прошли |
requests.blocked |
Запросы, которые были заблокированы |
requests.errors |
Ошибки поиска набора nft |
cache.hits |
Попадания в кэш (избежанные вызовы ядра) |
cache.misses |
Промахи в кэше (требуемые вызовы ядра) |
cache.entries |
Текущие кэшированные записи |
cache.hit_rate |
Процент попадания |
autoadd.success |
Успешные добавления хонейпота |
autoadd.failed |
Неудачные добавления хонейпота |
ratelimit.triggered |
Нарушения лимита скорости |
ratelimit.autobanned |
IP, автоматически добавленные в черный список |
challenge.issued |
Страницы вызова, обслуженные |
challenge.passed |
Успешно решенные вызовы |
challenge.failed |
Ошибки вызова |
🏗️ Архитектура
┌─────────────────────────────────────────────────────────────────────┐
│ ПОТОК ЗАПРОСОВ │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Входящий запрос │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Проверка │──── Превышен? ────▶ 429 + Авто-блокировка │
│ │ лимита │ │
│ └───────┬───────┘ │
│ │ ОК │
│ ▼ │
│ ┌───────────────┐ │
│ │ Проверка │──── Нет куки? ────▶ Обслужить JS задачу │
│ │ вызова │ │
│ └───────┬───────┘ │
│ │ Пройдено │
│ ▼ │
│ ┌───────────────┐ ┌─────────────┐ │
│ │ Проверка │────▶│ ПОПАДАНИЕ │────▶ Использовать кэшированный результат │
│ │ кэша │ └─────────────┘ │
│ └───────┬───────┘ │
│ │ ПРОМАХ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Запрос к │──── Контекст libnftables, локальный для потока │
│ │ nft (ядро) │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Сохранить в │ │
│ │ кэш │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Решение │──── Совпадение в черном списке? ────▶ Блокировать (403/444) │
│ │ │──── Промах в белом списке? ────▶ Блокировать (403/444) │
│ └───────┬───────┘ │
│ │ Разрешить │
│ ▼ │
│ ┌───────────────┐ │
│ │ Проверка │──── Совпадение местоположения? ────▶ Добавить в набор nft │
│ │ хонейпота │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ Продолжить к │
│ Обработчику контента │
│ │
├─────────────────────────────────────────────────────────────────────┤
│ ОБЩАЯ ПАМЯТЬ │
│ ┌────────────────┬─────────────────┬─────────────────────────────┐ │
│ │ Статистика │ Кэш LRU │ Ведра ограничения скорости │ │
│ │ (счетчики) │ (IP → Результат) │ (IP → Счетчик запросов) │ │
│ └────────────────┴─────────────────┴─────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
Макет памяти
| Компонент | Местоположение | Назначение |
|---|---|---|
| Контекст libnftables | Локальный для потока | Контекст для каждого рабочего процесса, чтобы избежать блокировок |
| Кэш поиска | Общая память | Кэш LRU сопоставлений IP→результат |
| Ведра ограничения скорости | Общая память | Счетчики запросов для каждого IP |
| Статистика | Общая память | Атомарные счетчики для метрик |
📚 Примеры
Пример 1: Основной черный список
## Создайте таблицу nft и набор
sudo nft add table ip filter
sudo nft add set ip filter blacklist '{ type ipv4_addr; }'
sudo nft add element ip filter blacklist '{ 1.2.3.4 }'
server {
listen 80;
nftset_blacklist filter:blacklist;
location / {
root /var/www/html;
}
}
Пример 2: API с ограничением скорости
server {
listen 80;
# Строгое ограничение скорости для API
nftset_ratelimit rate=100 window=1m autoban=filter:api_banned ban_time=3600;
# Разрешить только известным партнерам
nftset_whitelist filter:api_partners;
nftset_status 401;
location /api/ {
proxy_pass http://backend;
}
}
Пример 3: Полный стек безопасности
server {
listen 80 default_server;
# Уровень 1: Известные угрозы
nftset_blacklist filter:malware_ips filter:tor_exits filter:datacenter_ranges;
nftset_status 444;
nftset_cache_ttl 5m;
# Уровень 2: Ограничение скорости
nftset_ratelimit rate=60 window=1m autoban=filter:ratelimited ban_time=1800;
# Уровень 3: Вызов бота
nftset_challenge on;
nftset_challenge_difficulty 2;
# Реальный контент
location / {
root /var/www/html;
}
# Ловушки-хонейпоты - вернуть 404 (по умолчанию), чтобы выглядеть как отсутствующие файлы
location ~ ^/(wp-admin|phpmyadmin|admin)\.php$ {
nftset_autoadd filter:honeypot timeout=86400;
}
# Мониторинг
location = /metrics {
nftset_metrics;
allow 10.0.0.0/8;
deny all;
}
}
Пример 4: Тестирование в режиме пробного запуска
server {
listen 80;
# Тестирование новых правил без блокировки
nftset_blacklist filter:new_threat_list;
nftset_dryrun on;
location / {
root /var/www/html;
}
}
Проверьте логи:
tail -f /var/log/nginx/error.log | grep "DRYRUN"
Пример 5: Белый список CIDR (диапазоны сети)
## Создайте интервальный набор для диапазонов CIDR
sudo nft add table ip filter
sudo nft add set ip filter trusted '{ type ipv4_addr; flags interval; }'
sudo nft add element ip filter trusted '{ 192.168.1.0/24, 10.0.0.0/8 }'
## Версия для IPv6
sudo nft add table ip6 filter
sudo nft add set ip6 filter trusted6 '{ type ipv6_addr; flags interval; }'
sudo nft add element ip6 filter trusted6 '{ 2001:db8::/32 }'
server {
listen 80;
# Белый список целых сетей
nftset_whitelist filter:trusted;
location / {
root /var/www/html;
}
}
🔧 Устранение неполадок
Модуль не загружается
nginx: [emerg] dlopen() failed
Решение: Убедитесь, что NGINX был собран с --with-compat, и модуль был собран для той же версии NGINX.
Набор nft не найден
nftset: set 'filter:myset' does not exist
Решение: Создайте таблицу и набор nft перед запуском NGINX:
sudo nft add table ip filter
sudo nft add set ip filter myset '{ type ipv4_addr; }'
ПОДСКАЗКА: Список доступных наборов:
nft list sets
Доступ запрещен
nftset: kernel error
Решение: Рабочий процесс NGINX должен иметь возможность CAP_NET_ADMIN:
sudo setcap cap_net_admin+ep /usr/sbin/nginx
Отказы SELinux (RHEL/CentOS/AlmaLinux)
SELinux предотвращает использование /usr/sbin/nginx netlink_netfilter_socket
Решение: Установите включенный модуль политики SELinux:
cd selinux/
sudo ./install.sh
Или вручную:
## Проверить
semodule -l | grep nginx_nftset
Политика позволяет httpd_t (домен SELinux NGINX) использовать сокеты netlink_netfilter, необходимые для libnftables.
Высокое использование памяти
Решение: Уменьшите TTL кэша или ограничьте размер кэша в конфигурации общей памяти.
Ограничение скорости не работает
Решение: Убедитесь, что набор nft для авто-блокировки существует и поддерживает тайм-аут:
sudo nft add table ip filter
sudo nft add set ip filter ratelimited '{ type ipv4_addr; flags timeout; timeout 1h; }'
Лог показывает "matched=table:setname", но IP не в наборе nft
Это ожидаемое поведение. Модуль сообщает то, что он увидел в момент запроса. Если вы позже проверите набор nft и не найдете IP:
-
Истечение тайм-аута: IP был добавлен с тайм-аутом и с тех пор истек
# Проверьте флаги набора nft list set ip filter setname # Ищите "flags timeout" в выводе -
Кэш модуля: Модуль кэширует результаты поиска (по умолчанию 60s). Недавно удаленный IP может все еще отображаться как "совпадающий"
# Временно отключите кэш для отладки (не для производства!) nftset_cache_ttl 0; -
Запись была удалена: fail2ban, скрипты или ручные команды могли удалить ее
-
Проблема с конфигурацией ловушки: Если вы используете ловушки-хонейпоты с
nftset_autoadd, законные боты могли сработать на ловушках. Проверьте, чтобы ваши ловушки не пересекались с легитимными путями ботов (например, карты сайта, robots.txt). Используйтеrobots.txt, чтобы исключить пути ловушек из обхода.
autoadd не удается с ошибкой тайм-аута
Это означает, что вы используете timeout=N в nftset_autoadd, но набор был создан без поддержки тайм-аутов.
Решение: Воссоздайте набор nft с поддержкой тайм-аутов:
## Удалите и воссоздайте с флагом тайм-аута
sudo nft delete set ip filter honeypot
sudo nft add set ip filter honeypot '{ type ipv4_addr; flags timeout; timeout 1d; }'
🔄 Миграция с ipset-access
Если вы мигрируете с более старого ngx_http_ipset_access_module, выполните следующие шаги:
1. Преобразуйте ipset в наборы nft
## Старый ipset
ipset create bad_guys hash:ip timeout 86400
## Новый эквивалент набора nft
nft add table ip filter
nft add set ip filter bad_guys '{ type ipv4_addr; flags timeout; timeout 1d; }'
## Для диапазонов CIDR (hash:net → флаг interval)
## Старый: ipset create networks hash:net
## Новый:
nft add set ip filter networks '{ type ipv4_addr; flags interval; }'
2. Обновите конфигурацию NGINX
| Старый (ipset) | Новый (nftset) |
|---|---|
ipset_blacklist bad_guys; |
nftset_blacklist filter:bad_guys; |
ipset_whitelist trusted; |
nftset_whitelist filter:trusted; |
ipset_autoadd honeypot timeout=3600; |
nftset_autoadd filter:honeypot timeout=3600; |
ipset_ratelimit rate=100 autoban=ratelimited; |
nftset_ratelimit rate=100 autoban=filter:ratelimited; |
ipset_challenge on; |
nftset_challenge on; |
ipset_challenge_difficulty 3; |
nftset_challenge_difficulty 3; |
ipset_dryrun on; |
nftset_dryrun on; |
ipset_fail_open on; |
nftset_fail_open on; |
ipset_cache_ttl 60s; |
nftset_cache_ttl 60s; |
ipset_status 403; |
nftset_status 403; |
ipset_stats; |
nftset_stats; |
ipset_metrics; |
nftset_metrics; |
$ipset_result |
$nftset_result |
$ipset_matched_set |
$nftset_matched_set |
3. Обновите форматы логов
## Старый
log_format security '... ipset_result="$ipset_result" matched_set="$ipset_matched_set"';
## Новый
log_format security '... nftset_result="$nftset_result" matched_set="$nftset_matched_set"';
4. Обновите запросы Prometheus/Grafana
| Старая метрика | Новая метрика |
|---|---|
nginx_ipset_requests_total |
nginx_nftset_requests_total |
nginx_ipset_cache_total |
nginx_nftset_cache_total |
nginx_ipset_cache_entries |
nginx_nftset_cache_entries |
nginx_ipset_autoadd_total |
nginx_nftset_autoadd_total |
nginx_ipset_ratelimit_total |
nginx_nftset_ratelimit_total |
nginx_ipset_challenge_total |
nginx_nftset_challenge_total |
nginx_ipset_uptime_seconds |
nginx_nftset_uptime_seconds |
5. Ключевые различия
| Функция | ipset-access | nftset-access |
|---|---|---|
| Бэкенд | libipset (ядро ipset) | libnftables (nftables) |
| Формат набора | setname |
table:setname |
| CIDR наборы | тип hash:net |
флаг flags interval |
| Семейство | Указано в типе набора | Автоопределяется по IP клиента |
| firewalld | только бэкенд iptables | совместимость с бэкендом nftables |
Почему мигрировать?
- Совместимость с RHEL 9/Rocky 9: firewalld по умолчанию использует бэкенд nftables
- Современная поддержка ядра: nftables — будущее брандмауэра Linux
- Единое управление: Используйте команды
nftкак для брандмауэра, так и для контроля доступа - Лучшая поддержка CIDR: Интервальные наборы эффективно обрабатывают диапазоны сети
📋 Требования
- NGINX ≥ 1.22 (собран с
--with-compat) - Ядро Linux с поддержкой nftables
- Библиотека и заголовки разработки libnftables
- Возможности:
CAP_NET_ADMINдля операций с nftables
📜 Лицензия
Это проприетарное программное обеспечение. Все права защищены.
Доступно исключительно через GetPageSpeed Premium Repository.
👤 Автор
Данила Верши́нин GetPageSpeed LLC
🆘 Поддержка
- Honeypot v2.0 Использование nftset-access для авто-блокировки ботов
- Поддержка: Доступно для премиум подписчиков
- Контакт: GetPageSpeed Support
Модуль доступа NGINX NFTSet
Премиум модуль NGINX от GetPageSpeed LLC
www.getpagespeed.com