Source-based маршрутизация в Linux: Разделение и балансировка трафика по нескольким шлюзам | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Source-based маршрутизация в Linux: Разделение и балансировка трафика по нескольким шлюзам

06 июня 2026 13 мин. чтения

Source-based маршрутизация в Linux - это мощный механизм для управления исходящим трафиком через несколько интернет-каналов. Она позволяет распределять нагрузку между провайдерами, организовывать отказоустойчивые схемы и разделять трафик разных сервисов. Это руководство содержит проверенные на практике конфигурации для iproute2, iptables и nftables, которые можно скопировать и адаптировать под вашу сетевую инфраструктуру.

Вы получите готовые решения для двух ключевых подходов: статическое разделение по исходному IP-адресу и гибкую балансировку с маркировкой пакетов (fwmark). Каждый шаг сопровождается командами для немедленного применения и тестирования.

Зачем нужна source-based маршрутизация: сценарии и выбор подхода

Source-based маршрутизация решает задачи, где стандартной таблицы маршрутизации недостаточно. Она полезна при наличии двух или более внешних каналов связи. Основные сценарии применения - балансировка нагрузки, отказоустойчивость и разделение трафика.

Балансировка нагрузки распределяет исходящий трафик между несколькими каналами. Это увеличивает общую пропускную способность. Отказоустойчивая схема обеспечивает автоматическое переключение на резервный канал при падении основного. Разделение трафика направляет трафик определенных сервисов или подсетей через выделенный канал. Например, VoIP-трафик можно направить через канал с низкой задержкой, а фоновые задачи - через более дешевый.

В Linux реализованы два основных подхода. Первый - маршрутизация на основе исходного IP-адреса. Второй - маркировка пакетов с последующей маршрутизацией по метке (fwmark).

Source IP vs Fwmark: что выбрать для вашего кейса

Выбор метода зависит от требований к гибкости и сложности сетевой архитектуры.

Критерий Source-based routing (по исходному IP) Маршрутизация по fwmark
Принцип работы Правило ip rule сопоставляет исходный IP-адрес пакета с таблицей маршрутизации. Пакет помечается правилом iptables/nftables. Правило ip rule сопоставляет метку (fwmark) с таблицей маршрутизации.
Сложность настройки Низкая. Требует только настройки iproute2. Средняя. Требует согласованной работы iproute2 и фаервола (iptables/nftables).
Гибкость Ограниченная. Привязка к статическим IP-адресам или подсетям. Высокая. Маркировка возможна по любому критерию: порт, протокол, интерфейс, состояние соединения.
Балансировка нагрузки (Load Balancing) Только простейшая, на уровне подсетей. Полноценная. Возможна балансировка round-robin, по вероятности, на основе портов.
Отказоустойчивость (Failover) Реализуется через метрики маршрутов или скрипты мониторинга. Реализуется через метрики маршрутов или скрипты мониторинга.
Идеальный сценарий Статичное разделение трафика между фиксированными подсетями или серверами. Динамическая балансировка трафика приложений, разделение по типам сервисов (HTTP, SSH, VoIP).

Выбирайте source IP маршрутизацию для простых задач разделения, где источники трафика известны и статичны. Метод fwmark подходит для сложных сценариев, где решение о маршруте должно приниматься на основе параметров L4 (порт, протокол) или требует динамической балансировки.

Подготовка сети и проверка совместимости

Перед началом настройки убедитесь в совместимости системы и определите текущую конфигурацию. Инструкции проверены для дистрибутивов на базе ядра Linux 5.4 и новее, включая Ubuntu 22.04 LTS, Debian 11/12, CentOS/RHEL 8/9 и их производные. Обязательные пакеты: iproute2, iptables или nftables.

Типовая схема для настройки - сервер с двумя сетевыми интерфейсами, каждый из которых подключен к своему провайдеру. Интерфейс eth0 имеет адрес 192.168.1.10/24 и шлюз по умолчанию 192.168.1.1. Интерфейс eth1 - адрес 192.168.2.10/24 и шлюз 192.168.2.1. Альтернативный вариант - один физический интерфейс с несколькими VLAN или политиками маршрутизации.

Проверка версий ПО и текущей конфигурации маршрутизации

Выполните эти команды для сбора информации о системе. Сохраните вывод - он поможет вернуть конфигурацию в исходное состояние в случае ошибки.

# Проверка версий ключевых утилит
ip -V
iptables --version  # или nft --version

# Просмотр сетевых интерфейсов и их адресов
ip addr show

# Анализ основной таблицы маршрутизации
ip route show table main

# Проверка текущих правил маршрутизации
ip rule show

Обратите внимание на строку default via ... в выводе ip route show. Это текущий шлюз по умолчанию. В системе с несколькими активными шлюзами может присутствовать только один маршрут по умолчанию с наименьшей метрикой. Рекомендуется проводить настройки в тестовой среде или иметь план отката. Для сохранения конфигурации после перезагрузки используйте сетевые менеджеры (netplan, systemd-networkd) или помещайте команды в скрипты в директории /etc/network/if-up.d/.

Готовая конфигурация: source-based маршрутизация по исходному IP

Этот метод привязывает маршрут к исходному IP-адресу или подсети. Он прост в настройке и подходит для статичного разделения, когда определенные серверы или подсети должны всегда использовать конкретный внешний канал.

Принцип работы: для каждого канала создается отдельная таблица маршрутизации (например, 100 и 200). В каждую таблицу добавляется свой маршрут по умолчанию через соответствующий шлюз. Затем создаются правила ip rule, которые для пакетов с определенного исходного IP указывают ядру использовать не основную таблицу (main), а одну из созданных.

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

Предположим, у нас есть две внутренние подсети: 192.168.10.0/24 должна выходить в интернет через провайдера A (шлюз 192.168.1.1), а 192.168.20.0/24 - через провайдера B (шлюз 192.168.2.1).

Схема сети:
[Внутренняя сеть 192.168.10.0/24] -> [Linux-маршрутизатор (eth0:192.168.1.10)] -> [Шлюз провайдера A: 192.168.1.1]
[Внутренняя сеть 192.168.20.0/24] -> [Linux-маршрутизатор (eth1:192.168.2.10)] -> [Шлюз провайдера B: 192.168.2.1]

Выполните команды последовательно:

# 1. Создание таблиц маршрутизации и добавление маршрутов по умолчанию
ip route add default via 192.168.1.1 dev eth0 table 100
ip route add default via 192.168.2.1 dev eth1 table 200

# 2. Добавление правил для выбора таблицы на основе исходного адреса
ip rule add from 192.168.10.0/24 lookup 100 priority 1000
ip rule add from 192.168.20.0/24 lookup 200 priority 1010

# 3. (Важно!) Добавление правил для ответного трафика с внешних интерфейсов.
# Это гарантирует, что ответы на входящие соединения вернутся через тот же интерфейс.
ip rule add iif eth0 lookup 100 priority 1020
ip rule add iif eth1 lookup 200 priority 1030

Пояснение:
table 100 и table 200 - имена (номера) пользовательских таблиц маршрутизации.
priority в правилах определяет порядок их обработки. Чем меньше число, тем выше приоритет.
• Правила с iif (input interface) обрабатывают пакеты, пришедшие на указанный интерфейс, обеспечивая корректную асимметричную маршрутизацию для входящих соединений.

Для сохранения конфигурации в Ubuntu с Netplan создайте файл, например, /etc/netplan/99-routing-policy.yaml:

network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      addresses: [192.168.1.10/24]
      routes:
        - to: 0.0.0.0/0
          via: 192.168.1.1
          table: 100
      routing-policy:
        - from: 192.168.10.0/24
          table: 100
        - from: 192.168.1.0/24
          table: 100
    eth1:
      addresses: [192.168.2.10/24]
      routes:
        - to: 0.0.0.0/0
          via: 192.168.2.1
          table: 200
      routing-policy:
        - from: 192.168.20.0/24
          table: 200
        - from: 192.168.2.0/24
          table: 200

Примените конфигурацию: sudo netplan apply. Для диагностики сложных проблем с обратным трафиком изучите наше руководство по асимметричной маршрутизации, где разобраны все типичные сценарии и решения.

Гибкая балансировка через маркировку пакетов (fwmark)

Маршрутизация по меткам (fwmark) предоставляет максимальную гибкость. Решение о том, через какой шлюз отправить пакет, принимается на основе правил фаервола, которые могут анализировать не только IP-адреса, но и порты, протоколы или состояние соединения.

Принцип работы: цепочка правил в iptables или nftables помечает исходящие пакеты, присваивая им числовую метку. Отдельное правило ip rule add fwmark <метка> предписывает ядру искать маршрут для помеченных пакетов в указанной таблице маршрутизации. Этот метод идеален для балансировки нагрузки и сложного разделения трафика.

Балансировка всего исходящего трафика (round-robin)

Этот пример равномерно распределяет весь исходящий трафик между двумя шлюзами. Мы используем nftables как более современную альтернативу iptables.

Сначала создаем таблицы маршрутизации и правила для меток:

# Создание таблиц маршрутизации
ip route add default via 192.168.1.1 dev eth0 table 101
ip route add default via 192.168.2.1 dev eth1 table 102

# Создание правил маршрутизации для меток 1 и 2
ip rule add fwmark 1 lookup 101 priority 1100
ip rule add fwmark 2 lookup 102 priority 1110

# Правило для ответного трафика (конечно-адресная маршрутизация)
ip rule add from 192.168.1.10 lookup 101 priority 1120
ip rule add from 192.168.2.10 lookup 102 priority 1130

Теперь настроим nftables для вероятностной маркировки пакетов. Создайте файл /etc/nftables.conf со следующим содержимым:

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

table inet mangle {
    chain output {
        type route hook output priority mangle; policy accept;
        # С вероятностью 50% помечаем пакет меткой 1, иначе меткой 2.
        # numgen возвращает 0 или 1 с равной вероятностью.
        meta mark set numgen inc mod 2 map { 0 : 0x1, 1 : 0x2 }
    }
}

Загрузите правила: sudo nft -f /etc/nftables.conf. Теперь исходящие пакеты будут помечаться метками 1 или 2 с вероятностью 50% и направляться в соответствующие таблицы маршрутизации. Для тонкой настройки балансировки, например, 70/30, используйте параметр mod в numgen.

Разделение трафика по типу (например, HTTP и SSH)

Более практичный пример - направлять веб-трафик (HTTP/HTTPS) через один канал, а служебный SSH - через другой. Это повышает безопасность и позволяет приоритизировать критичные сервисы.

Настройка таблиц и правил маршрутизации остается прежней. Меняется только цепочка маркировки в nftables:

table inet mangle {
    chain output {
        type route hook output priority mangle; policy accept;
        ip protocol tcp tcp dport { 80, 443 } meta mark set 0x1
        ip protocol tcp tcp dport 22 meta mark set 0x2
        # Все остальные пакеты идут через основную таблицу (main)
    }
}

Этот подход гораздо гибче привязки к IP. Вы можете маркировать трафик по любому критерию: протоколу (например, весь UDP), адресу назначения или даже по совпадению с состоянием соединения (ct state). Для построения более сложных сетевых архитектур, включая программные маршрутизаторы, изучите наше практическое руководство по программным маршрутизаторам на Linux.

Настройка отказоустойчивости (Failover) и мониторинга

Отказоустойчивость гарантирует, что при падении одного из каналов трафик автоматически переключится на резервный. Простейшие методы используют метрики маршрутов, но для production-сред требуются скрипты мониторинга.

Метод с метриками работает на уровне ядра. Маршрут с меньшей метрикой считается предпочтительным. Если он становится недоступным, ядро использует маршрут с большей метрикой. Однако реакция на обрыв канала может быть медленной, так как зависит от механизмов обнаружения мертвых соседей (neighbor discovery).

Простой failover через метрики маршрутов

Это базовая настройка, не требующая сложных скриптов. Добавьте в основную таблицу маршрутизации два маршрута по умолчанию с разными метриками.

# Основной шлюз (метрика 100, приоритет выше)
ip route add default via 192.168.1.1 dev eth0 metric 100
# Резервный шлюз (метрика 200, приоритет ниже)
ip route add default via 192.168.2.1 dev eth1 metric 200

Пока шлюз 192.168.1.1 доступен, весь трафик будет идти через него. Если соединение с ним разорвется, ядро начнет использовать маршрут через 192.168.2.1. Главный недостаток - задержка обнаружения проблемы может составлять десятки секунд. Для критически важных систем этого недостаточно.

Автоматический мониторинг и переключение скриптом

Надежное решение - скрипт, который периодически проверяет доступность шлюзов и динамически управляет правилами маршрутизации. Вот пример bash-скрипта для активного мониторинга.

Создайте файл /usr/local/bin/failover_monitor.sh:

#!/bin/bash
# Конфигурация
PRIMARY_GW="192.168.1.1"
BACKUP_GW="192.168.2.1"
PRIMARY_TABLE=101
BACKUP_TABLE=102
CHECK_INTERVAL=5
PING_COUNT=3
PING_TIMEOUT=2

LOG_FILE="/var/log/failover.log"

# Функция логирования
log() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"
}

# Проверка доступности шлюза
check_gateway() {
    local gw=$1
    if ping -c "$PING_COUNT" -W "$PING_TIMEOUT" "$gw" &> /dev/null; then
        return 0 # Шлюз доступен
    else
        return 1 # Шлюз недоступен
    fi
}

# Основной цикл
while true; do
    if check_gateway "$PRIMARY_GW"; then
        # Основной шлюз доступен. Активируем основную таблицу.
        if ! ip rule show | grep -q "from all lookup $PRIMARY_TABLE"; then
            ip rule add from all lookup $PRIMARY_TABLE priority 1000
            ip rule del from all lookup $BACKUP_TABLE priority 1010 2>/dev/null
            log "PRIMARY gateway restored. Traffic switched to table $PRIMARY_TABLE."
        fi
    else
        # Основной шлюз недоступен. Переключаемся на резервный.
        if ! ip rule show | grep -q "from all lookup $BACKUP_TABLE"; then
            ip rule del from all lookup $PRIMARY_TABLE priority 1000 2>/dev/null
            ip rule add from all lookup $BACKUP_TABLE priority 1010
            log "PRIMARY gateway FAILED. Traffic switched to table $BACKUP_TABLE."
        fi
    fi
    sleep $CHECK_INTERVAL
done

Сделайте скрипт исполняемым и создайте службу systemd для его автозапуска:

sudo chmod +x /usr/local/bin/failover_monitor.sh
sudo systemctl edit --force --full failover-monitor.service

Вставьте конфигурацию службы:

[Unit]
Description=Failover Monitor for Multi-WAN
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
ExecStart=/usr/local/bin/failover_monitor.sh
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

Запустите и включите службу:

sudo systemctl daemon-reload
sudo systemctl enable --now failover-monitor.service

Для мониторинга состояния используйте sudo systemctl status failover-monitor.service и просмотр лога tail -f /var/log/failover.log. Этот подход обеспечивает переключение за 5-10 секунд. Для интеграции в существующие системы мониторинга (Zabbix, Prometheus) расширьте скрипт отправкой метрик. Подобные задачи управления маршрутизацией также можно решать с помощью специализированного оборудования, например, маршрутизаторов Keenetic. Подробные конфигурации для них собраны в нашем руководстве по маршрутизации Keenetic.

Типичные проблемы, тестирование и верификация

После настройки необходимо убедиться в корректности работы и знать, как диагностировать типичные проблемы. Самая распространенная - асимметричная маршрутизация, когда пакеты в одном направлении идут по одному пути, а ответные - по другому. Это ломает stateful-фаерволы и NAT.

Решение проблемы асимметричной маршрутизации

Проблема возникает, когда сервер отправляет пакет через интерфейс eth0 с IP 192.168.1.10, но ответ от удаленного хоста приходит на адрес 192.168.2.10 интерфейса eth1. Stateful-фаервол на стороне сервера или провайдера не узнает это соединение и сбрасывает пакеты.

Решение - настроить Source NAT (MASQUERADE) на исходящих интерфейсах. Это гарантирует, что весь исходящий трафик с конкретного интерфейса будет иметь один внешний IP-адрес, и ответный трафик вернется на него же. Для nftables добавьте в таблицу nat:

table ip nat {
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        oifname "eth0" masquerade
        oifname "eth1" masquerade
    }
}

Для iptables команды будут:

sudo iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

Это правило заменяет исходный IP-адрес пакета на адрес того интерфейса, через который он уходит. Второй вариант - согласовать политики маршрутизации с провайдерами, что на практике часто невозможно. Если вы работаете с туннелями (VPN, V2Ray), проблема асимметрии также актуальна. Готовые решения для селективной маршрутизации в таких сценариях вы найдете в статье про настройку V2RayTUN.

Команды для проверки работы маршрутизации

Используйте этот набор команд для пошаговой проверки и диагностики.

Задача Команда Ожидаемый результат
Проверить выбранный маршрут для конкретного исходного IP ip route get 8.8.8.8 from 192.168.10.50 Вывод должен показать, что пакет от 192.168.10.50 к 8.8.8.8 пойдет через нужный шлюз (например, 192.168.1.1 dev eth0).
Проверить выбранный маршрут для пакета с меткой ip route get 8.8.8.8 mark 1 Должен показать маршрут из таблицы, связанной с fwmark 1.
Визуализировать путь трассировки с указанием исходного IP traceroute -s 192.168.10.50 8.8.8.8 Первый хоп после вашего сервера должен быть IP-адресом выбранного шлюза.
Проверить, с какого внешнего IP видит сервер целевой хост curl --interface eth0 ifconfig.co curl --interface eth1 ifconfig.co Должны вернуться разные публичные IP-адреса, соответствующие каждому каналу.
Проанализировать метки пакетов в реальном времени sudo tcpdump -i any -vv -n "ip and (ip[1] & 0x07) != 0" (упрощенно) или использование nftables trace. Позволяет увидеть, какие пакеты помечаются.
Просмотреть все активные правила маршрутизации ip rule show Список всех правил с приоритетами. Убедитесь, что ваши правила присутствуют.
Просмотреть содержимое конкретной таблицы маршрутизации ip route show table 100 Должны отобразиться маршруты, добавленные в эту таблицу.

Для комплексной диагностики сетевых проблем, выходящих за рамки source-based маршрутизации, используйте наше практическое руководство по диагностике сетевой маршрутизации. Оно содержит готовые алгоритмы работы с traceroute, mtr и ip route для поиска точек обрыва, проблем с MTU и асимметричной маршрутизацией.

Source-based маршрутизация - мощный инструмент для построения отказоустойчивых и производительных сетевых конфигураций. Начните с простого разделения по IP, а для сложных сценариев динамической балансировки используйте маркировку fwmark. Не забывайте настраивать Source NAT для корректной работы с ответным трафиком и внедряйте мониторинг для production-сред. Представленные конфигурации являются рабочими шаблонами и требуют адаптации под конкретные IP-адреса и сетевую топологию.

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