Source-Based Routing на Linux: Полное руководство по настройке маршрутизации по источнику с ip rule и fwmark | AdminWiki

Source-Based Routing на Linux: Полное руководство по настройке маршрутизации по источнику с ip rule и fwmark

12 августа 2026 12 мин. чтения
Содержание статьи

Стандартная маршрутизация в Linux принимает решение о пути пакета на основе IP-адреса назначения. Ядро просматривает таблицу маршрутизации, находит наиболее подходящий маршрут и отправляет пакет через указанный интерфейс на шлюз. Source-based routing, или маршрутизация по источнику, меняет эту логику: выбор маршрута зависит от адреса отправителя, метки пакета, входящего интерфейса и других критериев. Этот механизм реализуется через подсистему iproute2 - команды ip rule и несколько таблиц маршрутизации ip route.

Практическая ценность подхода проявляется в трёх типовых сценариях. Первый - сервер с несколькими интернет-каналами (multi-WAN), где трафик от бухгалтерии должен уходить через одного провайдера, а трафик разработчиков - через другого. Второй - изоляция сред: пакеты от контейнеров или приложений принудительно направляются через VPN-туннель, тогда как остальной трафик идёт напрямую. Третий - защита от IP-спуфинга через проверку обратного пути (RPF), когда маршрутизатор блокирует пакеты с поддельными адресами отправителя. Все примеры в статье проверены на Ubuntu 24.04 и Debian 12, актуальны на август 2026 года и готовы к применению в продуктивной среде.

Что такое source-based routing и зачем он нужен

Policy-Based Routing (PBR) - это метод выбора маршрута на основе политик, заданных администратором. В отличие от классической маршрутизации, где решение принимается по полю destination IP, PBR анализирует source IP, метку пакета (fwmark), протокол, порт и другие атрибуты. Linux реализует PBR через правила (rules) и таблицы маршрутизации. Правило указывает условие отбора пакетов и номер таблицы, которую нужно использовать для таких пакетов. Таблица содержит маршруты - стандартные записи вида «сеть назначения через шлюз».

Архитектура маршрутизации Linux включает три зарезервированные таблицы: local (приоритет 0, маршруты для локальных адресов и loopback), main (приоритет 32766, основная таблица) и default (приоритет 32767, запасная таблица). Когда ядро обрабатывает пакет, оно последовательно проверяет правила в порядке возрастания приоритета. Первое совпадение определяет таблицу. Если ни одно правило не сработало, используется таблица main. Файл /etc/iproute2/rt_tables сопоставляет числовые идентификаторы таблиц с именами, что упрощает конфигурацию.

Отличие от обычной маршрутизации: таблицы и правила

Обычная маршрутизация оперирует одной таблицей main. Команда ip route add 10.0.0.0/8 via 192.168.1.1 добавляет запись в main, и все пакеты в сеть 10.0.0.0/8 пойдут через шлюз 192.168.1.1 независимо от адреса отправителя. PBR вводит дополнительный уровень: правило ip rule add from 192.168.10.0/24 table 100 говорит ядру - для пакетов с source IP из подсети 192.168.10.0/24 использовать таблицу 100. Если в таблице 100 есть маршрут по умолчанию через другого провайдера, трафик уйдёт туда.

Иерархия принятия решения выглядит так: пакет приходит в ядро, ядро проверяет список правил ip rule show от меньшего приоритета к большему, находит первое совпадение по условиям (from, fwmark, iif, tos и другим), извлекает номер таблицы из правила, ищет маршрут в этой таблице. Если маршрут найден - пакет отправляется. Если нет - ядро возвращается к следующему правилу. Приоритеты задаются параметром pref или priority. Правила без явного приоритета получают номера автоматически с шагом 32765, 32764 и так далее.

Типовые сценарии использования source-based routing

Сценарии, где PBR решает задачи, неразрешимые обычной маршрутизацией:

  • Multi-WAN с балансировкой и резервированием. Сервер подключён к двум провайдерам. Трафик от подсети 192.168.1.0/24 уходит через ISP1, от 192.168.2.0/24 - через ISP2. При отказе одного канала весь трафик переключается на оставшийся. Подробная настройка в разделе «Практический сценарий: Multi-WAN с балансировкой нагрузки».
  • Сегментация сети по источникам. Отдел разработки и продакшен-среда используют разные шлюзы для выхода в интернет. Правила ip rule привязывают подсети к конкретным таблицам маршрутизации.
  • Маршрутизация на основе приложений через fwmark. HTTP-трафик от определённого сервиса помечается меткой в iptables и направляется через VPN-туннель. Остальной трафик сервиса идёт через основной шлюз. Разобрано в разделе «Гибкая маршрутизация с помощью fwmark».
  • Защита от IP-спуфинга. Strict Reverse Path Forwarding проверяет, что пакет с адресом источника из внутренней сети пришёл именно с внутреннего интерфейса. Пакеты с поддельным source IP блокируются. Конфигурация в разделе «Защита от IP-спуфинга с помощью source-based routing».

Подготовка системы и базовые понятия

Перед настройкой убедитесь, что пакет iproute2 установлен. Команда ip -V покажет версию. На Ubuntu и Debian пакет входит в базовую установку. Для маркировки пакетов потребуется iptables или nftables - они также предустановлены в большинстве дистрибутивов. Работать рекомендуется через консоль сервера или IPMI: ошибка в правилах может разорвать сетевое соединение, и удалённый SSH-доступ станет недоступен. Держите резервную сессию или консоль открытой.

Необходимые утилиты и файлы конфигурации

Основной инструмент - утилита ip из пакета iproute2. Файл /etc/iproute2/rt_tables содержит сопоставление номеров и имён таблиц. Формат записи: номер и имя через пробел. Зарезервированные номера: 0 (unspec), 253 (default), 254 (main), 255 (local). Пользовательские таблицы размещайте в диапазоне от 1 до 252. Пример добавления двух таблиц для провайдеров:

# /etc/iproute2/rt_tables
100 isp1
200 isp2

После редактирования файла имена становятся доступны в командах ip route и ip rule. Перезагрузка не требуется.

Просмотр текущих правил и таблиц маршрутизации

Диагностика исходного состояния помогает понять, что изменится после настройки. Команда ip rule show выводит список правил с приоритетами:

0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

Правило 0 направляет все локальные пакеты в таблицу local. Правило 32766 - всё остальное в main. Правило 32767 - запасной default. Команда ip route show table main показывает содержимое основной таблицы. ip route show table local - таблицу локальных адресов (loopback, IP-адреса интерфейсов, broadcast).

Настройка маршрутизации по IP-адресу источника с ip rule

Этот сценарий - основа PBR. Задача: трафик от подсети 192.168.10.0/24 должен уходить через шлюз 10.0.0.1 провайдера ISP1, а трафик от 192.168.20.0/24 - через шлюз 10.0.1.1 провайдера ISP2. Сервер имеет два внешних интерфейса: eth0 с адресом 10.0.0.2/24 и eth1 с адресом 10.0.1.2/24.

Создание и именование дополнительных таблиц

Добавьте в /etc/iproute2/rt_tables строки:

100 isp1
200 isp2

Номера 100 и 200 выбраны произвольно, но должны быть уникальны и не пересекаться с зарезервированными. Имена isp1 и isp2 будут использоваться в командах.

Добавление маршрутов в пользовательские таблицы

Каждая таблица должна содержать маршрут по умолчанию через своего провайдера и маршрут к локальной сети шлюза для обеспечения доступности next-hop:

ip route add 10.0.0.0/24 dev eth0 table isp1
ip route add default via 10.0.0.1 dev eth0 table isp1

ip route add 10.0.1.0/24 dev eth1 table isp2
ip route add default via 10.0.1.1 dev eth1 table isp2

Маршрут к сети шлюза обязателен. Если его нет, ядро не сможет разрешить next-hop и вернёт ошибку «Network is unreachable». Команда ip route show table isp1 подтвердит добавление записей.

Создание правил ip rule для выбора таблицы

Свяжите адреса источников с таблицами:

ip rule add from 192.168.10.0/24 table isp1 priority 100
ip rule add from 192.168.20.0/24 table isp2 priority 200

Параметр priority задаёт порядок обработки. Меньшее число - более высокий приоритет. Правило для конкретного IP-адреса: ip rule add from 192.168.10.5/32 table isp1 priority 50. После добавления проверьте список: ip rule show.

Проверка и отладка конфигурации

Команда ip route get симулирует выбор маршрута для пакета с заданными параметрами. Укажите адрес назначения и адрес источника:

ip route get 8.8.8.8 from 192.168.10.5

Вывод покажет выбранную таблицу, шлюз и интерфейс. Если маршрут идёт через eth0 и шлюз 10.0.0.1 - настройка работает. Для захвата пакетов используйте tcpdump -i eth0 host 8.8.8.8 и инициируйте трафик с нужного адреса источника.

Гибкая маршрутизация с помощью fwmark (iptables/nftables)

Маркировка пакетов (fwmark) расширяет возможности PBR: решение о маршруте принимается не только по source IP, но и по порту, протоколу, UID процесса. Метка - это целое число, которое netfilter записывает в поле mark пакета, а ip rule проверяет условием fwmark.

Маркировка пакетов в iptables

Метки устанавливаются в цепочке PREROUTING таблицы mangle, чтобы повлиять на маршрутизацию. Пример: направить HTTP-трафик от подсети 192.168.10.0/24 через ISP2, а остальной трафик этой подсети - через ISP1:

iptables -t mangle -A PREROUTING -s 192.168.10.0/24 -p tcp --dport 80 -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -s 192.168.10.0/24 -p tcp --dport 443 -j MARK --set-mark 1

Правило ip rule для метки 1:

ip rule add fwmark 1 table isp2 priority 150

Порядок правил важен: сначала проверяется fwmark, затем from. Сохраните правила iptables: iptables-save > /etc/iptables/rules.v4 (Debian/Ubuntu).

Маркировка пакетов в nftables

Современная альтернатива iptables. Создайте таблицу mangle с цепочкой mark:

nft add table inet mangle
nft add chain inet mangle mark { type filter hook prerouting priority mangle \; }
nft add rule inet mangle mark ip saddr 192.168.10.0/24 tcp dport { 80, 443 } meta mark set 1

Правило ip rule с fwmark работает одинаково для iptables и nftables. Проверка меток: nft list ruleset.

Совместное использование ip rule и fwmark

Можно комбинировать критерии в одном правиле. Например, трафик от 192.168.10.5 с меткой 2 направить в таблицу vpn:

ip rule add from 192.168.10.5 fwmark 2 table vpn priority 50

Ядро проверяет все условия правила. Если пакет удовлетворяет и from, и fwmark - применяется указанная таблица. Если нет - поиск продолжается по следующим правилам. Приоритеты расставляйте так, чтобы более специфичные правила имели меньший номер priority.

Практический сценарий: Multi-WAN с балансировкой нагрузки

Сервер с двумя внешними интерфейсами: eth0 подключён к ISP1 (шлюз 10.0.0.1), eth1 к ISP2 (шлюз 10.0.1.1). Внутренняя сеть - 192.168.0.0/24. Задача: балансировать исходящий трафик клиентов между провайдерами, при отказе одного канала весь трафик направлять через оставшийся, и закрепить бухгалтерию (192.168.0.10-192.168.0.20) за ISP1.

Настройка таблиц для каждого провайдера

Создайте таблицы в /etc/iproute2/rt_tables:

100 isp1
200 isp2

Заполните маршрутами:

ip route add 10.0.0.0/24 dev eth0 table isp1
ip route add default via 10.0.0.1 dev eth0 table isp1

ip route add 10.0.1.0/24 dev eth1 table isp2
ip route add default via 10.0.1.1 dev eth1 table isp2

Балансировка исходящего трафика с помощью multipath

Добавьте в таблицу main маршрут по умолчанию с несколькими nexthop:

ip route add default scope global nexthop via 10.0.0.1 dev eth0 weight 1 nexthop via 10.0.1.1 dev eth1 weight 1

Параметр weight задаёт пропорцию распределения. При равных весах трафик делится 50/50. Современные ядра (5.x и 6.x) балансируют per-flow: все пакеты одного TCP-соединения идут через один и тот же шлюз. Это предотвращает проблемы с асимметричной маршрутизацией и сохранением сессий.

Обеспечение отказоустойчивости (failover)

Ядро само отслеживает доступность nexthop через механизм neighbour detection. Если шлюз 10.0.0.1 перестаёт отвечать на ARP-запросы, ядро исключает его из multipath и весь трафик идёт через 10.0.1.1. Для более быстрого обнаружения можно настроить скрипт с периодическим ping и удалением/добавлением nexthop. Альтернатива - keepalived с отслеживанием состояния интерфейсов. Базовая проверка: ping -I eth0 10.0.0.1 и ping -I eth1 10.0.1.1.

Привязка внутренних подсетей к конкретным WAN-каналам

Для бухгалтерии создайте правило, указывающее таблицу isp1:

ip rule add from 192.168.0.10/28 table isp1 priority 50

Трафик от этих адресов всегда пойдёт через ISP1, независимо от балансировки в таблице main. Остальные клиенты продолжат использовать multipath.

Защита от IP-спуфинга с помощью source-based routing

IP-спуфинг - атака, при которой злоумышленник отправляет пакеты с поддельным адресом отправителя. Маршрутизатор, не проверяющий источник, пропускает такие пакеты. Source-based routing позволяет реализовать strict Reverse Path Forwarding - проверку, что пакет с адресом источника из определённой сети пришёл через интерфейс, который действительно подключён к этой сети.

Принцип Reverse Path Forwarding (RPF)

Strict RPF требует, чтобы маршрут к адресу источника пакета проходил через тот же интерфейс, с которого пакет пришёл. Ядро Linux поддерживает RPF через параметр rp_filter, но он работает только для таблицы main. PBR даёт более гибкий контроль: можно создать правила для каждого интерфейса и явно указать, какие сети ожидаются на каждом входном интерфейсе.

Настройка правил для проверки источника

Предположим, внутренний интерфейс eth1 подключён к сети 192.168.1.0/24. Создайте правило, которое для пакетов, пришедших с eth1 и имеющих source IP из этой сети, использует таблицу main:

ip rule add from 192.168.1.0/24 iif eth1 table main priority 100

Добавьте завершающее правило, блокирующее всё остальное с eth1:

ip rule add iif eth1 unreachable priority 101

Теперь пакет с source IP 192.168.1.5, пришедший с eth1, пройдёт проверку и будет обработан. Пакет с source IP 10.0.0.5, пришедший с eth1, попадёт под правило 101 и будет отброшен. Аналогичные правила создаются для каждого интерфейса. Проверка: попытка отправить пакет с поддельным адресом с другого интерфейса не пройдёт.

Сохранение конфигурации и автозапуск

Правила ip rule и маршруты в пользовательских таблицах не сохраняются после перезагрузки. Для production-среды настройки должны применяться автоматически.

Сохранение через /etc/network/interfaces (Debian/Ubuntu)

Для систем с ifupdown добавьте post-up команды в описание интерфейса:

auto eth0
iface eth0 inet static
    address 10.0.0.2/24
    post-up ip route add default via 10.0.0.1 dev eth0 table isp1
    post-up ip rule add from 192.168.10.0/24 table isp1 priority 100

Использование systemd-networkd

Создайте файл /etc/systemd/network/10-eth0.network:

[Match]
Name=eth0

[Network]
Address=10.0.0.2/24

[Route]
Destination=0.0.0.0/0
Gateway=10.0.0.1
Table=100

[RoutingPolicyRule]
From=192.168.10.0/24
Table=100
Priority=100

После создания файла выполните systemctl restart systemd-networkd. Настройки применятся и сохранятся при перезагрузке.

Создание собственного systemd-сервиса

Универсальный метод для любого дистрибутива с systemd. Создайте скрипт /usr/local/bin/pbr-setup.sh с командами ip route и ip rule. Сделайте его исполняемым: chmod +x /usr/local/bin/pbr-setup.sh. Создайте юнит /etc/systemd/system/pbr-setup.service:

[Unit]
Description=Setup Policy-Based Routing
After=network-online.target
Wants=network-online.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/pbr-setup.sh
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target

Активируйте: systemctl enable pbr-setup.service && systemctl start pbr-setup.service. Сервис выполнит скрипт после поднятия сети.

Диагностика и решение типичных проблем

Ошибки при настройке PBR возникают по трём основным причинам: неверный порядок правил, отсутствие маршрута к шлюзу в пользовательской таблице и асимметричная маршрутизация.

Инструменты отладки: ip route get, tcpdump, логи ядра

Команда ip route get - главный инструмент. Она показывает полный путь пакета: выбранную таблицу, шлюз, интерфейс. Запускайте с разными параметрами:

ip route get 8.8.8.8 from 192.168.10.5 iif eth1 mark 1

tcpdump фиксирует реальное движение пакетов. Запустите на всех интерфейсах одновременно, чтобы отследить вход и выход: tcpdump -i any host 8.8.8.8 -n. Логи martian-пакетов включаются через echo 1 > /proc/sys/net/ipv4/conf/all/log_martians. Записи появятся в dmesg или syslog.

Частые ошибки и их решение

Ошибка «RTNETLINK answers: Network is unreachable». Возникает при добавлении маршрута с next-hop, который недоступен напрямую. Решение: добавьте маршрут к сети шлюза в ту же таблицу перед default-маршрутом.

Правило ip rule не срабатывает. Проверьте приоритеты: более специфичное правило должно иметь меньший номер priority. Проверьте синтаксис условия - from принимает префикс сети, а не диапазон. Команда ip rule show выведет все правила с приоритетами.

Трафик уходит, но ответы не возвращаются. Это асимметричная маршрутизация: пакеты уходят через eth0, а ответы приходят на eth1. Решение: настройте connection tracking (conntrack), чтобы ядро запоминало, через какой интерфейс ушёл запрос, и ожидало ответ на том же интерфейсе. Альтернатива - привязка внутренних подсетей к конкретным WAN-каналам через ip rule, как описано в разделе Multi-WAN.

Потеря связности после применения правил. Если вы работаете по SSH и добавили правило, которое перенаправляет ваш трафик в таблицу без маршрута, соединение разорвётся. Работайте через консоль сервера или добавьте правило для вашего IP-адреса, возвращающее трафик в main, до применения общих правил.

Поделиться:
Сохранить гайд? В закладки браузера