nftset-access: Блокировка IP с нулевой задержкой с использованием наборов nftables в ядре Linux
Установка Debian/Ubuntu
Эти документы применимы к пакету APT nginx-module-nftset-access, предоставляемому репозиторием GetPageSpeed Extras.
- Настройте репозиторий APT, как описано в настройке репозитория APT.
- Установите модуль:
sudo apt-get update
sudo apt-get install nginx-module-nftset-access
Показать дистрибутивы и архитектуры
| Дистрибутив | Версия | Компонент | Архитектуры |
|-------------|-------------------|-------------|------------------|
| debian | bookworm | main | amd64, arm64 |
| debian | bookworm-mainline | main | amd64, arm64 |
| debian | trixie | main | amd64, arm64 |
| debian | trixie-mainline | main | amd64, arm64 |
| ubuntu | focal | main | amd64, arm64 |
| ubuntu | focal-mainline | main | amd64, arm64 |
| ubuntu | jammy | main | amd64, arm64 |
| ubuntu | jammy-mainline | main | amd64, arm64 |
| ubuntu | noble | main | amd64, arm64 |
| ubuntu | noble-mainline | main | amd64, arm64 |
Корпоративный IP-контроль доступа для NGINX с использованием наборов nftables Linux. Блокируйте угрозы, ограничивайте злоумышленников, вызывайте ботов на проверку и защищайте свою инфраструктуру.
⚠️ Коммерческое ПО Это модуль закрытого исходного кода, доступный исключительно через репозиторий GetPageSpeed.
Требование плана: Требуется план Pro подписки GetPageSpeed NGINX Extras.
✨ Возможности
Основные возможности
| Особенность | Описание |
|---|---|
| Белый/Чёрный список | Разрешение или запрет на основе членства в наборе nftables |
| Несколько наборов | Проверка по нескольким наборам nft в одной директиве |
| Оперативные обновления | Изменение наборов nft без перезагрузки NGINX |
| Пользовательские коды состояния | Возврат любого HTTP кода состояния при блокировке |
| Поддержка CIDR | Использование интервалов для сетевых диапазонов (например, 192.168.1.0/24) |
Возможности производительности
| Особенность | Описание |
|---|---|
| Сессии на поток | Локальные для потоков контексты libnftables устраняют конкуренцию за блокировки |
| Кэш LRU | Кэш в共享ной памяти с конфигурируемым временем жизни |
| Коэффициенты попаданий кэша | Обычно более 95% коэффициент попаданий снижает вызовы ядра |
Возможности безопасности
| Особенность | Описание |
|---|---|
| Ограничение по скорости | Ограничение запросов на IP с конфигурируемыми временными интервалами |
| Авто-бан | Автоматическое внесение в черный список нарушителей ограничений скорости |
| JS Челлендж | Задача на доказательство работы останавливает автоматические боты |
| Ловушки для меда | Авто-блокировка 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; }'
## Создание списка ловушек для honeypot
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.
Шаг 1: Подписаться на репозиторий GetPageSpeed
Перейдите по ссылке Подписка на репозиторий GetPageSpeed, чтобы получить доступ.
Шаг 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 фильтр блокировка
# IPv6 клиент → ip6 фильтр блокировка
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-адресов администраторов, которые не должны подвергаться лимитам по количеству запросов или проверкам:
```nginx
## Административные IP-адреса обходят ограничение скорости и вызовы
nftset_whitelist filter:admin_ips;
nftset_ratelimit rate=100 window=1m autoban=filter:ratelimited ban_time=1800;
nftset_challenge on;
nftset_status код
Контекст: http, server
По умолчанию: 403
HTTP статус код, возвращаемый, когда запрос заблокирован.
nftset_status 403; # Запрещено (по умолчанию)
nftset_status 444; # Закрыть соединение без ответа (специальный NGINX)
nftset_status 429; # Слишком много запросов
nftset_status 503; # Сервис недоступен
Кэширование и производительность
nftset_cache_ttl время
Контекст: 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 заблокирует 1.2.3.4 (совпадает: filter:bad_guys)
Важно: При использовании переменных $nftset_result и $nftset_matched_set в режиме dryrun эти значения отражают состояние на момент времени, когда запрос обрабатывался, а не текущее состояние nft набора. Если вы позже вручную проверите nft набор и не найдете IP, возможные причины включают:
- Истечение времени ожидания: IP был добавлен с таймаутом (например,
timeout 1d) и с тех пор истек - Задержка кэша: Модуль кэширует результаты запросов (по умолчанию 60с). Запись, удаленная из nft набора, может все еще отображаться как "совпадающая", пока кэш не истечет
- Ручное удаление: Кто-то или что-то (fail2ban, скрипты) удалило запись
Это ожидаемое поведение — dryrun показывает вам точно то, что продакшен увидит в момент запроса.
Ограничение скорости
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
#### `nftset_challenge` on|off
**Контекст:** `http`, `server`
**По умолчанию:** `off`
Включает режим вызова JavaScript challenge. Браузеры должны решить задачу с доказательством выполнения работы, чтобы получить доступ к сайту. Эффективно против автоматизированных ботов и скрейперов.
```nginx
nftset_challenge on;
Как это работает:
1. Первый запрос получает страницу с задачей (HTTP 503)
2. Браузер выполняет JavaScript, который решает задачу с хешем
3. Решение сохраняется в cookie (_nftset_verified)
4. Последующие запросы с действительным cookie проходят
5. Cookie истекает через 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 статус код. Идеально для ловушек honeypot.
Параметры:
| Параметр | Обязательный | Описание |
|---|---|---|
| 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;
}
## Shell/exploit traps - severe, блокировка на 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-наборы поддерживают таймауты для каждой записи) - Кэш модуля (по умолчанию 60 секунд) может показывать недавно удаленную запись как все еще совпадающую - Что-то могло удалить запись после обработки запроса
Примеры использования
Пользовательский лог доступа:
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
## ПОМОЩЬ nginx_nftset_cache_entries Текущие записи кэша
## TYPE nginx_nftset_cache_entries gauge
nginx_nftset_cache_entries 5432
## ПОМОЩЬ nginx_nftset_autoadd_total Авто-добавление операций
## TYPE nginx_nftset_autoadd_total счетчик
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
## ПОМОЩЬ 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
## ПОМОЩЬ Модуля nginx_nftset_uptime_seconds uptime
## TYPE nginx_nftset_uptime_seconds gauge
nginx_nftset_uptime_seconds 86400
Запросы для Grafana Dashboard
Скорость запросов по результату:
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 Статистика 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 |
Успешные добавления honeypot |
autoadd.failed |
Неудачные добавления honeypot |
ratelimit.triggered |
Нарушения лимита скорости |
ratelimit.autobanned |
IP-адреса, автоматически добавленные в список блокировок |
challenge.issued |
Обслуженные страницы вызова |
challenge.passed |
Успешно решенные вызовы |
challenge.failed |
Неудачи вызова |
| ## 🏗️ Архитектура |
┌─────────────────────────────────────────────────────────────────────┐
│ СТЕПЫ ЗАПРОСА │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ Входящий запрос │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Проверка │──── Превышен? ────▶ 429 + Автоблокировка │
│ │ скорости │ │
│ └───────┬───────┘ │
│ │ ОК │
│ ▼ │
│ ┌───────────────┐ │
│ │ Проверка │──── Нет cookie? ────▶ Показать JS головоломку │
│ │ проверки │ │
│ └───────┬───────┘ │
│ │ Пройдён │
│ ▼ │
│ ┌───────────────┐ ┌─────────────┐ │
│ │ Проверка │────▶│ ПОПАДАНИЕ │────▶ Использовать кэшированный результат │
│ │ кэша │ └─────────────┘ │
│ └───────┬───────┘ │
│ │ ПРОПУСК │
│ ▼ │
│ ┌───────────────┐ │
│ │ Запрос nft │──── Контекст libnftables локальный для потока │
│ │ (ядро) │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Сохранить в │ │
│ │ кэш │ │
│ └───────┬───────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ Решение │──── Совпадение в черном списке? ────▶ Блокировать (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 is preventing /usr/sbin/nginx from using netlink_netfilter_socket
Решение: Установите включенный модуль политики SELinux:
cd selinux/
sudo ./install.sh
Или вручную:
## Проверка
semodule -l | grep nginx_nftset
Политика позволяет httpd_t (домен SELinux NGINX) использовать сокеты netlink_netfilter, необходимые libnftables.
Высокое использование памяти
Решение: Уменьшите TTL кэша или ограничьте размер кэша в конфигурации общей памяти.
Ограничение скорости не работает
Решение: Убедитесь, что nft set для автоматической блокировки существует и поддерживает таймаут:
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 set
Это ожидаемое поведение. Модуль сообщает то, что он видел в момент запроса. Если вы позже проверите nft set и не найдете IP:
-
Истечение таймаута: IP был добавлен с таймаутом и с тех пор истек
# Проверить флаги набора nft list set ip filter setname # Ищите "flags timeout" в выводе -
Кэш модуля: Модуль кэширует запросы (по умолчанию 60 секунд). Недавно удаленный IP может по-прежнему появляться как "matched"
# Временно отключите кэш для отладки (не для производства!) nftset_cache_ttl 0; -
Запись была удалена: fail2ban, скрипты или командные строки могли её удалить
-
Проблема конфигурации ловушки: Если вы используете ловушки honeypot с
nftset_autoadd, легитимные боты могли активировать ловушки. Проверьте, что ваши места ловушек не пересекаются с легитимными путями ботов (такими как карты сайтов, robots.txt). Используйтеrobots.txt, чтобы исключить пути ловушек из обхода.
autoadd неудачен с ошибкой таймаута
Это означает, что вы используете timeout=N в nftset_autoadd, но nft set был создан без поддержки таймаута.
Решение: Воссоздайте nft set с поддержкой таймаута:
## Удалить и создать заново с флагом времени ожидания
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. Конвертируйте ipsets в 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 → флаг интервала)
## Старое: 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 | доступ к nftset |
|---|---|---|
| Бэкенд | libipset (ядро ipset) | libnftables (nftables) |
| Формат набора | setname |
table:setname |
| Наборы CIDR | тип hash:net |
флаги 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
Модуль доступа NGINX NFTSet
Премиум модуль NGINX от GetPageSpeed LLC
www.getpagespeed.com