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

nftset-access: Блокировка IP с нулевой задержкой с использованием наборов nftables в ядре Linux

Установка Debian/Ubuntu

Эти документы применимы к пакету APT nginx-module-nftset-access, предоставляемому репозиторием GetPageSpeed Extras.

  1. Настройте репозиторий APT, как описано в настройке репозитория APT.
  2. Установите модуль:
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. Блокируйте угрозы, ограничивайте злоумышленников, вызывайте ботов на проверку и защищайте свою инфраструктуру.

Version GetPageSpeed

⚠️ Коммерческое ПО Это модуль закрытого исходного кода, доступный исключительно через репозиторий 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, возможные причины включают:

  1. Истечение времени ожидания: IP был добавлен с таймаутом (например, timeout 1d) и с тех пор истек
  2. Задержка кэша: Модуль кэширует результаты запросов (по умолчанию 60с). Запись, удаленная из nft набора, может все еще отображаться как "совпадающая", пока кэш не истечет
  3. Ручное удаление: Кто-то или что-то (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:

  1. Истечение таймаута: IP был добавлен с таймаутом и с тех пор истек

    # Проверить флаги набора
    nft list set ip filter setname
    # Ищите "flags timeout" в выводе
    

  2. Кэш модуля: Модуль кэширует запросы (по умолчанию 60 секунд). Недавно удаленный IP может по-прежнему появляться как "matched"

    # Временно отключите кэш для отладки (не для производства!)
    nftset_cache_ttl 0;
    

  3. Запись была удалена: fail2ban, скрипты или командные строки могли её удалить

  4. Проблема конфигурации ловушки: Если вы используете ловушки 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

🆘 Поддержка

Модуль доступа NGINX NFTSet
Премиум модуль NGINX от GetPageSpeed LLC
www.getpagespeed.com