О BGP

2022-02-06

Краткое содержание предыдущей серии. Большой Интернет состоит из автономных систем (AS). Конкретные IP сети (размером от /24 для IPv4) принадлежат конкретным автономным системам. Маршрутизаторы автономных систем анонсируют маршруты до своих сетей, а также транзитные маршруты через свою автономную сеть, маршрутизаторам соседних дружественных автономных сетей по протоколу BGP.

Таким образом, каждому маршрутизатору становятся известны маршруты до каждой автономной системы в Интернете (из тех, маршруты до которых их интересуют), а значит, и маршруты до IP сетей этих автономных систем. Исходя из этих данных, каждый маршрутизатор строит свою таблицу маршрутизации для протокола IP.

Маршрутов до некоторой автономной системы может быть множество. Но в таблицу IP маршрутизации войдёт лишь по одному маршруту до каждой IP сети. Маршрутизатор выбирает один маршрут из множества исходя из своих собственных соображений. Как правило, выбирается маршрут с наименьшим количеством транзитных автономных систем.

Иллюстрация работы BGP

На этом рисунке маршрутизатор AS 1 почему-то выбрал путь до AS 4 через AS 3 и AS 2. Это не типичное решение. Путь прямо через AS 2, минуя AS 3, — короче. В количестве транзитных автономных систем. Однако, возможно, канал между AS 1 и AS 2 очень узкий, и AS 1 имеет явные указания предпочитать маршруты через AS 3. Всё зависит только от собственных знаний и предпочтений AS 1.

Однако, в BGP есть интересный механизм со странным названием BGP Community. Это ещё один атрибут BGP анонса. Набор числовых значений. Их чаще всего записывают как два десятичных числа через двоеточие: 20473:6000. Первым числом чаще всего является номер автономной системы, для которой предназначено это Community. Или которая добавила это Community.

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

Стандартные Community существуют, но их буквально лишь несколько штук. В основном они запрещают передачу анонсов дальше определённых границ. В реальности у каждой автономной системы — свой набор Community.

Вот, например, документация по BGP Community от Vultr. AS20473, то есть автономная система за номером 20473.

Маршрутизаторы Vultr добавляют некоторые Community в исходящие анонсы автоматически. Это так называемые информационные (или Marking) Community. Vultr хороший, он передаёт в интернеты все Community, которые выставляете вы как клиент Vultr. Но также добавляет своё Community 20473:400, сигнализируя всему миру, что этот анонс не он придумал, а его клиенты так пожелали. А добавленное Community 20473:11 говорит, что этот анонс происходит из датацентра в Нью-Джерси. Для всех датацентров Vultr есть такие Community.

На некоторые Community маршрутизаторы Vultr реагируют определённым образом. Если вы как клиент Vultr добавите их в свои анонсы. Это так называемые Action (или Control) Communities. 20473:6000 вообще запрещает дальнейшую передачу анонсов, довольно бессмысленно, если уж вы начали делать BGP анонсы через Vultr. 64600:123 запрещает передачу анонсов в AS 123, это может быть полезно, если вы почему-то не хотите, чтобы AS 123 знало бы о вашем существовании в этом датацентре. Помните, вы же выставляете эти Community в BIRD в каждой локации. И в разных локациях они могут быть разными.

20473:6001, 20473:6002, 20473:6003 делают "Prepend 1x, 2x, 3x". Это удлинение пути до вашей AS путём повтора AS в анонсах, один, два и три раза. С точки зрения стороннего маршрутизатора путь до вашей сети удлиняется, пусть и повтором одинаковых автономных систем. Что должно, теоретически, понизить приоритет анонсированных маршрутов.

20473:64609 устанавливает локальную метрику маршрутов на маршрутизаторах Vultr в 0. Это ещё более радикальный способ понизить приоритет. Но касается он только маршрутизаторов Vultr.

Вот это вот: закрыть анонсы совсем или понизить приоритет анонсированных маршрутов — и есть почти все способы, которыми можно влиять на чужие маршрутизаторы. Нюанс лишь в том, в какой анонс, из какого датацентра, включить этот Community. И маршрутизаторам какой автономной системы адресовать наши пожелания. Отрубать анонсы прямо на ближайшей AS, в Vultr, — как-то очень грубо.

Первый пример.

Клиент в Джорджии

Клиент находится в штате США Джорджия. Очевидно, в Северной Америке. Он подключен к провайдеру ATT (AT&T Inc.). Ближайший датацентр Vultr находится в Атланте, столице Джорджии. И там у нас есть сервис с anycast адресом. К сожалению, у Vultr нет прямых связей с ATT в Атланте, и ATT узнаёт путь до нашей anycast сети транзитом через другие автономные системы.

Одним из таких транзитных провайдеров является PCCW (PCCW Global, Inc.). Автономная система за номером 3491. Как и положено большим провайдерам, он представлен во многих уголках мира, включая и Австралию. А в Сиднее, в Австралии, у нас тоже есть сервис с anycast адресом, подключенный к Vultr.

И вот, по какой-то причине, ведомой только ATT, они получили от PCCW маршрут до нашего сервиса в Австралии, и сочли, что этот маршрут лучше, чем любой другой маршрут до наших сервисов в Америке. Даже лучше, чем маршрут до Атланты. И клиент из Джорджии ходит до нашего сервиса в Австралии. Что вовсе не близко.

Что делать?

Очевидно, нужно что-то делать с анонсами в Сиднее. Они не должны попадать в Северную Америку. Наш сервис в Австралии предназначен для пользователей в Австралии. Незачем пользователям из Северной Америки ходить в Австралию.

Можно попросить Vultr не распространять наш анонс из Сиднея в автономную систему PCCW (AS 3491), добавив к нашим анонсам Community 64600:3491. Теоретически, это поможет. Но это может сломать доступ к нашему сервису пользователям из Австралии, которые подключены к PCCW. Они могут не увидеть, что для них есть сервис в Сиднее, и пойти куда-нибудь подальше, на другой континент. Нехорошо.

К счастью, у PCCW есть очень полезные Community. И узнать о них можно, о чудо, через whois.

$ whois -h whois.ripe.net AS3491 
...
remarks:        1.1 Regions
remarks:
remarks:        Per region breakdown of our routes.
remarks:
remarks:        Region                          Customers   Peers
remarks:        -----------------------------------------------------
remarks:        North America (East Coast)      3491:100    3491:1000
remarks:        North America (West Coast)      3491:200    3491:2000
remarks:        Europe                          3491:300    3491:3000
remarks:        Asia                            3491:400    3491:4000
remarks:        Africa                          3491:500    3491:5000
remarks:        Australia                       3491:700    3491:7000
...
remarks:        2.5.1 All other regions
remarks:
remarks:        Do not export prefixes to other regions than that customer is connected to
remarks:
remarks:        Description                                   Community
remarks:        --------------------------------------------------------
remarks:        Do not export to other regions                3491:53900
remarks:
...

Community 3491:53900 запрещает экспорт маршрутов в другие регионы. В данном случае нам хотелось бы, чтобы маршрут из Австралии не уходил в Северную Америку. Вроде это достаточно безопасно.

Мы добавили Community 3491:53900 в наш анонс из Сиднея. И действительно, ATT в Джорджии, потеряв сведения о том, что наш anycast адрес доступен ещё и где-то в Австралии, зарулил клиента на наш anycast в Атланте. Проблема решена.

Второй пример.

Клиент в Миннесоте

В этот раз клиент находится в Миннесоте. Если посмотреть по карте, то видно, что Миннесота граничит Висконсином, а тот граничит с Иллинойсом, где в Чикаго, в датацентре Vultr, у нас запущен наш сервис с anycast адресом. Чикаго — действительно самая близкая локация для этого клиента. Но клиент ходит на наш сервис в Атланте, штат Джорджия. Опять Атланта, да. А это на полторы тысячи километров южнее и +40мс к пингу.

восток США

Почему?

Клиент подключен к маленькому местечковому провайдеру Jaguar (Jaguar Communications, AS 15011). А Jaguar подключен к двум уже большим провайдерам Hurricane (Hurricane Electric LLC, AS 6939) и Cogent (Cogent Communications, AS 174). Мне определённо нравятся названия североамериканских интернет провайдеров. Hurricane такой большой, что подключен много к чему и где. Cogent имеет прямое подключение к Vultr в Атланте, но не в Чикаго. Видимо, поэтому Jaguar считает, что маршрут через Cogent лучше, и заруливает клиента в Атланту.

Отрубать анонсы из Vultr в Cogent в Атланте снова не хочется. Могут пострадать клиенты, подключенные непосредственно к Cogent. У Cogent нашлась документация по их Community. После нескольких экспериментов мы остановились на Community 174:10, добавили его в наш анонс в Атланте. Это понижает приоритет наших маршрутов на маршрутизаторах Cogent ниже плинтуса. Но, вроде как маршрут остаётся там, что, пожалуй, хорошо.

Действительно, после этого клиент начал ходить на наш anycast адрес не через Cogent, а через Hurricane. Однако, Hurricane направлял клиента не в Чикаго, а в Нью-Джерси. Беда. Хотя 10 миллисекунд мы выиграли.

Беда потому, что у Hurricane Electric нет никаких известных Community, чтобы сказать им, что Чикаго ближе к Миннесоте, чем Нью-Джерси. Так что пока тупик. Это тем более странно, что у Ураганчика есть отличное looking glass и совершенно офигенные инструменты для диагностики BGP.

Как узнать, к каким провайдерам подключен некоторый IP адрес? Ну, любой IP принадлежит к какой-то сети. А сеть принадлежит к какой-нибудь автономной системе. А автономная система принадлежит какой-нибудь организации. Это всё можно узнать через whois.

А у утилиты MTR есть замечательный ключик -z, который всё сделает сам. Вот, например, от меня до Яндекса:

$ mtr -z -r -c 5 ya.ru
Start: 2022-02-06T19:47:07+0600
HOST: gelin-zenbook2              Loss%   Snt   Last   Avg  Best  Wrst StDev
1. AS41843  openwrt              0.0%     5    1.7   2.2   1.7   3.2   0.6
2. AS41843  2a02:2698:5400::503  0.0%     5    3.7   2.8   2.1   3.7   0.8
3. AS41843  2a02:2698:5400::1e0  0.0%     5    4.8   5.0   2.3  10.6   3.3
4. AS9049   2a02:2698:a100:da::  0.0%     5   43.4  47.1  42.4  57.4   6.1
5. AS9049   2a02:2698:a100:da::  0.0%     5   42.3  42.6  42.3  43.0   0.3
6. AS???    ???                 100.0     5    0.0   0.0   0.0   0.0   0.0
7. AS208722 2a02:6b8:0:1a00::ff  0.0%     5   51.3  50.5  49.5  51.4   0.9
8. AS208722 ya.ru                0.0%     5   49.2  49.3  49.0  50.2   0.5

Что это за автономные системы?

$ whois AS41843 | egrep 'org-name|role' 
org-name:       JSC "ER-Telecom Holding"
role:           Network Operation Center CJSC ER-Telecom Company Omsk branch
$ whois AS9049 | egrep 'org-name|role' 
org-name:       JSC "ER-Telecom Holding"
role:           ER-Telecom ISP General Contact Role
role:           ER-Telecom ISP Contact Role
$ whois AS208722 | egrep 'org-name|role' 
org-name:       Yandex Oy
role:           Yandex Oy Network Operations

Вроде всё правильно.

Есть некоторая сложность разобраться в том, на какой из сервисов по anycast адресу ходит наш клиент. Это, конечно, видно по логам самих сервисов. Но чисто с точки зрения IP это можно проверить примерно такой командой:

$ ping -I $ANYCAST_ADDR $CLIENT_ADDR

Можно запустить это на каждом сервере (ssh и даже parallel вам в помощь). Ключ -I говорит отправлять ICMP echo request именно с anycast IP адреса. ICMP echo reply придёт только на один сервер, тот самый, куда и ходит клиент.

Узнать, какие есть Community у конкретной автономной системы — отдельное сисадминское искусство. Хорошо, что у Vultr их network support team этим искусством владеет. А ребята из One Step Consulting Inc. какие-то доки бережно собрали тут: https://onestep.net/communities/

Да, в BIRD добавить Community в экспортируемые маршруты не просто, а очень просто:

export filter {
    bgp_community.add((174,10));
    accept;
};