5. Настройка передачи IP-префиксов в EVPN-сети (RT-5)
Что же делать, если мы хотим передать в нашу overlay-сеть некие внешние маршруты, не привязанные к какому-то конкретному узлу? Маршруты RT-2 здесь не подойдут. Как помним, маршруты RT-2 жестко привязаны к наличию MAC-адреса и к хост-маске /32 или /128. То есть мы не можем передать в маршруте RT-2 подсеть с произвольной маской. Вроде бы, проблема неразрешима? Именно поэтому был написан еще один RFC - 9136, в котором был описан новый вид EVPN-маршрута - IP Prefix Advertisment, тип маршрута 5.
В чем его "фишка"? Он отвязывается от MAC-адреса, а также снимает ограничение на длину маски, передаваемую в NLRI. Таким образом в RT-5 мы можем передавать, например, маршрут по умолчанию, или маршруты до каких-нибудь внешних подсетей, или даже внутренних подсетей, которые обслуживают наши клиентские домены.
Можно задаться вопросом, а зачем нам передавать маршруты внутренних подсетей, если всё равно MAC/IP-информацию о конечных узлах мы получаем из маршрутов RT-2? А вот зачем.
Посмотрите на иллюстрацию:

Представим, что "тихий узел" потихоньку сидит себе в сети, и не отправляет никаких данных. Допустим, это какой-то сервер, типа syslog, который ждет обращений к нему со стороны клиентов. Если сервер не отправляет ничего в сеть, то и VTEP2 не знает о его присутствии в сети, следовательно не генерирует маршрут RT-2, а следовательн VTEP1 не имеет никакой информации о сети 192.168.200.0/24 в своей таблице маршрутизации, и не знает ничего о хосте 192.168.200.20.
Если при этом пользователь хочет обратиться к серверу, то он отправит пакет на VTEP1 (на свой шлюз по умолчанию). VTEP1 видит, что пакет адресован не ему, заглянет в свою таблицу маршрутизации, чтобы понять, куда отправить пакет дальше, и подходящего маршрута не найдет! Следовательно VTEP1 ответит пользователю: "у меня нет маршрута к узлу назначению, извини". Таким образом, связности не будет, пока сервер за VTEP2 каким-то образом не даст о себе знать.
И вот тут-то нам и поможет маршрут RT-5! Если VTEP2 начнет анонсировать маршрут до подсети 192.168.200.0/24, то VTEP1 будет иметь маршрут в сеть назнчения, даже если сервер никак о себе не заявляет. В таком случае, ситуация развернется следующим образом:


Пользователь отправляет ICMP-пинг на VTEP1 (свой шлюз), VTEP1 смотрит в таблицу маршрутизации и видит маршрут до сети назначения (192.168.200.0/24), под которую подпадает IP-адрес 192.168.200.20. Таким образом, пакет будет отправлен на VTEP2. VTEP2 увидит, что IP назначения принадлежит сети, которая напрямую к нему подключена посредством интерфейса vlan 200, и со спокойной совестью сгенерирует и отправит в порты, принадлежащие VLAN 200, ARP-запрос, чтобы узнать MAC-адрес "тихого узла", на который последний с радостью ответит. А вот когда он ответит, тут-то VTEP2 и анонсирует RT2 маршрут для "тихого" сервера :). Хотя, технически, он и не нужен - нам для маршрутизации вполне достаточно маршрута RT-5. Тем не менее, теперь мы без проблем сможем связаться с "застенчивым" узлом в удаленной подсети :).
Еще один момент. В структуре NLRI RT-5 (если посмотреть ее Wireshark'ом) можно увидеть такое поле, как Gateway IP. Также в некоторой вендорской документации (например, Juniper), можно встретить разделение маршрутов RT-5 на два типа: "Pure RT-5 route" и "Standard RT-5 route". Отличаются они тем, что в первом случае поле Gateway IP не заполнено (значение равно 0), а во втором случае заполнено неким IP-адресом. Зачем же оно нужно, если в EVPN вместо в качестве next-hop используется VTEP IP (и Router's MAC в качестве вспомогательного средства)? За деталями (весьма зубодробительными) добро пожаловать в RFC 9136, но, вкратце, можно сказать, что в поле Gateway IP едет IP-адрес некст-хопа некоего хоста внутри overlay-сети, который обеспечивает доступ в сеть, префикс которой и переносится данным RT-5 маршрутом.
В-общем, проще продемонстрировать на примере:
PE1 и PE2 - это VTEP'ы. Host1 подключен к PE1 и поднимает с ним BGP-сессию внутри overlay-сети. Host1 по этой BGP-сессии анонсирует в сторону PE-1 некую подсеть SN1, которая расположена за ним. PE-1 в свою очередь, данную подсеть, полученную по BGP от Host1, анонсирует уже в EVPN как маршрут RT-5. И поле Gateway IP в NLRI заполняется IP-адресом Host1.
PE2 устанавливает данный маршрут для SN1 в свою таблицу маршрутизации. При этом next-hop у данного маршрута SN1 будет IP-адрес Host1. В свою очередь IP-адрес Host1 будет разрешаться через соответствующий маршрут RT-2. IP-адрес Host в данном случае будет называться Overlay Index.
Overlay Index необязательно должен быть IP-адресом. Это может быть и MAC-адрес (в таком случае он едет в комьюнити Router's MAC, а не в поле Gateway IP), также это может быть номер ESI. Но в рамках данного материала мы их рассматривать не будем. Если интересно: https://datatracker.ietf.org/doc/html/rfc9136#section-3.2 описывает Overlay Index'ы и приводит некоторые примеры их использования.
Теперь давайте вернемся к настройкам. :) Как последнюю нашу задачу, нам нужно реализовать "внешнюю связность" для нашего PoD'а. Означает это следующее: мы должны импортировать в нашу overlay-сеть некие внешние маршруты через некоторое внешнее устройство (например, это выделенный маршрутизатор/фаерволл, подключенный к одному из наших Leaf'ов). Маршруты будут импортированы в EVPN в качестве маршрутов 5-го типа (IP Prefix Route), а точнее это будет один маршрут - default. Благодаря ему клиенты в разных VRF получат связность друг с другом, а также доступ во внешние сети.
Мы поделим наших клиентов на две независимых VRF: VRF1 и VRF2. Client-1 и Client-2 будут принадлежать VRF1, а Client-3 и Client-4 будут жить в VRF2. Каждого клиента поместим в свой VNI (так будет нагляднее для целей данной главы).
К Leaf-3, который теперь будет играть специальную роль пограничного лифа, будет подключен маршрутизатор GW-1 (на базе Linux/FRR), который будет инжектировать внешние маршруты в нашу топологию. Какова будет его (GW-1) роль? Роль его будет чем-то вроде внешнего файрволла. То есть Leaf-3 будет отдавать на него два физических линка, каждый из которых будет принадлежать своей VRF. Через инжектируемый маршрут по умолчанию, клиенты в одном VRF смогут иметь связность с клиентами в другом VRF. Трафик будет проходить через GW-1 (удобное место, на котором можно реализовать различные политики безопасности).
Leaf-3 по обоим линкам будет отдавать на GW-1 суммарные маршруты подсетей, находящихся за IRB-интерфейсами всех VLAN'ов нашей фабрики.
Задача GW-1 будет состоять в том, чтобы принять маршруты с каждого линка, а обратно отдавать маршрут 0.0.0.0/0.
Приступим.
Топология, клиенты, адреса
Измененная топология - добавлен GW-1. Клиенты снова подключены к своим лифам одним линком (не то, что мультихоминг как-то мешает текущей настройке, просто так будет нагляднее в выводе show-команд).

L2VXLAN/L3VXLAN
Leaf-1
192.168.10.254/24
10
1010
1:1010
Leaf-2
192.168.20.254/24
20
1020
1:1020
Leaf-3
192.168.30.254/24
30
1030
1:1030
Leaf-3
192.168.40.254/24
40
1040
1:1040
Клиенты
Client-1
02:00:00:00:01:bb
192.168.10.1/24
10
VRF1
Client-2
02:00:00:00:02:bb
192.168.20.2/24
20
VRF1
Client-3
02:00:00:00:03:bb
192.168.30.3/24
30
VRF2
Client-4
02:00:00:00:04:bb
192.168.40.4/24
40
VRF2
IP-VRF
VRF1
10001
1:10001
VRF2
10002
1:10002
Настройка
По сути сначала мы повторим настройку из части 3 с небольшими изменениями (единственное значимое изменение - разделение клиентов на 2 VRF). После этого на каждом лифе мы включим анонсирование адресов подсетей, в которых у нас есть клиенты, как маршруты RT-5. Затем на Leaf-3 мы выполним настройку BGP-соседства с GW-1 и анонсируем в его сторону наши подсети. Обратно от GW-1 примем дефолтный маршрут. Поехали!
Настройка Leaf-1
Снова приведем здесь начальную конфигурацию, с которой мы начинаем работу (с настроенным underlay):
Теперь переходим к настройке overlay.
Создадим VRF1 и включим для него маршрутизацию:
Создадим клиентский VLAN:
Теперь настроим физический порт, в который подключен наш клиент Client-1:
Создадим IRB-интерфейс:
Теперь настроим интерфейс VXLAN:
Anycast MAC:
Настроим MAC-VRF для VLAN 10:
Теперь настроим IP-VRF и L3VNI для VRF1, который мы будем использовать для передачи маршрутизируемого трафика (inter-VNI):
Здесь есть новая команда - redistribute connected, выполненная в секции address-family ipv4. Эта команда включает анонсирование префиксов подсетей в EVPN как маршруты 5-го типа.
Теперь включим AF EVPN в настройках процесса BGP:
Общий вид выполненных настроек:
C Leaf-1 закончили. Leaf-2 настроим по примерно такому же принципу.
Настройка Leaf-2
Начальная конфигурация:
Конфигурация overlay:
Настройка Leaf-3
Начальная конфигурация:
Настройка overlay:
Обратите внимание, что на Leaf-3 мы создали оба VRF, хотя клиенты Client-3 и Client-4 находятся в VRF2. "Поддержка" VRF1 нам нужна для отправки и принятия маршрутов в данном VRF от GW-1, а также анонсирование этих маршрутов в EVPN. Естественно, необходимо выделить и L3VNI для VRF1. Для VRF1 мы отдаем команду redistribute connected, просто для того, чтобы анонсировать стыковочную сеть до GW-1 (для консистентности). Строго говоря, это не обязательно, но пусть будет.
Теперь переходим к настройке пиринга с GW-1.
Настроим линки в сторону GW-1:
Создадим префикс-лист, отфильтровывающий host-маршруты (/32-маршруты). Мы не хотим отправлять в сторону GW-1 маршруты /32 наших клиентских хостов:
Создадим маршрутную карту, чтобы отфильтровать /32-маршруты EVPN от анонсирования в сторону GW-1.
Теперь настроим BGP-пиринг с GW-1. Определим пир-группу GW-1, укажем группу CLOS в качестве родителя, чтобы наследовать большинство нужных нам настроек BGP, а затем пропишем AS GW-1 (65099) и повесим на направление в сторону GW-1 нашу route-карту.
Общий вид выполненной конфигурации пиринга с GW-1:
Настройка GW-1
Для GW-1 мы возьмем Ubuntu Server 22.04, а в качестве маршрутизационного ПО - FRR 10. Настройки на GW-1 будут совершенно простейшие: по сути, что получили в один линк, то и отправили во второй. И всё. Получается такой своеобразный "отражатель маршрутов", который еще и пропускает через себя трафик. Настраиваем!
В самом начале включим функциональность маршрутизатора:
Сначала настроим интерфейсы через Netplan (стандартная утилита настройки сетевой части в Ubuntu):
Строго говоря, lo0 здесь не нужен, но пусть будет для красоты, все же "с него" будем брать router-id.
Создадим процесс BGP в AS 65099:
Укажем Router ID:
Отключим обязательное требование о наличии фильтрационной политики для eBGP:
Создадим агрегированный маршрут "по умолчанию", который мы будем отдавать на Leaf-3 по обоим линкам. Параметр "summary-only" означает, что более специфические маршруты, подпадающие под агреггированный маршрут, будут отфильтровываться и не анонсироваться:
Создадим пир-группу для обоих наших подключений:
Укажем удаленную AS как "external", то есть любую, отличающуюся от нашей (чтобы не вводить явно номер):
Включим BFD:
Аутентификацию:
Подкрутим таймеры:
И пропишем IP-адреса соседей (линки в сторону Leaf-3):
Общий вид выполненной конфигурации:
На этом настройка нашей сети закончена.
Проверки
Что мы хотим сейчас, в итоге, получить?
На Leaf-1 и Leaf-2 настроены VNI в VRF1, а на Leaf-3 - VNI в VRF2. Наша цель - обеспечить возможность хостам в VRF1 общаться с хостами в VRF2. Весь трафик при этом будет проходить через внешний маршрутизатор GW-1, на котором, при желании, можно повесить какие-нибудь политики безопасности или организовать фаервол. GW-1 должен отдавать маршрут по умолчанию в каждый из VRF.
Проверять будем с помощью пингов от клиентов в VRF1 до клиентов в VRF2 (и наоборот). Также с помощью tcpdump убедимся, что inter-VRF трафик действительно идет через GW-1, а также посмотрим show-команды (нас особенно интересуют маршруты RT-5).
Проверка Leaf-1
Посмотрим, какие маршруты RT-5 имеет Leaf-1 в своей RIB:
Мы видим четыре дефолтных маршрута. Два из них в VRF1, два в VRF2 (два - потому что доступны через 2 спайна). Взглянем на них подробнее:
Мы видим, что некст-хопом является Leaf-3, AS-PATH состоит из Spine (65100) -> Leaf-3 (65003) -> GW-1 (65099). AS-PATH оканчивается на GW-1, который и является родителем этих маршрутов. Route-Target-AS у маршрутов разные - 1:10001 и 1:10002 - соответственно, принадлежат в VRF1 и VRF2 соответственно. Комьюнити Router's MAC содержит в себе MAC-адрес VTEP'а назначения: Leaf-3. VNI - L3VNI соответствующих VRF.
Теперь взглянем подробно на маршрут, который порождает сам Leaf-1:
Это маршрут для подсети, расположенной в VLAN 10. VNI - L3VNI 10001, Router's MAC - MAC-адрес Leaf-1. Route-Target-AS:1:10001 - маршрут принадлежит VRF1 и должен быть установлен в него на тех VTEP'ах, на которых настроен VNI, импортирующий данное комьюнити.
Посмотрим в таблицу маршрутизации Leaf-1 для VRF1:
Мы видим маршрут "по умолчанию" с next-hop'ом - Leaf-3. Трафик по этому маршруту будет отправлен на Leaf-3, инкапсулирован в VNI 10001, а DST_MAC в инкапсулированном пакете будет равен router-mac, что позволит Leaf-3 поднять принятый пакет на третий уровень. Так же мы в таблице видим стыковочную сеть 10.99.1.0/24 между Leaf-3 и GW-1.
Проверка Leaf-2
Видим тот же набор маршрутов. 192.168.20.0/24 мы порождаем сами, поэтому AS-PATH у него пустой (помним, что собственная AS к маршруту приставляется на выходе из автономной системы). Так же мы видим четыре дефолтных маршрута, ведущих к GW-1, как мы видели и на Leaf-1.
Таблица маршрутизации:
В таблицу маршрутизации дефолтный маршрут установился.
Проверка Leaf-3
Маршруты типа RT-5 на Leaf-3:
Видим два дефолтных маршрута, которые мы принимаем от GW-1 и анонсируем в EVPN в соответствующих VRF. Так же порождаем маршруты стыковочных сетей между нами и GW-1, а также сети 192.168.30.0/24 и 192.168.40.0/24.
Взглянем на таблицу маршрутизации в VRF1:
Мы видим два дефолтных маршрута, ведущих в сторону GW-1 (интерфейс Ethernet5). Также мы видим напрямую присоединенную стыковочную сеть с GW-1. А также видим четыре маршрута для клиентских сетей, полученные от Leaf-1 и Leaf-2 через два Spine'а. Строго говоря, получили мы эти маршруты от Spine'ов, но сети анонсируются именно Leaf'ами. Spine'ы их просто ретранслируют нам, а мы эти сети передаем на GW-1, который потом их ретранслирует нам же, но в VRF2.
Посмотрим, что у нас в VRF2:
Опять же видим дефолтный маршрут от GW-1 (интерфейс Ethernet6). Видим стыковочную сеть с GW-1, а также две присоединенных сети, в которых у нас живут Client-3 и Client-4. Сетей 192.168.10.0/24 и 192.168.20.0/24 мы не видим, так как GW-1 их саггрегировал в дефолтный маршрут.
Давайте подробнее посмотрим на дефолтные маршруты в обоих VRF:
Обратите внимание - эти маршруты передаются не как RT-5, а как обычные IPv4-маршруты, так как GW-1 ничего не знает ни о каких EVPN и VXLAN. Эти маршруты наш Leaf-3 уже ретранслирует в EVPN, при этом конвертируя их в RT-5.
Проверка GW-1
Посмотрим, какие маршруты мы получаем от Leaf-3 по линку для VRF1:
Мы получаем стыковочную сеть, а также маршруты из VRF1. А отдаем?
Отдаем в сторону Leaf-3 VRF1 только дефолт.
Из VRF2 мы получаем следующее:
Стыковочная сеть с Leaf-3 и две сети, в которых живут Client-3 и Client-4.
А отдаем?
Дефолт :).
Посмотрим в таблицу маршрутизации:
Мы здесь видим агрегированный дефолт-маршрут, который ведет "в никуда", который мы анонсируем в сторону Leaf-3. Видим Видим стыковочные сети с Leaf-3, а также все четыре клиентских сети, которые мы получаем от Leaf-3 для VRF1 и VRF2.
Больше GW-1 ничего не делает, поэтому и смотреть здесь особо не на что.
Перейдем к проверкам клиентов.
Проверка связности клиентов
Запустим пинг от Client-1 до Client-4:
Посмотрим, как идет трафик, проследим его путь.
Мы видим его на линке между Leaf-1 и Spine-1, инкапсулированный в L3VNI 10001:
Обратите внимание на DST_MAC в инкапсулированном пакете - он равен маку Leaf-3 и присутствовал в комьюнити Router's MAC в соответствующем маршруте EVPN.
Видим трафик на линке между Spine-1 и Leaf-3:
Видим трафик на линке между Leaf-3 и GW-1, в который терминируется VRF1:
Видим трафик на линке между Leaf-3 и GW-1, в который терминируется VRF2:
И теперь видим трафик на линке, напрямую присоединенном к Client-4:
Обратите внимание, что SRC_MAC в кадре, в котором едет ICMP Request - это Anycast MAC IRB-интерфейса Leaf-3.
Визуализировать путь трафика можно таким образом:

Наши маршруты RT-5 работают, давайте под конец проверим связность всех клиентов друг с другом:
Client-1
Ping Client-2
Ping Client-3
Ping Client-4
Client-2
Ping Client-1
Ping Client-3
Ping Client-4
Client-3
Ping Client-1
Ping Client-2
Ping Client-4
Client-4
Ping Client-1
Ping Client-2
Ping Client-3
Итого: связность между клиентами в двух разных VRF через внешний маршрутизатор - есть.
На этом настройку нашей EVPN-сети можно считать завершенной. Мы настроили основной функционал оверлей-сети, основанной на EVPN/VXLAN: L2-связность между клиентами в пределах одного широковещательного домена, L3-связность между VNI, резервируемое подключение (Multihoming) и инжектирование внешних префиксов в EVPN.
Надеюсь, данный материал был вам полезен.
Если у вас появились какие-то вопросы или замечания касательно содержимого статьи, то связаться со мной можно по электронной почте.
Удачи и всего хорошего!
Виталий Швецов ([email protected])
Last updated