Массовое снятие блокировок IP распадается на три независимые операции: удалить правила из iptables, вычистить элементы из наборов ipset и снять баны в Fail2ban. Единой команды «разблокировать всё» нет, потому что каждый инструмент хранит состояние отдельно и ничего не знает о содержимом соседнего.
Рабочий порядок такой: сначала снимаем бан в Fail2ban, чтобы он не вернул правило обратно, затем чистим ipset, затем удаляем оставшиеся правила iptables, и только потом сохраняем результат в persistent-файлы. Нарушите последовательность — и блокировка вернётся после первого перезапуска сервиса или перезагрузки сервера.
Ниже разбираем команды по каждому уровню, показываем, как применить изменения без разрыва активных сессий, и закрываем статью чек-листом проверки. Все примеры используют учебные адреса из диапазона 203.0.113.0/24, подставляйте свои.
Почему массовое снятие блокировок IP — это отдельная задача
Блокировка одного адреса обычно живёт на одном из трёх уровней, и выглядят они по-разному. Правило iptables видно в выводе iptables -L, элемент ipset лежит внутри именованного набора, а бан Fail2ban хранится в памяти демона и дублируется в его базе. Разблокировка «наугад» через iptables -F сносит всю цепочку целиком, включая правила, которые держат доступ к SSH.
| Уровень | Где хранится блокировка | Чем снимать | Что ломается при ошибке |
|---|---|---|---|
| iptables | Правило в цепочке INPUT, FORWARD, OUTPUT или DOCKER-USER | iptables -D по номеру или спецификации | Сдвиг нумерации, удаление чужого правила |
| ipset | Элемент внутри набора hash:ip или hash:net | ipset del или ipset flush | Осиротевшее правило iptables после destroy |
| Fail2ban | Бан-лист jail плюс действие (action), которое пишет в iptables или ipset | fail2ban-client set jail unbanip | Повторный бан после restart или reload |
Ключевая деталь: Fail2ban не хранит блокировку у себя. Он сканирует логи, а при срабатывании фильтра обновляет правила файрвола, чтобы отклонить IP нарушителя на заданное время, — и делает это через выбранное действие (action), чаще всего iptables или ipset. При разбане он удаляет запись тем же действием. Поэтому ручное удаление правила, которое поставил Fail2ban, приводит к рассинхрону: демон считает адрес забаненным, а в фильтре правила уже нет.
Три типовые ошибки массового снятия встречаются чаще остальных: потеря порядка правил при удалении по номерам, сброс счётчиков и конфликт с persistent-сохранением. Общий обзор стратегий блокировки и автоматизации собран в материале блокировка IP-адресов: стратегии, инструменты и практическая автоматизация, оттуда удобно взять контекст, если вы только выстраиваете защиту.
Удаление правил iptables: по номеру и по спецификации
У iptables есть ровно два способа удалить правило: по позиции в цепочке и по полной спецификации. Первый быстрее для одиночных правок, второй безопаснее для скриптов и продакшена.
Сначала посмотрите, что вообще происходит в цепочке. Ключ --line-numbers добавляет нумерацию, -n отключает обратное разрешение DNS, иначе вывод превратится в простыню из имён хостов.
iptables -L INPUT -n --line-numbers iptables -L INPUT -n --line-numbers | grep DROP
Строка вывода выглядит так: сначала номер, затем target, протокол, опции, источник и назначение. Если добавить -v или -x, порядок колонок сместится, поэтому в скриптах не привязывайтесь к номеру поля, фильтруйте по адресу через grep и берите первый столбец через awk.
Как удалить правило по номеру без сдвига нумерации
Удаление по номеру сдвигает все последующие правила вверх. Правило с номером 7 после удаления правила 5 займёт позицию 6. Если удалять в возрастающем порядке, второе обращение попадёт не туда.
iptables -D INPUT 12
Правильный подход: собрать все нужные номера заранее, отсортировать по убыванию и удалять с конца. Тогда сдвиг не влияет на оставшиеся цели.
iptables -L INPUT -n --line-numbers | grep -F '203.0.113.5' | awk '{print $1}' | sort -rn | while read -r n; do iptables -D INPUT "$n"; done
Для продакшена удобнее второй способ. Он не зависит от текущей нумерации и повторяем в идемпотентных скриптах: повторный запуск просто вернёт ошибку, что правило не найдено, и ничего не испортит.
Удаление по спецификации: синтаксис и подводные камни
Спецификация должна совпадать с исходным правилом символ в символ: адрес источника, протокол, порт, интерфейс, target. Минимальный случай выглядит так.
iptables -D INPUT -s 203.0.113.5 -j DROP
Если правило добавляли с комментарием через модуль comment, комментарий тоже входит в спецификацию, иначе iptables ответит ошибкой Bad rule (does a matching rule exist in that chain?).
iptables -D INPUT -s 203.0.113.5 -m comment --comment "bruteforce ssh" -j DROP # правило, ссылающееся на набор ipset, удаляется по совпадению match-set iptables -D INPUT -m set --match-set blacklist src -j DROP
Проверяйте результат через iptables -S, он печатает правила в том же виде, в котором их принимает -D. Это самый быстрый способ скопировать спецификацию без ручного пересчёта колонок.
iptables -S INPUT | grep '203.0.113.5' iptables -L -n -v
Отдельно проверьте, какой бинарник вы редактируете. На современных дистрибутивах iptables может быть обёрткой над nftables (iptables-nft), а рядом живёт iptables-legacy со своим независимым набором правил. Правки в одном не видны в другом, и блокировка словно остаётся на месте. Сравнение бэкендов и готовые примеры правил разобраны в статье настройка файрвола в Linux: сравнение iptables, nftables и ufw.
Массовое удаление правил iptables для диапазона или списка IP
Когда адресов десятки, ручное перечисление спецификаций превращается в источник опечаток. Два рабочих шаблона: цикл по списку адресов и сбор номеров с удалением с конца.
Удаление правил для списка IP через цикл
Подготовьте файл, по одному адресу в строке, и прогоните его циклом. Конструкция 2>/dev/null || true гасит ошибку на адресах, для которых правила уже нет.
while read -r ip; do iptables -D INPUT -s "$ip" -j DROP 2>/dev/null || true done < ips.txt
Вариант через номера удобнее, когда правила отличаются по параметрам и спецификацию повторить сложно. Номера собираются по адресу и удаляются по убыванию.
for ip in 203.0.113.5 203.0.113.7 203.0.113.9; do
iptables -L INPUT -n --line-numbers | grep -F "$ip" | awk '{print $1}'
done | sort -rn | while read -r n; do iptables -D INPUT "$n"; done
Учтите масштаб: каждая команда -D перестраивает цепочку целиком, и на цепочке из нескольких тысяч правил цикл из сотен удалений заметно нагружает ядро. Для больших чёрных списков держите адреса в ipset, там добавление и удаление элемента не перебирает правила.
Удаление правил для диапазона CIDR
Если адрес блокировали как подсеть, ровно эта же подсеть должна быть в команде удаления. Запись отдельного IP вместо /24 правило не найдёт.
iptables -D INPUT -s 203.0.113.0/24 -j DROP ip6tables -D INPUT -s 2001:db8::/32 -j DROP
Проверьте, не создано ли правило через ipset: если в цепочке стоит ссылка на набор, удалять надо элемент набора, а не правило целиком. Удаление правила разом отключит блокировку для всего набора, включая адреса, которые вы снимать не собирались.
Работа с ipset: удаление IP, диапазонов и полная очистка
Набор ipset сам трафик не фильтрует. Он служит списком, на который ссылается правило iptables. Отсюда практическое следствие: набор можно очистить, а правило оставить, и тогда оно просто перестанет что-либо блокировать.
ipset list ipset list blacklist ipset test blacklist 203.0.113.5
Команда test отвечает «203.0.113.5 is in set blacklist» или «is NOT in set». Это самый быстрый способ проверить отдельный адрес, не выгружая весь список.
Удаление одного IP или диапазона из ipset
ipset del blacklist 203.0.113.5 ipset del blacklist 203.0.113.0/24
Диапазон удаляется только из наборов, которые поддерживают CIDR: hash:net, hash:net,port, hash:ip,port,net и подобные. Для IPv4 эти типы принимают как IP-диапазон, так и запись CIDR при добавлении и удалении элементов. Для набора типа hash:ip адрес с маской не принимается, ipset вернёт ошибку синтаксиса. Если адреса в наборе нет, команда тоже завершится ошибкой вида «Element cannot be deleted from the set: it's not added», поэтому в скриптах добавляйте || true.
Полная очистка набора: flush vs destroy
Две команды, которые часто путают. flush удаляет все элементы, но сам набор остаётся и правило iptables продолжает на него ссылаться. destroy удаляет набор целиком, и правило, которое на него ссылалось, перестаёт работать или начинает выдавать ошибку при следующей загрузке конфигурации.
ipset flush blacklist ipset list blacklist ipset destroy blacklist
Берите flush, если набор ещё нужен: он остаётся пустым и готовым к новым адресам. Destroy применяйте только тогда, когда правило iptables на набор уже удалено или переписано. Порядок действий для полного отказа от набора: сначала удалить правило, потом destroy.
Изменения в ipset живут в памяти, поэтому их нужно сохранять отдельно от iptables.
ipset save > /etc/ipset.conf ipset restore < /etc/ipset.conf
Если вы строите защиту на динамических наборах с автоматическим timeout, посмотрите разбор динамические наборы nftables: rate limiting и временная блокировка IP: там показан похожий подход, но на стороне nftables, где элемент истекает сам и снимать его вручную не нужно.
Fail2ban: снятие бана для одного IP, диапазона и всех адресов
Fail2ban управляет блокировками через действия. Типовое действие прописывает правило в iptables или добавляет адрес в ipset, поэтому разбан идёт не напрямую в фильтр, а через клиент демона: тогда он снимает и запись в бан-листе, и своё правило.
fail2ban-client status fail2ban-client status sshd
Вывод status по конкретному jail содержит блок «Banned IP list» с текущими адресами. Дополнительно список можно получить командой fail2ban-client get sshd banip, а список всех активных jail — через fail2ban-client status без аргументов.
Разбан одного IP в конкретном jail
fail2ban-client set sshd unbanip 203.0.113.5 fail2ban-client status sshd
Если адрес забанен в нескольких jail, разбан в одном оставит блокировку от другого: правило в iptables или запись в ipset от второго jail никуда не денутся. Проверяйте все jail, где может появляться этот адрес, и для каждого вызывайте unbanip отдельно.
Временная приостановка jail помогает, когда адрес попадает под фильтр повторно сразу после разбана. Команда fail2ban-client stop sshd останавливает наблюдение, но не снимает уже выданные баны. Забыть её включить обратно легко, поэтому держите паузу короткой и возвращайте jail командой fail2ban-client start sshd.
Массовый разбан: диапазон и все IP
Для одного адреса и подсети команда одна и та же: строка, переданная в unbanip, удаляется из бан-листа по точному совпадению. Массовый разбан надёжнее делать циклом по фактическому списку из status, а не перебором возможных адресов.
fail2ban-client status sshd | sed -n 's/.*Banned IP list:[[:space:]]*//p' | tr ' ' '\n' | while read -r ip; do [ -n "$ip" ] && fail2ban-client set sshd unbanip "$ip" done
Для полной очистки всех jail в новых версиях Fail2ban существует fail2ban-client unban --all. Он снимает баны во всех jail сразу, поэтому перед запуском убедитесь, что это действительно нужно: снятие блокировок для brute-force подрядчика или сканера уязвимостей вернёт их к активности. В версиях без поддержки ключа --all тот же результат даёт цикл по списку jail.
Перезапуск демона массовым разбаном не считается. Fail2ban хранит выданные баны в своей базе данных (файл задаётся переменной dbfile в fail2ban.conf) и при старте восстанавливает их, если время бана не истекло. Значит, разбан нужно делать через unbanip, а не через systemctl restart fail2ban.
Как применить изменения без разрыва активных соединений
Удаление правила DROP само по себе соединений не рвёт: пакеты, которые блокировались, и так не доходили, а уже разрешённые потоки продолжают идти. Риск возникает при сбросе цепочек, перезагрузке правил из неполного файла или при добавлении правила DROP выше разрешающего правила для established-трафика.
Проверка правил для established соединений
В рабочем фильтре правило для уже установленных соединений обычно стоит первым в цепочке. Проверить его наличие и счётчики можно так.
iptables -L INPUT -n -v | grep -E 'ESTABLISHED|RELATED' iptables -I INPUT 1 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Вторая команда добавляет правило в начало цепочки, если его нет. Ненулевые счётчики в выводе показывают, что правило реально обрабатывает трафик. В конфигурациях с Docker аналогичное правило живёт в цепочке DOCKER-USER и в FORWARD, поэтому проверяйте их тоже, иначе разрыв соединений придёт оттуда, где вы не смотрели.
Счётчики трогать не нужно. iptables -Z обнуляет статистику и лишает вас ориентира: после сброса невозможно понять, применяется ли правило и сколько пакетов оно отбросило. Для аудита сохраняйте вывод с -v до и после изменений.
Сохранение изменений: iptables-save, ipset save, persistent
iptables-save > /etc/iptables/rules.v4 ipset save > /etc/ipset.conf netfilter-persistent save
Пути и службы зависят от дистрибутива: в Debian и Ubuntu это пакет iptables-persistent с обёрткой netfilter-persistent, в других системах роль загрузчика выполняет собственный unit или nftables.conf. Проверьте, какой механизм активен у вас, командой systemctl list-unit-files | grep -i -E 'netfilter|iptables|ipset'.
Файл для iptables-restore должен содержать полный актуальный набор правил: по умолчанию команда очищает таблицу перед загрузкой, а ключ --noflush меняет это поведение на добавление правил к текущим, что при частичном файле даёт дубликаты. Точное поведение ключей сверяйте с man-страницей вашей версии iptables-restore. Восстановление из свежего iptables-save безопаснее ручного редактирования файла.
Отдельно проверьте настройки Fail2ban: если демон пишет правила сам, после перезагрузки он вернёт баны из своей базы и добавит их поверх восстановленных правил. Снятие блокировки, не сохранённое в обоих местах, живёт до первого reboot.
Типичные ошибки при массовом снятии блокировок
- iptables -F или -X. Очистка цепочки целиком сносит и правила доступа, включая разрешение SSH. Восстановить их из памяти нельзя, только из сохранённого дампа.
- Удаление по номерам в возрастающем порядке. Нумерация сдвигается после каждой команды, и вместо целевого правила удаляется соседнее.
- Конфликт с persistent. Правила удалены в памяти, но файл правил остался старым. После перезагрузки или перезапуска netfilter-persistent блокировка возвращается.
- Разбан только в Fail2ban. Если действие настроено на ipset или правило добавлялось вручную, запись в фильтре останется, а демон будет считать адрес разбаненным.
- Дубликаты правил. Один и тот же адрес мог быть заблокирован дважды разными правилами. Удаление первого ничего не меняет, нужен полный поиск по цепочке.
- Grep без учёта контекста. Поиск по подстроке адреса задевает соседние подсети и правила белого списка. Сверяйте найденные строки с полным выводом перед удалением.
- Забытые цепочки. Docker пишет в DOCKER-USER и FORWARD, трафик через локальный прокси проходит OUTPUT. Проверка только INPUT создаёт ложное ощущение, что блокировка снята.
- Сброс счётчиков. iptables -Z обнуляет статистику и ломает аудит: становится непонятно, какие правила действительно срабатывают.
- Нет бэкапа. Перед любыми правками сохраните состояние, иначе откат придётся собирать по памяти.
iptables-save > backup-rules-$(date +%F).v4 ipset save > backup-ipset-$(date +%F).conf
Базовые принципы защиты сервера и типичные промахи в конфигурации фильтра собраны в отдельном руководстве файрвол для Linux-сервера: настройка защиты от атак. Перед массовыми правками полезно свериться с политикой по умолчанию: если в цепочке стоит DROP по умолчанию, удаление разрешающего правила закрывает доступ целиком.
Чек-лист: как убедиться, что блокировка действительно снята
- Правила iptables. Выполните iptables -S | grep 203.0.113.5 и iptables -L -n -v | grep 203.0.113.5. В выводе не должно остаться правил с target DROP или REJECT для этого адреса ни в одной цепочке.
- Наборы ipset. Проверьте ipset test blacklist 203.0.113.5. Ответ «is NOT in set» подтверждает, что элемента нет. Просмотрите все наборы через ipset list -n, чтобы не пропустить второй список с тем же адресом.
- Бан-лист Fail2ban. Выполните fail2ban-client status sshd по каждому jail. Адреса не должно быть в строке Banned IP list.
- Фактическая доступность. Проверьте порт с другого хоста: nc -vz 203.0.113.10 443 или curl -I --max-time 5 http://203.0.113.10. С самого сервера проверка неинформативна: локальный трафик не всегда проходит через INPUT.
- Логи. Посмотрите tail -n 50 /var/log/fail2ban.log и journalctl -u fail2ban -n 50. Записи вида «Unban» подтверждают, что демон снял бан через своё действие, а не потерял его из виду.
- Persistent-состояние. Убедитесь, что изменения ушли в файлы: iptables-save | grep 203.0.113.5 и ipset save | grep 203.0.113.5 не должны ничего находить.
- Проверка после перезагрузки. Плановая перезагрузка или systemctl restart netfilter-persistent покажет, вернулась ли блокировка из сохранённого конфига или из базы Fail2ban.
Если все семь пунктов чистые, а адрес по-прежнему недоступен, блокировка стоит выше или ниже вашего сервера: в CDN, на внешнем межсетевом экране, в конфигурации Nginx через deny или в sshd через AllowUsers. Такие ограничения команды iptables не показывают. Методика поиска источника ограничений на периметре описана в материале практический аудит сетевой инфраструктуры.
Держите под рукой сохранённый дамп правил, список наборов ipset и статус jail перед каждой массовой правкой. Это занимает минуту, а откат после неожиданного поведения фильтра превращает в одну команду.
Источники
- Man page of IPSET — типы наборов и работа с элементами.
- dpvs/doc/IPset.md — поддержка CIDR типами hash:net, hash:net,port, hash:ip,port,net.
- Fail2ban — Official NixOS Wiki — как jail и action связаны с правилами файрвола.
- Настройка и использование Fail2ban — анализ логов и применение действия администратора.
- fail2ban save banned ip's after restart — Server Fault — переменная dbfile в fail2ban.conf.
- Delete all fail2ban bans in Ubuntu Linux — команда unban с версии 0.10.0.
- Защита от брутфорс-атак (fail2ban) | Ideco NGFW Novum — fail2ban-client unban --all.
- How to Set Up Fail2ban on FreeBSD — хранение банов в базе и их восстановление при перезапуске.
- Configure Fail2Ban for permanent and persistent bans — сохранение банов и их восстановление при старте.