Сети для самых маленьких. Часть 22: BGP

OSPF из прошлой части строит карту одной сети и считает по ней кратчайшие пути. Интернет — это семьдесят с лишним тысяч независимых сетей, у каждой свой владелец, свои деньги и свои интересы, и никто не согласится отдать соседу карту своей сети, а «кратчайший путь» там не критерий: провайдер повезёт трафик туда, где ему дешевле, а не ближе. Для этого нужен протокол другого рода — не про расстояния, а про политику. Это BGP, Border Gateway Protocol, версия 4, RFC 4271, 1994 год: единственный протокол маршрутизации между сетями, и единственный, на котором держится интернет целиком.

У меня в блоге уже есть серия о BGP на практике — там кластер Kubernetes анонсирует адреса роутеру. Здесь — сам протокол с нуля.


Автономная система

Единица интернета в терминах BGP — автономная система (AS): набор сетей под одним управлением с одной политикой маршрутизации. Провайдер, облако, университет, крупная компания со своими адресами. У каждой — номер AS: 16-битный исторически, с 2007 года 32-битный, выдаётся региональной регистратурой вместе с блоком адресов из пятой части. Диапазоны 64512–65534 и 4200000000–4294967294 — частные, для использования внутри своей сети без регистрации; 64496–64511 — для документации, ими и будем пользоваться.

Между AS два вида отношений, и из них растёт вся политика:

  • транзит — провайдер за деньги пропускает ваш трафик куда угодно и анонсирует ваши префиксы всему интернету;
  • пиринг — две сети обмениваются трафиком друг друга и своих клиентов бесплатно, обычно на точке обмена (IXP), и никому дальше чужие маршруты не передают.

Отсюда базовое правило: клиентам и пирам отдаём всё, провайдерам и пирам отдаём только своё и клиентское. Нарушить его — значит оказаться транзитом для чужого трафика за свой счёт.


Где живёт BGP

Три решения, которые отличают BGP от всех IGP:

Поверх TCP, порт 179. Никакого своего механизма надёжности: сессия — обычное TCP-соединение, и всё, что мы знали о TCP из десятой части, применимо. Пропал пакет — TCP повторит; файрвол должен пропускать 179 порт между соседями.

Соседей не ищут. Никакого Hello на multicast: каждый сосед прописан руками с адресом и номером AS. Случайно установить сессию BGP нельзя — только намеренно, и это правильно для протокола, где один неверный сосед может увести трафик всего интернета.

Path-vector. BGP не передаёт карту и не считает кратчайшие пути. Он передаёт префиксы с атрибутами, главный из которых — список AS, через которые префикс прошёл. Это distance-vector из прошлой части, где вместо числа хопов — весь путь: петля обнаруживается, если свой номер AS уже в списке.

Сообщения

Четыре типа плюс один дополнительный, общий заголовок 19 байт (16 байт маркера из единиц, длина, тип):

Тип Сообщение Что
1 OPEN первое после установления TCP: версия 4, мой номер AS, hold time, Router ID, список возможностей (capabilities: IPv6, 32-битные AS, route refresh, …)
2 UPDATE маршруты: список отозванных префиксов, атрибуты пути, список новых префиксов с этими атрибутами
3 NOTIFICATION ошибка с кодом; после неё сессия закрывается
4 KEEPALIVE «я жив», раз в 60 секунд; hold time 180 — три пропущенных, и сосед мёртв
5 ROUTE-REFRESH «пришли мне всё заново» — чтобы применить новую политику без разрыва сессии

Состояния сессии: Idle → Connect (пытаемся TCP) → Active (TCP не вышло, пробуем снова) → OpenSent → OpenConfirm → Established. Классическая ловушка: состояние Active звучит бодро, а означает «сессии нет, TCP не устанавливается» — чаще всего файрвол или неверный адрес. Работает только Established.

После установления соседи отдают друг другу все маршруты, разрешённые политикой, одним потоком UPDATE, а дальше — только изменения. Полная таблица интернета сегодня — больше миллиона префиксов IPv4 и около двухсот тысяч IPv6; первичная загрузка — десятки мегабайт и минуты.


UPDATE и атрибуты пути

Самое важное сообщение. Структура: «вот эти префиксы больше недействительны» (withdrawn), «вот атрибуты» и «вот префиксы, к которым они относятся» (NLRI). Один UPDATE — один набор атрибутов и сколько угодно префиксов с ним.

$ sudo tcpdump -i eth1 -n -v 'tcp port 179'
IP 198.51.100.1.179 > 198.51.100.2.41234: Flags [P.], ...: BGP
	Update Message (2), length: 55
	  Origin (1), length: 1, Flags [T]: IGP
	  AS Path (2), length: 6, Flags [T]: 64500 64510
	  Next Hop (3), length: 4, Flags [T]: 198.51.100.1
	  Multi Exit Discriminator (4), length: 4, Flags [O]: 0
	  Updated routes:
	    192.0.2.0/24

Провайдер с AS 64500 сообщает: до 192.0.2.0/24 идти через меня (198.51.100.1), путь — через 64500 и дальше 64510, откуда префикс родом. Атрибуты, которые нужно знать:

Атрибут Что Кто ставит
AS_PATH список AS от нас до источника; каждый роутер, передавая префикс в другую AS, добавляет свой номер в начало все
NEXT_HOP адрес, на который слать трафик для этого префикса тот, кто передаёт в другую AS
ORIGIN как префикс попал в BGP: IGP (командой network), EGP (история), incomplete (redistribute) источник
LOCAL_PREF предпочтение внутри своей AS: больше — лучше; наружу не передаётся мы, на входе
MED подсказка соседней AS, через какой из нескольких линков с нами заходить: меньше — лучше сосед, на выходе
COMMUNITY метки AS:число, которые ничего не значат сами по себе, но по ним строят политику: «64500:100 — получено от клиента», «64500:666 — не анонсировать в Европу»; есть well-known: NO_EXPORT — не передавать за пределы AS кто угодно
AGGREGATOR, ATOMIC_AGGREGATE префикс получен объединением более мелких тот, кто объединил

AS_PATH — одновременно и защита от петель, и грубый измеритель расстояния, и инструмент политики: удлинив свой путь повторением собственного номера (prepending, 64496 64496 64496), сеть делает его менее привлекательным для остальных и так перекладывает входящий трафик на другой линк.


eBGP и iBGP

Одна и та же сессия BGP ведёт себя по-разному в зависимости от того, в одной AS соседи или в разных. Это не два протокола, а два набора правил внутри одного.

                      AS 64500 (провайдер A)         AS 64501 (провайдер B)
                            PA                              PB
                            │ eBGP                          │ eBGP
             198.51.100.1 ──┤                               ├── 198.51.100.5
                            │                               │
   ┌────────────────────────┼───────── AS 64496 ────────────┼────────────────────────┐
   │         198.51.100.2 ──┤                               ├── 198.51.100.6         │
   │                        R1 ───────── iBGP ──────────── R2                        │
   │                     10.0.0.1      (через OSPF)      10.0.0.2                    │
   │                         \───── 203.0.113.0/24 ──────/  наша сеть                │
   └─────────────────────────────────────────────────────────────────────────────────┘

eBGP — между разными AS, R1 ↔ PA:

  • при передаче префикса роутер добавляет свой номер AS в AS_PATH и ставит NEXT_HOP = свой адрес на этом линке: сосед из другой AS знает только этот адрес;
  • сессия ожидается с напрямую подключённым соседом: пакеты шлются с TTL 1, и сосед через роутер не ответит (для сессий через несколько хопов — ebgp-multihop);
  • маршруты от eBGP-соседа передаются всем: и другим eBGP, и iBGP-соседям, — с поправкой на политику;
  • административная дистанция 20: eBGP-маршрут побеждает OSPF (110) при одинаковом префиксе.

iBGP — внутри одной AS, R1 ↔ R2:

  • AS_PATH не меняется: внутри AS номер не добавляют;
  • NEXT_HOP не меняется: R2 получит от R1 префикс 192.0.2.0/24 с next hop 198.51.100.1 — адресом провайдера A, которого R2 не знает. Маршрут без достижимого next hop не используется. Два решения: либо внутренняя маршрутизация (OSPF) знает сеть 198.51.100.0/30 — для этого линк к провайдеру объявляют в OSPF как passive, либо R1 перед отдачей в iBGP подменяет next hop на себя: next-hop-self. Второе — стандарт;
  • маршрут, полученный от iBGP-соседа, не передаётся другим iBGP-соседям — правило split horizon против петель, поскольку AS_PATH внутри AS не меняется и петлю по нему не поймать. Следствие: все BGP-роутеры AS должны быть соединены iBGP-сессиями каждый с каждым, полная сетка, n(n−1)/2 сессий;
  • административная дистанция 200: iBGP слабее OSPF, и если один и тот же префикс известен из обоих, победит OSPF;
  • сессии обычно между loopback-адресами (update-source lo), чтобы не зависеть от конкретного линка, а достижимость loopback'ов обеспечивает OSPF. Вот зачем iBGP нужен IGP: BGP не умеет доставить пакет до своего же соседа внутри AS, он знает только, что делать с префиксами извне.

Полная сетка на 50 роутерах — 1225 сессий, и её заменяют route reflector: один-два роутера, с которыми у всех остальных (клиентов) есть iBGP, и которые отражают маршруты между клиентами, нарушая split horizon по правилам (атрибуты ORIGINATOR_ID и CLUSTER_LIST ловят петли). Клиентам нужна одна сессия вместо полусотни. Альтернатива — конфедерации: разбить AS на под-AS с eBGP между ними, снаружи невидимое; встречается реже.


Выбор лучшего пути

До одного префикса у роутера обычно несколько путей — от двух провайдеров, от iBGP-соседей. В таблицу маршрутов попадает один (или несколько равных при multipath), и выбирает его цепочка правил, по порядку, до первого различия:

  1. Больший LOCAL_PREF. Политика своей AS бьёт всё: «провайдер A предпочтительнее B».
  2. Локально порождённый (network) — лучше полученного.
  3. Короче AS_PATH.
  4. ORIGIN: IGP лучше EGP лучше incomplete.
  5. Меньший MED — только среди путей от одной и той же соседней AS.
  6. eBGP лучше iBGP.
  7. Меньшая метрика IGP до NEXT_HOP — ближайший выход из AS (hot potato: избавиться от чужого трафика побыстрее).
  8. Старший путь, затем меньший Router ID соседа, затем меньший адрес соседа — чтобы выбор был детерминированным.
$ vtysh -c 'show bgp ipv4 unicast 192.0.2.0/24'
BGP routing table entry for 192.0.2.0/24, version 12
Paths: (2 available, best #1, table default)
  64500 64510
    198.51.100.1 from 198.51.100.1 (10.0.1.1)
      Origin IGP, metric 0, localpref 200, valid, external, bestpath-from-AS 64500, best (Local Pref)
      Community: 64496:100
  64501 64520 64510
    10.0.0.2 from 10.0.0.2 (10.0.0.2)
      Origin IGP, localpref 100, valid, internal

Два пути: через провайдера A напрямую (eBGP) и через провайдера B за R2 (iBGP, next hop 10.0.0.2 — R2 подменил его на себя). Первый выбран по Local Pref 200 против 100 — ещё до сравнения AS_PATH, который у него тоже короче.

Управление выбором — это и есть работа с BGP:

  • Исходящий трафик (куда мы шлём) управляется легко: LOCAL_PREF на входящих маршрутах. «Всё от провайдера A — localpref 200».
  • Входящий трафик (как к нам идут) управляется плохо: решение принимает чужая сеть. Инструменты — prepending (сделать путь через B длиннее), MED (подсказка одному соседу), community, которые провайдер обещал учитывать («64500:80 — понизь localpref у себя»), и крайний — анонсировать через A более длинные префиксы (/25 вместо /24), потому что самый длинный префикс побеждает всё (шестая часть). Последнее засоряет таблицу интернета и не приветствуется.

Политика выражается фильтрами на каждой сессии в обе стороны: prefix-list (какие префиксы), as-path-list (какие пути), route-map (условие → действие: принять, отбросить, выставить атрибут). Сессия без фильтра на выход — классическая авария: сеть с двумя провайдерами отдаёт маршруты одного другому и становится транзитом для части интернета на своём стомегабитном линке.


Что ломается в масштабе интернета

Угон префикса. BGP верит соседу. Если AS 64520 по ошибке или умышленно анонсирует 203.0.113.0/24, принадлежащий нам, провайдеры 64520 это примут, передадут дальше, и часть интернета понесёт наш трафик туда. Так в 2008 году пакистанский провайдер на час «забрал» YouTube, а в 2018-м через угон увели криптовалюту. Защита в три слоя:

  • Фильтры у провайдеров: принимать от клиента только префиксы, которые он зарегистрировал в базах IRR (whois-базы маршрутной политики). Работает, если провайдер фильтрует.
  • RPKI: владелец адресов публикует через регистратуру подписанное заявление ROA — «префикс 203.0.113.0/24 имеет право анонсировать только AS 64496, не длиннее /24». Роутеры скачивают проверенный набор ROA с валидатора и помечают маршруты: valid, invalid, unknown. Invalid — отбрасывать. С 2020-х большинство крупных сетей так и делают, и угон с чужим AS в источнике перестаёт распространяться.
  • Максимум префиксов на сессию (maximum-prefix): сосед, приславший вместо 10 своих префиксов полную таблицу (классическая утечка), отключается автоматически.

Утечка маршрутов — не злой умысел, а ошибка политики: сеть отдала одному провайдеру маршруты другого, и трафик между двумя гигантами пошёл через чей-то офисный роутер. Вылечить может только отдающая сторона; RPKI от этого не защищает, потому что источник в AS_PATH правильный.

Сходимость. BGP медленный по замыслу: таймер MRAI задерживает отправку UPDATE на секунды, чтобы не рассылать каждую промежуточную версию; отказ линка где-то в мире расходится по интернету за минуты, и в это время часть сетей видит старые пути. Для быстрого обнаружения отказа соседа есть BFD — тот же протокол быстрых пакетов, что и для OSPF, — и он сообщает BGP об обрыве за доли секунды вместо 180 секунд hold time.

Безопасность сессии. TCP-сессию можно сбросить подделанным RST, если угадать номера последовательности. Защита — TCP MD5 (подпись каждого сегмента общим ключом, опция TCP 19) или новый TCP-AO, и GTSM: слать с TTL 255 и принимать только пакеты с TTL 255, что гарантирует соседа в одном хопе.


BGP не только для интернета

Протокол оказался настолько гибким, что его используют там, где об интернете речи нет.

  • Дата-центры. В фабриках spine-leaf из восемнадцатой части вместо OSPF всё чаще eBGP: каждому коммутатору свой частный номер AS, между всеми — eBGP, политика через AS_PATH (RFC 7938). Масштабируется лучше link-state, и один протокол на всё.
  • EVPN — расширение BGP для передачи MAC-адресов и VNI между VTEP, тот самый control plane для VXLAN.
  • MPLS L3VPN — провайдеры держат в одном BGP маршруты сотен клиентов, различая их метками (семейство VPNv4), и клиент получает «свою» сеть через всю провайдерскую. MP-BGP, multiprotocol, — общее имя для BGP с несколькими семействами адресов: IPv4, IPv6, VPNv4, EVPN в одной сессии.
  • Kubernetes и балансировка. Узлы кластера анонсируют адреса сервисов роутеру по eBGP, и адрес становится маршрутом, который есть, пока жив хоть один узел. Это та самая серия: kube-vip и Calico с FRR на роутере.
  • Anycast. Один префикс анонсируется из десятков точек мира, и BGP приводит каждого клиента к ближайшей — так работают корневые DNS из двенадцатой части и все крупные CDN.

На FRR

R1 из схемы: eBGP с провайдером A, iBGP с R2, наш префикс наружу, фильтры в обе стороны:

router bgp 64496
 bgp router-id 10.0.0.1
 neighbor 198.51.100.1 remote-as 64500
 neighbor 198.51.100.1 description provider-a
 neighbor 198.51.100.1 password s3cret
 neighbor 10.0.0.2 remote-as 64496
 neighbor 10.0.0.2 update-source lo
 address-family ipv4 unicast
  network 203.0.113.0/24
  neighbor 198.51.100.1 route-map from-a in
  neighbor 198.51.100.1 route-map to-a out
  neighbor 198.51.100.1 maximum-prefix 1300000
  neighbor 10.0.0.2 next-hop-self
 exit-address-family

ip prefix-list ours seq 5 permit 203.0.113.0/24
route-map to-a permit 10
 match ip address prefix-list ours
route-map from-a permit 10
 set local-preference 200

remote-as, равный своему, делает сессию iBGP, отличный — eBGP; FRR сам применит нужные правила. network 203.0.113.0/24 вводит префикс в BGP, если он есть в таблице маршрутов (обычно статика в null, чтобы агрегат был всегда). to-a выпускает наружу только наш префикс, from-a принимает всё с localpref 200. На R2 — зеркально с провайдером B и localpref 100.

Состояние сессий:

$ vtysh -c 'show bgp summary'
Neighbor        V         AS   MsgRcvd   MsgSent   TblVer  InQ OutQ  Up/Down State/PfxRcd   PfxSnt Desc
198.51.100.1    4      64500   1234567   1234560        0    0    0 3d02h15m      1012345        1 provider-a
10.0.0.2        4      64496      1234      1230        0    0    0 3d02h10m            3        3

В колонке State/PfxRcd либо число принятых префиксов (сессия Established), либо состояние: Active, Connect, Idle (Admin). Миллион префиксов от провайдера, один наш наружу, три внутри — нормальная картина для сети с полной таблицей.

Посмотреть снаружи, как ваш префикс видит мир: любой looking glass провайдера, bgp.tools, RIPE RIS — они покажут AS_PATH до вас из разных точек, и по ним видно, работает ли prepending и не увёл ли кто ваш префикс.


Что запомнить

  • Интернет — автономные системы со своей политикой; BGP передаёт между ними префиксы с атрибутами, а не карту. Транзит и пиринг определяют, кому что анонсировать.
  • Поверх TCP 179, соседи прописаны руками, работает только Established; Active — значит не работает.
  • UPDATE несёт AS_PATH (путь и защита от петель), NEXT_HOP, LOCAL_PREF (своя политика, больше — лучше), MED (подсказка соседу, меньше — лучше), community (метки для политики).
  • eBGP между AS: добавляет свой AS в путь, ставит next hop на себя, сосед в одном хопе. iBGP внутри AS: путь и next hop не меняет, iBGP-маршруты другим iBGP не передаёт, поэтому полная сетка или route reflector, next-hop-self и IGP для достижимости соседей.
  • Лучший путь: LOCAL_PREF, свой, короче AS_PATH, ORIGIN, MED, eBGP над iBGP, ближний выход. Исходящим управляют localpref, входящим — prepending, MED, community и более длинные префиксы.
  • Фильтры в обе стороны на каждой сессии, maximum-prefix, RPKI против угона, TCP MD5 и GTSM для сессии.

Дальше — Часть 23: TLS и сертификаты, последняя: как защищают одно TCP-соединение, рукопожатие TLS 1.3 по сообщениям, откуда берутся ключи и почему есть forward secrecy, что такое сертификат X.509 и цепочка доверия, кто такие удостоверяющие центры и как они проверяют владельца, Let's Encrypt и протокол ACME, отзыв и Certificate Transparency, и что TLS не скрывает.


Серия «Сети для самых маленьких»

  1. Модели OSI и TCP/IP — зачем сетевой стек разбит на уровни и как данные обрастают заголовками по пути пакета.
  2. Ethernet — кадр по байтам, MAC-адреса и как коммутатор решает, в какой порт отправить кадр.
  3. Wi-Fi — чем радио отличается от кабеля, как клиент подключается к точке доступа и как защищается эфир.
  4. PPPoE — как провайдер заворачивает сессию абонента в Ethernet и откуда берётся MTU 1492.
  5. IPv4: адреса, маски и подсети — как читать адрес и маску, делить сеть на подсети и решать, нужен ли шлюз.
  6. IPv4: заголовок, маршрутизация и NAT — как роутер выбирает маршрут для пакета и как вся квартира выходит в интернет с одного адреса.
  7. ARP — как по IP-адресу соседа узнать его MAC-адрес и почему соседа так легко подменить.
  8. ICMP — служебные сообщения IP, как на самом деле работают ping и traceroute и что ломается, когда их режут.
  9. UDP — восемь байт заголовка, порты и почему отправка без соединения иногда лучше.
  10. TCP — как из ненадёжного IP получается надёжный поток байтов и почему потеря пакета режет скорость.
  11. DHCPv4 — как машина без адреса получает адрес, маску, шлюз и DNS четырьмя сообщениями.
  12. DNS — как имя превращается в адрес: дерево зон, рекурсивные серверы, записи и кеширование.
  13. IPv6: адреса и заголовок — как записываются 128-битные адреса, какие они бывают и чем заголовок IPv6 отличается от IPv4.
  14. ICMPv6 и Neighbor Discovery — как в IPv6 без ARP и широковещания находят соседей и роутер.
  15. SLAAC — как хост собирает себе адрес IPv6 из объявления роутера без всякого сервера.
  16. DHCPv6 — зачем DHCP, если есть SLAAC, и как провайдер выдаёт домашнему роутеру целый блок сетей.
  17. VLAN — как один коммутатор и один кабель несут несколько независимых сетей.
  18. VXLAN — как растянуть сеть Ethernet через роутеры, завернув кадры в UDP.
  19. IPsec и IKEv2 — как шифруют пакеты на сетевом уровне и договариваются о ключах.
  20. VPN и прокси — куда уходит каждый пакет при включённом VPN и чем прокси отличается от VPN.
  21. OSPF — как роутеры одной сети сами строят общую карту и считают по ней кратчайшие пути.
  22. BGP (эта статья) — как десятки тысяч независимых сетей интернета договариваются о маршрутах.
  23. TLS и сертификаты — как защищают одно TCP-соединение и откуда браузер знает, что сервер настоящий.

Оставить комментарий могут только зарегистрированные пользователи.

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