Firewall: когда защита превращается в ловушку

Введение: почему firewall — это не "поставил и забыл"

Firewall в корпоративной сети — это не просто набор правил, а система, которая должна работать вместе с инфраструктурой, а не против неё. На практике встречаются два крайних подхода:

  1. "Давайте всё откроем, а потом разберёмся" — результат: DDoS на почтовый сервер, утечки данных и звонки из СМИ.
  2. "Закроем всё, кроме SSH" — результат: разработчики не могут протестировать API, QA не может запустить автотесты, а DevOps сидит в чате и ругается с сет-инженерами.

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


Проблема: когда firewall становится врагом

Сценарий 1: "Почему у нас не работает Slack?"

Ситуация: после обновления правил межсетевого экрана перестали работать внутренние сервисы. Логи показывают, что трафик на порт 443 (HTTPS) блокируется, хотя в правилах есть строка:

allow tcp any any port 443

Причина: правило сработало, но не так, как ожидалось. Дело в том, что Slack использует не только порт 443, но и динамические порты для WebRTC (обычно 3478–3481 для STUN, а также случайные порты выше 1024 для RTP). Если в правилах нет исключения для UDP-трафика на этих портах, соединение обрывается.

Решение:

# Для корпоративных сервисов (Slack, Teams, Zoom)
allow udp any any port 3478:3481
allow udp any any port 10000:65535  # Диапазон для RTP (настраивается под конкретный случай)

Сценарий 2: "Почему базы данных атакуют изнутри?"

Ситуация: в логах MySQL появляются подозрительные запросы с IP-адресов внутренней сети. Оказалось, что правило для базы данных было настроено слишком широко:

allow tcp 10.0.0.0/8 192.168.100.5 port 3306

Проблема: подсеть 10.0.0.0/8 — это все частные IP-адреса (от 10.0.0.0 до 10.255.255.255). Если в сети есть роутеры или сервисы с IP в этом диапазоне, они могут отправлять запросы к базе без фильтрации.

Решение:

# Ужесточаем правило до конкретной подсети
allow tcp 192.168.100.0/24 192.168.100.5 port 3306
# Или ещё лучше — ограничиваем по хостам
allow tcp 192.168.100.100 192.168.100.5 port 3306
allow tcp 192.168.100.200 192.168.100.5 port 3306

Практика: как настраивать firewall без боли

1. Начинайте с минимального набора правил

Лучше всего использовать принцип "закрыто всё, открыто только необходимое". Настройка по умолчанию:

# iptables (Linux)
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]

# Разрешаем loopback
-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT

# Разрешаем иконку (ICMP) для пингов
-A INPUT -p icmp --icmp-type echo-request -j ACCEPT
-A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT

# Разрешаем SSH (только с определённого IP или диапазона)
-A INPUT -p tcp --dport 22 -s 192.168.100.100/32 -j ACCEPT
-A OUTPUT -p tcp --sport 22 -d 192.168.100.100/32 -j ACCEPT

# Разрешаем HTTP/HTTPS для веб-сервисов
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
-A OUTPUT -p tcp --sport 80 -j ACCEPT
-A OUTPUT -p tcp --sport 443 -j ACCEPT

COMMIT

2. Используйте сетевые группы (network sets) для упрощения управления

В современных firewall (например, nftables или pf в FreeBSD) можно создавать группы IP-адресов или сервисов:

# Пример для pf (FreeBSD)
table <web_servers> { 192.168.100.10, 192.168.100.20 }
table <db_servers> { 192.168.100.5 }

pass in proto tcp from <web_servers> to <db_servers> port = 3306
block in all

3. Логируйте всё, что блокируется

Без логирования firewall превращается в "чёрный ящик". Настройте логирование в iptables:

-A INPUT -j LOG --log-prefix "IPTables-Dropped: " --log-level 4
-A INPUT -j DROP

Логи будут писаться в /var/log/messages или /var/log/syslog. Пример записи:

IPTables-Dropped: IN=eth0 OUT= MAC=00:11:22:33:44:55:66:77:88:99:ab:cd:ef SRC=192.168.100.100 DST=10.0.0.5 LEN=40 TOS=0x00 PREC=0x00 TTL=64 ID=12345 DF PROTO=TCP SPT=54321 DPT=3306 WINDOW=5840 RES=0x00 SYN URGP=0

4. Автоматизируйте обновление правил

Если правила руками — это боль, используйте:

  • Ansible/Terraform: для развёртывания правил на новых серверах.
  • Git + CI/CD: для контроля версий конфигураций firewall.
  • Скрипты на Python/Bash: для динамического обновления правил (например, при добавлении нового микросервиса).

Пример скрипта на Python для добавления правила в iptables:

import subprocess

def add_iptables_rule(src_ip, dst_ip, port, protocol="tcp"):
    cmd = [
        "sudo", "iptables",
        "-A", "INPUT",
        "-p", protocol,
        "-s", src_ip,
        "-d", dst_ip,
        "--dport", str(port),
        "-j", "ACCEPT"
    ]
    subprocess.run(cmd, check=True)

# Пример использования
add_iptables_rule("192.168.100.100", "192.168.100.5", 8080)

Примеры реальных конфигураций

Пример 1: Защита API-шлюза от DDoS

# Ограничиваем количество соединений с одного IP
-A INPUT -p tcp --dport 8080 -m connlimit --connlimit-above 100 -j DROP

# Блокируем сканирование портов
-A INPUT -p tcp --tcp-flags SYN,ACK,FIN,RST RST -j DROP

# Ограничиваем скорость запросов (например, 1000 запросов в минуту с одного IP)
-A INPUT -p tcp --dport 8080 -m recent --name API_FLOOD --set
-A INPUT -p tcp --dport 8080 -m recent --name API_FLOOD --update --seconds 60 --hitcount 1000 -j DROP

Пример 2: Разделение трафика между разработчиками и продакшеном

# Разработчики могут подключаться только к staging
-A INPUT -p tcp -s 192.168.100.0/24 --dport 8080 -d 10.0.10.10 -j ACCEPT

# Продакшен доступен только из DMZ
-A INPUT -p tcp -s 192.168.200.0/24 --dport 8080 -d 10.0.20.10 -j ACCEPT

# Всё остальное блокируется
-A INPUT -p tcp --dport 8080 -j DROP

Типичные ошибки и как их избежать

Ошибка Причина Как исправить
Слишком широкие правила allow tcp any any port 80 Ужесточить до конкретных IP или подсетей.
Отсутствие логирования Нет видимости блокируемого трафика. Включить логирование для всех отвергнутых пакетов.
Забытые правила по умолчанию DROP стоит после ACCEPT. Проверять порядок правил (iptables -L -n -v).
Блокировка внутреннего трафика Забыли разрешить OUTPUT. Добавить правила для исходящего трафика.
Статические IP в динамических сетях IP-адреса сервисов меняются. Использовать DNS-имена или динамические обновления правил.
Отсутствие резервной копии Правила не сохранены. Экспортировать конфигурацию (iptables-save > /etc/iptables.rules).
Перегрузка CPU из-за сложных правил Слишком много условий в одном правиле. Разбивать на простые, читаемые правила.

Вывод: firewall как часть DevOps-процессов

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

  1. Начинайте с минимализма: лучше иметь мало правил и постепенно расширять их, чем сразу открывать всё.
  2. Автоматизируйте всё: ручные настройки — источник ошибок. Используйте IaC (Infrastructure as Code).
  3. Логируйте и мониторьте: без логов вы не сможете быстро реагировать на инциденты.
  4. Документируйте правила: добавьте комментарии в конфигурации и обновляйте документацию при изменениях.
  5. Тестируйте изменения: перед применением новых правил в продакшене протестируйте их в staging-окружении.
  6. Обучайте команду: не все знают, как работает сетевой трафик. Проведите обучающий вебинар или мастер-класс.

Практический совет: если у вас уже есть проблемы с firewall, начните с аудита текущих правил. Используйте команду:

iptables -L -n -v

Она покажет текущие правила и статистику их использования. Если правило не используется (0 packets), его можно удалить.

Firewall — это не стена, а фильтр. Хороший фильтр пропускает нужное и блокирует лишнее, не мешая работе команды. Настройте его правильно, и он станет незаметной, но надёжной защитой.