[Перевод] Играем в морской бой по BGP

BGP — клей интернета. Для протокола, который нарисовали на двух салфетках в 1989 году одновременно удивительно и ужасно, что он обрабатывает почти все взаимодействия между ISP, являясь фундаментальной частью интернета.

У BGP плохая репутация главным образом из-за доверительного характера связей между пирами по дефолту и трудной задачи проверки легитимности маршрутов. Вот почему мы повсюду слышим о взломах BGP разной степени серьёзности: от смены маршрутизации всего YouTube до сервиса AWS Route 53.

Но чтобы понять природу этих взломов, следует понять топологию интернета. Начнём с одинокого маршрутизатора:

lggeoargt5imx7dl8yan8cxndlg.png


От одного маршрутизатора мало пользы, если он не может ничего маршрутизировать. Поэтому подключим к нему другой маршрутизатор на физическом уровне (это может быть что угодно: от медного Ethernet и подводного оптоволокна до линков 802.11 Wi-Fi).

Затем два подключённых маршрутизатора (в нашем случае красный и синий) должны понять, что могут маршрутизировать трафик друг для друга. В конце концов, смысл маршрутизаторов — это направление трафика из одного пункта назначения в другой.

Как упомянуто выше, общепринятый способ осуществить это между интернет-провайдерами — установить BGP с обеих сторон, и позволить им «объявить» друг другу, что они могут маршрутизировать трафик:

ohcv4ad9nw9yt2zfkuskukm6ahu.gif

Но не очень полезно, если они разговаривают только друг с другом, вдруг красный и синий маршрутизаторы не связаны напрямую? Чем больше рутеров мы подключаем, тем более сложную топологию маршрутизации мы формируем. Это возможно, потому что каждый узел BGP делится таблицами маршрутизации с другими узлами, к которым он подключён:

xugw3silqx9r_jigrfbp5a89bui.gif

То, как маршрутизаторы обмениваются информацией между собой, зависит от политики конфигурации, и это обычно зависит от условий реального мира для соседних узлов. Существуют различные настройки для клиентов, соглашений об обмене трафиком и вышестоящих провайдеров.

Из-за этого маршрутизаторам требуется набор запрограммированных инструкций, чтобы отфильтровывать то, что они не хотят отдавать или брать с других узлов. Но время от времени злоумышленники получают доступ к маршрутизатору, который связан с другим маршрутизатором, не имеющим таких фильтров. Исправить это на программном уровне невероятно трудно, потому что это требует изменений у маршрутизаторов каждого провайдера. Предыдущие попытки не получили широкого распространения.

У BGP есть способ кодирования информации с помощью маршрута, называемого community. Он определён в RFC1997 (к сожалению, написанного в 1996 году, немного промахнулись). Community можно присоединить к объявлению маршрута и оно состоит из 32-битного числа. На практике это значение разбивается на два 16-битных числа (один для ASN и один для сигнала, связанного с/для этого ASN):

dp1jqwebgpdffjywht8o0oyeggs.png

Они используются, чтобы передавать дополнительную информацию о маршруте, например, где провайдер взял этот маршрут:

vnfpihy7op-wngfrcitnr99zrbg.png

Это полезно с точки зрения фильтрации. Например, если у вас много провайдеров и вы пытаетесь не выпустить трафик за пределы страны, то можете использовать соответствующие community, чтобы направить трафик по этим маршрутам.

Это заставило меня задуматься. О чём ещё можно сигнализировать через community? И как далеко можно зайти?

После некоторого тестирования выяснилось, что каждая сеть Tier-1 стирает community, кроме бывшей Level 3, которая позволяет передачу community от маршрутизатора источника до клиента. Это также означает, что один маршрутизатор может отправлять информацию другим, даже не имея прямой связи.


Зная о наличии непрямого канала связи по BGP, я хотел как-то использовать это для установления каких-нибудь нетрадиционных коммуникаций. Я выбрал в качестве среды «морской бой», поскольку для этой игры требуется передача минимального количества информации (координаты X и Y, а также информация о последнем выстреле: попал или промазал).

Два игры по BGP были созданы два community.

qdsujljum6vztiln1xxvhzje7sg.png

Вся игра вмещается в два 16-битных числа, позволяющих надёжно играть через два community.

Поскольку морской бой — игра для двоих, я пригласил поиграть AS203729. Он подключен к BGP в Нью-Йорке, а моя установка работает в Лондоне.

Планируя игру, мы предполагали, что из-за частоты обновления маршрутов можем вызвать демпфирование трафика BGP. Поскольку мы оба сидим на реальном трафике продакшна, то согласились установить 30-секундный таймер на каждый ход, ибо из-за демпфирования произойдут сбои на рабочих серверах.

Через игровые маршрутизаторы проходил и другой трафик, поэтому пришлось держать в онлайне обычного демона маршрутизации и нельзя было применять специального демона BGP. Чтобы обойти это ограничение, бинарник игры генерировал и перезагружал конфигурацию BIRD, используя управляющий сокет демонов для опроса на предмет изменения маршрута.

С такими настройками 16 мая 2018 года я AS206924 и AS203729 сыграли, вероятно, первую настольную игру в истории, которая проводилась чисто по BGP.

t0cbksnfb2p-wdzhfoqhcabg8vc.gif

Игра прошла гладко, за исключением 45-минутной паузы из-за вышеупомянутого демпфирования. Это произошло на моей стороне и заставило Level 3 применять менее оптимальный маршрут для моего трафика в течение 45 минут. Чтобы не допустить повторения ситуации, мы решили перейти на 90-секундный период между ходами.

Несмотря на это, последний удар по флоту моего друга AS203729 был нанесен на 68-м ходу. Что делает меня первым победителем настольной игры, проведённой по публичному протоколу интернет-маршрутизации.

Было это логично? Наверное, нет. Было ли это весело? Черт возьми, да.

Исходный код с обеих сторон опубликован, хотя я не предлагаю повторять этот эксперимент.

До следующего раза!

© Habrahabr.ru