Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Предисловие
Бывает так что при разборе причин деградации сетевых сервисов хочется иметь машину времени. Ну или хотя бы что-то, что записывало бы историю измерений маршрутов... Если Вы попадали когда-нибудь в такую ситуацию, то, возможно, это будет интересно.
Современные сети, основанные на маршрутизации 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:8080
httproot=contrib
session=s0
whoisjsonconfig=whois.json
[s0]
mode=bmpactive
bgppeer=10.0.0.1
peeras=65535
EOF
В секции 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, и полученная информация будет отображаться в попапе. Иногда это долго, но бывает полезно.
Буду рад, если этот инструмент пригодится еще кому-нибудь. Найденные проблемы, пожелания, идеи, конструктивная критика приветствуется.