Learning Platform
Глоссарий Troubleshooting
Урок 15.03 · 22 мин
Начальный
FirewalliptablesnftablesSecurity GroupsNetwork Security

Firewalls — stateful vs stateless, iptables/nftables, security groups

Firewall (сетевой экран) — это компонент, который разрешает или запрещает сетевые пакеты на основе правил. Звучит просто, но за этим определением скрывается целый класс систем разной сложности: от примитивного «пропускать только порт 80» до глубокого анализа трафика на уровне приложения с распознаванием SQL injection и XSS.

В этом уроке разберём, какие бывают firewall, в чём ключевая разница между stateless и stateful, как читать и писать правила iptables/nftables (стандарт Linux), и что такое security groups в облаке. Это базовый инструмент, который вы будете применять во всех сетевых задачах — от защиты домашнего роутера до конфигурации production VPC в AWS.


Где живёт firewall и что фильтрует

Firewall стоит на «границе» — между двумя сегментами сети с разным уровнем доверия. Типичные места:

  1. Edge firewall — между интернетом и вашим datacenter / VPC. Защищает всю инфраструктуру.
  2. Host firewall — на самом сервере (iptables, ufw, Windows Defender Firewall). Защищает один хост.
  3. App firewall (WAF) — перед веб-приложением, разбирает HTTP-запросы. Об этом отдельно.
  4. Microsegmentation — внутри datacenter, между группами серверов. Service mesh.
Уровни firewall: от edge до host
InternetUntrusted zone. Все, кто угодно
Edge FWГраница VPC / datacenter. Самый внешний уровень защиты
DMZDemilitarized zone -- сегмент с публичными сервисами (web servers). Доступен из интернета и из внутренней сети
Internal FWГраница между DMZ и внутренней сетью. Из DMZ внутрь можно только специально разрешённым правилам
App tierApplication servers. Видны из DMZ через internal FW, не видны из интернета напрямую
Host FWiptables/ufw на каждом сервере -- последний рубеж. Защищает от lateral movement если что-то скомпрометировано
DB tierБазы данных. Доступ только с конкретных app-серверов, не из интернета

Принцип defense in depth: даже если один firewall обходится, есть следующий. Compromise одного web-сервера не должен дать атакующему прямой доступ к БД.


Stateless firewall — решение по каждому пакету

Простейший firewall смотрит на каждый пакет независимо и применяет правила: if src_ip == X and dst_port == Y -> allow/deny. Не помнит ничего о предыдущих пакетах. Это stateless (packet filter).

Пример правила: «пропускать TCP-пакеты с dst_port=80, всё остальное — блокировать».

Проблема: TCP — двусторонний. Запрос идёт от клиента к серверу, ответ обратно. Stateless firewall на стороне сервера, разрешающий пакеты на port 80, должен также разрешать исходящий трафик с src_port=80 — иначе ответы не дойдут до клиента.

# Простой stateless подход в iptables:
# Разрешить входящие на 80:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
# Разрешить исходящие с 80 (ответы):
iptables -A OUTPUT -p tcp --sport 80 -j ACCEPT

# Проблема: это разрешит любому отправлять трафик с src_port=80 на наш сервер.
# Атакующий, подделав src_port=80, сможет лезть куда угодно

Stateless firewall:

  • Плюсы: простой, быстрый, не требует memory для соединений.
  • Минусы: грубый, требует осторожной симметричной настройки, плохо защищает от подделок source port.

Stateless подход используется в железных firewalls на гигабитных скоростях, в простых ACL на маршрутизаторах. Для большинства задач сегодня выбирают stateful.


Stateful firewall — отслеживает соединения

Stateful firewall помнит state каждого TCP-соединения. Когда видит SYN — регистрирует «новое соединение от X:p1 к Y:p2». Все последующие пакеты этого соединения автоматически разрешены, потому что они часть установленной коммуникации.

Stateful: пропускаем ответы автоматически
Client X:p1 -> SYN -> Server Y:80Клиент инициирует TCP-соединение на порт 80
Firewall запоминаетВ connection tracking table: src=X:p1, dst=Y:80, state=SYN_SENT. Все пакеты этого 5-tuple проходят без новых правил
Server Y:80 -> SYN-ACK -> Client X:p1Ответ автоматически разрешён -- он связан с известным соединением
State: ESTABLISHEDПосле 3-way handshake соединение в state=ESTABLISHED, все его пакеты проходят пока не закрыто

В Linux это conntrack — модуль ядра, ведущий таблицу всех соединений. Размер таблицы можно посмотреть:

# Текущее число соединений:
sudo conntrack -L | wc -l

# Лимит (можно увеличить через sysctl):
sysctl net.netfilter.nf_conntrack_max

# Hashsize -- параметр производительности:
sysctl net.netfilter.nf_conntrack_buckets

Преимущества stateful:

  • Простые правила. Не нужно описывать обратное направление вручную.
  • Защита от spoofing. Пакет с src_port=80 на наш сервер, не являющийся ответом, отбрасывается.
  • Возможность работы с UDP в state-aware режиме (пусть UDP без connection, но conntrack отслеживает «pseudo-connection» по timeout-ам).

Минусы:

  • Память. Каждое соединение — запись в таблице. Под нагрузкой (10M concurrent) нужно тюнить ядро.
  • Сложнее производительности. Каждый пакет ищется в conntrack table.

В современном Linux iptables/nftables по умолчанию stateful через модуль conntrack. Stateless подход редок и применяется только в специальных случаях.


iptables — классика, до сих пор стандарт

iptables — интерфейс к netfilter (фреймворк фильтрации в Linux kernel). Создан в начале 2000-х, до сих пор повсеместно. Правила организованы в цепочки (chains) внутри таблиц (tables).

Главные tables:

  • filter (default) — разрешить/запретить пакеты.
  • nat — NAT, port forwarding, redirect.
  • mangle — модификация заголовков (QoS, marking).
  • raw — работа до conntrack.

Главные chains в filter:

  • INPUT — пакеты, адресованные хосту.
  • OUTPUT — пакеты, исходящие от хоста.
  • FORWARD — пакеты, проходящие через хост (если он роутер).
# Посмотреть текущие правила:
sudo iptables -L -v -n

# Пример: разрешить SSH и HTTP, остальное запретить
# (приостановите если хотите воспроизвести -- может отрубить вас от SSH!)

# Политика по умолчанию -- DROP всё, что не разрешено:
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# Разрешить loopback:
iptables -A INPUT -i lo -j ACCEPT

# Разрешить ESTABLISHED и RELATED (stateful magic):
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Разрешить SSH (port 22) из любого источника:
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Разрешить HTTP (80) и HTTPS (443):
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Разрешить ICMP (ping) -- удобно для отладки:
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

Ключевые моменты:

  • -A INPUT — append правило в chain INPUT.
  • -p tcp --dport 22 — match для TCP-пакетов на dst port 22.
  • -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT — разрешить пакеты, относящиеся к установленным соединениям. Это критично! Без этого правила ваши собственные ответы будут блокироваться.
  • -P INPUT DROP — политика по умолчанию = DROP.
DANGER

ВНИМАНИЕ: при настройке firewall удалённо через SSH не делайте ‘iptables -P INPUT DROP’ до того, как добавите правило для SSH! Иначе отрубите себя от сервера. Используйте ‘iptables -F’ (flush) перед политикой DROP только локально, или применяйте правила через atomic-режим (iptables-apply).

Правила сохраняются в memory до перезагрузки. Чтобы пережили reboot:

# Debian/Ubuntu:
sudo apt install iptables-persistent
sudo netfilter-persistent save

# RHEL/CentOS:
sudo iptables-save > /etc/sysconfig/iptables
sudo systemctl enable iptables

nftables — современная замена iptables

nftables — новая система фильтрации в Linux, призванная заменить iptables. Создана теми же разработчиками (netfilter team), но лучше архитектурно: единый язык для IPv4/IPv6/ARP/bridge, более выразительный синтаксис, лучшая производительность.

В Debian 11+ и RHEL 8+ nftables — default. iptables до сих пор работает, но как обёртка над nftables (iptables-nft).

Пример конфига nftables (/etc/nftables.conf):

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;

        # Разрешить loopback
        iif lo accept

        # Разрешить established/related
        ct state established,related accept

        # SSH, HTTP, HTTPS
        tcp dport { 22, 80, 443 } accept

        # ICMP
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Преимущества:

  • Sets и maps. Группы IP, портов, можно делать словари (например, tcp dport map { 80: jump web, 443: jump web, 22: jump ssh }).
  • IPv4/IPv6 в одной таблице. Раньше нужны были отдельные iptables и ip6tables.
  • Atomic updates. Применение всего правил-файла транзакционно.
# Загрузить:
sudo nft -f /etc/nftables.conf

# Посмотреть текущие правила:
sudo nft list ruleset

# Добавить правило в существующую цепочку:
sudo nft add rule inet filter input tcp dport 8080 accept

ufw — удобный wrapper для домашнего использования

Для тех, кому iptables/nftables кажется слишком многословным, есть ufw (Uncomplicated Firewall). Это wrapper, генерирующий iptables-правила из простых команд:

# Включить и поставить default deny:
sudo ufw enable
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Разрешить порты по именам или номерам:
sudo ufw allow ssh
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Разрешить с конкретного IP:
sudo ufw allow from 10.0.0.0/24 to any port 5432

# Посмотреть правила:
sudo ufw status verbose

ufw — хороший выбор для домашнего сервера или dev-машины. В production обычно идёт прямо iptables/nftables, потому что нужны более сложные правила (rate limiting, conntrack tuning, marking).


Security groups в облаках

В AWS, GCP, Azure firewall выглядит иначе — через Security Groups (или Network Security Groups в Azure). Это виртуальные firewall, применяемые к VM или ENI (network interface).

Особенности AWS Security Groups:

  • Stateful по умолчанию. Не нужно описывать обратное направление — ответы на разрешённые запросы автоматически проходят.
  • Только allow rules. Нет понятия «deny — всё, что не разрешено явно, запрещено».
  • Применяются к instances. Не к подсетям (для подсетей есть NACL — Network ACL).
  • Можно ссылаться на другие SG. Правило «разрешить от security-group sg-web», вместо хардкода IP.
SG: web-tier
  Inbound:
    HTTPS (443) from 0.0.0.0/0
    HTTP (80) from 0.0.0.0/0
    SSH (22) from 1.2.3.4/32  # только с моего bastion IP
  Outbound: всё разрешено

SG: db-tier
  Inbound:
    PostgreSQL (5432) from sg-web   # только от web-tier serversов
  Outbound: всё разрешено

Это паттерн micro-segmentation: каждый tier разрешает доступ только нужным компонентам. Если кто-то скомпрометировал web-server, он не сможет лезть в БД с других IP — только если он в SG web-tier.

GCP — похожая концепция, называется Firewall Rules. Azure — Network Security Groups. Все три stateful, allow-only.


NAT и firewall

Многие host firewalls умеют делать NAT (Network Address Translation). Это базовая функциональность домашнего роутера:

# Включить ip forwarding:
sudo sysctl -w net.ipv4.ip_forward=1

# В iptables NAT table, masquerade -- замена source IP исходящих пакетов на IP роутера:
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

# Это делает интернет доступным для всех клиентов в LAN через один внешний IP

Port forwarding:

# Перенаправить входящие на порту 80 внешнего IP на внутренний 192.168.1.10:8080:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.1.10:8080

# Не забыть разрешить forwarding:
iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 8080 -j ACCEPT

В облаке port forwarding обычно делается через load balancer (Network Load Balancer), а не iptables.


Реальный production-firewall

В production firewall редко настраивается вручную. Обычно используется один из подходов:

  1. Configuration management (Ansible, Puppet, Chef, SaltStack) — описание правил декларативно, применение синхронно на все хосты.
  2. Cloud provider — Security Groups в Terraform/CloudFormation. Декларативное описание, ревью через PR.
  3. Service mesh (Istio, Linkerd) — firewall на уровне Kubernetes pods через сетевые policies.

Пример Terraform для AWS SG:

resource "aws_security_group" "web" {
  name = "web-tier"

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  ingress {
    from_port   = 22
    to_port     = 22
    protocol    = "tcp"
    cidr_blocks = ["1.2.3.4/32"]  # только bastion
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

Преимущества декларативного подхода:

  • Version control. Изменения в git с историей.
  • Code review. Каждое правило проходит через PR.
  • Reproducibility. Можно поднять идентичную инфраструктуру в новом регионе.
  • Audit. Видно, кто, когда и зачем менял правило.

Попробуй сам

Соберём минимальный firewall на iptables и проверим, что он работает. Создайте VM в Vagrant/VirtualBox или используйте dev-сервер (НЕ production, чтобы не отрубить себя).

# 1. Сохранить текущие правила (на всякий случай):
sudo iptables-save > /tmp/iptables-backup.txt

# 2. Установить чистые правила: default DROP + разрешённые порты
sudo iptables -F  # flush существующие
sudo iptables -P INPUT DROP
sudo iptables -P OUTPUT ACCEPT
sudo iptables -P FORWARD DROP

# Loopback всегда:
sudo iptables -A INPUT -i lo -j ACCEPT

# Stateful: разрешить ответы на наши исходящие:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Разрешить SSH (КРИТИЧНО если работаете удалённо):
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# Разрешить HTTP/HTTPS:
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# Разрешить ICMP echo (ping):
sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

# 3. Посмотрите результат:
sudo iptables -L -v -n

# 4. Проверьте, что вы доступны по http (если есть сервер):
curl -v http://your-server-ip

# 5. Попробуйте подключиться на закрытый порт (например 12345):
nc -zv your-server-ip 12345
# должно быть connection refused или timeout

# 6. Восстановить исходное (когда поэкспериментировали):
sudo iptables-restore < /tmp/iptables-backup.txt

Посмотрите conntrack table:

# Сколько активных соединений:
sudo conntrack -L 2>/dev/null | head -20

# Видно: установленные TCP, UDP "соединения", ICMP echo-reply state
# Это и есть state, на котором держится stateful firewall

iptables на практике: полный разбор PREROUTING, FORWARD, POSTROUTING цепочек
Проверка знанийKnowledge check
Junior спрашивает: 'Я поставил Security Group в AWS, разрешающую только нужные порты. На самом инстансе ставить ещё iptables -- зачем? Это же двойная работа'
ОтветAnswer
Хороший вопрос, и ответ в принципе defense in depth. Security Group в облаке защищает на уровне инфраструктуры -- на гипервизоре. Это первая линия защиты, и обычно её достаточно. НО есть несколько сценариев, где host firewall (iptables) даёт дополнительную ценность. Первый -- если SG ошибочно открыли. Бывает: коллега в спешке открыл порт 5432 на 0.0.0.0/0 'на минутку для тестов' и забыл закрыть. Host firewall, явно блокирующий всё кроме нужного, спасает -- через него тоже надо пройти. Второй -- multi-tenant сценарии. На одном инстансе несколько Docker-контейнеров или несколько сервисов. SG защищает от внешних, но не от внутренних -- два сервиса на одном хосте могут лезть друг к другу. Host firewall с ipset/policy маршрутами решает. Третий -- in-depth логирование. iptables может логировать дропы (--LOG), что даёт детальный аудит атак. SG логирует только в VPC Flow Logs (платно, медленнее). Четвёртый -- portability. Если вы переедете с AWS на GCP/on-premises, ваш host firewall переедет с приложением. Это спасает в edge cases. Пятый -- compliance. Некоторые стандарты (PCI-DSS, FedRAMP) требуют host firewall независимо от внешних защит. Шестой -- скорость реакции. Изменения в SG применяются через AWS API (минуты до распространения), iptables -- мгновенно. В production небольшого сервиса достаточно SG. В большой системе с compliance/audit -- ставят оба. Это типичный 'belt and suspenders' подход в security.

Проверьте понимание

Результат: 0 из 0
Концептуальный
Вопрос 1 из 6. В чём ключевое отличие stateful firewall от stateless?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4