понедельник, 22 февраля 2021 г.

VyOS | Странная лаба | Scripting



В этой части попробуем пощупать встроенные возможность скриптинга на VyOS.
Получилось много картинок, мне жаль ваши модемы. 

Тестируем

Но для начала, давайте уже протестируем работает ли вообще вся схема. 

Правила 

Для этого нам нужно:

Добавить еще один хост за AS1 (120.0.0.1). Это у нас будет "что-то в Интернетах".

set interfaces ethernet eth2 address '120.0.0.0/31'
set interfaces ethernet eth2 description 'Smth on the Internet'

Добавить правила на файерволах.

Для начала, нам нужно обeспечить прохождение BGP сессии через файерволы. Для этого нужно создать нужные зоны и политики. Не делайте так как ниже, это "несекурно", лучше создать специфичные правила. У меня просто все разрешено в Интернет.

Создаем политику "Можно в Интернет"

set firewall name TO-WORLD default-action 'drop'
set firewall name TO-WORLD rule 1 action 'accept'

Разрешаем related/established обратно из Интернета (BGP в том числе)

set firewall name WORLD-TO-R rule 1 action 'accept'
set firewall name WORLD-TO-R rule 1 state established 'enable'
set firewall name WORLD-TO-R rule 1 state related 'enable'
set firewall name WORLD-TO-R rule 2 action 'drop'
set firewall name WORLD-TO-R rule 2 state invalid 'enable'

Создаем сами зоны, добавляем к ним интерфейсы и политики.

set zone-policy zone R default-action 'drop'
set zone-policy zone R description 'R1'
set zone-policy zone R from WORLD firewall name 'WORLD-TO-R'
set zone-policy zone R interface 'eth1'

set zone-policy zone WORLD from R firewall name 'TO-WORLD'
set zone-policy zone WORLD interface 'eth2'

Теперь создаем политики для клиентского трафика в Интернет по аналогичной схеме. Ниже разрешаем обратный трафик из Интернета.

set firewall name WORLD-TO-VL11 rule 1 action 'accept'
set firewall name WORLD-TO-VL11 rule 1 state established 'enable'
set firewall name WORLD-TO-VL11 rule 1 state related 'enable'
set firewall name WORLD-TO-VL11 rule 2 action 'drop'
set firewall name WORLD-TO-VL11 rule 2 state invalid 'enable'

set firewall name WORLD-TO-VL12 rule 1 action 'accept'
set firewall name WORLD-TO-VL12 rule 1 state established 'enable'
set firewall name WORLD-TO-VL12 rule 1 state related 'enable'
set firewall name WORLD-TO-VL12 rule 2 action 'drop'
set firewall name WORLD-TO-VL12 rule 2 state invalid 'enable'

Переиспользуем одинаковую для всех политику для Интернета. 

set zone-policy zone WORLD from VL11 firewall name 'TO-WORLD'
set zone-policy zone WORLD from VL12 firewall name 'TO-WORLD'

Добавляем наши политики в нужные зоны.

set zone-policy zone VL11 from WORLD firewall name 'WORLD-TO-R'
set zone-policy zone VL12 from WORLD firewall name 'WORLD-TO-R'

Ну и NATим все это используя тот самый 100.0.0.0/27.

set nat source rule 100 description 'TO-WORLD-PAT'
set nat source rule 100 outbound-interface 'eth2'
set nat source rule 100 source address '10.0.0.0/16'
set nat source rule 100 translation address '100.0.0.0/27'

Для тестов я планирую использовать iperf. Так что разрешим TCP/5003 от PC1 к PC2. Все настройки правил проводим сразу на двух файерволах из-за специфичности прохождения трафика. )

set firewall name VL12-TO-VL11 rule 10 action 'accept'
set firewall name VL12-TO-VL11 rule 10 destination port '5003'
set firewall name VL12-TO-VL11 rule 10 protocol 'tcp'
set firewall name VL12-TO-VL11 rule 10 source address '10.0.12.12'

Netflow

Для того чтобы узнать как проходит трафик я планирую использовать Netflow. Стоит признать, что в VyOS он довольно удобно настраивается и буквально в пару команд можно включить локальный коллектор, что мне и надо. Подробнее тут

Важное замечание. К сожалению, я не смог его включить на rolling release, хотя на стабильной сборке все работает. Мне пришлось обновится на последний rolling. Не страшно, зато иллюстрирует, почему не надо rolling release использовать в проде. 

На каждой железке включаем netflow на каждом интерфейсе. Можно смотреть что за интерфейсы и на каждый интерфейс настраивать netflow.

show int
set system flow-accounting interface eth0
set system flow-accounting interface eth1
set system flow-accounting interface eth3 

Но можно воспользоваться тем, что у нас Linux и все это совместить.

for _INT in `run show int | egrep -o "^eth[0-9]"`; do set system flow-accounting interface $_INT; done

Дополнительно включим netflow для исходящего трафика 

set system flow-accounting enable-egress

Теперь нам надо как-то протестить как бегает трафик. Я буду использовать iperf сервер на PC1 и на сервере за AS1.

На сервере

iperf3 -s -D -p 5003

Подключаемся с клиента к сервера по порту 5003 в 4 потока (пытаемся задействовать все ECMP пути которые у нас есть) в течении 120 секунд.

iperf3 -c 120.0.0.1 -p 5003 -P 4 -t 120

PC1 в Интернет и обратно

Итак, для начала посмотрим как ходит трафик от PC1 в Интернет. Запускаем iperf клиент и смотрим flow на каждом устройстве.

На R1 предсказуемо видно все 4 потока от 10.0.11.11 до 120.0.0.1. Тут же видно и обратный трафик. 


Аналогично на F1. 


Далее B1, AS2 и AS1. Везде видно обратный трафик. 




Как видно, трафик ходит только по одному "крылу" не смотря на то, что у нас включен BGP Multipath. Происходит это, как я понимаю, из-за особенности балансировки в VyOS. Используется per-session метод. Новая сессия балансируется в линк с меньшим количеством сессий. Нам использование нескольких потоков (разных SourcePort) ничем не помогло, значит сессия не учитывает номера портов?

PC2 в Интернет и обратно

С PC2(10.0.12.12) ситуация чуть интересней. Уже на R2 заметно, что трафик ходит не симметрично. Обратного трафика тут нет. 


Аналогично вплоть до AS1. 




На AS1 трафик приходит



И уходит в AS2, а не AS3. 


Далее B1. 


Файервол F1. 


Видим, что F2 получил сессию от F1 и "разнатил" все обратно. 


Ну и завершающий шаг. От R1 до клиента. Напомним, R1 является VRRP BACKUP роутером в этом сегменте. 


PC2 к PC1 и обратно

Тут тоже небольшие причуды, которые затрагивали раньше.  Трафик туда и обратно ходит через разные пары R-F. 




Отказы

Теперь посмотрим, что будет случаться при некоторых очевидных отказах. 

Потеря R1/R2

Как несложно догадаться, трафик между сетями ходить будет без проболем. С трафиком в интернет чуть интересней. Возвращается трафик через B1, если R1 совсем прилег, то BGP сессия пропадет и все станет работать. Пока BGP не сойдется могут быть проблемы в зависимости от того как ходит трафик.  Как мы знаем reconvergence в "ванильном" BGP занимает вечность. Поэтому в этом случае надо уповать на BFD. 

Смена VRRP роли

Что будет, если кто-то/что-то сменит роль скажем на R1. Например, нужно перезагрузить устройство. В таком случае мы уберем только исходящий трафик. А вот входящий все еще будет приходить на R1. 

Вот обратный трафик от PC2 к серверу в Интернете. 


Вот трафик "туда". 


Картинка снизу демонстрирует почему при смене роли VRRP стоило бы и фильтровать анонсы в сторону B маршрутизаторов. 

Потеря F1/F2

При выходе из строя F1/F2 мы получаем примерно похожую ситуация на предыдущий тест. BGP сессия пропадет (рано или поздно), R1/R2 потеряет 0.0.0.0/0, B1/B2 лишится 100.0.0.0/27. Входящий трафик уйдет сам собой (но не сразу, помним про сходимость). Но вот часть исходящего трафика будет умирать на R1. Трафик будет уходить по дефолтному маршруту в VRF к файерволу, которого нет. 

Здесь видно почему при потере BGP сессии нужно убирать VRRP MASTER с R маршрутизаторов. Опять же BGP сессия при отсутствии BFD будет "протухать" вечность.
 

Выход из строя B1/B2

Такой сценарий поменяет таблицу маршрутизации в верхней части сети и там все будет хорошо. Не оптимально, но работать будет. А вот внизу R1 или R2 все еще будут держать свои VRRP группы и слать трафик в Инетрнет в VRFе к файерволу. Последний имеет статический дефолт к умершему B1 или B2. И будет файервол нам слать Destination Host Unreachable.


В таком случае, просто перевод группы на соседний R маршрутизатора решит проблему.



Опять та же история. При потере BGP сессии через файервол нужно убирать MASTERа с R роутеров. 

Вообще, модель отказоустойчивости не самая лучшая. У нас образовалась концепция эдаких цепочек B-F-R.  Мы не можем себе позволить терять больше одного устройства в цепочке. Выход из строя B1 и R2, например сделают невозможным хождение трафика в инетрнет.  R и F уровни и каждой цепочки просто не соединены. С одной стороны, цели такой изначально не стояло, но надо подумать над этим моментом. Запишем себе.

BFD

Для будущих тестов считаю необходимым включить BFD на линках, чтобы ускорить падение BGP сессий. Без этого reconvergence занимает вечность и тестить все это будет мучительно. 

По идее, конечно, на всех линках стоит это сделать, но я сделаю только для B-R сессий.

B
set protocols bfd peer 172.16.0.0 multihop
set protocols bfd peer 172.16.0.0 source address '172.16.1.0'
set protocols bgp 64500 neighbor 172.16.0.0 bfd

R
set protocols bfd peer 172.16.1.0 multihop
set protocols bfd peer 172.16.1.0 source address '172.16.0.0'
set protocols bgp 65501 neighbor 172.16.1.0 bfd

F
set firewall name WORLD-TO-R rule 10 action 'accept'
set firewall name WORLD-TO-R rule 10 destination address '172.16.0.0'
set firewall name WORLD-TO-R rule 10 destination port '4784'
set firewall name WORLD-TO-R rule 10 protocol 'udp'
set firewall name WORLD-TO-R rule 10 source address '172.16.1.0'
set firewall name WORLD-TO-R rule 20 action 'accept'
set firewall name WORLD-TO-R rule 20 destination address '172.16.0.0'
set firewall name WORLD-TO-R rule 20 destination port '179'
set firewall name WORLD-TO-R rule 20 protocol 'tcp'
set firewall name WORLD-TO-R rule 20 source address '172.16.1.0'

Фильтруем анонсы при смене VRRP роли

Наконец мы добрались до главной темы. Для начала разберемся с ситуацией, когда при смене VRRP группы на BACKUP вышестоящие B1/B2 продолжают слать трафик.

Создаем два скрипта в /config/ директории

Во-первых, используем source для того чтобы работали aliasы VyOS. Во-вторых, используем рекомендованную конструкцию if. Чтобы не залочить конфигурацию нужно запускать скрипты через sg vyattacfg -c. Вот это и проверяем. Описано про это подробней здесь

Сама логика скрипта проста как топор.  Пишем в логи сообщение, вешает роут-мап который фильтрует все и рестартуем BGP сессию.

vi /config/vrrp-goes-backup.sh

#!/bin/vbash
source /opt/vyatta/etc/functions/script-template

if [ "$(id -g -n)" != 'vyattacfg' ] ; then
    exec sg vyattacfg -c "/bin/vbash $(readlink -f $0) $@"
fi

logger "Filtering BGP import/export filter due to VRRP state change (BACKUP)" 

#########################
configure
set protocols bgp 65501 neighbor 172.16.1.0 address-family ipv4-unicast route-map export 'SEE-YOU-LATER'
set protocols bgp 65501 neighbor 172.16.1.0 address-family ipv4-unicast route-map import 'SEE-YOU-LATER'
commit
save
run reset ip bgp 172.16.1.0
########################

Здесь убираем роут-мап и рестартуем сессию.

vi /config/vrrp-goes-master.sh

#!/bin/vbash
source /opt/vyatta/etc/functions/script-template

if [ "$(id -g -n)" != 'vyattacfg' ] ; then
    exec sg vyattacfg -c "/bin/vbash $(readlink -f $0) $@"
fi

logger "Removing  BGP import/export filter due to VRRP state change (MASTER)" 

#########################
configure
delete  protocols bgp 65501 neighbor 172.16.1.0 address-family ipv4-unicast route-map 
commit
save
run reset ip bgp 172.16.1.0
########################

Далее, как обычно, добавляем права на запуск

chmod +x /config/vrrp-goes-*

И вешаем скрипты на VRRP группу

set high-availability vrrp group VLAN11 transition-script backup '/config/vrrp-goes-backup.sh'
set high-availability vrrp group VLAN11 transition-script master '/config/vrrp-goes-master.sh'

Время тестов!

На B1 видим один префикс, который приходит от R1.


Меняем приоритет в VRRP группе. Лог присутствует.


B1 анонс потерял. Красота ) Теперь B1 отправит трафик на B2, который сейчас на стороне активных VRRP групп...


 Обратно все также работает.


B1 получает один префикс и шлет трафик к ближайшему файерволу.


На R2 повторяем конфигурацию.

Конечно, можно добавить немного логики в скрипт, но это уже совсем другая история.

Меняем VRRP состояние при падении BGP

Тут есть два варианта.

От BGP

Включить логинг смены состояний BGP сессий, настроить event-handler для того, чтобы он реагировал на соответствующее сообщение в логах соответствующим скриптом. В скриптах же просто менять приоритет VRRP группы.

От VRRP

Написать скрипт healthcheck, который будет проверять дефолтный маршрут или BGP сессию и переводить группу в FAIL состояние.

VRRP Health-check

Не смотря на наличие документации об event-handler, он был убран в версии 1.3 и сейчас переписывается. Так что пока реализуем второй вариант, который мне, признаться, нравится больше.

Создаем сам скрипт. Можно использовать разную логику, но давайте, например, проверять есть ли живая BGP сессия и получаем ли мы default маршрут. Скрипт должен завершаться с кодом 0, если все хорошо и с любым другим кодом, если нет.

vi  /config/we-are-isolated.sh 

#!/bin/bash
if [ `/usr/bin/vtysh -c "show ip bgp neighbors 172.16.1.0" | grep Estab | wc -l` -eq 1 ] && [ `ip route | grep default | wc -l` -eq 1 ];then
   exit 0
else
   logger "BGP peer is dead. Moving VRRP to FAULT"
   exit 1
fi

Далее, добавляем ему прав

chmod +x  /config/we-are-isolated.sh 

И добавляем в VRRP

set high-availability vrrp group VLAN11 health-check failure-count '3'
set high-availability vrrp group VLAN11 health-check interval '2'
set high-availability vrrp group VLAN11 health-check script '/config/we-are-isolated.sh'

Давайте проверять. Например, что будет если B1 потеряет свои аплинки и линк до B2, а значит и дефолтный маршрут?

Вот, что было до. R1 получает один префикс от B1 и является VRRP Master для VLAN11.


Теперь тушим все интерфейсы на B1 к аплинкам. Ожидаемо дефолтный маршрут теперь не доходит до R1 и он переходит в FAULT состояние. Отлично. 

Вместо выводов

Конечно, я не сильно углублялся в скриптинг, более того тот же event-handler, например, на данный момент недоступен. А он позволяет запускать скрипты на основе syslog сообщений и это довольно заманчиво. Однако как видно выше, хотя бы в части VRRP скрипты свою роль выполняют. Думаю, что в других частях системы ситуация похожая. Возможно в дальнейшем пофантазируем на эту тему дальше. В любом случае, эдакий self healing подход это довольно популярная тема в последнее время. Почему бы не "обучить" устройство лечить себя само. Тем более в Linux это уже давно реальность с тем же monit. 

Оставайтесь с нами. 

Ну и да, все вышесказанное не имеет отношение к моему работодателю.






Комментариев нет:

Отправить комментарий