Firewall: когда защита превращается в ловушку
Введение: почему firewall — это не "поставил и забыл"
Firewall в корпоративной сети — это не просто набор правил, а система, которая должна работать вместе с инфраструктурой, а не против неё. На практике встречаются два крайних подхода:
- "Давайте всё откроем, а потом разберёмся" — результат: DDoS на почтовый сервер, утечки данных и звонки из СМИ.
- "Закроем всё, кроме 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 — это не просто техническая деталь, а часть культуры безопасности в команде. Вот ключевые моменты для успешной работы:
- Начинайте с минимализма: лучше иметь мало правил и постепенно расширять их, чем сразу открывать всё.
- Автоматизируйте всё: ручные настройки — источник ошибок. Используйте IaC (Infrastructure as Code).
- Логируйте и мониторьте: без логов вы не сможете быстро реагировать на инциденты.
- Документируйте правила: добавьте комментарии в конфигурации и обновляйте документацию при изменениях.
- Тестируйте изменения: перед применением новых правил в продакшене протестируйте их в staging-окружении.
- Обучайте команду: не все знают, как работает сетевой трафик. Проведите обучающий вебинар или мастер-класс.
Практический совет: если у вас уже есть проблемы с firewall, начните с аудита текущих правил. Используйте команду:
iptables -L -n -v
Она покажет текущие правила и статистику их использования. Если правило не используется (0 packets), его можно удалить.
Firewall — это не стена, а фильтр. Хороший фильтр пропускает нужное и блокирует лишнее, не мешая работе команды. Настройте его правильно, и он станет незаметной, но надёжной защитой.