mikrotik-wiki.ru
Главная
Загрузка...

PCC балансировка нагрузки на MikroTik

RouterOS 7.xRouting13 мин30 мар. 2026 г.
TelegramVK

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-address
  • both-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 выполняют два действия:

  1. Классифицируют новые соединения и назначают connection-mark
  2. На основе 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/0PCC хеш: делим на 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

  1. Отключите кабель ISP1
  2. Подождите 30 секунд (Netwatch interval + timeout)
  3. Проверьте: все клиенты должны продолжать работать через ISP2
[admin@MikroTik] >
/log print where message~"PCC"

Должно появиться сообщение PCC: ISP1 down, all traffic via ISP2.

  1. Подключите кабель ISP1 обратно
  2. Проверьте восстановление: 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 не срабатывает.

Решение: правильный порядок:

  1. Исключения (banking, DNS) — в начале
  2. mark-connection с PCC — в середине
  3. 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-правила.

[admin@MikroTik] >
[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"
Routing / PCC балансировка нагрузки на MikroTik