Балансировка нагрузки и отказоустойчивость каналов связи: настройка маршрутизации и failover | AdminWiki

Балансировка нагрузки и отказоустойчивость каналов связи: настройка маршрутизации и failover

12 августа 2026 11 мин. чтения

Зачем нужна балансировка нагрузки и failover: типовые сценарии

Офис с двумя интернет-каналами по 100 Мбит/с от разных провайдеров обходится дешевле одного канала на 200 Мбит/с от корпоративного оператора. При этом два канала дают не только экономию, но и резервирование: при аварии на линии первого провайдера трафик автоматически уходит через второго. Эта схема называется multi-WAN и решает три задачи одновременно: снижение затрат на связь, увеличение суммарной пропускной способности и защиту от простоев.

Для критичных сервисов, таких как VPN-туннели между офисами или публичные веб-серверы, отказоустойчивость становится обязательной. Даже 15 минут недоступности почтового сервера или корпоративного портала оборачиваются потерянными заявками и репутационным ущербом. Правильно настроенный failover переключает трафик на резервный канал за секунды, без ручного вмешательства администратора.

В этой статье разобраны практические методы: ECMP-балансировка через ip route с весами nexthop, policy routing для разделения трафика по типам и источникам, автоматическое переключение при сбоях с помощью скриптов и keepalived. Конфигурации приведены для Linux, Cisco IOS и MikroTik RouterOS. Все примеры проверены на практике и актуальны для 2026 года.

Основы многопутевой маршрутизации: ECMP и policy routing

Ядро Linux поддерживает многопутевую маршрутизацию через механизм ECMP (Equal-Cost Multi-Path). Когда в таблице маршрутизации есть несколько записей с одинаковой метрикой для одной сети назначения, ядро распределяет исходящие пакеты между ними. Решение о выборе конкретного пути принимается на основе хеша от заголовков пакета: обычно используются IP-адреса источника и назначения, порты и протокол. Это гарантирует, что все пакеты одного TCP-соединения пойдут по одному и тому же маршруту, сохраняя порядок доставки.

Policy routing расширяет стандартную маршрутизацию, позволяя принимать решение не только по адресу назначения, но и по источнику трафика, метке пакета (fwmark) или входящему интерфейсу. Этот механизм незаменим, когда нужно направить VoIP-трафик через канал с минимальной задержкой, а почтовый трафик - через более дешёвый, но менее стабильный линк.

ECMP: как работает балансировка на основе весов

В команде ip route параметр weight задаёт пропорцию распределения трафика между шлюзами. Если у первого провайдера канал 100 Мбит/с, а у второго 50 Мбит/с, веса 2 и 1 обеспечат пропорциональное использование полосы. Ядро не измеряет реальную загрузку канала - оно статистически распределяет новые соединения согласно весам. Для одного и того же соединения маршрут фиксируется в conntrack-таблице, что исключает переброс пакетов между каналами и разрыв сессии.

Ограничения ECMP: балансировка работает на уровне потоков (per-flow), а не пакетов (per-packet). Один "тяжёлый" поток, например загрузка ISO-образа, пойдёт только через один канал и не будет разделён между провайдерами. Кроме того, статический ECMP не отслеживает состояние шлюза: если канал провайдера "упал", но интерфейс на маршрутизаторе остаётся активным, ядро продолжит отправлять пакеты в "чёрную дыру". Для решения этой проблемы нужны механизмы failover, описанные в следующем разделе.

Policy routing: управление трафиком на основе правил

Policy routing настраивается через ip rule и дополнительные таблицы маршрутизации. По умолчанию ядро использует таблицу main (id 254), но можно создать произвольное количество пользовательских таблиц. Правило в ip rule определяет условие (например, "пакет пришёл с IP 192.168.1.100") и указывает, в какой таблице искать маршрут для этого пакета.

Типичный сценарий: весь трафик от бухгалтерии направляется через провайдера А, а трафик от отдела разработки - через провайдера Б. Для этого создаются две таблицы маршрутизации, в каждой прописан свой шлюз по умолчанию, а затем добавляются правила ip rule, привязывающие исходные IP-адреса к соответствующим таблицам. Маркировка пакетов (fwmark) через iptables или nftables даёт ещё более гибкий контроль: можно разделять трафик по портам назначения, протоколам или даже доменным именам после разрешения DNS.

Настройка балансировки нагрузки на Linux с помощью ip route и nexthop

Для настройки ECMP-балансировки между двумя провайдерами используется команда ip route add с несколькими блоками nexthop. Каждый блок описывает отдельный шлюз и его вес. Обязательное условие: для каждого исходящего интерфейса должен быть настроен NAT (MASQUERADE в iptables или nftables), иначе обратные пакеты не вернутся на маршрутизатор.

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

Исходные данные: провайдер ISP1 подключён к интерфейсу eth0, шлюз 192.168.1.1, сеть 192.168.1.0/24; провайдер ISP2 подключён к интерфейсу eth1, шлюз 10.0.0.1, сеть 10.0.0.0/24. Локальная сеть: eth2, 192.168.100.0/24. Настроим балансировку с весами 2:1.

# Добавление маршрута по умолчанию с двумя nexthop
ip route add default \
  nexthop via 192.168.1.1 dev eth0 weight 2 \
  nexthop via 10.0.0.1 dev eth1 weight 1

# NAT для обоих провайдеров (iptables)
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

# NAT для nftables
echo 'table ip nat {
  chain postrouting {
    type nat hook postrouting priority srcnat;
    oifname "eth0" masquerade
    oifname "eth1" masquerade
  }
}' > /etc/nftables.d/multi-wan.nft

Для сохранения маршрута после перезагрузки добавьте его в конфигурацию сетевых интерфейсов. В Debian/Ubuntu используется файл /etc/network/interfaces, в RHEL/AlmaLinux - /etc/sysconfig/network-scripts/route-<интерфейс>. Альтернативный вариант - systemd-networkd с секцией [Route] и несколькими Gateway.

Проверка распределения трафика

Команда ip route get позволяет проверить, какой шлюз будет выбран для конкретного адреса назначения. Ядро рассчитывает хеш на основе параметров соединения, поэтому для разных IP-адресов результат будет разным:

# Проверка маршрута до 8.8.8.8
ip route get 8.8.8.8
# Вывод: 8.8.8.8 via 192.168.1.1 dev eth0 src 192.168.1.100

# Проверка маршрута до 1.1.1.1
ip route get 1.1.1.1
# Вывод: 1.1.1.1 via 10.0.0.1 dev eth1 src 10.0.0.100

Для массовой проверки запустите несколько запросов curl к сервисам, возвращающим ваш внешний IP. Примерно две трети запросов должны показать IP первого провайдера, одна треть - второго. Команда для тестирования:

for i in {1..30}; do curl -s ifconfig.me; echo; done | sort | uniq -c

Реализация failover: автоматическое переключение при сбое канала

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

Существует три подхода: самописный скрипт мониторинга, демон keepalived с отслеживанием интерфейсов и протокол BFD для быстрого обнаружения сбоев на уровне миллисекунд. Выбор зависит от требований ко времени восстановления и сложности инфраструктуры.

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

Скрипт на bash, запускаемый по cron каждые 10 секунд, проверяет доступность шлюза провайдера через ping. При трёх последовательных неудачах маршрут по умолчанию заменяется на резервный. Когда основной канал восстанавливается, маршрут возвращается к исходной конфигурации.

#!/bin/bash
PRIMARY_GW="192.168.1.1"
BACKUP_GW="10.0.0.1"
PRIMARY_IF="eth0"
BACKUP_IF="eth1"
TARGET="8.8.8.8"
FAIL_COUNT=0
MAX_FAIL=3

# Проверка через ping с указанием интерфейса
ping -I $PRIMARY_IF -c 1 -W 2 $TARGET > /dev/null 2>&1
if [ $? -ne 0 ]; then
  FAIL_COUNT=$((FAIL_COUNT + 1))
  echo "$(date): Primary link failure #$FAIL_COUNT" >> /var/log/failover.log
fi

if [ $FAIL_COUNT -ge $MAX_FAIL ]; then
  # Замена маршрута по умолчанию
  ip route replace default via $BACKUP_GW dev $BACKUP_IF
  echo "$(date): Switched to backup link" >> /var/log/failover.log
fi

Недостатки этого подхода: время реакции ограничено интервалом cron (минимум 60 секунд для стандартного cron, или требуется дополнительная настройка systemd-таймеров). Ложные срабатывания возможны при кратковременных всплесках задержки. Для production-сред рекомендуется использовать keepalived.

Использование keepalived для отслеживания каналов

Keepalived реализует протокол VRRP и может управлять не только виртуальными IP-адресами, но и маршрутами. Демон отслеживает состояние интерфейса или доступность удалённого хоста через механизм track_script и при сбое изменяет приоритет виртуального маршрутизатора, что приводит к переключению маршрута по умолчанию.

Пример конфигурации keepalived для отслеживания двух каналов и переключения между ними:

vrrp_script chk_primary {
  script "/usr/bin/ping -I eth0 -c 1 -W 1 8.8.8.8"
  interval 2
  weight -10
  fall 3
  rise 2
}

vrrp_instance WAN_FAILOVER {
  state MASTER
  interface eth2
  virtual_router_id 51
  priority 100
  advert_int 1

  track_script {
    chk_primary
  }

  notify_master "/usr/local/bin/switch-to-backup.sh"
  notify_backup "/usr/local/bin/switch-to-primary.sh"
}

При падении основного канала приоритет экземпляра снижается на 10, keepalived переходит в состояние BACKUP и выполняет скрипт переключения маршрута. Время реакции - 3-6 секунд, что приемлемо для большинства корпоративных сценариев. Для более быстрого обнаружения сбоев на маршрутизаторах Cisco и MikroTik используйте BFD, который детектирует отказ за 50-300 мс.

Настройка на сетевом оборудовании: Cisco и MikroTik

Принципы многопутевой маршрутизации универсальны, но реализация на специализированном оборудовании имеет особенности. Cisco IOS использует статические маршруты с разными административными расстояниями и объекты track для отслеживания доступности. MikroTik RouterOS предлагает метод PCC (Per Connection Classifier) для балансировки и встроенную проверку шлюза через check-gateway.

Cisco: статические маршруты с отслеживанием доступности

На маршрутизаторах Cisco настраиваются два статических маршрута по умолчанию с разными административными расстояниями (AD). Маршрут с меньшим AD является основным. Объект track отслеживает доступность удалённого хоста через ICMP-эхо-запросы. При недоступности хоста track переводит основной маршрут в неактивное состояние, и трафик уходит через резервный маршрут с более высоким AD.

! Настройка отслеживания доступности
ip sla 1
 icmp-echo 8.8.8.8 source-interface GigabitEthernet0/0
 frequency 5
ip sla schedule 1 life forever start-time now

track 1 ip sla 1 reachability
 delay down 15 up 10

! Статические маршруты с разными AD
ip route 0.0.0.0 0.0.0.0 192.168.1.1 track 1
ip route 0.0.0.0 0.0.0.0 10.0.0.1 10

! Проверка состояния
show ip route static
show track 1

Для балансировки нагрузки Cisco поддерживает ECMP из коробки: достаточно указать несколько статических маршрутов с одинаковым AD. Маршрутизатор автоматически распределяет потоки на основе хеша от IP-адресов и портов. Настройка CEF (Cisco Express Forwarding) выполняется по умолчанию на современных платформах.

MikroTik: балансировка PCC и проверка шлюза

Per Connection Classifier (PCC) в RouterOS разделяет трафик по соединениям на основе заданных полей заголовка. В mangle-правилах настраивается классификатор, который маркирует каждое соединение, а затем маршруты с соответствующими маркировками направляют трафик через нужные шлюзы. Этот метод точнее стандартного ECMP, так как позволяет балансировать даже внутри одной подсети назначения.

Базовая конфигурация PCC для двух провайдеров:

# Маркировка соединений (mangle)
/ip firewall mangle
add chain=prerouting in-interface=LAN \
  connection-mark=no-mark \
  per-connection-classifier=both-addresses-and-ports:2/0 \
  action=mark-connection new-connection-mark=ISP1_conn
add chain=prerouting in-interface=LAN \
  connection-mark=no-mark \
  per-connection-classifier=both-addresses-and-ports:2/1 \
  action=mark-connection new-connection-mark=ISP2_conn

# Маркировка маршрутов
/ip firewall mangle
add chain=prerouting connection-mark=ISP1_conn \
  in-interface=LAN action=mark-routing new-routing-mark=to_ISP1
add chain=prerouting connection-mark=ISP2_conn \
  in-interface=LAN action=mark-routing new-routing-mark=to_ISP2

# Маршруты с проверкой шлюза
/ip route
add dst-address=0.0.0.0/0 gateway=192.168.1.1 \
  routing-mark=to_ISP1 check-gateway=ping
add dst-address=0.0.0.0/0 gateway=10.0.0.1 \
  routing-mark=to_ISP2 check-gateway=ping

Опция check-gateway=ping заставляет RouterOS периодически проверять доступность шлюза. При недоступности маршрут временно деактивируется, и трафик уходит через оставшийся канал. Для более тонкой настройки используйте рекурсивные маршруты с проверкой через удалённый хост, например 8.8.8.8, а не только шлюз провайдера. Это защищает от ситуаций, когда шлюз доступен, но магистраль провайдера не работает.

Мониторинг доступности и критерии выбора оптимального маршрута

Простая проверка "пинг проходит/не проходит" недостаточна для принятия решений о переключении каналов. Канал может работать с приемлемой задержкой, но терять 5% пакетов, что критично для VoIP, но терпимо для почты. Мониторинг должен собирать три метрики: задержку (RTT), джиттер (вариацию задержки) и процент потерь пакетов.

Инструменты для сбора статистики: mtr (My Traceroute) показывает маршрут и потери на каждом хопе в реальном времени, smokeping строит графики задержки за длительный период, bmon или iftop отслеживают утилизацию полосы. На основе этих данных можно написать скрипт, который динамически изменяет веса nexthop или полностью исключает канал с деградировавшим качеством из маршрутизации.

Критерии переключения зависят от типа трафика. Для VPN-туннелей и терминальных сессий критичен джиттер: значение выше 30 мс делает работу некомфортной. Для HTTP-трафика допустимы потери до 2% без заметного ухудшения пользовательского опыта. Коммерческие SD-WAN-решения выполняют такой анализ автоматически, но на базе Linux можно построить аналогичную логику с помощью скриптов, взаимодействующих с ip route и conntrack.

Типичные ошибки и их устранение

Асимметричная маршрутизация и обрыв TCP-сессий. Пакеты запроса уходят через одного провайдера, а ответы возвращаются через другого. Stateful-файрвол на стороне клиента или провайдера отбрасывает такие пакеты, так как не видит начала соединения. Решение: привязка соединений к одному каналу через conntrack и policy routing. Маршрутизация на основе fwmark гарантирует, что все пакеты одного соединения пойдут через один и тот же шлюз. Подробнее эта проблема и методы её решения разобраны в статье об асимметричной маршрутизации.

Проблемы с NAT. Для каждого исходящего интерфейса должен быть настроен SNAT или MASQUERADE. Если пакет уходит через eth1 с исходным IP-адресом, принадлежащим сети eth0, обратный трафик не дойдёт до маршрутизатора. Проверьте, что правила NAT охватывают все интерфейсы, через которые может уходить трафик. В nftables это делается явным перечислением oifname, в iptables - отдельными правилами для каждого интерфейса.

Забытые обратные маршруты у провайдеров. Некоторые провайдеры применяют фильтрацию исходящего трафика (uRPF) и отбрасывают пакеты с IP-адресами, не принадлежащими их сети. При использовании нескольких каналов убедитесь, что каждый провайдер знает о вашей локальной сети через BGP-анонсы или статические маршруты на их стороне.

Слишком агрессивный мониторинг. Проверка доступности каждую секунду с таймаутом 500 мс приводит к ложным переключениям при кратковременных флуктуациях задержки. Рекомендуемый интервал - 5-10 секунд с порогом в 3 последовательных неудачи перед переключением. Для BFD допустимы более агрессивные настройки, так как протокол спроектирован для быстрого обнаружения сбоев без ложных срабатываний.

Готовые конфигурации для multi-WAN с использованием nftables и mwan3, а также примеры настройки policy routing с ip rule рассмотрены в руководстве по настройке multi-WAN. Для более глубокого понимания основ маршрутизации, включая протоколы BGP и OSPF, обратитесь к статье об основах маршрутизации в 2026 году.

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