Бывает так что при разборе причин деградации сетевых сервисов хочется иметь машину времени. Ну или хотя бы что-то, что записывало бы историю измерений маршрутов... Если Вы попадали когда-нибудь в такую ситуацию, то, возможно, это будет интересно.
Современные сети, основанные на маршрутизации IP-пакетов, а точнее сервисы, которые они предоставляют, по факту управляются протоколом BGP. Этот протокол был спроектирован в конце 80-хх на трех салфетках. Да, с тех пор в этот протокол добавили массу возможностей, в том числе обмен маршрутной информацией VPN, правилами фильтрации трафика и всяким прочим полезным, но основа там осталась все той же, описанной на трех салфетках. И в этом есть свой плюс, потому что этот протокол в своей сути очень прост.
Но я хотел поговорить не о его простоте, а о "махании кулаками после драки", с которой частенько приходится сталкивать любой службе эксплуатации сети, или NOC - network operation centre (а может быть и center).
Поступает жалоба "а у меня вот сайт не открывается", или "вот час тому назад плохо работал сайт такой-то, а 5 минут тому назад он починился". Инженер идет на маршрутизатор и смотрит что маршрут к адресу рекомого сайта изменился 5 минут тому назад. И что с этим можно сделать? Чаще всего мало чего. Маршрутизатор знает, что вот такой маршрут "прилетел" 5 минут тому назад, а вот что было раньше? Может быть ничего существенного и не произошло, у маршрута обновились какие-нибудь информационные параметры, а пакеты как летели, так и летят в том же направлении. А может быть наоборот - маршрут изменился существенно и пакеты летят совсем в другом направлении. И узнать историю без дополнительного инструментария (или машины времени) нет возможности. И опять же - хорошо бы узнать, что же именно менялось. Да, есть глобальный инструмент bgplay. Но он рассчитан на использование в Интернете и запоминает изменения при перестроении маршрута между разными провайдерами. А вот изменения внутри сети одного провайдера он не ловит, да и не должен, так как не все то что происходит внутри автономной системы, должно быть видно снаружи.
И вот захотелось мне заиметь такой инструмент. Поиски готового ни к чему не привели (ни на что тут не претендую, может плохо искал). Соответственно, если нет готового решения - почему бы и не попробовать сделать самому? Все вроде понятно, собираем маршрутную информацию и храним историю изменений.
А вот дальше я подзавис. Самая лучшая библиотека, даже я бы сказал целый фреймворк, для обработки BGP - это пакет exabgp. Всем хорош и удобен. Один, на мой взгляд, существенный минус - он на python. Не то чтобы я был питононенавистником, отнюдь. Но каждый инструмент хорош, когда применяется по назначению. А python имеет всем известные особенности (интерпретатор, GIL), которые препятствуют эффективной обработке данных, если алгоритмы реализовывать именно на нем. И в данном случае мне хотелось бы иметь реализацию инструмента на компилируемом (как минимум) языке, с управляемыми политиками блокировок. А также иметь возможность выделить обработку протокола BGP в виде библиотеки и желательно чтобы применяемый язык мог позволить библиотеке жить без своего неотделимого и неотъемлемого рантайма (привет, golang!). Для чего? Ну, например, для того чтобы в перспективе применять эту библиотеку для других bgp-шных приложений. Ну и для скорости. Далеко не для всех видов запросов для поиска маршрутной информации возможно построить эффективный индекс.
Решил я попробовать в качестве основного языка по этой теме Rust и в общем все что хотел получилось. Работу с протоколом BGP выделил в библиотеку. В отличие от exabgp реализовывать логику работы BGP FSM в библиотеке я не стал, по той простой причине что в Rust для сети используется не одно API, std там строго синхронное, а в реальных задачах лучше иметь возможность применять по желанию и потребности асинхронные библиотеки. Библиотеку разумеется назвал zettabgp, а приложение bgpexplorer.
Принцип работы прост. Bgpexplorer может как выступать в роли bgp-спикера, то есть роутер (лучше всего route reflector) устанавливает с сервером bgp-соседство, и отдает в сторону сервера всю маршрутную информацию. Приложение накапливает в своей RIB (Routing Information Database) как актуальную маршрутную информацию, так и историческую. Для просмотра и поисковых запросов доступен веб-интерфейс. Сейчас все хранится в оперативной памяти и ее нужно достаточно много - в зависимости разумеется от того, какого объема таблицу маршрутизации нужно отслеживать.
Если интересно попробовать - то это просто. Нужна сеть, которую нужно мониторить и комп (сервер) с достаточно большим объемом ОЗУ чтобы маршрутная информация туда поместилась.
На сервере нужно взять исходники с гитхаба, предполагается что уже есть git и rust.
$ git clone https://github.com/wladwm/bgpexplorer...$ cd bgpexplorer$ cargo build...
Приложение собрано. Теперь на роутере настроим соседство с сервером.
Если это Cisco, то:
! Номер автономки тут 65535 разумеется для примера, как и адресаrouter bgp 65535 ! указываем адрес сервера с той же автономкой, чтобы сессия была IBGP neighbor 10.1.1.1 remote-as 65535 ! указываем с какого адреса соединяться neighbor 10.1.1.1 update-source Loopback0 ! будем ждать попыток соединения с сервера neighbor 10.1.1.1 transport connection-mode passive address-family ipv4 ! для паблик инета активируем neighbor 10.1.1.1 activate ! отправляем на сервер вообще все что есть neighbor 10.1.1.1 route-reflector-client ! Активируем если нужно ipv4 labeled-unicast neighbor 10.1.1.1 send-label address-family vpnv4 ! включаем VPNv4 neighbor 10.1.1.1 activate neighbor 10.1.1.1 send-community extended
Возвращаемся на сервер и подготовим конфигурационный файл для приложения
$ cat > bgpexplorer.ini <<EOF[main]httplisten=0.0.0.0:8080httproot=contribsession=s0whoisjsonconfig=whois.json[s0]mode=bmpactivebgppeer=10.0.0.1peeras=65535EOF
В секции main указываем:
-
httplisten на каком адресе и порту будет работать протокол http
-
httproot где лежит корень файлового сервиса. Там лежит index.html и все такое прочее.
-
Whoisjsonconfig указывает на файл конфигурации сервиса whois
-
Session это имя секции, описывающей режим работы bgp, в данном примере s0
В секции сессии (s0 в данном примере) указано:
-
bgppeer адрес роутера BGP для активного режима
-
Peeras номер автономной системы
-
protolisten адрес:порт, где ожидать входящего соединения по протоколу BGP или BMP
-
Mode варианты работы протокола
В mode можно указать:
-
bgppassive ждать входящего подключения от роутера
-
bgpactive инициировать подключение к роутеру
-
bmpactive инициировать подключение к роутеру по протоколу BMP
-
bmppassive ждать входящего подключения от роутера по протоколу BMP
После написания ini-файла можно запустить bgpexplorer, например, командой
cargo run
После чего можно открыть браузер и направить его на адрес сервера с указанием порта.
На самом верху будет выбор RIB для просмотра - IPv4, IPv6, VPN разные всякие и т.п.
Далее строка для фильтра, а уже после нее - пейджинг и собственно маршрутная информация.
Неактивные маршруты будут отображены серым курсивом. У маршрутов, у которых есть история изменений будет кнопка разворачивания истории.
В фильтре можно задавать кроме собственно подсетей фильтрацию по community, aspath, nexthop, route-target, route-distinguisher.
При наведении курсора на ASn, адреса роутеров будет выполняться запрос к whois или DNS, и полученная информация будет отображаться в попапе. Иногда это долго, но бывает полезно.
Буду рад, если этот инструмент пригодится еще кому-нибудь. Найденные проблемы, пожелания, идеи, конструктивная критика приветствуется.