PCC балансировка нагрузки на MikroTik
PCC балансировка нагрузки между провайдерами на MikroTik
PCC (Per Connection Classifier) — механизм классификации соединений в MikroTik, позволяющий распределить исходящий трафик между несколькими WAN-каналами. В отличие от ECMP, PCC гарантирует, что все пакеты одного соединения пойдут через одного провайдера, что критически важно для работы банковских систем, VPN и сессий с привязкой к IP. В этом руководстве настроим балансировку между двумя ISP с failover, разберём расширение до трёх WAN и решим типичные проблемы.
Описание
Зачем нужна балансировка нагрузки
Когда в организации два и более провайдера, хочется использовать оба канала одновременно, а не держать второй в резерве. Балансировка нагрузки решает эту задачу — трафик распределяется между каналами, увеличивая общую пропускную способность.
Сравнение методов балансировки
| Метод | Принцип | Плюсы | Минусы |
|---|---|---|---|
| PCC | Классификация по параметрам соединения (IP, порт) | Одно соединение = один ISP; гибкая настройка | Сложная конфигурация; требуется mangle |
| ECMP | Два default route с одинаковой distance | Простая настройка (2 строки) | Пакеты одного соединения могут идти через разных ISP; проблемы с NAT |
| Failover | Основной + резервный маршрут (distance) | Максимальная надёжность; простота | Второй канал простаивает при нормальной работе |
| Bonding | Объединение каналов на L2 | Полное объединение bandwidth | Требуется поддержка на стороне ISP (LACP) |
PCC — оптимальный выбор для большинства сценариев с двумя независимыми ISP.
Как работает PCC
PCC классифицирует каждое новое соединение на основе хеша выбранных полей пакета и распределяет его в одну из групп. Формат записи: per-connection-classifier=<поля>:<делитель>/<остаток>.
Поля для классификации:
both-addresses— src-address + dst-addressboth-addresses-and-ports— src-address + dst-address + src-port + dst-port (рекомендуется)src-address— только адрес источникаdst-address— только адрес назначенияboth-ports— src-port + dst-port
Пример: per-connection-classifier=both-addresses-and-ports:2/0 означает — если хеш от (src-addr, dst-addr, src-port, dst-port) при делении на 2 даёт остаток 0, то пакет попадает в эту группу.
Для двух ISP: делитель = 2, остатки 0 и 1. Для трёх ISP: делитель = 3, остатки 0, 1 и 2.
Архитектура сети
code[ISP 1] [ISP 2] 203.0.113.1/24 198.51.100.1/24 | | ether1 ether2 | | ┌────┴─────────────────────┴────┐ │ MikroTik Router │ │ ether1: 203.0.113.10/24 │ │ ether2: 198.51.100.10/24 │ │ bridge-lan: 192.168.88.1/24│ └──────────────┬───────────────┘ │ [LAN Switch] │ ┌────┬────┼────┬────┐ PC1 PC2 PC3 PC4 PC5
Настройка
Шаг 1: Базовая конфигурация интерфейсов
[admin@MikroTik] ># Именуем интерфейсы для удобства /interface/set ether1 comment="WAN1 - ISP1" /interface/set ether2 comment="WAN2 - ISP2" # Bridge для LAN /interface/bridge add name=bridge-lan /interface/bridge/port add bridge=bridge-lan interface=ether3 /interface/bridge/port add bridge=bridge-lan interface=ether4 /interface/bridge/port add bridge=bridge-lan interface=ether5 # IP-адреса /ip/address add address=203.0.113.10/24 interface=ether1 comment="WAN1" /ip/address add address=198.51.100.10/24 interface=ether2 comment="WAN2" /ip/address add address=192.168.88.1/24 interface=bridge-lan comment="LAN"
Если провайдер выдаёт IP по DHCP:
[admin@MikroTik] >/ip/dhcp-client add interface=ether1 add-default-route=no use-peer-dns=no \ comment="WAN1 DHCP" /ip/dhcp-client add interface=ether2 add-default-route=no use-peer-dns=no \ comment="WAN2 DHCP"
Важно: add-default-route=no — мы будем управлять маршрутами вручную через routing-mark.
Шаг 2: NAT masquerade на обоих WAN
Каждый WAN-интерфейс должен иметь своё правило masquerade:
[admin@MikroTik] >/ip/firewall/nat add chain=srcnat out-interface=ether1 action=masquerade \ comment="NAT via ISP1" /ip/firewall/nat add chain=srcnat out-interface=ether2 action=masquerade \ comment="NAT via ISP2"
Не используйте одно правило с out-interface=!bridge-lan — при падении одного ISP masquerade на его интерфейсе не будет работать, и трафик, перенаправленный на другой ISP, получит неправильный NAT.
Шаг 3: Routing tables и маршруты по умолчанию
Создаём отдельные таблицы маршрутизации для каждого ISP:
[admin@MikroTik] >/routing/table add name=to-ISP1 fib /routing/table add name=to-ISP2 fib
Маршруты по умолчанию:
[admin@MikroTik] ># Основной маршрут в таблице main (для локального трафика роутера) /ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 distance=1 \ comment="Default via ISP1" /ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 distance=2 \ comment="Default via ISP2 (backup)" # Маршруты в именованных таблицах /ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 routing-table=to-ISP1 \ comment="PCC route ISP1" /ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 routing-table=to-ISP2 \ comment="PCC route ISP2"
Шаг 4: Mangle — маркировка соединений через PCC
Это ядро всей конфигурации. Правила mangle выполняют два действия:
- Классифицируют новые соединения и назначают connection-mark
- На основе connection-mark назначают routing-mark для пакетов
[admin@MikroTik] ># Шаг 4.1: Маркируем соединения из LAN через PCC /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-address-type=!local connection-state=new \ per-connection-classifier=both-addresses-and-ports:2/0 \ action=mark-connection new-connection-mark=ISP1-conn passthrough=yes \ comment="PCC: mark connection for ISP1" /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-address-type=!local connection-state=new \ per-connection-classifier=both-addresses-and-ports:2/1 \ action=mark-connection new-connection-mark=ISP2-conn passthrough=yes \ comment="PCC: mark connection for ISP2"
[admin@MikroTik] ># Шаг 4.2: Маркируем маршруты на основе connection-mark /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ connection-mark=ISP1-conn action=mark-routing new-routing-mark=to-ISP1 \ passthrough=no comment="PCC: route via ISP1" /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ connection-mark=ISP2-conn action=mark-routing new-routing-mark=to-ISP2 \ passthrough=no comment="PCC: route via ISP2"
Разберём ключевые параметры:
| Параметр | Значение | Объяснение |
|---|---|---|
chain=prerouting | — | Обрабатываем пакеты до принятия решения о маршрутизации |
in-interface=bridge-lan | — | Только трафик из LAN |
dst-address-type=!local | — | Исключаем трафик к самому роутеру (Winbox, DNS) |
connection-state=new | — | Классифицируем только новые соединения |
per-connection-classifier=both-addresses-and-ports:2/0 | — | PCC хеш: делим на 2 группы, берём остаток 0 |
passthrough=yes | — | Для mark-connection — пакет продолжает обработку |
passthrough=no | — | Для mark-routing — пакет прекращает обработку в mangle |
Шаг 4.3: Обработка входящего трафика
Трафик, приходящий от ISP, должен уходить обратно через того же ISP (чтобы не было асимметричной маршрутизации):
[admin@MikroTik] >/ip/firewall/mangle add chain=prerouting in-interface=ether1 \ connection-state=new action=mark-connection new-connection-mark=ISP1-conn \ passthrough=yes comment="Mark incoming ISP1 connections" /ip/firewall/mangle add chain=prerouting in-interface=ether2 \ connection-state=new action=mark-connection new-connection-mark=ISP2-conn \ passthrough=yes comment="Mark incoming ISP2 connections"
Эти правила гарантируют, что ответы на входящие соединения (port forward, VPN) уходят через правильного ISP.
Шаг 5: DNS
Рекомендуется направлять DNS-запросы через одного ISP для избежания проблем с CDN:
[admin@MikroTik] >/ip/dns set servers=8.8.8.8,8.8.4.4 allow-remote-requests=yes
Или используйте DNS-серверы обоих провайдеров:
[admin@MikroTik] >/ip/dns set servers=203.0.113.53,198.51.100.53 allow-remote-requests=yes
Шаг 6: DHCP-сервер для LAN
[admin@MikroTik] >/ip/pool add name=dhcp-pool ranges=192.168.88.100-192.168.88.250 /ip/dhcp-server add name=dhcp-lan interface=bridge-lan address-pool=dhcp-pool \ lease-time=12h /ip/dhcp-server/network add address=192.168.88.0/24 gateway=192.168.88.1 \ dns-server=192.168.88.1
Failover при падении ISP
Мониторинг каналов через Netwatch
PCC сам по себе не отслеживает доступность ISP. Если один провайдер упадёт, половина соединений перестанет работать. Решение — Netwatch с переключением маршрутов.
[admin@MikroTik] ># Скрипт при падении ISP1 /system/script add name=isp1-down source={ /ip/route disable [find comment="PCC route ISP1"] /log warning "PCC: ISP1 down, all traffic via ISP2" } # Скрипт при восстановлении ISP1 /system/script add name=isp1-up source={ /ip/route enable [find comment="PCC route ISP1"] /log warning "PCC: ISP1 up, PCC restored" } # Скрипт при падении ISP2 /system/script add name=isp2-down source={ /ip/route disable [find comment="PCC route ISP2"] /log warning "PCC: ISP2 down, all traffic via ISP1" } # Скрипт при восстановлении ISP2 /system/script add name=isp2-up source={ /ip/route enable [find comment="PCC route ISP2"] /log warning "PCC: ISP2 up, PCC restored" }
[admin@MikroTik] ># Netwatch для мониторинга ISP1 /tool/netwatch add host=203.0.113.1 type=icmp interval=10s timeout=3s \ up-script="/system/script run isp1-up" \ down-script="/system/script run isp1-down" \ comment="Monitor ISP1 gateway" # Netwatch для мониторинга ISP2 /tool/netwatch add host=198.51.100.1 type=icmp interval=10s timeout=3s \ up-script="/system/script run isp2-up" \ down-script="/system/script run isp2-down" \ comment="Monitor ISP2 gateway"
При падении ISP1 его маршрут в таблице to-ISP1 отключается. Все пакеты с routing-mark=to-ISP1 не найдут маршрут и будут использовать default route из таблицы main, который ведёт через ISP2 (distance=2).
Для более надёжного мониторинга пингуйте внешний хост через конкретный ISP (а не шлюз ISP, который может отвечать даже при потере аплинка):
[admin@MikroTik] ># Маршрут к тестовому хосту через ISP1 /ip/route add dst-address=8.8.8.8/32 gateway=203.0.113.1 scope=10 \ comment="Probe route ISP1" # Маршрут к тестовому хосту через ISP2 /ip/route add dst-address=8.8.4.4/32 gateway=198.51.100.1 scope=10 \ comment="Probe route ISP2" # Netwatch по внешним хостам /tool/netwatch add host=8.8.8.8 type=icmp interval=10s timeout=3s \ up-script="/system/script run isp1-up" \ down-script="/system/script run isp1-down" \ comment="Monitor ISP1 via external host" /tool/netwatch add host=8.8.4.4 type=icmp interval=10s timeout=3s \ up-script="/system/script run isp2-up" \ down-script="/system/script run isp2-down" \ comment="Monitor ISP2 via external host"
Расширение до трёх ISP
Для трёх провайдеров меняем делитель PCC с 2 на 3:
[admin@MikroTik] ># Routing table для третьего ISP /routing/table add name=to-ISP3 fib # Маршрут /ip/route add dst-address=0.0.0.0/0 gateway=100.64.0.1 routing-table=to-ISP3 \ comment="PCC route ISP3" # NAT /ip/firewall/nat add chain=srcnat out-interface=ether3 action=masquerade \ comment="NAT via ISP3" # PCC mangle — три группы /ip/firewall/mangle remove [find comment~"PCC:"] /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-address-type=!local connection-state=new \ per-connection-classifier=both-addresses-and-ports:3/0 \ action=mark-connection new-connection-mark=ISP1-conn passthrough=yes /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-address-type=!local connection-state=new \ per-connection-classifier=both-addresses-and-ports:3/1 \ action=mark-connection new-connection-mark=ISP2-conn passthrough=yes /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-address-type=!local connection-state=new \ per-connection-classifier=both-addresses-and-ports:3/2 \ action=mark-connection new-connection-mark=ISP3-conn passthrough=yes # Mark routing /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ connection-mark=ISP1-conn action=mark-routing new-routing-mark=to-ISP1 passthrough=no /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ connection-mark=ISP2-conn action=mark-routing new-routing-mark=to-ISP2 passthrough=no /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ connection-mark=ISP3-conn action=mark-routing new-routing-mark=to-ISP3 passthrough=no
Исключение определённого трафика из PCC
Отправка всего DNS через одного ISP
CDN-сервисы (YouTube, Netflix) определяют ближайший сервер по IP DNS-резольвера. Если DNS-запросы уходят через разных ISP, ответы могут быть неоптимальными.
[admin@MikroTik] >/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-port=53 protocol=udp action=mark-routing new-routing-mark=to-ISP1 \ passthrough=no comment="DNS always via ISP1" place-before=0 /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-port=53 protocol=tcp action=mark-routing new-routing-mark=to-ISP1 \ passthrough=no comment="DNS TCP always via ISP1" place-before=1
Направление конкретных хостов через определённого ISP
Например, банковские сервисы через ISP1:
[admin@MikroTik] >/ip/firewall/address-list add list=via-ISP1 address=online.sberbank.ru \ comment="Sberbank" /ip/firewall/address-list add list=via-ISP1 address=online.vtb.ru \ comment="VTB" /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-address-list=via-ISP1 connection-state=new \ action=mark-connection new-connection-mark=ISP1-conn passthrough=yes \ comment="Banking via ISP1" place-before=0 /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-address-list=via-ISP1 connection-mark=ISP1-conn \ action=mark-routing new-routing-mark=to-ISP1 passthrough=no \ comment="Banking route via ISP1" place-before=1
Проверка
Просмотр маркированных соединений
[admin@MikroTik] >/ip/firewall/connection print where connection-mark=ISP1-conn count-only=yes /ip/firewall/connection print where connection-mark=ISP2-conn count-only=yes
Количество должно быть примерно одинаковым (распределение 50/50 статистическое, точность растёт с количеством соединений).
Подробный список соединений
[admin@MikroTik] >/ip/firewall/connection print where connection-mark=ISP1-conn
Вывод покажет src-address, dst-address и через какой ISP идёт каждое соединение.
Проверка routing-mark на пакетах
[admin@MikroTik] >/ip/firewall/mangle print stats
Столбцы Bytes и Packets покажут, сколько трафика обработало каждое правило. Если у одного из правил counters нулевые — проблема в конфигурации.
Traceroute с разных устройств
С разных клиентских устройств выполните traceroute к одному хосту. Первый hop должен различаться (203.0.113.1 или 198.51.100.1), подтверждая что трафик идёт через разных ISP.
Проверка маршрутов
[admin@MikroTik] >/ip/route print where routing-table=to-ISP1 /ip/route print where routing-table=to-ISP2 /ip/route print where routing-table=main
Мониторинг Netwatch
[admin@MikroTik] >/tool/netwatch print
Столбец Status должен показывать up для обоих ISP.
Тестирование failover
- Отключите кабель ISP1
- Подождите 30 секунд (Netwatch interval + timeout)
- Проверьте: все клиенты должны продолжать работать через ISP2
[admin@MikroTik] >/log print where message~"PCC"
Должно появиться сообщение PCC: ISP1 down, all traffic via ISP2.
- Подключите кабель ISP1 обратно
- Проверьте восстановление:
PCC: ISP1 up, PCC restored
Типичные ошибки
1. Банковские сайты блокируют соединение (разные IP)
Проблема: некоторые банковские системы и платёжные шлюзы проверяют, что все запросы в рамках сессии приходят с одного IP-адреса. При PCC с both-addresses-and-ports разные TCP-соединения к одному серверу могут уходить через разных ISP (разные src-port = разный хеш).
Симптом: авторизация в банке проходит, но через минуту сессия сбрасывается; ошибка «сессия истекла».
Решение: используйте both-addresses вместо both-addresses-and-ports для проблемных хостов, или направляйте их целиком через одного ISP (через address-list, см. выше).
Альтернатива — изменить PCC-классификатор для всего трафика:
[admin@MikroTik] ># Менее гранулярное, но более стабильное распределение per-connection-classifier=both-addresses:2/0 per-connection-classifier=both-addresses:2/1
С both-addresses все соединения между парой хостов всегда идут через одного ISP.
2. DNS через разных провайдеров — проблемы с CDN
Проблема: DNS-запросы распределяются по обоим ISP. CDN (Cloudflare, Google) определяет геолокацию по IP DNS-резольвера. Ответ оптимизирован для ISP1, но контент грузится через ISP2.
Симптом: медленная загрузка сайтов, высокий latency к CDN.
Решение: направляйте все DNS-запросы через одного ISP (см. раздел «Исключение определённого трафика из PCC»). Или используйте локальный DNS-кэш на роутере.
3. add-default-route=yes в DHCP-клиенте
Проблема: если DHCP-клиент добавляет default route автоматически, он конфликтует с маршрутами PCC.
Решение: всегда используйте add-default-route=no для WAN-интерфейсов с PCC:
[admin@MikroTik] >/ip/dhcp-client set [find interface=ether1] add-default-route=no /ip/dhcp-client set [find interface=ether2] add-default-route=no
4. Трафик самого роутера не балансируется
Проблема: PCC-правила в chain=prerouting с in-interface=bridge-lan не затрагивают трафик, генерируемый самим роутером (обновления, DNS-запросы, NTP).
Пояснение: это нормальное поведение. Трафик роутера использует main routing table. Если нужно балансировать и его — добавьте правила в chain=output:
[admin@MikroTik] >/ip/firewall/mangle add chain=output dst-address-type=!local \ connection-state=new per-connection-classifier=both-addresses-and-ports:2/0 \ action=mark-connection new-connection-mark=ISP1-conn passthrough=yes /ip/firewall/mangle add chain=output dst-address-type=!local \ connection-state=new per-connection-classifier=both-addresses-and-ports:2/1 \ action=mark-connection new-connection-mark=ISP2-conn passthrough=yes /ip/firewall/mangle add chain=output connection-mark=ISP1-conn \ action=mark-routing new-routing-mark=to-ISP1 passthrough=no /ip/firewall/mangle add chain=output connection-mark=ISP2-conn \ action=mark-routing new-routing-mark=to-ISP2 passthrough=no
5. Неправильный порядок правил mangle
Проблема: правила mark-routing стоят перед mark-connection. В результате connection-mark ещё не назначен, и mark-routing не срабатывает.
Решение: правильный порядок:
- Исключения (banking, DNS) — в начале
- mark-connection с PCC — в середине
- mark-routing по connection-mark — в конце
[admin@MikroTik] >/ip/firewall/mangle print
Проверьте порядок и при необходимости переместите правила.
6. Port forwarding не работает
Проблема: при PCC входящие соединения (dst-nat/port forward) могут получить неправильный routing-mark, и ответные пакеты уйдут через другого ISP.
Решение: добавьте правила mark-connection для входящего трафика на WAN-интерфейсах (Шаг 4.3). Это гарантирует, что ответы уйдут через того же ISP.
7. Несимметричное распределение
Проблема: один ISP нагружен на 80%, другой — на 20%.
Пояснение: PCC — статистический метод. При малом количестве соединений распределение может быть неравномерным. С ростом числа соединений (100+) распределение приближается к 50/50.
Если ISP имеют разную пропускную способность (например, 100 Мбит и 50 Мбит), можно настроить неравномерное распределение с делителем 3:
[admin@MikroTik] ># ISP1 (100 Мбит) — 2/3 трафика per-connection-classifier=both-addresses-and-ports:3/0 → ISP1 per-connection-classifier=both-addresses-and-ports:3/1 → ISP1 per-connection-classifier=both-addresses-and-ports:3/2 → ISP2
Полная конфигурация (2 ISP + failover)
[admin@MikroTik] ># ============================== # PCC Load Balancing — 2 ISP # ============================== # Интерфейсы /interface/bridge add name=bridge-lan /interface/bridge/port add bridge=bridge-lan interface=ether3 /interface/bridge/port add bridge=bridge-lan interface=ether4 /interface/bridge/port add bridge=bridge-lan interface=ether5 # IP-адреса /ip/address add address=203.0.113.10/24 interface=ether1 /ip/address add address=198.51.100.10/24 interface=ether2 /ip/address add address=192.168.88.1/24 interface=bridge-lan # DNS /ip/dns set servers=8.8.8.8,8.8.4.4 allow-remote-requests=yes # Routing tables /routing/table add name=to-ISP1 fib /routing/table add name=to-ISP2 fib # Маршруты /ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 distance=1 /ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 distance=2 /ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 routing-table=to-ISP1 \ comment="PCC route ISP1" /ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 routing-table=to-ISP2 \ comment="PCC route ISP2" # NAT /ip/firewall/nat add chain=srcnat out-interface=ether1 action=masquerade /ip/firewall/nat add chain=srcnat out-interface=ether2 action=masquerade # Mangle — mark connections (PCC) /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-address-type=!local connection-state=new \ per-connection-classifier=both-addresses-and-ports:2/0 \ action=mark-connection new-connection-mark=ISP1-conn passthrough=yes /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ dst-address-type=!local connection-state=new \ per-connection-classifier=both-addresses-and-ports:2/1 \ action=mark-connection new-connection-mark=ISP2-conn passthrough=yes # Mangle — mark routing /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ connection-mark=ISP1-conn action=mark-routing new-routing-mark=to-ISP1 passthrough=no /ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \ connection-mark=ISP2-conn action=mark-routing new-routing-mark=to-ISP2 passthrough=no # Mangle — incoming connections (для port forward и симметричной маршрутизации) /ip/firewall/mangle add chain=prerouting in-interface=ether1 connection-state=new \ action=mark-connection new-connection-mark=ISP1-conn passthrough=yes /ip/firewall/mangle add chain=prerouting in-interface=ether2 connection-state=new \ action=mark-connection new-connection-mark=ISP2-conn passthrough=yes # DHCP Server /ip/pool add name=dhcp-pool ranges=192.168.88.100-192.168.88.250 /ip/dhcp-server add name=dhcp-lan interface=bridge-lan address-pool=dhcp-pool lease-time=12h /ip/dhcp-server/network add address=192.168.88.0/24 gateway=192.168.88.1 dns-server=192.168.88.1 # Failover — Netwatch скрипты /system/script add name=isp1-down source={ /ip/route disable [find comment="PCC route ISP1"] /log warning "PCC: ISP1 down" } /system/script add name=isp1-up source={ /ip/route enable [find comment="PCC route ISP1"] /log warning "PCC: ISP1 up" } /system/script add name=isp2-down source={ /ip/route disable [find comment="PCC route ISP2"] /log warning "PCC: ISP2 down" } /system/script add name=isp2-up source={ /ip/route enable [find comment="PCC route ISP2"] /log warning "PCC: ISP2 up" } # Netwatch /tool/netwatch add host=203.0.113.1 type=icmp interval=10s timeout=3s \ up-script="/system/script run isp1-up" \ down-script="/system/script run isp1-down" /tool/netwatch add host=198.51.100.1 type=icmp interval=10s timeout=3s \ up-script="/system/script run isp2-up" \ down-script="/system/script run isp2-down"
Заключение
PCC — наиболее зрелый и надёжный метод балансировки нагрузки между несколькими ISP на MikroTik. Ключевые принципы: одно соединение всегда идёт через одного ISP, каждый WAN имеет свой masquerade, а Netwatch обеспечивает failover при падении провайдера. Для критичных сервисов (банки, VPN) используйте address-list для принудительной маршрутизации через конкретного ISP. При трёх и более провайдерах просто увеличьте делитель PCC и добавьте соответствующие routing-table и mangle-правила.
[ISP 1] [ISP 2]
203.0.113.1/24 198.51.100.1/24
| |
ether1 ether2
| |
┌────┴─────────────────────┴────┐
│ MikroTik Router │
│ ether1: 203.0.113.10/24 │
│ ether2: 198.51.100.10/24 │
│ bridge-lan: 192.168.88.1/24│
└──────────────┬───────────────┘
│
[LAN Switch]
│
┌────┬────┼────┬────┐
PC1 PC2 PC3 PC4 PC5
# Именуем интерфейсы для удобства
/interface/set ether1 comment="WAN1 - ISP1"
/interface/set ether2 comment="WAN2 - ISP2"
# Bridge для LAN
/interface/bridge add name=bridge-lan
/interface/bridge/port add bridge=bridge-lan interface=ether3
/interface/bridge/port add bridge=bridge-lan interface=ether4
/interface/bridge/port add bridge=bridge-lan interface=ether5
# IP-адреса
/ip/address add address=203.0.113.10/24 interface=ether1 comment="WAN1"
/ip/address add address=198.51.100.10/24 interface=ether2 comment="WAN2"
/ip/address add address=192.168.88.1/24 interface=bridge-lan comment="LAN"
/ip/dhcp-client add interface=ether1 add-default-route=no use-peer-dns=no \
comment="WAN1 DHCP"
/ip/dhcp-client add interface=ether2 add-default-route=no use-peer-dns=no \
comment="WAN2 DHCP"
/ip/firewall/nat add chain=srcnat out-interface=ether1 action=masquerade \
comment="NAT via ISP1"
/ip/firewall/nat add chain=srcnat out-interface=ether2 action=masquerade \
comment="NAT via ISP2"
/routing/table add name=to-ISP1 fib
/routing/table add name=to-ISP2 fib
# Основной маршрут в таблице main (для локального трафика роутера)
/ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 distance=1 \
comment="Default via ISP1"
/ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 distance=2 \
comment="Default via ISP2 (backup)"
# Маршруты в именованных таблицах
/ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 routing-table=to-ISP1 \
comment="PCC route ISP1"
/ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 routing-table=to-ISP2 \
comment="PCC route ISP2"
# Шаг 4.1: Маркируем соединения из LAN через PCC
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-address-type=!local connection-state=new \
per-connection-classifier=both-addresses-and-ports:2/0 \
action=mark-connection new-connection-mark=ISP1-conn passthrough=yes \
comment="PCC: mark connection for ISP1"
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-address-type=!local connection-state=new \
per-connection-classifier=both-addresses-and-ports:2/1 \
action=mark-connection new-connection-mark=ISP2-conn passthrough=yes \
comment="PCC: mark connection for ISP2"
# Шаг 4.2: Маркируем маршруты на основе connection-mark
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
connection-mark=ISP1-conn action=mark-routing new-routing-mark=to-ISP1 \
passthrough=no comment="PCC: route via ISP1"
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
connection-mark=ISP2-conn action=mark-routing new-routing-mark=to-ISP2 \
passthrough=no comment="PCC: route via ISP2"
/ip/firewall/mangle add chain=prerouting in-interface=ether1 \
connection-state=new action=mark-connection new-connection-mark=ISP1-conn \
passthrough=yes comment="Mark incoming ISP1 connections"
/ip/firewall/mangle add chain=prerouting in-interface=ether2 \
connection-state=new action=mark-connection new-connection-mark=ISP2-conn \
passthrough=yes comment="Mark incoming ISP2 connections"
/ip/dns set servers=8.8.8.8,8.8.4.4 allow-remote-requests=yes
/ip/dns set servers=203.0.113.53,198.51.100.53 allow-remote-requests=yes
/ip/pool add name=dhcp-pool ranges=192.168.88.100-192.168.88.250
/ip/dhcp-server add name=dhcp-lan interface=bridge-lan address-pool=dhcp-pool \
lease-time=12h
/ip/dhcp-server/network add address=192.168.88.0/24 gateway=192.168.88.1 \
dns-server=192.168.88.1
# Скрипт при падении ISP1
/system/script add name=isp1-down source={
/ip/route disable [find comment="PCC route ISP1"]
/log warning "PCC: ISP1 down, all traffic via ISP2"
}
# Скрипт при восстановлении ISP1
/system/script add name=isp1-up source={
/ip/route enable [find comment="PCC route ISP1"]
/log warning "PCC: ISP1 up, PCC restored"
}
# Скрипт при падении ISP2
/system/script add name=isp2-down source={
/ip/route disable [find comment="PCC route ISP2"]
/log warning "PCC: ISP2 down, all traffic via ISP1"
}
# Скрипт при восстановлении ISP2
/system/script add name=isp2-up source={
/ip/route enable [find comment="PCC route ISP2"]
/log warning "PCC: ISP2 up, PCC restored"
}
# Netwatch для мониторинга ISP1
/tool/netwatch add host=203.0.113.1 type=icmp interval=10s timeout=3s \
up-script="/system/script run isp1-up" \
down-script="/system/script run isp1-down" \
comment="Monitor ISP1 gateway"
# Netwatch для мониторинга ISP2
/tool/netwatch add host=198.51.100.1 type=icmp interval=10s timeout=3s \
up-script="/system/script run isp2-up" \
down-script="/system/script run isp2-down" \
comment="Monitor ISP2 gateway"
# Маршрут к тестовому хосту через ISP1
/ip/route add dst-address=8.8.8.8/32 gateway=203.0.113.1 scope=10 \
comment="Probe route ISP1"
# Маршрут к тестовому хосту через ISP2
/ip/route add dst-address=8.8.4.4/32 gateway=198.51.100.1 scope=10 \
comment="Probe route ISP2"
# Netwatch по внешним хостам
/tool/netwatch add host=8.8.8.8 type=icmp interval=10s timeout=3s \
up-script="/system/script run isp1-up" \
down-script="/system/script run isp1-down" \
comment="Monitor ISP1 via external host"
/tool/netwatch add host=8.8.4.4 type=icmp interval=10s timeout=3s \
up-script="/system/script run isp2-up" \
down-script="/system/script run isp2-down" \
comment="Monitor ISP2 via external host"
# Routing table для третьего ISP
/routing/table add name=to-ISP3 fib
# Маршрут
/ip/route add dst-address=0.0.0.0/0 gateway=100.64.0.1 routing-table=to-ISP3 \
comment="PCC route ISP3"
# NAT
/ip/firewall/nat add chain=srcnat out-interface=ether3 action=masquerade \
comment="NAT via ISP3"
# PCC mangle — три группы
/ip/firewall/mangle remove [find comment~"PCC:"]
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-address-type=!local connection-state=new \
per-connection-classifier=both-addresses-and-ports:3/0 \
action=mark-connection new-connection-mark=ISP1-conn passthrough=yes
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-address-type=!local connection-state=new \
per-connection-classifier=both-addresses-and-ports:3/1 \
action=mark-connection new-connection-mark=ISP2-conn passthrough=yes
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-address-type=!local connection-state=new \
per-connection-classifier=both-addresses-and-ports:3/2 \
action=mark-connection new-connection-mark=ISP3-conn passthrough=yes
# Mark routing
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
connection-mark=ISP1-conn action=mark-routing new-routing-mark=to-ISP1 passthrough=no
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
connection-mark=ISP2-conn action=mark-routing new-routing-mark=to-ISP2 passthrough=no
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
connection-mark=ISP3-conn action=mark-routing new-routing-mark=to-ISP3 passthrough=no
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-port=53 protocol=udp action=mark-routing new-routing-mark=to-ISP1 \
passthrough=no comment="DNS always via ISP1" place-before=0
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-port=53 protocol=tcp action=mark-routing new-routing-mark=to-ISP1 \
passthrough=no comment="DNS TCP always via ISP1" place-before=1
/ip/firewall/address-list add list=via-ISP1 address=online.sberbank.ru \
comment="Sberbank"
/ip/firewall/address-list add list=via-ISP1 address=online.vtb.ru \
comment="VTB"
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-address-list=via-ISP1 connection-state=new \
action=mark-connection new-connection-mark=ISP1-conn passthrough=yes \
comment="Banking via ISP1" place-before=0
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-address-list=via-ISP1 connection-mark=ISP1-conn \
action=mark-routing new-routing-mark=to-ISP1 passthrough=no \
comment="Banking route via ISP1" place-before=1
/ip/firewall/connection print where connection-mark=ISP1-conn count-only=yes
/ip/firewall/connection print where connection-mark=ISP2-conn count-only=yes
/ip/firewall/connection print where connection-mark=ISP1-conn
/ip/firewall/mangle print stats
/ip/route print where routing-table=to-ISP1
/ip/route print where routing-table=to-ISP2
/ip/route print where routing-table=main
/tool/netwatch print
/log print where message~"PCC"
# Менее гранулярное, но более стабильное распределение
per-connection-classifier=both-addresses:2/0
per-connection-classifier=both-addresses:2/1
/ip/dhcp-client set [find interface=ether1] add-default-route=no
/ip/dhcp-client set [find interface=ether2] add-default-route=no
/ip/firewall/mangle add chain=output dst-address-type=!local \
connection-state=new per-connection-classifier=both-addresses-and-ports:2/0 \
action=mark-connection new-connection-mark=ISP1-conn passthrough=yes
/ip/firewall/mangle add chain=output dst-address-type=!local \
connection-state=new per-connection-classifier=both-addresses-and-ports:2/1 \
action=mark-connection new-connection-mark=ISP2-conn passthrough=yes
/ip/firewall/mangle add chain=output connection-mark=ISP1-conn \
action=mark-routing new-routing-mark=to-ISP1 passthrough=no
/ip/firewall/mangle add chain=output connection-mark=ISP2-conn \
action=mark-routing new-routing-mark=to-ISP2 passthrough=no
/ip/firewall/mangle print
# ISP1 (100 Мбит) — 2/3 трафика
per-connection-classifier=both-addresses-and-ports:3/0 → ISP1
per-connection-classifier=both-addresses-and-ports:3/1 → ISP1
per-connection-classifier=both-addresses-and-ports:3/2 → ISP2
# ==============================
# PCC Load Balancing — 2 ISP
# ==============================
# Интерфейсы
/interface/bridge add name=bridge-lan
/interface/bridge/port add bridge=bridge-lan interface=ether3
/interface/bridge/port add bridge=bridge-lan interface=ether4
/interface/bridge/port add bridge=bridge-lan interface=ether5
# IP-адреса
/ip/address add address=203.0.113.10/24 interface=ether1
/ip/address add address=198.51.100.10/24 interface=ether2
/ip/address add address=192.168.88.1/24 interface=bridge-lan
# DNS
/ip/dns set servers=8.8.8.8,8.8.4.4 allow-remote-requests=yes
# Routing tables
/routing/table add name=to-ISP1 fib
/routing/table add name=to-ISP2 fib
# Маршруты
/ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 distance=1
/ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 distance=2
/ip/route add dst-address=0.0.0.0/0 gateway=203.0.113.1 routing-table=to-ISP1 \
comment="PCC route ISP1"
/ip/route add dst-address=0.0.0.0/0 gateway=198.51.100.1 routing-table=to-ISP2 \
comment="PCC route ISP2"
# NAT
/ip/firewall/nat add chain=srcnat out-interface=ether1 action=masquerade
/ip/firewall/nat add chain=srcnat out-interface=ether2 action=masquerade
# Mangle — mark connections (PCC)
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-address-type=!local connection-state=new \
per-connection-classifier=both-addresses-and-ports:2/0 \
action=mark-connection new-connection-mark=ISP1-conn passthrough=yes
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
dst-address-type=!local connection-state=new \
per-connection-classifier=both-addresses-and-ports:2/1 \
action=mark-connection new-connection-mark=ISP2-conn passthrough=yes
# Mangle — mark routing
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
connection-mark=ISP1-conn action=mark-routing new-routing-mark=to-ISP1 passthrough=no
/ip/firewall/mangle add chain=prerouting in-interface=bridge-lan \
connection-mark=ISP2-conn action=mark-routing new-routing-mark=to-ISP2 passthrough=no
# Mangle — incoming connections (для port forward и симметричной маршрутизации)
/ip/firewall/mangle add chain=prerouting in-interface=ether1 connection-state=new \
action=mark-connection new-connection-mark=ISP1-conn passthrough=yes
/ip/firewall/mangle add chain=prerouting in-interface=ether2 connection-state=new \
action=mark-connection new-connection-mark=ISP2-conn passthrough=yes
# DHCP Server
/ip/pool add name=dhcp-pool ranges=192.168.88.100-192.168.88.250
/ip/dhcp-server add name=dhcp-lan interface=bridge-lan address-pool=dhcp-pool lease-time=12h
/ip/dhcp-server/network add address=192.168.88.0/24 gateway=192.168.88.1 dns-server=192.168.88.1
# Failover — Netwatch скрипты
/system/script add name=isp1-down source={
/ip/route disable [find comment="PCC route ISP1"]
/log warning "PCC: ISP1 down"
}
/system/script add name=isp1-up source={
/ip/route enable [find comment="PCC route ISP1"]
/log warning "PCC: ISP1 up"
}
/system/script add name=isp2-down source={
/ip/route disable [find comment="PCC route ISP2"]
/log warning "PCC: ISP2 down"
}
/system/script add name=isp2-up source={
/ip/route enable [find comment="PCC route ISP2"]
/log warning "PCC: ISP2 up"
}
# Netwatch
/tool/netwatch add host=203.0.113.1 type=icmp interval=10s timeout=3s \
up-script="/system/script run isp1-up" \
down-script="/system/script run isp1-down"
/tool/netwatch add host=198.51.100.1 type=icmp interval=10s timeout=3s \
up-script="/system/script run isp2-up" \
down-script="/system/script run isp2-down"