Библиотека — Linux — сеть: стек, конфигурация, firewall [X]
Шифр
linux-networking
Разделы
linux network
Сверено
2 сентября — в этот день утверждения статьи сверялись с первоисточниками, а не правился текст
Объём
21 497 знаков · 23 раздела · чтения около 20 минут

Linux — сеть: стек, конфигурация, firewall


Обзор

Сетевой стек Linux — это одна из наиболее активно развивающихся частей ядра. За последние 15 лет он прошёл путь от ifconfig/iptables к iproute2/nftables, от плоской конфигурации к network namespaces, от iptables-цепочек к eBPF/XDP-программам, работающим на уровне драйвера. Эта статья покрывает уровни от L2/L3-конфигурации до firewall'а и traffic control, с фокусом на архитектурные решения и причины, по которым одни инструменты вытесняют другие.

В отличие от FreeBSD, где сетевая конфигурация унифицирована (ifconfig + rc.conf + PF), в Linux существует несколько конкурирующих стеков конфигурации: NetworkManager, systemd-networkd, ifupdown, netplan — выбор зависит от дистрибутива и use case. Ядерные механизмы (iproute2, netfilter) при этом универсальны, и именно на них стоит фокусироваться для глубокого понимания.

Архитектура: iproute2 как единый интерфейс

Почему ip победил ifconfig

ifconfig (пакет net-tools) использует ioctl() и /proc/net для взаимодействия с ядром. Эти интерфейсы не развивались с 2000-х годов и не поддерживают: множественные адреса на интерфейсе без костылей (eth0:0 — virtual subinterfaces), policy-based routing, network namespaces, tunnels (GRE, VXLAN, WireGuard), современные метаданные интерфейсов.

iproute2 (команда ip) использует Netlink — сокетный API ядра, специально спроектированный для сетевого управления. Netlink асинхронный, поддерживает multicast-нотификации (подписка на изменения), и масштабируется значительно лучше. На системе со 128 интерфейсами ip addr show отрабатывает за ~16ms, тогда как ifconfig -a — за ~1.5s (разница в ~100x из-за множества open()/read() по /proc).

На современных дистрибутивах net-tools часто не установлен по умолчанию. Команда ip — единственный штатный инструмент для L2/L3-конфигурации.

Структура команды ip

ip организован по объектам, каждый из которых соответствует подсистеме ядра:

ip link — L2: интерфейсы, MTU, состояние (up/down), MAC, создание виртуальных интерфейсов (veth, bridge, vlan, vxlan, wireguard). ip addr (или ip a) — L3: IP-адреса на интерфейсах. Один интерфейс может иметь множество адресов. ip route — таблицы маршрутизации. Linux поддерживает множество таблиц (main, local, custom), выбор между которыми определяется ip rule. ip rule — policy routing: выбор таблицы маршрутизации на основе source IP, fwmark, incoming interface. ip neigh — ARP/NDP-таблица (замена arp). ip netns — управление network namespaces. ip tunnel, ip link add type <tunnel> — туннели (GRE, IPIP, sit, VXLAN, WireGuard).

Все команды поддерживают -j (JSON-вывод, с iproute2 4.13+), что делает ip пригодным для программного разбора без хрупкого awk/grep.

# JSON вывод для скриптов
ip -j -p addr show dev eth0

# Мониторинг изменений в реальном времени (netlink multicast)
ip monitor route    # следить за изменениями маршрутов
ip monitor neigh    # следить за ARP-таблицей

Конфигурация сети: три модели

Linux не имеет единого механизма конфигурации сети. Выбор определяется дистрибутивом и сценарием использования.

NetworkManager

Дефолт на десктопах (Fedora, Ubuntu Desktop, RHEL с GUI). Разработан Red Hat. Ориентирован на динамические среды: Wi-Fi, VPN, смена сетей, hotplug. Использует D-Bus API, имеет GUI (nm-applet, GNOME Settings) и CLI (nmcli, nmtui). Хранит конфиги в /etc/NetworkManager/ (connection profiles в /etc/NetworkManager/system-connections/).

nmcli — мощный инструмент, часто недооцённый:

nmcli device status                              # список интерфейсов
nmcli connection show                            # все профили подключения
nmcli connection add type ethernet ifname eth0 \
    con-name "static" ipv4.method manual \
    ipv4.addresses "192.168.1.100/24" \
    ipv4.gateway "192.168.1.1" \
    ipv4.dns "1.1.1.1"
nmcli connection up "static"

systemd-networkd

Часть systemd. Ориентирован на серверы и контейнеры: статическая конфигурация, предсказуемость, минимальные зависимости. Конфигурация через .network, .netdev, .link файлы в /etc/systemd/network/ (с приоритетом) или /usr/lib/systemd/network/ (дефолты пакетов).

# /etc/systemd/network/20-wired.network
[Match]
Name=en*

[Network]
Address=192.168.1.100/24
Gateway=192.168.1.1
DNS=1.1.1.1
DNS=8.8.8.8

systemd-networkd хорошо интегрирован с systemd-resolved (DNS) и systemd-networkd-wait-online (определение готовности сети). Не имеет GUI. Управление: networkctl list, networkctl status.

ifupdown и Netplan

ifupdown (/etc/network/interfaces) — классический механизм Debian. Прост, но ограничен: нет D-Bus API, плохая поддержка динамических изменений, отсутствие Wi-Fi без дополнительных инструментов. В Debian 13 сменился его DHCP-клиент: набор isc-dhcp объявлен устаревшим вслед за upstream, и связке с ifupdown теперь предлагается dhcpcd-base (NetworkManager и systemd-networkd несут собственные реализации DHCP и в пакете isc-dhcp-client не нуждаются).

Netplan (Ubuntu 17.10+) — YAML-фронтенд, генерирующий конфигурацию для NetworkManager или systemd-networkd:

# /etc/netplan/01-config.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s3:
      addresses: [192.168.1.100/24]
      routes:
        - to: default
          via: 192.168.1.1
      nameservers:
        addresses: [1.1.1.1]

Когда что использовать

NetworkManager — десктопы, ноутбуки, среды с Wi-Fi и VPN, где нужна динамическая смена подключений. systemd-networkd — серверы, контейнеры, embedded, где конфигурация статическая и предсказуемая. ifupdown — базовый механизм Debian, который никуда не делся: на современной системе под systemd networking.service поднимает lo, а остальными интерфейсами на десктопной установке управляет NetworkManager, причём NM намеренно не трогает интерфейсы, перечисленные в /etc/network/interfaces. Netplan — Ubuntu; абстракция над двумя вышеперечисленными, в Debian доступна отдельным пакетом netplan.io.

NetworkManager и systemd-networkd могут конфликтовать. На одной системе должен быть активен один из них. Если оба установлены, NetworkManager обычно берёт управление интерфейсами, которые не описаны в конфигурации networkd.

systemd-resolved: DNS-резолвинг

systemd-resolved — stub-резолвер, работающий на 127.0.0.53:53. Обеспечивает: кеширование DNS, DNSSEC-валидацию, split DNS (разные DNS-серверы для разных доменов — критически важно для VPN), DNS-over-TLS.

resolved различает четыре режима интеграции с /etc/resolv.conf. stub — симлинк на /run/systemd/resolve/stub-resolv.conf, где указан stub-резолвер и поисковые домены; рекомендуемый вариант. uplink — симлинк на /run/systemd/resolve/resolv.conf с реальными апстрим-серверами в обход stub'а. static — симлинк на неизменный /usr/lib/systemd/resolv.conf, в котором единственным сервером записан 127.0.0.53, а поисковых доменов нет. foreign — файл ведёт кто-то другой, и resolved сам читает его как источник конфигурации.

resolvectl status                     # текущие DNS-серверы по интерфейсам
resolvectl query example.com          # тестовый запрос с диагностикой
resolvectl dns eth0 1.1.1.1 8.8.8.8  # задать DNS для интерфейса
resolvectl domain eth0 ~corp.local    # split DNS: *.corp.local → DNS eth0

Gotcha: многие приложения (особенно в контейнерах) не используют NSS/resolved и делают DNS-запросы напрямую по адресу из /etc/resolv.conf. Если resolved не активен или /etc/resolv.conf указывает на недоступный сервер, DNS ломается. При использовании Docker совместно с resolved необходимо убедиться, что контейнеры видят 127.0.0.53 или имеют альтернативный DNS. Ровно для таких клиентов, идущих мимо локальных DNS API, resolved держит второй stub на 127.0.0.54: он работает в режиме прокси — без DNSSEC-валидации и без LLMNR/mDNS.

Network namespaces и виртуальные интерфейсы

Network namespaces — фундамент сетевой изоляции в Linux, на котором построены контейнеры (Docker, Podman, LXC — см. статью 6). Каждый namespace — изолированный сетевой стек: свои интерфейсы, маршруты, firewall-правила, /proc/net.

# Создание namespace и пары veth-интерфейсов
ip netns add ns1
ip link add veth0 type veth peer name veth1
ip link set veth1 netns ns1

# Конфигурация внутри namespace
ip addr add 10.0.0.1/24 dev veth0
ip link set veth0 up
ip netns exec ns1 ip addr add 10.0.0.2/24 dev veth1
ip netns exec ns1 ip link set veth1 up

# Проверка изоляции
ip netns exec ns1 ip route   # видит только свою таблицу маршрутизации

Виртуальные интерфейсы, создаваемые через ip link add:

veth (virtual ethernet pair) — пара связанных интерфейсов, пакет, вошедший в один конец, выходит из другого. Основа подключения контейнеров к host network. bridge — программный L2-коммутатор. Docker по умолчанию создаёт bridge docker0 и подключает контейнеры через veth-пары. macvlan — виртуальный интерфейс с собственным MAC-адресом на физическом интерфейсе. Контейнер получает «свой» адрес в физической сети без NAT. ipvlan — как macvlan, но разделяет MAC хоста. Полезно когда коммутатор ограничивает MAC per port. vxlan — L2-over-UDP туннели для overlay-сетей (Flannel, Calico в VXLAN-mode). wireguard — VPN-интерфейс (с ядра 5.6 — in-tree модуль).

Firewall: nftables

Эволюция: ipchains → iptables → nftables

Все три поколения firewall'а в Linux построены на Netfilter — подсистеме ядра, предоставляющей hooks (точки перехвата) в сетевом стеке. nftables (с ядра 3.13, 2014) заменяет iptables, ip6tables, arptables и ebtables единым framework'ом.

Ключевые архитектурные отличия nftables от iptables:

Нет предопределённых таблиц и цепочек. iptables создаёт filter/INPUT, filter/FORWARD, nat/PREROUTING и т.д. даже если они не нужны — каждая неиспользуемая цепочка всё равно обходится при обработке пакета. В nftables администратор создаёт только нужные таблицы и цепочки.

Единый синтаксис для IPv4/IPv6. Семейство inet позволяет писать одно правило для обоих протоколов. В iptables нужны два раздельных набора правил (iptables + ip6tables).

Множество действий в одном правиле. iptables: одно правило — один target (-j ACCEPT). nftables: правило может одновременно считать пакеты, ставить mark и выносить verdict.

Sets и maps. Встроенные структуры данных для эффективного matching по множеству адресов/портов (аналог ipset, но native). Maps позволяют делать lookup: «если source IP в этом множестве, перенаправь на такой-то vmap target».

VM вместо hardcoded matching. iptables использует фиксированные match-модули в ядре. nftables компилирует правила в байткод для лёгкой VM ядра — это позволяет атомарные обновления правил и лучшую производительность на больших ruleset'ах.

Hooks (точки перехвата)

                                    ┌──────────┐
                                    │  local    │
                                    │ processes │
                                    └────┬─┬────┘
                                         │ ↑
                                    output input
                                         │ │
─→ [ingress] → prerouting → routing → forward → postrouting →
                  decision

ingress — самый ранний hook, привязан к конкретному интерфейсу (с ядра 4.2). Пакеты ещё не дефрагментированы. prerouting → input — для пакетов, адресованных локальной системе. prerouting → forward → postrouting — для транзитных пакетов (роутер). output → postrouting — для пакетов, генерируемых локально.

Практика: базовый server firewall

#!/usr/sbin/nft -f

flush ruleset

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

        # conntrack: разрешить established и related
        ct state established,related accept

        # loopback
        iif lo accept

        # ICMP (ping и прочее)
        ip protocol icmp accept
        ip6 nexthdr icmpv6 accept

        # SSH
        tcp dport 22 accept

        # HTTP/HTTPS
        tcp dport { 80, 443 } accept

        # логировать и дропнуть остальное
        log prefix "nft-drop: " counter drop
    }

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

    chain output {
        type filter hook output priority 0; policy accept;
    }
}
nft list ruleset             # показать текущие правила
nft -f /etc/nftables.conf    # загрузить из файла (атомарно)
nft add rule inet filter input tcp dport 8080 accept  # добавить правило
nft -a list chain inet filter input  # показать с handle-номерами
nft delete rule inet filter input handle 7  # удалить по handle

Миграция с iptables

На практике существуют три пути: нативный nftables (рекомендуется), iptables-nft (старый синтаксис, backend nf_tables — транзитный вариант), iptables-legacy (старый backend — deprecated). Debian 10+ и Fedora 32+ по умолчанию используют iptables-nft: при вызове iptables правила транслируются в nftables backend. Для полного перехода: iptables-save > rules.txt && iptables-restore-translate -f rules.txt > ruleset.nft.

XDP и eBPF-based networking

XDP (eXpress Data Path) — framework для обработки пакетов на уровне драйвера сетевой карты, до выделения sk_buff. Пакет обрабатывается eBPF-программой, которая может вернуть один из verdicts: XDP_PASS (передать в стек), XDP_DROP (отбросить), XDP_TX (отправить обратно), XDP_REDIRECT (перенаправить на другой интерфейс).

XDP работает на порядок быстрее nftables для простых задач (DDoS-mitigation, L4 load balancing) — миллионы pps на одном ядре. Cilium (CNI для Kubernetes) использует eBPF/XDP вместо iptables для service routing, network policy и load balancing. Это активно вытесняет kube-proxy (iptables-based) в production Kubernetes.

Подробнее о eBPF — в статье 10 (Мониторинг и отладка).

Traffic control (tc)

tc — инструмент для управления очередями и шейпинг трафика. Архитектура: qdisc (queueing discipline) привязывается к интерфейсу, внутри qdisc — classes и filters.

# Ограничить исходящую полосу до 100 Mbit/s на eth0
tc qdisc add dev eth0 root tbf rate 100mbit burst 32kbit latency 400ms

# Показать текущие qdiscs
tc qdisc show dev eth0

# fq_codel — default qdisc в современных ядрах (умное управление очередями)
tc qdisc replace dev eth0 root fq_codel

tc — глубокая тема, на уровне «знать что существует и где копать». Для большинства серверных задач достаточно знать, что fq_codel хорошо справляется с bufferbloat без ручной настройки и в типичной системе уже назначен qdisc'ом по умолчанию — но назначает его не ядро: собственный встроенный дефолт ядра по-прежнему pfifo_fast, а fq_codel прописывает дистрибутив через net.core.default_qdisc (systemd делает это в /usr/lib/sysctl.d/50-default.conf).

Сетевые tunables (/proc/sys/net/)

Ядро предоставляет сотни параметров в /proc/sys/net/. Наиболее важные:

# Форвардинг пакетов (роутер, Docker-хост)
sysctl net.ipv4.ip_forward=1
sysctl net.ipv6.conf.all.forwarding=1

# Защита от spoofing (reverse path filtering)
sysctl net.ipv4.conf.all.rp_filter=1   # strict mode

# TCP tuning для high-bandwidth links
sysctl net.core.rmem_max=16777216
sysctl net.core.wmem_max=16777216
sysctl net.ipv4.tcp_rmem="4096 131072 16777216"
sysctl net.ipv4.tcp_wmem="4096 16384 16777216"

# Количество подключений в backlog
sysctl net.core.somaxconn=65535
sysctl net.ipv4.tcp_max_syn_backlog=65535

# BBR congestion control (Google, лучше чем CUBIC на lossy links)
sysctl net.ipv4.tcp_congestion_control=bbr
sysctl net.core.default_qdisc=fq

Постоянная конфигурация — через файлы в /etc/sysctl.d/*.conf (см. статью 1). Подробнее о sysctl — в статье 5 (Ядро).

Нюансы и trade-off'ы

NetworkManager vs systemd-networkd — не только «десктоп vs сервер». NetworkManager в последних версиях отлично работает на серверах через nmcli и keyfile-backend. systemd-networkd проще, но не поддерживает Wi-Fi (нужен wpa_supplicant/iwd отдельно) и не имеет VPN-плагинов. На RHEL/Fedora серверах NetworkManager — дефолт и рекомендуемый вариант, даже без GUI.

nftables: atomic ruleset replacement. Ключевое преимущество перед iptables: nft -f rules.nft загружает весь ruleset атомарно — нет окна, когда часть правил применена, а часть нет. В iptables iptables-restore тоже близок к атомарности, но при ручном iptables -A каждая команда — отдельная транзакция с возможным race condition.

iptables-nft как ловушка. На системах с iptables-nft (Debian, Fedora) команды iptables и nft работают с одним и тем же backend — но видят правила по-разному. Правила, созданные через iptables, видны через nft list ruleset, но правила из nft не видны через iptables -L. Смешивание двух инструментов на одной системе — источник трудноотлаживаемых проблем.

ss вместо netstat. ss (socket statistics, часть iproute2) — замена netstat (часть net-tools). ss получает данные через netlink-интерфейс sock_diag, а разбор /proc/net остался в нём лишь запасным путём — отсюда и заметный выигрыш на системах с тысячами сокетов. Основные вызовы: ss -tlnp (TCP listen + PID), ss -s (summary), ss -i (TCP internal info, включая congestion window).

DNS и split horizon. systemd-resolved решает реальную проблему: при подключении к VPN нужно отправлять DNS-запросы для корпоративных доменов через VPN-tunnel, а остальные — через обычный DNS. Без resolved это требует хаков с dnsmasq или ручного управления /etc/resolv.conf. С resolved: resolvectl domain tun0 ~corp.local — элегантное решение.

Сравнение с FreeBSD

Конфигурация интерфейсов: FreeBSD использует ifconfig для всего — от IP-адресов до VLAN и bridge. В Linux ifconfig deprecated, вместо него ip. Фундаментальное отличие: FreeBSD ifconfig — часть base system, развивается вместе с ядром. Linux net-tools — заброшенный userspace-пакет, который не может использовать возможности ядра (netlink). Поэтому замена была неизбежна.

Firewall: FreeBSD предлагает PF (портирован из OpenBSD) — мощный, с лаконичным конфигурационным файлом и встроенным state tracking. Аналог в Linux — nftables, но с другой философией: PF конфигурируется плоским файлом с правилами, nftables — через nft CLI или файл с программируемыми таблицами/цепочками/sets. PF имеет pf.conf как единую точку конфигурации; nftables более гибок, но менее предсказуем для новичка. IPFW (ещё один firewall FreeBSD) ближе к iptables по модели: линейные правила с номерами.

Netgraph (FreeBSD) — модульный graph-based framework для обработки пакетов: узлы графа выполняют трансформации, пакеты проходят по рёбрам. Аналога в Linux нет — вместо этого используется комбинация tc + nftables + eBPF/XDP, каждый на своём уровне стека. Netgraph элегантнее концептуально, но менее производителен на high-traffic и менее широко используется.

Network namespaces в Linux не имеют прямого аналога в FreeBSD. Ближайшее — VNET (виртуализированный сетевой стек в jail), который даёт каждому jail'у собственные интерфейсы, маршруты и firewall. Функциональность похожа, но реализация принципиально другая: VNET дублирует весь стек, Linux namespaces — более лёгкая абстракция на уровне структур данных.

Источники


Связанные заметки

Из библиотеки института уносят только знания. Читателей здесь не считают: посещение не регистрируется, отметок в издании не остаётся, счётчиков нет ни у одного издания фонда.

Издание пополняется и пересверяется. Текст доступен на условиях CC BY-SA 4.0 — унесённое можно передавать дальше на тех же условиях.