====== Soft-Router (функция маршрутизации) ======
{{indexmenu_n>4}}
===== Общее описание =====
Подробнее о решении: {{youtube>YgWU35Ay-0k?}}.
Сам СКАТ не занимается построением таблицы маршрутизации. Он делегирует эту работу проверенным специализированным инструментам, в примере [[dpi:dpi_components:router#внутренняя_архитектура_роутера|внутренней архитектуры роутера]] использован [[dpi:dpi_components:router#конфигурирование_роут-демона_bird_frr_etc|роут-демон BIRD]]. Роут-демон обрабатывает требуемые протоколы маршрутизации (BGP, OSPF и пр.) и по ним строит общую таблицу маршрутизации, которую загружает в ядро. СКАТ по этой таблице осуществляет маршрутизацию пакетов.
Вместо BIRD можно использовать любой другой демон, строящий таблицу маршрутизации в ядре Linux, например, [[https://frrouting.org/|FRRouting]], [[https://www.quagga.net|QUAGGA]], [[https://www.juniper.net/documentation/product/en_US/crpd|Juniper CRPD]] и другие. СКАТ для вычитывания таблицы маршрутизации использует только стандартный интерфейс Linux, поэтому совместим с любым демоном.
В будущих версиях в целях экономии памяти возможно появление опциональных специализированных API для связи с тем или иным демоном, чтобы миновать построение kernel route table и взаимодействовать с демоном напрямую, минуя ядро.
Так как BIRD строит таблицу маршрутизации в ядре ОС, то, во избежание применения этих правил самим Linux-сервером, роут-демон BIRD работает в отдельном net namespace (на схеме [[dpi:dpi_components:router#внутренняя_архитектура_роутера|внутренней архитектуры роутера]] это ''bird netns''). Пакеты протоколов маршрутизации поступают на in/out-девайсы СКАТа в общем трафике. Для каждого in/out-девайса создается veth-пара "теневых" интерфейсов с предопределенными именами: dpi-интерфейс veth-пары работает как TAP-интерфейс, rib-интерфейс - как обычный системный интерфейс в netns BIRD'а.
Системные требования описаны в разделе [[dpi:dpi_brief:dpi_requirements#системные_требования_для_маршрутизатора_soft-router|Требования к оборудованию и производительность]].
==== Внутренняя архитектура роутера ====
{{ :dpi:dpi_components:router:router_architecture.png?direct&700 |}}
Данные из kernel route table вычитываются (rtnetlink) в RIB роутера. RIB - это префиксное дерево, его удобно модифицировать по событиям изменения (удаления/добавления записей) route table ядра. Но использовать RIB в маршрутизации нельзя, так как он не поддерживает многопоточный доступ со стороны рабочих потоков (требуется блокировка, что неприемлемо). Поэтому в СКАТ RIB живет в потоке роутера и недоступен рабочим потокам.
Рабочие потоки используют FIB. Эта структура заточена на многопоточный поиск (LPM - longest prefix match), но не предназначена для модификаций (удаления/добавления новых записей). FIB можно только построить с нуля по RIB и затем использовать для LPM. Поэтому в СКАТ существуют два FIB - текущая (которая сейчас используется для роутинга рабочими потоками) и "будущая". СКАТ раз в ''router_fib_refresh'' секунд проверяет, не было ли изменений в RIB с момента построения текущей FIB. Если изменения были, СКАТ строит (в потоке роутера) новую FIB на месте "будущей", а затем переключает текущую FIB на новую. Тем самым рабочие потоки увидят все изменения, которые произошли в таблице маршрутизации.
=== Значения по умолчанию в роутере ===
**''router_max_ip4_route_count = 1000000''.** Максимальное количество маршрутов IPv4 для конкретного VRF.\\
**''router_max_ip6_route_count = 200000''.** Максимальное количество маршрутов IPv6 для конкретного VRF.\\
**''router_multipath_page = 8192''.** Максимальное число страниц для распределения multi-path маршрутов.\\
**''router_fib_refresh = 15s''.** Интервал обновления FIB.\\
**''router_arp_cache_size = 1024''.** Размер ARP-кеша.\\
==== Общее описание VRF ====
Статья в блоге: [[https://vasexperts.ru/blog/skat/vrf-lite-i-l3vpn-v-skat/|VRF Lite и L3VPN в СКАТ]]
В СКАТ реализован VRF Lite — он разделяет таблицы маршрутизации, но не помещает трафик отдельного VRF в уникальный туннель (MPLS, VXLAN).
VRF (Virtual Routing and Forwarding instance) — это механизм виртуализации маршрутизации. VRF позволяет создавать виртуальные маршрутизаторы на одном физическом устройстве с независимыми таблицами маршрутизации, списками интерфейсов и другими параметрами. Это позволяет создавать виртуальные изолированные среды и гарантирует, что каждый VRF имеет независимые настройки и не имеет общих параметров с другими VRF и физическим устройством. Коммуникация между разными VRF возможна, но строго локальна для данного устройства, и VRF на одном маршрутизаторе никак не связан с VRF на другом.
Каждый VRF представляет собой отдельный VPN и не пересекается с другими VRF.
Примером может служить выделение трафика от IPTV приставки, которая также находится в L2-домене с BRAS, как и CPE (Customer Premises Equipment — сетевое оборудование, которое обеспечивает доступ пользователя к сети провайдера). IPTV приставка получает доступ только к локальным ресурсам, CPE получает доступ в интернет.
VRF может называться Virtual Routing Instance в Juniper, VRF в Cisco и MikroTik, но всё это — механизм виртуализации маршрутизации с аналогичными функциями.
==== Реализация VRF Lite в СКАТ ====
{{ :dpi:dpi_components:router:vrf_lite.png?direct&1000 |}}
Приставка Lite означает, что СКАТ только разделяет таблицы маршрутизации, но не помещает трафик отдельного VRF в уникальный туннель (MPLS, VXLAN). VRF Lite позволяет изолировать предоставляемые сервисы между собой и оптимизировать маршрутизацию при использовании разных каналов.
Реализация VRF Lite в СКАТ выполнена с помощью Soft-Router, который строит RIB таблицу и пишет/читает из таблицы. СКАТ отводит трафик в ядро Linux для демона маршрутизации. FastDPI обеспечивает построение FIB таблицы.
Демон маршрутизации работает в изолированном пространстве для того, чтобы операционная система не стала роутером. СКАТ направляет всю сигнализацию в роутер, роутер сам строит правила маршрутизации и после этого СКАТ, учитывая эти правила, начинает заниматься переадресацией и маршрутизацией пакетов.
В текущей версии на данный момент нет поддержки L3VPN и MPLS, но при необходимости можно настроить особую контекстную маршрутизацию.
VRF Lite в СКАТ — это отдельная услуга 254, которая может быть как подключена абоненту, так и не подключаться. Абонент по умолчанию попадает в указанный в СКАТ VRF по умолчанию.
=== Логика работы ===
Маршрутизация в СКАТ может происходить с помощью демонов маршрутизации FRR или BIRD — это отдельный процесс, который занимается обменом динамической маршрутизации протоколов сигнализации (BGP, OSPF). В контексте VRF Lite архитектуре Linux, на которой работает СКАТ, больше подходит BIRD. При использовании BIRD есть возможность работать с route leaking (перетеканием маршрутов) между таблицами маршрутизации.
В этом разделе рассмотрены варианты с одним пространством имен и несколькими таблицами маршрутизации, что больше подходит для демона маршрутизации BIRD. Также существует концепция с несколькими пространствами имен и с одной таблицей. Эта концепция более характерна для FRR.
GRT (Global routing table) на данной схеме — условное название, это точно такая же kernel route table, как и остальные на схеме. Таблица названа так для удобства тестирования и усложнения проверок. В ней использовались собственные правила маршрутизации от нескольких роутеров, они могут быть множественные, либо иметь свои контексты.
Все правила и фильтры настраиваются в роутере (в данном случае — в BIRD). При запуске BIRD, когда работает СКАТ и поднимается BGP-соседство, одни приходящие маршруты складываются в таблицу Kernel_rt N, другие складываются в GRT и потом по заданным правилам перетекают в Kernel_rt 1 и Kernel_rt 2.
В СКАТ описаны всё те же N VRF, направленные на определенные таблицы с правилами маршрутизации. Каждый инстанс читает из таблиц, на основе этих таблиц строятся изолированные FIB.
СКАТ имеет свой уникальный ARP-кеш, который он строит на основе ответов на ARP-запросы. В СКАТ может быть несколько ARP-таблиц, у нескольких VRF может быть одна общая таблица.
Вследствие **изоляции** в рамках СКАТ одна и та же подсеть может быть доступна через разные hop и разные роутеры и маршрутизироваться по-разному. После того как построится FIB, когда пойдет трафик — сначала авторизуется абонент и помещается в нужный VRF. FIB может обновляться уже после того, как абонент авторизовался. Перемещать абонента между VRF можно динамически после авторизации абонента с помощью CoA.
Default gateway для этого абонента тоже будет перемещен в другой VRF и может стать недоступен для других абонентов (которые могут уже использовать сеть).
Действия при исходящем от абонента трафике:
- Найти, к какому VRF принадлежит абонент.
- Найти, куда направлен пакет.
- Найти в FIB, на какой hop затерминировать пакет и терминировать. **Актуально только при создании flow, далее nexthop запоминается для flow.**
Действия при входящем трафике:
- Анализ dest.
- Проверка состояния абонента.
- Тест на оригинацию пакета.
Для других групп абонентов все происходит аналогично изолированно, в соответствии с правилами. Анонсирование происходит из того VRF, на котором находится абонент.
===== Конфигурирование подсетей TAP =====
Для каждого ''router_device'' обязательно должно быть указано, какие подсети отводятся на TAP (фактически, это отведение пакетов протоколов маршрутизации на BIRD). СКАТ будет выделять из общего трафика на девайсе обращения к этим подсетям и направлять все такие пакеты на соответствующий TAP-интерфейс.
Подсети задаются параметрами ''subnet'' (для IPv4) и ''subnet6'' (для IPv6) в описании ''router_device''. Каждая подсеть задается отдельным параметром ''subnet''/''subnet6''. Всего в описании ''router_device'' может быть до 16 разных ''subnet'' параметров и до 16 разных ''subnet6''.
Например, такая конфигурация
router_device {
# Имя девайса из in_dev/out_dev
device=41-00.1
# Имя TAP-интерфейса для девайса (default='dpi' + device)
tap=dpi41
# Имя парного TAP-интерфейса в netns для девайса (default='rib' + device)
peer=rib41
# Какие IPv4-подсети отводим на TAP
subnet=10.0.2.0/30
subnet=8.8.8.0/29
# Какие IPv6-подсети отводим на TAP
subnet6=2001::1/124
# link-local адрес интерфейса, с которым взаимодействует bird
subnet6=fe80::82d:cff:fe5f:9453/128
}
задает две IPv4-подсети для девайса ''41-00.1'', которые будут отводиться на TAP-интерфейс ''tap41'' и одну IPv6-подсеть + link-local адрес интерфейса, с которым взаимодействует bird.
Если используется IPv6, следует учитывать, что в IPv6 большую роль играют link-local адреса, которые также должны быть указаны в параметрах ''subnet6''.
OSPF использует мультикастные адреса 224.0.0.5 и 224.0.0.6, поэтому если на ''router_device'' используется протокол OSPF, эти адреса тоже следует задать в описании ''router_device'':
router_device {
device=41-00.1
tap=dpi41
peer=rib41
# OSPF multicast
subnet=224.0.0.5/32
subnet=224.0.0.6/32
}
В параметре ''router_device'' должна быть указана хотя бы одна IPv4 или IPv6-подсеть.
===== Создание veth-интерфейсов =====
Все, что описано в данном разделе, — создание veth-интерфейсов, запуск BIRD и пр. - должно быть задано в скриптах загрузки системы и выполняться **до** запуска fastdpi.
Пусть у нас в fastdpi.conf заданы следующие девайсы:
in_dev=41-00.0
out_dev=41-00.1
Предположим, что нам требуется настроить в BIRD протокол BGP для uplink, то есть на девайсе ''41-00.1''.
Теневые veth-интерфейсы нужно создавать для каждого in/out-девайса, в трафике которого идут пакеты протоколов маршрутизации, они требуют конфигурирования в BIRD. Если девайс не участвует в маршрутизации (как ''in_dev=41-00.0'' в этом примере), для него не надо создавать veth-пару.
Чтобы перенаправить BGP-трафик c ''41-00.1'' на BIRD, который работает в ''bird'' netns, нам нужно создать veth-пару теневых для ''41-00.1'' интерфейсов.
Создаем ''bird'' netns (имя ''bird'' здесь выбрано произвольно, вы можете использовать другое имя netns), в котором будет работать BIRD:
ip netns add bird
Создаем veth пару:
ip link add dpi41-00.1 type veth peer name rib41-00.1 netns bird
rib-интерфейс должен иметь IP-адрес (и IPv6, если IPv6 поддерживается). Этот адрес будет адресом BGP-пира для BGP-соседа.
ip netns exec bird ip address add 10.0.0.4/24 broadcast 10.0.0.255 dev rib41-00.1
ip netns exec bird ip address add 2098::4/124 dev rib41-00.1
# включаем ARP на интерфейсе
ip netns exec bird ip link set dev rib41-00.1 arp on
# set tx checksum offload off - выключаем расчет контрольной суммы на интерфейсе
# замечено, что расчет CRC на интерфейсе может быть некорректным (по крайней мере, на некоторых сборках ядра CentOS-8)
ip netns exec bird ethtool -K rib41-00.1 tx off
IP-адрес rib-интерфейсов должны отличаться от IP-адреса СКАТ, задаваемого параметрами ''bras_arp_ip'' и ''bras_ipv6_address''. Более того, во избежание непонятных ситуаций адреса ''bras_arp_ip'' и ''bras_ipv6_address'' не должны входить ни в какую подсеть, отводимую на TAP-интерфейсы.
dpi-интерфейс **не должен** иметь ни IPv4, ни IPv6 адреса, так как в СКАТ он используется как TAP-интерфейс и наличие на нем адресов не требуется (более того, даже может мешать, если сам интерфейс начнет генерировать и отправлять пакеты):
ip link set dev dpi41-00.1 arp off
# Disable IPv6 on dpiXXX interfaces (чтобы не было даже link-local адреса)
echo 1>/proc/sys/net/ipv6/conf/dpi41-00.1/disable_ipv6
Наконец, поднимаем все созданные интерфейсы:
ip link set dpi41-00.1 up
ip netns exec bird ip link set lo up
ip netns exec bird ip link set rib41-00.1 up
Не забываем про firewall:
firewall-cmd --zone=internal --add-source=10.0.0.1/24
Не забывайте, что BIRD должен быть запущен в ''bird'' netns:
ip netns exec bird /usr/local/sbin/bird
Состоянием линков veth-интерфейсов управляет СКАТ: если девайс ''41-00.1'' link down, то СКАТ переведет в link down veth-интерфейсы этого девайса; как только линк ''41-00.1'' поднимется, СКАТ переведет veth-интерфейсы в link up.
//Как быть с VLAN?//
СКАТ пересылает пакеты в rib-интерфейсы "как есть", без всякого преобразования. Это значит, что в случае наличия VLAN, нужно средствами Linux создать vlan-интерфейсы на rib-интерфейсе, а уже к этим vlan-интерфейсам привязать bird.\\ В fastdpi.conf vlan-интерфейсы, созданные на rib-интерфейсе, не должны нигде фигурировать, — вы должны в качестве ''tap'' и ''peer'' указать два конца veth-пары.
//MTU//
СКАТ **не** выставляет MTU на veth-интерфейсах. При конфигурировании veth-интерфейсов следует задать MTU штатными средствами Linux.
===== Настройка СКАТ =====
==== Конфигурирование СКАТ ====
=== Обязательные параметры ===
Чтобы включить функционал роутера, в fastdpi.conf необходимо активировать параметр
# [cold] Включение функционала роутера
# Булевый параметр:
# 0, false, off - функционал роутера отключен (default)
# 1, true, on - функционал роутера включен
# Не допускает изменения "на лету" через reload
router=1
Далее необходимо указать, в каком netns работает BIRD и номер таблицы маршрутизации ядра, которую он строит:
# [cold] Имя net namespace, в котором запущен BIRD
router_netns=bird
# [cold] Номер таблицы маршрутизации ядра, которую использует fastDPI
router_kernel_table=1
Также обязательно должны быть заданы следующие параметры BRAS, даже если никакой из режимов BRAS не включен:
# Виртуальный MAC-адрес СКАТ
bras_arp_mac=00:E0:ED:43:84:42
# Виртуальный IP-адрес СКАТ
bras_arp_ip=188.227.73.40
# Если используется IPv6, необходимо задать виртуальные IPv6-адреса:
# Задает глобальный IPv6 адрес СКАТа
bras_ipv6_address=2098::1
# Задает IPv6 link-local адрес СКАТа (префикс FE80::/10)
# Если данный параметр не задан явно, он вычисляется по bras_arp_mac
#bras_ipv6_link_local
Эти три параметра являются **обязательными** для включения роутера.
Прочие параметры, перечисленные ниже, не являются обязательными и предназначены для тонкой настройки роутера в СКАТ.
=== Дополнительные параметры ===
Максимальное число маршрутов задается параметрами:
# [cold] Максимальное число маршрутов в IPv4 route table
# По умолчанию = 1000000
#router_max_ip4_route_count=1000000
# [cold] Максимальное число маршрутов в IPv6 route table
# По умолчанию = 200000
#router_max_ip6_route_count=200000
СКАТ при старте в режиме роутера преаллоцирует память для внутренних route table в соответствии с этими параметрами. Советуем устанавливать эти опции (если необходимо) с запасом в 20-30%, чтобы в процессе работы роутера гарантированно хватило преаллоцированной памяти.
Рабочая таблица маршрутизации (FIB) СКАТ обновляется раз в ''router_fib_refresh'' секунд:
# [hot] Период обновления FIB, секунд
# По умолчанию - раз в 15 секунд
#router_fib_refresh=15
Устанавливать данный параметр слишком маленьким (меньше 5 секунд) особого смысла нет.
Максимальный размер neighbor cache (ARP cache) и тайм-аут обновления записей этого кеша задается параметрами:
# [cold] Max размер ARP cache (neighbor сache для IPv6)
# По умолчанию - 1024, max = 32K
#router_arp_cache_size=1024
СКАТ содержит отдельные neighbor-кеши для IPv4 и IPv6, каждый размером ''router_arp_cache_size''.
СКАТ сам не посылает ARP-запросы для устаревших записей кеша. Вместо этого он полагается на обновление кеша со стороны ядра Linux: СКАТ мониторит ARP-ответы, приходящие на адрес подсети TAP-интерфейсов, и в соответствии с этими ответами обновляет свой ARP-кеш. То же самое относится и к IPv6 (мониторинг ICMPv6 neighbor discovery).
Роутер работает в отдельном потоке на отдельном ядре CPU. При старте СКАТ задает параметры этого потока по умолчанию, которые могут быть изменены параметрами:
# [cold] Добавление к приоритету служебного потока роутера (повышение приоритета)
#router_sched_add_prio=0
# [cold] Ядро привязки потока роутера, -1 - автоопределение
#router_bind_core=-1
Изменять эти параметры надо только в крайнем случае, лучше дать СКАТу самому определить ядро и приоритет. Например, явное указание ядра для роутера ''router_bind_core'' может пригодиться в случае, если ядер не хватает; тогда можно явно привязать роутер к ядру, к которому привязан какой-то другой служебный поток (ajb, ctl).
Ни в коем случае не привязывайте роутер к ядру рабочего потока или диспетчера!
=== Конфигурирование VRF ===
Настройки ''router_netns'' и ''router_kernel_table'' задают VRF по умолчанию (default VRF) и применяются при описании других VRF как значения по умолчанию для соответствующих параметров VRF.
При подготовке fastDPI к работе в режиме роутера администратору нужно создать необходимые netns и TAP-интерфейсы для отвода трафика на route-демоны. В конфигурации ''fastdpi.conf'' указываются уже готовые (существующие) netns и TAP-интерфейсы, только в этом случае запустится СКАТ.
Каждая VRF задается отдельной новой секцией в конфигурации роутера:
== Описание таблицы маршрутизации (VRF) ==
router_vrf {
id=
netns=
kernel_table=
neighbor_cache=
}
router_default_vrf=
**''id''** — строка, уникальный id VRF. Для абонента в Радиус VSA авторизации может быть указана VRF — это и есть данный id. Максимальный размер — 15 символов.\\
**''netns''** — имя netns, из которого вычитывается VRF. Если не задано — считается равным опции ''router_netns''. В этом netns находятся peer TAP-интерфейсы для данной VRF.\\
**''kernel_table''** — номер таблицы маршрутизации ядра для данной VRF. Если не задано — считается равным опции ''router_kernel_table''.\\
**''router_default_vrf''** — строка, id default VRF. Default VRF используется для абонентов, у которых нет свойства ''vrf_id''.\\
**''neighbor_cache''** — cтрока, имя ARP кеша для данной VRF по умолчанию, каждый VRF имеет свой собственный, изолированный от других ARP/Neighbor кеш. Если нужно, чтобы несколько разных VRF имели общий ARP/Neighbor кеш, то следует задать в описании этих VRF одно и то же значение опции ''neighbor_cache''.
Параметры для данной VRF:
**''max_ip4_route_count''** — максимальное количество маршрутов IPv4.\\
**''max_ip6_route_count''** — максимальное количество маршрутов IPv6.\\
**''multipath_page''** — максимальное число страниц для распределения multi-path маршрутов. Одна страница вмещает 64 разных multi-path маршрута. //На одной странице могут размещаться маршруты нескольких ECMP-групп. Одна группа может быть размещена по нескольким страницам (если количество маршрутов в группе более 64, если нет ограничений на количество маршрутов в демоне роутера)//\\
**''fib_refresh''** — интервал обновления FIB.\\
**''arp_cache_size''** — размер ARP-кеша.
Эти параметры определяют требуемую память и частоту обновления для данного VRF. Здесь можно указать значения по умолчанию (берутся из глобальных опций) или переопределить их.
* Если в конфигурации **нет** секций ''router_vrf'', режим работы остается прежним: back compatibility, это означает, что в СКАТ описана одна VRF, которая является дефолтной.
* Если в конфигурации **есть** секции ''router_vrf'', режим работы — поддержка VRF. При этом ровно одна VRF должна быть дефолтной, то есть должна быть задана опция ''router_default_vrf=id дефолтной VRF''.
**''bras_vrf_isolation''** - изоляция VRF. L2 BRAS не изолирует абонентов из разных VRF: Если данный режим включен (1), то абоненты из разных VRF будут изолированы друг от друга. Значение по умолчанию: 0.
При включении этой опции:
- ARP абонента к шлюзу - обрабатывается fastDPI только если абонент и шлюз в одном VRF
- ICMP ping шлюза - обрабатывается fastDPI только если абонент и шлюз в одном VRF
- local interconnect - применяется только если оба абонента в одном VRF
**''bras_egress_filtering''** - фильтрация исходящего трафика subs->inet (битовая маска). По умолчанию отключена (0).
При включении этой опции пакет будет дропнут при выполнении следующих условий:
- IP-адрес абонента (srcIP) неизвестный для L2 BRAS
- bras_term_by_as = 0
- AS абонента не local
== Описание router_device ==
В описание ''router_device'' добавляется id VRF.
Описание одного интерфейса роутера:
router_device {
device=
tap=
peer=
vrf=
subnet=
subnet=
subnet6=
subnet6=
}
**''device''** — имя девайса из ''in_dev/out_dev''.\\
**''tap''** — имя TAP-интерфейса для девайса (''default='DPI' + device'').\\
**''peer''** — имя парного TAP-интерфейса в netns для VRF (''default='rib' + device'').\\
**''vrf''** — идентификатор VRF, в котором находится peer. Если не указан — считается равным default VRF.
**''subnet''** и **''subnet6''** — подсети, отводимые из общего трафика на TAP-девайс. Для ''router_device'' обязательно должен быть задан хотя бы один параметр ''subnet'' или ''subnet6''!
**''subnet''** — перечисление IPv4-подсетей, отводимых из общего трафика на TAP-девайс.\\
**''subnet6''** — перечисление IPv6-подсетей, отводимых из общего трафика на TAP-девайс.
Каждая IPv4 и IPv6 подсеть указывается отдельно в параметре ''subnet'' и ''subnet6'' соответственно. Всего может быть не более 16 параметров ''subnet'' и 16 параметров ''subnet6'' для одного ''router_device''.
Подсети для одного порта не должны пересекаться.\\
Например, BGP1 из VRF1 — подсеть 10.20.30.0/24, BGP2 из VRF2 — подсеть 10.20.30.0/20.\\
Для каждого ''router_device'' должны быть указаны разные ''tap'' и ''peer'' интерфейсы. Например, для первого — ''tap=dpi_ospf'' и ''peer=rib_ospf'', для второго — ''tap=dpi_bgp'' и ''peer=rib_bgp''.
== Управление VRF абонентами ==
VRF ID поступает в fastDPI при авторизации, в новой услуге 254.
''VasExperts-Service-Profile = "254:VRF_ID"''
Здесь “VRF_ID” — идентификатор VRF.
=== Пример настройки VRF в СКАТ ===
in_dev=0b-00.0
out_dev=13-00.0
scale_factor=1
ctrl_port=29000
ctrl_dev=lo
federal_black_list=0
black_list_sm=1
black_list_redirect=http://vasexperts.ru/test/blocked.php
num_threads=1
router=1
router_vrf {
id=ROUTER
netns=router
kernel_table=100
neighbor_cache=shared
}
router_vrf {
id=ROUTER2
netns=router
kernel_table=101
neighbor_cache=shared
}
router_device {
device=13-00.0
vrf=ROUTER
tap=dpi_ospf
peer=rib_ospf
subnet=224.0.0.5/30
subnet=192.168.123.69/32
}
router_device {
device=13-00.0
vrf=ROUTER2
tap=dpi_bgp
peer=rib_bgp
subnet=192.168.123.70/32
}
router_subs_announce=6
enable_auth=1
auth_servers=127.0.0.1%lo:29002
bras_enable=1
bras_arp_ip=10.10.102.189
bras_arp_mac=00:0c:29:f5:85:47
bras_dhcp_mode=1
bras_dhcp_server=10.10.99.3%ens256;reply_port=67
bras_pppoe_enable=1
bras_pppoe_session=100
bras_ppp_auth_list=2,3,1
enable_acct=1
netflow=4
netflow_timeout=300
bras_pppoe_service_name=demoDPI
==== Задание имен veth-интерфейсов ====
В fastdpi.conf описываются все TAP-интерфейсы, связанные с девайсами:
# Описание одного интерфейса роутера
# ВНИМАНИЕ! '{' должен быть на той же строке, что и имя секции router_device!
router_device {
# Имя девайса из in_dev/out_dev
device=
# Имя TAP-интерфейса для девайса (default='dpi' + device)
#tap=
# Имя парного TAP-интерфейса в netns для девайса (default='rib' + device)
#peer=
# ВНИМАНИЕ! '}' должен быть на отдельной строке!
}
Например, для такой конфигурации
in_dev=41-00.0
out_dev=41-00.1
где к роутеру подключен только ''out_dev'', описание будет такое:
in_dev=41-00.0
out_dev=41-00.1
router_device {
# Имя девайса из in_dev/out_dev
device=41-00.1
# Имя TAP-интерфейса для девайса (default='dpi' + device)
tap=dpi41
# Имя парного TAP-интерфейса в netns для девайса (default='rib' + device)
peer=rib41
}
Можно не задавать имена ''tap'' и ''peer'' интерфейсов (в этом случае подразумеваются имена по умолчанию), но описать ''router_device'' нужно:
in_dev=41-00.0
out_dev=41-00.1
# TAP для out_dev:
router_device {
device=41-00.1
}
# TAP для in_dev
router_device {
device=41-00.0
}
В этом случае предполагаются такие имена TAP-интерфейсов:
* для ''in_dev=41-00.0'': со стороны СКАТа ''dpi41-00.0'', со стороны BIRD ''rib41-00.0''
* для ''out_dev=41-00.1'': со стороны СКАТа ''dpi41-00.1'', со стороны BIRD ''rib41-00.1''
==== Поддержка LAG ====
В СКАТ 10.1 добавлена поддержка агрегации каналов в роутере.
Для агрегированных каналов пакеты, которые нужно отводить на TAP-интерфейс, могут прийти на любой девайс, входящий в LAG. Чтобы не создавать фактически одинаковые TAP-интерфейсы для каждого девайса из LAG, роутер учитывает, какие девайсы входят в LAG и для всех таких девайсов делает отвод трафика указанных подсетей на TAP (к демону BIRD).
Каждый LAG задается отдельной секцией в fastdpi.conf, в которой перечисляются все девайсы, входящие в LAG:
# Входные/выходные девайсы, объединенные в LAG
in_dev=01-00.0:02-00.0
out_dev=01-00.1:02-00.1
# Описываем LAG в сторону inet
lag {
# Необязательное имя LAG, используется только для вывода в лог
name=inet
# Каждый девайс, входящий в LAG, описывается отдельным параметром device
device=01-00.1
device=02-00.1
}
# Описание одного интерфейса роутера
router_device {
# Имя девайса из out_dev. Только для этого девайса делаем veth-пару TAP-интерфейсов
device=01-00.1
# Имя TAP-интерфейса для девайса (default='dpi' + device)
tap=dpi0
# Имя парного TAP-интерфейса в netns для девайса (default='rib' + device)
peer=rib0
# Подсети, отводимые из общего трафика на TAP-девайс (пример)
subnet=10.0.10.0/26
#...прочие подсети...
}
При таком описании отвод трафика на TAP ''tap0'' будет происходить с обоих девайсов ''01-00.1'' и ''02-00.1'', заданных в секции ''lag'', в соответствии с правилами (подсетями), заданными для ''01-00.1'' в ''router_device''.
В секции ''lag'' должно быть указано не менее двух девайсов, причем все девайсы должны быть одного направления (либо все девайсы из in_dev, либо все девайсы out_dev). Один девайс может входить только в один LAG (или не входить вообще ни в какой).
Если роутер работает как в сторону inet, так и в сторону subs (например, BGP на стороне inet и OSPF внутри сети, в сторону subs), то описываются две секции ''lag'':
# LAG в сторону inet
lag {
name=inet
device=01-00.1
device=02-00.1
}
# LAG в сторону subs
lag {
name=subs
device=01-00.0
device=02-00.0
}
и для каждой конфигурируется отдельная секция ''router_device''.
Всего возможно задать не более 10 различных lag-секций.
Секции ''lag'' в fastdpi.conf - это холодный параметр, требуется рестарт fastdpi при изменении описания LAG.
====ARP менеджмент====
NeighborDB - это БД nexthop, которую обслуживает сам fastDPI: посылает ARP request для выяснения MAC-адреса nexthop, обновляет ARP кеш для этих nexthop. Для обновления используются следующие опции:
* ''router_neighbor_lifetime'' — время жизни записи в ARP кеше, в секундах.\\ По истечении этого времени запись нужно обновить отправкой ARP request (ICMPv6 NDP в случае IPv6). Значение по умолчанию: 300 секунд
* ''router_neighbor_refresh_timeout'' — время ожидания ответа на ARP request (сек). Значение по умолчанию: 3 секунды
* ''router_neighbor_refresh_attempt'' — количество безуспешных попыток обновления, нужных для того чтобы перевести запись ARP-кеша в состояние Unreachable (недостижимая); другими словами, сколько подряд надо послать ARP Request без ответа, чтобы запись стала unreachable.\\ Значение по умолчанию: 10 попыток
* ''router_neighbor_unreachable_refresh'' — после того, как запись становится Unreachable, fastDPI периодически пытается оживить её, посылая ARP Request. Данная опция задает этот период в секундах (по умолчанию 30 сек).
Запись nexthop состоит из:
* nexthop IP;
* //Обязательно// — имя порта, через который осуществляется связь с этим nexthop (в случае LAG — один из портов, входящих в LAG);
* //Опционально// — VLAN
* //Опционально// — MAC-адрес nexthop. Записи с явно заданным MAC-адресом nexthop являются static ARP cache record — по ним никогда не посылается ARP-запросов IPv4 и IPv6 NeighborDB хранится в SDR в файле ''router.mdb''. SDR (System Data Repository) — это новая сущность наподобие UDR, но содержащая системные настройки. Каталог, где располагается SDR, задается новой опцией ''sdr_path'', по умолчанию это ''/var/db/dpisdr''.
Управление NeighborDB (добавление/модификация/удаление записей) производится через команды CLI:
* ''router neighbor dump'' — вывод полного списка всех загруженных записей и их внутреннего состояния
* ''router neighbor dump db'' — вывод дампа БД router.mdb.
* ''router neighbor add'' — добавление новой записи (нового nexthop) в NeighborDB.
* ''router neighbor update'' — модификация существующей записи NeighborDB
* ''router neighbor delete'' — удаление записи NeighborDB
* ''router neighbor refresh'' — принудительное обновление (отправка ARP Request) MAC-адреса конкретного nexthop IP или всех nexthop в указанном VRF или всей NeighborDB
* ''router neighbor purge'' — удаление всех записей NeighborDB (полная очистка NeighborDB).
Синтаксис каждой из этих команд см. ''fdpi_cli ?''
**Приоритетность в ARP кеше**\\
С появлением NeighborDB в fastDPI появлились два независимых источника записей в ARP кеше:
* [прежний] BIRD/FRR: fastDPI отлавливает взаимодействие BIRD/FRR с соседями и соотвественно заполняет свой ARP кеш для nexthop; fastDPI не обновляет статус таких записей отправкой ARP Request, а надеется на то, что это сделает BIRD/FRR
* [новый] NeighborDB: fastDPI сам следит за актуальностью записей, своевременно отправляя ARP Request. **Записи NeighborDB имеют бОльший приоритет**, чем записи от BIRD/FRR.
===== Поддержка Multi-path routing (ECMP) =====
В СКАТ 10.2 добавлена поддержка multi-path routing ([[https://en.wikipedia.org/wiki/Equal-cost_multi-path_routing|ECMP]]).
СКАТ делает балансировку трафика (round-robin) на уровне flow по всем маршрутам из multi-path.
Балансировка на уровне flow означает, что конкретный flow будет закреплен за одним из маршрутов из multi-path и выбранный маршрут не будет изменяться до окончания данного flow (если, конечно, не будет изменен состав multi-path по внешним событиям от демона маршрутизации).
Для включения multi-path в СКАТ не требуется никакой настройки. Поддержка ECMP включается в конфигурационных параметрах демона маршрутизации.
Например, в BIRD поддержка ECMP включается указанием ''merge paths yes'' в протоколе ''kernel'', см. https://bird.network.cz/?get_doc&v=20&f=bird-6.html#ss6.6.
===== Особенности анонсирования адресов =====
==== Анонсы абонентов и NAT pool ====
NAT-пулы анонсируются только в default VRF.
Включение анонсирования адресов абонентов производится параметром в fastdpi.conf:
# [cold] Флаги анонса адресов абонентов
# Битовая маска
# Значения:
# 0x00001 - анонсировать адрес абонента в сторону subs
# 0x00002 - анонсировать адрес абонента в сторону inet (если у абонента не подключен NAT)
# 0x00004 - анонсировать NAT-подсети в сторону inet
# 0x00008 - анонсировать абонентские шлюзы (направление задается флагами 1 и 2)
# 0x10000 - деанонсировать L3-абонента при наступлении acct idle (закрытие acct-сесси по idle timeout)
# Значение по умолчанию: 0 - ничего никуда не анонсировать
#router_subs_announce=0
# [hot] Метрика для анонсов адресов абонентов
# Значение по умолчанию = 32
#router_subs_metrics=32
{{ :dpi:dpi_options:router:анонс_public_cidr_для_nat-сервиса.png?600 |Анонс Public CIDR для NAT-сервиса}}
Подсети белых адресов NAT анонсируются только в сторону inet при старте СКАТа и при добавлении/удалении/изменении NAT-профилей.
{{ :dpi:dpi_options:router:анонс_public_ip_адресов_после_авторизации.png?600 |Анонс Public IP адресов после авторизации}}
Адреса абонентов могут анонсироваться как в сторону inet, так и в сторону subs. Но если IP адрес абонента [[dpi:opt_cgnat:сgnat_settings#дополнительные_настройки|входит в диапазон приватных адресов и на него назначена 11 услуга, т.е. натится]], адрес абонента не анонсируется в сторону inet (так что нужно быть осмотрительными при определении диапазонов приватных адресов). Анонс производится в таблицу маршрутизации BIRD для всех TAP-девайсов разрешенного направления, далее BIRD подхватывает изменения и анонсирует их по нужным протоколам в соответствии со своей конфигурацией.
[СКАТ 10.2+] Если в fastdpi.conf задано ''nat_exclude_private=1'', то есть не применять NAT для пакетов "приватный IP -> приватный IP", то СКАТ **будет** анонсировать приватный адрес абонента с подключенным NAT в сторону inet, так как вышестоящий роутер должен знать маршрут до серого IP-адреса абонента.
Описание параметров [[dpi:opt_cgnat:сgnat_settings#параметры_и_возможные_значения|по ссылке]]
==== Анонс адресов L3-абонентов ====
В СКАТ 10.2 действует следующий алгоритм анонсов IP-адресов [[dpi:bras_bng:general_setup#настройка_bras_l3_в_fastdpi|L3-абонентов]]:
* по умолчанию, анонс адреса производится для успешной авторизации (accept) и НЕ производится для неуспешной (reject)
* fastdpi.conf-параметр ''auth_announce_reject'' позволяет глобально разрешить анонсы для reject:
# [hot] Анонсировать (1) или нет (0) неавторизованных (Reject) абонентов
# Значение по умолчанию - 0 (не анонсировать)
#auth_announce_reject=0
* добавлен новый Радиус-атрибут ''VasExperts-Route-Announce'': значение 0 - не анонсировать адрес абонента, значение 1 - анонсировать. Данный атрибут перекрывает (имеет более высокий приоритет), чем ''auth_announce_reject''.
Итого при решении вопроса, нужно ли анонсировать IP-адрес абонента или нет, применяется следующий алгоритм:
* если в ответе Радиуса (Accept или Reject) явно задан атрибут ''VasExperts-Route-Announce'', анонс будет производиться для ''VasExperts-Route-Announce=1'' и НЕ будет для ''VasExperts-Route-Announce=0''
* если атрибута ''VasExperts-Route-Announce'' в ответе Радиуса нет:
* Для Access-Accept (успешная авторизация) IP-адрес абонента анонсируется
* Для Access-Reject (неуспешная авторизация) IP-адрес анонсируется только если fastdpi.conf-параметр ''auth_announce_reject=1''
этот алгоритм применяется на стадии вызова функции анонсирования роутера; будет или нет анонсирован IP-адрес абонента и в какую сторону, — это регулируется fastdpi.conf-параметром роутера ''router_subs_announce''.
Данный алгоритм также применяется для ARP-авторизации и GTP-авторизации, то есть для всех типов авторизации, где IP-адрес абонента известен на момент вызова авторизации и не может быть изменен.
Для прочих видов L2-авторизации (DHCP, PPP, — всех, где явно **выдается** IP-адрес) атрибут ''VasExperts-Route-Announce'' не принимается в расчет, анонс происходит по факту выдачи IP-адреса абоненту.
===== Конфигурирование Роут-демона (BIRD, FRR, etc.) =====
Настройки Роут-демона (BIRD, FRR, etc.) и СКАТ **должны быть согласованы**: роут-демон должен создавать kernel route table с номером, задаваемым параметром ''router_kernel_table''.\\
Поддерживаемые роут-демоны:
- [[https://bird.network.cz/?get_doc&f=bird.html&v=20|BIRD: официальная документация]]. Поддерживается BIRD версии 2 и выше. Версия 1 **не** поддерживается.
- [[http://docs.frrouting.org/en/latest/|FRRouting: официальная документация]]
- [[https://www.quagga.net/|QUAGGA: официальная документация]]
- [[https://www.juniper.net/documentation/product/en_US/crpd|Juniper CRPD: официальная документация]]
В примере приведен частный случай, за дополнительной информацией обратитесь к документации конкретного роут-демона. В контексте VRF Lite архитектуре Linux, на которой работает СКАТ, больше подходит BIRD.
==== Пример настройки BIRD ====
# Указать дополнительные функции для проверки:
# Любой публичный адрес
function is_public() {
if net !~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
return true;
return false;
}
# Любой приватный адрес
function is_private() {
if net ~ [ 10.0.0.0/8+, 172.16.0.0/12+, 192.168.0.0/16+, 100.64.0.0/10+ ] then
return true;
return false;
}
# Шлюз по умолчанию
filter default_gw {
if net ~ [0.0.0.0/0] then
accept;
reject;
}
# Описать фильтры:
# Маршруты, которые не получены из других протоколов маршрутизации (и префикс не /32)
filter exclude_external_routes {
if (source = RTS_INHERIT) && (net.len != 32) then
accept;
reject;
}
# Исключить маршруты из других протоколов маршрутизации, публичные подсети, приватные - не /32
filter exclude_ext_1_ip {
if (source = RTS_INHERIT) && (is_public() || (is_private() && (net.len != 32))) then
accept;
reject;
}
log "/var/log/bird.log" all;
router id 192.168.123.65;
debug protocols all;
# Описать таблицы
ipv4 table grt;
ipv4 table bird00;
ipv4 table bird01;
protocol device {
}
protocol direct {
disabled; # Отключено по умолчанию
ipv4; # Подключение к таблице IPv4 по умолчанию
ipv6; # ... и к таблице IPv6 по умолчанию
}
# Описать "протоколы" kernel
protocol kernel kernel_grt {
ipv4 { # Подключить протокол к таблице IPv4 по каналу
table grt;
import all; # Импорт в таблицу, по умолчанию - импортировать все
export all; # Экспорт в протокол. Значение по умолчанию - экспорт отсутствует
};
scan time 5;
learn; # Изучить пришедшие маршруты из kernel-таблицы
kernel table 99; # Kernel-таблица для синхронизации с (по умолчанию: основная)
}
protocol kernel kernel_bird00 {
ipv4 { # Подключить протокол к таблице IPv4 по каналу
table bird00;
import all; # Импорт в таблицу, по умолчанию - импортировать все
export all; # Экспорт в протокол. Значение по умолчанию - экспорт отсутствует
};
scan time 5;
learn; # Изучить пришедшие маршруты из kernel-таблицы
kernel table 100; # Kernel-таблица для синхронизации с (по умолчанию: основная)
}
protocol kernel kernel_bird01 {
ipv4 { # Подключить протокол к таблице IPv4 по каналу
table bird01;
import all; # Импорт в таблицу, по умолчанию - импортировать все
export all; # Экспорт в протокол. Значение по умолчанию - экспорт отсутствует
};
scan time 20;
learn; # Изучить пришедшие маршруты из kernel-таблицы
kernel table 101; # Kernel-таблица для синхронизации с (по умолчанию: основная)
}
# Другой экземпляр для IPv6, пропускающий параметры по умолчанию
protocol kernel {
ipv6 { export all; };
}
protocol static {
ipv4; # Снова канал IPv4 с параметрами по умолчанию
}
# Протоколы OSPF (каждый инстанс со своей таблицей)
protocol ospf v2 ospf_grt {
tick 1;
rfc1583compat no;
stub router no;
ecmp yes limit 16;
ipv4 {
table grt;
import all;
export all;
};
area 0.0.0.0 {
networks {
192.168.123.64/30;
};
interface "rib.102" {
cost 1;
rx buffer large;
type broadcast;
authentication none;
};
};
};
protocol ospf v2 ospf_bird01 {
tick 1;
rfc1583compat no;
ecmp yes limit 16;
ipv4 {
table bird01;
import all;
export all;
#export filter exclude_ext_1_ip;
};
area 0.0.0.0 {
networks {
192.168.123.68/30;
};
interface "rib.202" {
cost 1;
rx buffer large;
type broadcast;
authentication none;
};
};
}
# Описать "протоколы" маршрутизации, которые предназначены для "переливания" маршрутов между таблицами (с использованием фильтров)
protocol pipe grt_bird00 {
table grt;
peer table bird00;
import all;
export filter default_gw;
}
protocol pipe grt_bird01 {
table grt;
peer table bird01;
import all; # filter exclude_ext_1_ip;
export all; #filter default_gw;
}
===== Отладка Роутера =====
Роутер СКАТа в целях отладки может записывать в pcap трафик с BIRD:
# [hot] Запись pcap с TAP-интерфейсов роутера
# Note: записывать можно и утилитой tcpdump, указав имя TAP-интерфейса.
# Но проблема в том, что tcpdump не работает с интерфейсами в режиме DOWN,
# то есть tcpdump'ом невозможно записать трафик при переходе интерфейса
# из состояния DOWN в состояние UP.
# Имена TAP-интерфейсов через ';' или 'all' (записывать со всех)
# Для каждого TAP-интерфейса создается отдельный pcap-файл с именем
# tap_<имя_интерфейса>_xxx.pcap в каталог, задаваемый параметром ajb_udpi_path (по умолчанию /var/dump/dpi)
#router_tap_pcap=all|список TAP-интерфейсов через ';'
# [hot] Направление пакетов для записи pcap с TAP-интерфейсов
# Значения:
# 1 - TAP -> вовне (пакеты от TAP-интерфейса)
# 2 - извне -> TAP (пакеты на TAP-интерфейс)
# 0 или 3 - все направления
#router_tap_pcap_dir=0
# [hot] Интервал ротации TAP pcap, секунд
# 0 - берется из параметра ajb_udpi_ftimeout (ajb_udpi_ftimeout задается в минутах)
#router_tap_pcap_rotate=0
Также можно включить запись в pcap обмена данными с ядром (rtnetlink):
# [hot] Записывать или нет rtnetlink messages в pcap
# 0 - не записывать
# 1 - записывать
# Префикс pcap-файлов = "rtnl"
#router_rtnl_pcap=0
Кроме того, если включена запись пакетов в pcap по маске адреса (''ajb_save_ip''), то роутер будет записывать в pcap также результирующий пакет после применения маршрутизации. То есть в pcap окажутся две записи для одного входящего пакета: первая запись — исходный пакет, вторая — отправленный пакет.
====Трассировка====
# [hot] Флаги трассировки различных частей роутера
# 0x0001 транзит состояний FSM обработки rtnetlink (оповещения от BIRD)
# 0x0002 события FSM обработчика rtnetlink (оповещения от BIRD)
# 0x0004 дамп данных rtnetlink
# 0x0010 трассировка RIB (построение route info base)
# 0x0020 трассировка таблицы маршрутизации
# 0x0040 трассировка FIB
# 0x0080 трассировка ARP-кеша
# 0x0100 трассировка TAP
# 0x0200 трассировка TAP pcap
# 0x0400 трассировка объявлений
#router_trace=0
===== CLI-команды =====
СКАТ имеет набор CLI-команд по просмотру текущего состояния роутера. Полный список команд см.
fdpi_cli help router
Команды дампа RIB и FIB выводят очень много данных, так как эти структуры могут содержать сотни тысяч записей в случае BGP full view. Поэтому при вызове этих команд советуем перенаправлять вывод в файл.
Также не забывайте, что построением таблицы маршрутизации по BGP, OSPF и пр. занимается BIRD, у которого есть собственная утилита командной строки ''birdc'' и собственный конфигурационный файл с развитой системой команд по фильтрации, заданию static-маршрутов и пр.
Кроме того, стандартная утилита Linux ''ip'' дает полный контроль над kernel route table. При использовании утилиты ''ip'' не забывайте указывать правильный netns (''router_netns'') и номер таблицы маршрутизации (''router_kernel_table'').