Выберите продукт

systemd-networkd: policy routing и таблицы маршрутизации (ip rule, multiple gateways, source routing)

Разберём, как настроить policy routing через systemd-networkd: отдельные таблицы маршрутов, правила ip rule по исходному адресу и меткам, два шлюза на разных интерфейсах или на одном, и базовый failover по метрикам. Плюс проверка и отладка.
systemd-networkd: policy routing и таблицы маршрутизации (ip rule, multiple gateways, source routing)

Policy routing (маршрутизация по политике) в Linux — это когда маршрут выбирается не только по адресу назначения, но и по дополнительным условиям: исходному адресу (source routing), метке fwmark, входящему интерфейсу, UID, DSCP и т.д. На практике это решает задачи «несколько шлюзов (multiple gateways)», раздельный трафик для разных IP, VPN/туннелей, multi-homing и управляемый failover.

Ниже — практические конфиги для systemd-networkd: как завести свои таблицы маршрутизации, добавить правила (аналог ip rule) и описать маршруты в этих таблицах. В конце — короткий блок про Netplan на Ubuntu и чек-лист отладки.

Короткая модель: как работает policy routing в Linux

В упрощённом виде ядро выбирает маршрут в два шага:

  1. Подбирает правило из ip rule (routing policy): если пакет подходит под условие — смотреть маршруты в таблице N.
  2. В выбранной таблице ищет подходящий ip route (default via … или более специфичный префикс).

Типовая схема для двух аплинков:

  • для каждого провайдера/линка — отдельная таблица (например, 100 и 200);
  • в каждой таблице — свой default route через свой шлюз;
  • правила отправляют трафик в нужную таблицу по признаку (чаще всего по исходному IP).

Policy routing не «склеивает» два шлюза в один. Это механизм выбора таблицы. Балансировка и «умный» failover требуют отдельной логики: метрик, multipath, мониторинга доступности или динамической маршрутизации.

Что подготовить перед настройкой

1) Убедитесь, что сеть обслуживает именно systemd-networkd

На Debian/Ubuntu чаще встречаются три варианта:

  • чистый systemd-networkd — работаем напрямую с /etc/systemd/network/*.network;
  • Netplan на Ubuntu — он генерирует конфиги либо для networkd, либо для NetworkManager; здесь нужен рендерер networkd;
  • NetworkManager — тогда примеры ниже не применяются «как есть».

Быстрая проверка:

systemctl status systemd-networkd
networkctl status

2) Заранее спланируйте ID/имена таблиц

Удобно завести имена таблиц в /etc/iproute2/rt_tables. Это не строго обязательно (можно использовать числовой ID), но отладку упрощает заметно.

sudoedit /etc/iproute2/rt_tables
100 isp1
200 isp2

После этого в networkd можно писать Table=isp1 или Table=100 — выбирайте единый стиль и придерживайтесь его везде.

Схема выбора таблицы маршрутизации через ip rule для двух провайдеров

Базовый кейс: source routing для двух аплинков (2 шлюза)

Сценарий: у сервера два интерфейса/две подсети с разными шлюзами. Нужно, чтобы исходящий трафик «с IP провайдера 1» уходил через ISP1, а «с IP провайдера 2» — через ISP2. Это классический source routing: правило выбирается по From=.

Пример: два интерфейса (ens3 и ens4)

Допустим:

  • ens3: 203.0.113.10/24, шлюз 203.0.113.1 (ISP1)
  • ens4: 198.51.100.10/24, шлюз 198.51.100.1 (ISP2)

Создадим два файла.

/etc/systemd/network/10-ens3.network (ISP1)

[Match]
Name=ens3

[Network]
Address=203.0.113.10/24

[Route]
Destination=203.0.113.0/24
Scope=link
Table=isp1

[Route]
Gateway=203.0.113.1
Table=isp1

[RoutingPolicyRule]
From=203.0.113.10/32
Table=isp1
Priority=1000

/etc/systemd/network/10-ens4.network (ISP2)

[Match]
Name=ens4

[Network]
Address=198.51.100.10/24

[Route]
Destination=198.51.100.0/24
Scope=link
Table=isp2

[Route]
Gateway=198.51.100.1
Table=isp2

[RoutingPolicyRule]
From=198.51.100.10/32
Table=isp2
Priority=1001

Применяем:

sudo systemctl restart systemd-networkd

Проверка: правила и маршруты по таблицам

ip rule show
ip route show table isp1
ip route show table isp2

Самый полезный тест — что именно выбрало ядро:

ip route get 1.1.1.1 from 203.0.113.10
ip route get 1.1.1.1 from 198.51.100.10

Ожидаемо: для каждого from будет свой шлюз и свой интерфейс.

Зачем добавлять link-route до своей подсети в «свою» таблицу

Когда вы включаете policy routing, важно, чтобы в выбранной таблице были не только default routes, но и «локальные» маршруты (connected routes) — минимум до подсети, где находится ваш шлюз. Иначе можно получить ситуацию: default в таблице есть, но до самого next-hop (шлюза) в этой таблице маршрута нет, и пакет не уйдёт корректно.

Практическое правило: каждая «провайдерская» таблица должна быть самодостаточной: маршрут до своего L2/L3-сегмента (Scope=link) плюс default через свой gateway.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Один интерфейс, два IP и два шлюза (multiple gateways на одной карте)

Иногда оба адреса висят на одном интерфейсе (один порт, два публичных IP, два шлюза). Подход тот же: две таблицы, два default, два правила. Отличие — один Name= и два Address=.

[Match]
Name=ens3

[Network]
Address=203.0.113.10/24
Address=198.51.100.10/24

[Route]
Destination=203.0.113.0/24
Scope=link
Table=isp1

[Route]
Gateway=203.0.113.1
Table=isp1

[RoutingPolicyRule]
From=203.0.113.10/32
Table=isp1
Priority=1000

[Route]
Destination=198.51.100.0/24
Scope=link
Table=isp2

[Route]
Gateway=198.51.100.1
Table=isp2

[RoutingPolicyRule]
From=198.51.100.10/32
Table=isp2
Priority=1001

С точки зрения ядра это два независимых набора правил/таблиц; физически один интерфейс или два — принципиально не важно.

Как сделать «основной интернет» и не сломать сервер

Если вы описали policy routing, но не задали «главный» default route в таблице main, часть трафика без явного исходного адреса (системные службы, установщик пакетов, часть исходящих соединений) может начать вести себя непредсказуемо.

Рабочий подход для серверов:

  • оставить один default в main (основной провайдер),
  • а policy routing применять только для трафика с конкретных source-IP (правила From=).

В networkd default в main задаётся маршрутом без Table=:

[Route]
Gateway=203.0.113.1
Metric=100

Failover gateway: что реально сделать статикой, а где нужен мониторинг

Важно различать два типа «переключения»:

  • переключение при падении интерфейса (link down) — относительно просто, маршруты исчезают сами;
  • переключение при частичных отказах (линк up, но «интернета нет» за шлюзом) — требует мониторинга доступности и реакции.

Простой failover: два default в main с разными Metric

Если достаточно «когда ISP1-интерфейс реально упал — уйти через ISP2», можно держать два default в main и разнести их метриками:

[Route]
Gateway=203.0.113.1
Metric=100

[Route]
Gateway=198.51.100.1
Metric=200

Но это не гарантирует переключение, если линк поднят, а апстрим сломан. Если нужен именно такой сценарий, обычно добавляют внешний мониторинг и автоматизацию, которая правит маршруты/правила через ip.

Практика: мониторинг + правка маршрутов

В связке с policy routing часто получается так: статикой (networkd) держим «правильную» структуру таблиц, а «умное» переключение делаем отдельным systemd unit + таймером. Он периодически проверяет доступность контрольного адреса и при необходимости меняет default/приоритеты.

Если вы ещё на стадии проектирования multi-homing, полезно заранее подумать про DNS-сторону и отказоустойчивость на уровне приложения. По теме может пригодиться статья про weighted routing и failover в DNS (когда часть логики переносится на уровень записи/пула адресов).

Отладка policy routing на Linux: проверка ip rule и ip route get в консоли

Netplan на Ubuntu: как это соотносится с networkd

Netplan — генератор конфигов. Если вы хотите именно systemd-networkd, убедитесь, что в Netplan указан renderer networkd. Дальше два варианта:

  • описывать policy routing средствами Netplan (в современных версиях есть routing-policy),
  • или завести конфиги напрямую в /etc/systemd/network/ и не усложнять YAML.

На практике всегда проверяйте «конечную истину»: networkctl status, ip rule и ip route show table .... Не столь важно, пришло это из Netplan или из ваших .network-файлов.

Отладка: быстрый чек-лист, если «не пингуется»

1) Смотрите фактические правила и маршруты

ip rule
ip route
ip route show table isp1
ip route show table isp2

2) Проверяйте выбор маршрута командой ip route get

ip route get 8.8.8.8 from 203.0.113.10
ip route get 8.8.8.8 from 198.51.100.10

3) Типовые ошибки

  • В таблице есть default, но нет маршрута до подсети шлюза: добавьте Destination=... Scope=link в эту таблицу.
  • Асимметричная маршрутизация: вход пришёл через ISP1, а ответ ушёл через ISP2 — внешние фаерволы/антиспуфинг это часто режут. Лечится source routing по правильному IP и корректной привязкой сервисов.
  • Сервис слушает на одном IP, а исходящий трафик идёт с другого: некоторым демонам нужно явно задавать bind/source address (зависит от приложения).
  • Reverse path filtering (rp_filter) ломает multi-homing: в сложных схемах часто используют loose-режим rp_filter=2 на нужных интерфейсах.

Если у вас несколько публичных IP и дополнительно есть NAT/SNAT (например, часть сервисов должна выходить строго с конкретного адреса), посмотрите материал про управление SNAT для нескольких IP через nftables: это частая «вторая половина» задачи после корректных таблиц маршрутизации.

Мини-шпаргалка: соответствие networkd ↔ iproute2

  • [Route] Table=...ip route add ... table ...
  • [RoutingPolicyRule] From=... Table=... Priority=...ip rule add from ... table ... priority ...
  • Metric= → метрика маршрута (аналогично ip route ... metric N)

Итог

systemd-networkd позволяет декларативно описывать policy routing: вы раскладываете маршруты по таблицам и управляете выбором таблицы через правила, аналогичные ip rule. Это надёжно работает на Debian/Ubuntu и хорошо сочетается с Netplan при renderer networkd.

Если вы подбираете площадку под проекты, где такие сетевые схемы встречаются регулярно (несколько аплинков, несколько публичных IP, VPN/туннели), удобнее держать всё на полноценном VDS: проще дебажить сеть, управлять sysctl и не упираться в ограничения окружения.

Поделиться статьей

Вам будет интересно

OpenSSH hardening 2026: KEX, hostkey, CA подписи и FIDO2-ключи без боли для легаси OpenAI Статья написана AI (GPT 5)

OpenSSH hardening 2026: KEX, hostkey, CA подписи и FIDO2-ключи без боли для легаси

Пошагово поджимаем OpenSSH в 2026: инвентаризация через sshd -T, выбор современного KEX и hostkey, запрет ssh-rsa без поломки RSA ...
Kubernetes: ImagePullBackOff из‑за Docker Hub rate limit — mirror и registry cache на практике OpenAI Статья написана AI (GPT 5)

Kubernetes: ImagePullBackOff из‑за Docker Hub rate limit — mirror и registry cache на практике

ImagePullBackOff нередко вызван Docker Hub pull rate limit: кластер внезапно перестаёт скачивать образы, особенно при автоскейле и ...
Kubernetes StorageClass, PV и PVC: почему PVC Pending и как это чинить (provisioner, topology, access modes) OpenAI Статья написана AI (GPT 5)

Kubernetes StorageClass, PV и PVC: почему PVC Pending и как это чинить (provisioner, topology, access modes)

Если PVC в Kubernetes остаётся в Pending, значит подходящий PV не найден или не создан. В статье разбираем цепочку StorageClass → ...