Белый список IP: как исключить доверенные адреса из блокировок в iptables, nftables, Fail2ban, Nginx и Cloudflare | AdminWiki

Белый список IP: как исключить доверенные адреса из блокировок в iptables, nftables, Fail2ban, Nginx и Cloudflare

24 сентября 2026 14 мин. чтения
Содержание статьи

Почему доверенные IP попадают под блокировки и как работает whitelist

Белый список IP (whitelist) - это правило, которое пропускает доверенный адрес раньше, чем срабатывает блокировка. В iptables и nftables пакет идёт по цепочке сверху вниз до первого совпадения (first-match), поэтому ACCEPT для администратора обязан стоять выше DROP и REJECT. Правило, добавленное в конец цепочки, не защищает: трафик до него уже отброшен.

Уровней фильтрации несколько. Запрос последовательно проходит Cloudflare, Nginx, Fail2ban и пакетный фильтр ядра. Исключение в Fail2ban не отменяет запрет в Nginx, а allow в Nginx бесполезен, если пакеты режет iptables. Whitelist настраивают на каждом уровне, где включена блокировка.

Схема обработки: Cloudflare → Nginx → Fail2ban → iptables/nftables. Чем ближе к ядру, тем меньше информации о запросе, но тем раньше отбрасывается трафик.

Для первичной диагностики хватает четырёх команд:

iptables -L -v -n
nft list ruleset
fail2ban-client status
tail -f /var/log/nginx/error.log

Команды и конфиги ниже рассчитаны на iptables-legacy и iptables-nft, nftables, Fail2ban 0.11+, Nginx 1.18+. Если firewall на сервере только планируется, начните с готовых конфигураций в материале про настройку файрвола на Linux-сервере.

Порядок обработки цепочек: почему ACCEPT должен быть выше DROP

Типичная ошибка выглядит так: сначала добавляют блокирующее правило, затем исключение для доверенного адреса.

iptables -A INPUT -j DROP
iptables -A INPUT -s 203.0.113.10 -j ACCEPT

Первый пакет от 203.0.113.10 попадёт под DROP и до ACCEPT не дойдёт. Флаг -A добавляет правило в конец цепочки, что для whitelist почти всегда неверно. Рабочий вариант - вставка первой строкой:

iptables -I INPUT 1 -s 203.0.113.10 -j ACCEPT

В nftables логика та же, но различаются операторы: insert ставит правило в начало цепочки, add - в конец.

nft insert rule inet filter input ip saddr 203.0.113.10 accept
nft add rule inet filter input ip saddr 203.0.113.10 accept

Проверьте фактический порядок и счётчики пакетов:

iptables -L INPUT -v -n --line-numbers
nft list chain inet filter input

Если счётчик у правила ACCEPT растёт, адрес проходит фильтр. Нулевой счётчик при активном трафике означает, что правило стоит после блокирующего и не применяется. Не используйте -A для whitelist, если точно не знаете текущий порядок строк в цепочке.

Уровни фильтрации: где именно блокируется IP

Прежде чем что-то настраивать, определите уровень блокировки. Симптом подсказывает, где искать.

СимптомУровеньГде смотреть
Нет ответа на ping, TCP-соединение не устанавливаетсяiptables/nftables или Cloudflareiptables -L -v -n, nft list ruleset, IP Access Rules
Соединение есть, ответ 403Nginxдирективы allow/deny, error.log
Ответ 429 при рабочих лимитахNginx limit_req или Cloudflare Rate Limitinglimit_req_zone, логи Cloudflare
SSH подключается и сразу рвётся, либо бан после нескольких попытокFail2banfail2ban-client banned, /var/log/fail2ban.log
Запрос не доходит до сервера, отдаётся страница CloudflareCloudflare WAFSecurity Events в панели

Whitelist на одном уровне не отменяет блокировку на другом. Какие инструменты блокировки применяются на практике и как они сочетаются, разобрано в статье про блокировку IP-адресов и практическую автоматизацию.

Whitelist в iptables: приоритет ACCEPT и готовые правила

Для одного адреса достаточно одной строки, вставленной в начало INPUT:

iptables -I INPUT 1 -s 203.0.113.10 -j ACCEPT

Для подсети администраторов:

iptables -I INPUT 1 -s 203.0.113.0/24 -j ACCEPT

Для нескольких адресов администраторов и систем мониторинга (Zabbix, Prometheus) вставьте каждое правило первой строкой. Порядок между самими whitelist-правилами не важен, важно, что все они выше блокирующих.

iptables -I INPUT 1 -s 203.0.113.10 -j ACCEPT
iptables -I INPUT 1 -s 203.0.113.11 -j ACCEPT
iptables -I INPUT 1 -s 198.51.100.0/24 -j ACCEPT

Проверьте, что правила встали наверх, и посмотрите счётчики:

iptables -L INPUT -v -n --line-numbers

Убедитесь, какой бэкенд используется в системе. В современных дистрибутивах команда iptables часто работает через nftables:

iptables --version

Если в выводе есть nf_tables, вы работаете с iptables-nft, и правила транслируются в nftables. Это важно учитывать при отладке, потому что часть правил может приходить из чужих цепочек.

Правила живут до перезагрузки. Сохраните их подходящим для дистрибутива способом:

iptables-save > /etc/iptables/rules.v4
service iptables save
netfilter-persistent save

Первая команда подходит для Debian/Ubuntu с netfilter-persistent, вторая - для классических RHEL/CentOS. Без сохранения whitelist исчезнет после reboot вместе со всей конфигурацией.

Fail2ban добавляет свои цепочки (например, f2b-sshd) и вызывает их из INPUT. Правило ACCEPT в INPUT, стоящее выше вызова этих цепочек, пропускает адрес и мимо банов, но корректнее исключать адрес в самом Fail2ban через ignoreip.

Как проверить, что whitelist срабатывает раньше блокировки

Проверка строится на трёх шагах. Сначала убедитесь, что правило на месте и стоит первым:

iptables -L INPUT -v -n --line-numbers | head
nft list chain inet filter input

Затем посмотрите счётчик конкретного адреса:

iptables -L -v -n | grep 203.0.113.10

Дальше проверьте доступ с доверенной машины:

curl -I https://example.com
ssh admin@example.com

Если обе проверки проходят, whitelist в пакетном фильтре работает. Если curl отдаёт 403, а SSH работает, блокировка находится в Nginx, а не в iptables. Если не проходит SSH, ищите бан Fail2ban или правило DROP выше вашего ACCEPT.

Whitelist в nftables: синтаксис и порядок правил

В nftables whitelist добавляют оператором insert, чтобы правило оказалось в начале цепочки:

nft insert rule inet filter input ip saddr 203.0.113.10 accept
nft insert rule inet filter input ip saddr 203.0.113.0/24 accept

Несколько адресов можно перечислить в одном правиле через множество:

nft insert rule inet filter input ip saddr { 203.0.113.10, 203.0.113.11 } accept

Оператор add добавляет правило в конец цепочки и для whitelist опасен тем же, чем -A в iptables. Если нужно поставить правило в конкретную позицию, nftables позволяет сослаться на handle существующего правила: insert rule с position вставляет новое правило перед указанным, add rule с position - после него.

nft insert rule filter output position 8 ip daddr 127.0.0.8 drop

Проверить порядок и убедиться, что правило первое:

nft list chain inet filter input
nft list ruleset

Имена таблицы и цепочки зависят от дистрибутива и активного firewall. Встречаются inet filter input, inet firewalld filter_INPUT и другие. Перед вставкой правила выполните nft list ruleset и уточните фактические названия, иначе команда вернёт ошибку No such file or directory.

Сохранение между перезагрузками:

nft list ruleset > /etc/nftables.conf
systemctl enable --now nftables

Как избежать конфликта iptables и nftables

Определите, какой инструмент реально управляет фильтром:

iptables --version
update-alternatives --display iptables
nft list ruleset

При бэкенде iptables-nft команды iptables транслируются в правила nftables, поэтому iptables -L и nft list ruleset показывают одни и те же данные в разном виде. Прямые nftables-правила и цепочки от iptables сосуществуют, но разобраться в приоритетах между ними сложно.

Практическое правило: выберите один инструмент для управления фильтром на сервере. Смешение iptables и прямых правил nftables на одной машине приводит к ситуации, когда whitelist добавлен, счётчик растёт, а блокировка всё равно срабатывает из цепочки, о которой вы забыли.

Fail2ban: параметр ignoreip и проверка исключений

Fail2ban исключает адреса параметром ignoreip. Готовый фрагмент /etc/fail2ban/jail.local:

[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 203.0.113.10 203.0.113.0/24
bantime = 1h
findtime = 10m
maxretry = 4

[sshd]
enabled = true

[nginx-http-auth]
enabled = true

В ignoreip перечисляют отдельные адреса, подсети в нотации CIDR и адреса IPv6 через пробел. Локальный адрес и IPv6 loopback стоит оставить всегда, иначе сервисы на самом хосте начнут банить себя.

Проверка, что адрес попал в исключения:

fail2ban-client status sshd
fail2ban-client banned
fail2ban-client set sshd unbanip 203.0.113.10
fail2ban-client reload

В выводе fail2ban-client status sshd есть блок Ignored IP, и ваши адреса должны быть в нём. Команда fail2ban-client banned показывает текущие баны по всем jail. Если адрес уже забанен, снимите бан вручную и только потом проверяйте ignoreip. После правки конфига перезагрузите Fail2ban: reload применяет изменения без полного перезапуска.

Проверить, какие строки лога вообще попадают под фильтр, помогает fail2ban-regex с указанием файла лога и фильтра. Это отделяет проблему с ignoreip от проблемы с ложными срабатываниями фильтра.

ignoreip не отменяет блокировки на уровне iptables и nftables. Если Fail2ban пишет свои правила в пакетный фильтр, а перед ним стоит ваш DROP, доверенный адрес всё равно не пройдёт. Настраивайте исключения на обоих уровнях.

Глобальный и локальный ignoreip: что выбрать

Список в секции [DEFAULT] действует для всех jail сразу. Параметры из [DEFAULT] можно переопределить для конкретного jail как опции спецификации действия в этом jail. Практический вывод: если задать ignoreip внутри отдельного jail, для него начнёт действовать именно этот список, а не общий. Поэтому при дублировании одного адреса в [sshd] остальные адреса из [DEFAULT] для этого jail перестанут учитываться.

Схема, которая не ломается при росте конфига: общий список доверенных адресов держите в [DEFAULT], а внутри jail добавляйте только специфичные адреса и дублируйте общий перечень целиком. Например, [nginx-http-auth] с ignoreip = 127.0.0.1/8 ::1 203.0.113.10 203.0.113.0/24 198.51.100.5.

Nginx: allow/deny и защита от блокировок на уровне веб-сервера

Директивы allow и deny обрабатываются в порядке следования. Доверенные адреса перечисляют выше deny all:

location /admin {
    allow 203.0.113.10;
    allow 203.0.113.0/24;
    deny all;
}

Если deny all поставить первым, доверенный адрес получит 403, потому что совпадение уже найдено. Проверка конфига и результата:

nginx -t
curl -I https://example.com/admin

Отдельный случай - лимиты запросов. Модуль limit_req и директива limit_conn не смотрят на allow/deny и режут трафик по частоте. Админский адрес или система мониторинга легко попадает под 429 при выгрузке метрик или массовой проверке доступности. Исключение строится через карту, где доверенной подсети присваивается пустой ключ:

geo $limited {
    default 1;
    203.0.113.0/24 0;
}

map $limited $limit_key {
    0 "";
    1 $binary_remote_addr;
}

limit_req_zone $limit_key zone=api:10m rate=10r/s;

Пустой ключ в limit_req_zone означает, что лимит для этого адреса не применяется - это штатное поведение nginx, а не обходной приём. Как лимиты сочетаются с фильтрацией на сетевом уровне, показано в руководстве по многоуровневой защите от DDoS.

Как учесть реальный IP за Cloudflare в Nginx

За Cloudflare в $remote_addr окажется адрес edge-сервера, а не адрес администратора. Директивы allow/deny в этом случае сработают не по тому IP. Включите модуль realip и укажите, каким подсетям доверять:

set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
real_ip_header CF-Connecting-IP;

Подсети в примере приведены выборочно, полный и актуальный перечень публикует Cloudflare в официальной документации и отдаёт по API. Список меняется, поэтому его стоит обновлять по расписанию, а не переносить один раз: если его «вписать и забыть», realip перестанет работать или начнёт отбрасываться легитимный трафик из новых диапазонов.

При real_ip_recursive on Nginx идёт по цепочке forwarded-адресов справа налево и выбирает последний адрес, не входящий в доверенный диапазон прокси. Это полезно, когда перед Cloudflare стоит ещё один прокси.

Проверка: добавьте в формат лога обе переменные и сравните значения при заходе с доверенного адреса.

log_format debug '$http_cf_connecting_ip $remote_addr $request';

После корректной настройки realip значение $remote_addr совпадёт с реальным адресом клиента, и allow/deny начнут работать предсказуемо.

Cloudflare: IP Access Rules и обход блокировок

Whitelist на периметре Cloudflare настраивают двумя способами: IP Access Rules с действием Allow и Custom Rules в WAF с действием Skip.

IP Access Rules позволяют создавать allowlist, block и challenge по IP-адресу, ASN или стране посетителя. Allow для IP или ASN обходит настроенные custom rules, rate limiting rules, WAF Managed Rules и firewall rules (deprecated). Правило добавляют в разделе безопасности панели: адрес или подсеть плюс действие Allow. Подробнее об этом - в документации Cloudflare по IP Access Rules.

Важная оговорка: Cloudflare рекомендует вместо IP Access Rules использовать custom rules для IP- или гео-блокировок. При переходе на custom rules действие block из IP Access Rules стоит заменять на действие block, которое не обходит все средства защиты приложений Cloudflare. То есть Allow в IP Access Rules - это широкое исключение, и применять его нужно осознанно.

Rate limiting rules оцениваются по порядку, и некоторые действия, например block, останавливают оценку других правил. Поэтому проверяйте Rate Limiting отдельно: если админский скрипт генерирует много запросов, счётчик лимита может продолжить расти, и адрес попадёт под 429. Порядок оценки описан в документации Cloudflare по rate limiting rules.

Второй вариант - Custom Rule в WAF с выражением по адресу и действием Skip для оставшихся правил. Так исключение обходит и managed-наборы, которые вы не контролируете напрямую:

ip.src eq 203.0.113.10

Любые настройки Cloudflare не отменяют фильтрацию на origin. Трафик, дошедший до сервера, продолжат проверять Nginx и iptables. Сравнение периметровых решений смотрите в статье про геофильтрацию в Cloudflare, AWS WAF и Nginx.

Cloudflare Access и Tunnel как альтернатива whitelist

Статический список IP плохо подходит администраторам с динамическими адресами и сотрудникам на домашнем интернете. Вместо расширения whitelist закройте админские пути аутентификацией: Cloudflare Access проверяет вход через SSO, и IP-адрес перестаёт быть фактором доступа.

Cloudflare Tunnel убирает необходимость открывать входящие порты на сервере. Типовая последовательность команд:

cloudflared tunnel create admin-wiki
cloudflared tunnel route dns admin-wiki admin.example.com
cloudflared tunnel run admin-wiki

Ограничение честное: системы мониторинга обычно не проходят SSO, и для них whitelist по IP остаётся рабочим вариантом. Для Cloudflare Access это значит, что исключения по адресу всё равно придётся держать для Zabbix, Prometheus и подобных агентов.

Типичные ошибки: почему белый список не работает

Пять причин закрывают почти все случаи, когда правило добавлено, но доверенный адрес всё равно блокируется.

  1. Правило ACCEPT добавлено в конец цепочки. Флаг -A в iptables и оператор add в nftables ставят его после блокирующих правил. Исправление: iptables -I INPUT 1 или nft insert rule inet filter input.
  2. Конфликт iptables и nftables. На сервере с бэкендом iptables-nft правила живут в двух представлениях, и блокировка приходит из цепочки, которую не видно в выводе iptables -L. Проверьте iptables --version и nft list ruleset.
  3. ignoreip не сработал. Причины: адрес продублирован в jail и перекрыл глобальный список, опечатка в CIDR, конфиг не перезагружен. Проверьте fail2ban-client status sshd и /var/log/fail2ban.log.
  4. В Nginx deny all стоит выше allow. Порядок директив внутри location и server решает результат, первое совпадение выигрывает.
  5. IP заблокирован на периметре, а whitelist настроен только на сервере. Запрос не доходит до Nginx, поэтому в логах его нет. Смотрите IP Access Rules, WAF и Rate Limiting в панели Cloudflare.

Чек-лист диагностики: где именно блокируется IP

  1. С доверенного адреса выполните ping и curl -I. Отсутствие ответа указывает на сетевой уровень или периметр, ответ 403 или 429 - на прикладной.
  2. Проверьте пакетный фильтр: iptables -L -v -n --line-numbers, nft list ruleset. Смотрите счётчики у блокирующих правил.
  3. Проверьте Fail2ban: fail2ban-client status, fail2ban-client banned, лог /var/log/fail2ban.log.
  4. Проверьте логи веб-сервера: tail -f /var/log/nginx/error.log и access.log. Если запроса нет, блокировка выше Nginx.
  5. Проверьте периметр: IP Access Rules, Custom Rules WAF, Rate Limiting и Security Events.
  6. Снимите трафик на интерфейсе: tcpdump -i eth0 host 203.0.113.10. Наличие SYN без ответа подтверждает отброс на сетевом уровне.

Безопасность whitelist: как не открыть лишнего

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

Ограничение по портам для системы мониторинга выглядит так:

iptables -I INPUT 1 -s 203.0.113.10 -p tcp --dport 10050 -j ACCEPT

Адрес Zabbix-сервера получает доступ только к агенту на порту 10050, а не ко всем сервисам. Такой же подход применяйте к Prometheus, сборщикам логов и CI/CD-раннерам.

Не добавляйте 0.0.0.0/0 и не расширяйте подсети без причины. Каждый лишний диапазон - это чужие хосты, которые получат ваши привилегии при смене владельца адреса.

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

Храните перечень доверенных адресов в git или в ролях Ansible, а не только в живых правилах на сервере. Так список не потеряется при переустановке, а изменения проходят ревью. Общая рамка работы с доступом на сервере описана в руководстве по управлению доступом и защите Linux-сервера.

Как защитить whitelist от компрометации

Адрес из whitelist получает доступ в обход защиты. Если машину администратора скомпрометировали, злоумышленник наследует это доверие. Логирование попаданий даёт заметить аномалии:

iptables -I INPUT 1 -s 203.0.113.10 -j LOG --log-prefix "WHITELIST: "

Правило LOG ставят рядом с ACCEPT, чтобы видеть объём трафика с доверенных адресов. Всплеск в нерабочее время или нехарактерные порты - повод проверить машину.

Для админских путей в Nginx добавьте второй слой: basic auth, клиентские сертификаты или auth_request к SSO. Тогда одного IP для доступа недостаточно. В Cloudflare предпочтительнее Access вместо статического списка: он проверяет пользователя, а не адрес.

Раз в квартал пересматривайте список: iptables -L -v -n, nft list ruleset, fail2ban-client status, конфиги Nginx. Правило ACCEPT с нулевым счётчиком пакетов за месяц стоит удалить.

Чек-лист: настройка whitelist на всех уровнях

  1. Соберите список доверенных адресов: администраторы, системы мониторинга, CI/CD, офисные VPN.
  2. iptables или nftables: добавьте ACCEPT первой строкой INPUT, проверьте iptables -L INPUT -v -n --line-numbers.
  3. Fail2ban: пропишите ignoreip в /etc/fail2ban/jail.local и примените fail2ban-client reload.
  4. Nginx: поставьте allow выше deny all, при работе за Cloudflare включите realip и real_ip_header CF-Connecting-IP.
  5. Cloudflare: добавьте IP Access Rules с действием Allow или Custom Rule WAF со Skip, отдельно проверьте Rate Limiting.
  6. Проверьте доступ с доверенного адреса: ping, curl -I, ssh.
  7. Проверьте логи всех уровней: iptables -L -v -n, fail2ban-client status, /var/log/nginx/error.log, Security Events.
  8. Сохраните правила: iptables-save, nft list ruleset > /etc/nftables.conf, конфиги в git или Ansible.
  9. Запланируйте аудит списка и удаление адресов, по которым нет трафика.

Главное правило остаётся неизменным: whitelist должен обрабатываться раньше блокирующих правил на каждом уровне. Проверяйте это счётчиками пакетов и логами, а не по памяти.

Поделиться:
Сохранить гайд? В закладки браузера