Сети для самых маленьких. Часть 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 hop198.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), и выбирает его цепочка правил, по порядку, до первого различия:
- Больший LOCAL_PREF. Политика своей AS бьёт всё: «провайдер A предпочтительнее B».
- Локально порождённый (
network) — лучше полученного. - Короче AS_PATH.
- ORIGIN: IGP лучше EGP лучше incomplete.
- Меньший MED — только среди путей от одной и той же соседней AS.
- eBGP лучше iBGP.
- Меньшая метрика IGP до NEXT_HOP — ближайший выход из AS (hot potato: избавиться от чужого трафика побыстрее).
- Старший путь, затем меньший 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 не скрывает.
Серия «Сети для самых маленьких»
- Модели OSI и TCP/IP — зачем сетевой стек разбит на уровни и как данные обрастают заголовками по пути пакета.
- Ethernet — кадр по байтам, MAC-адреса и как коммутатор решает, в какой порт отправить кадр.
- Wi-Fi — чем радио отличается от кабеля, как клиент подключается к точке доступа и как защищается эфир.
- PPPoE — как провайдер заворачивает сессию абонента в Ethernet и откуда берётся MTU 1492.
- IPv4: адреса, маски и подсети — как читать адрес и маску, делить сеть на подсети и решать, нужен ли шлюз.
- IPv4: заголовок, маршрутизация и NAT — как роутер выбирает маршрут для пакета и как вся квартира выходит в интернет с одного адреса.
- ARP — как по IP-адресу соседа узнать его MAC-адрес и почему соседа так легко подменить.
- ICMP — служебные сообщения IP, как на самом деле работают ping и traceroute и что ломается, когда их режут.
- UDP — восемь байт заголовка, порты и почему отправка без соединения иногда лучше.
- TCP — как из ненадёжного IP получается надёжный поток байтов и почему потеря пакета режет скорость.
- DHCPv4 — как машина без адреса получает адрес, маску, шлюз и DNS четырьмя сообщениями.
- DNS — как имя превращается в адрес: дерево зон, рекурсивные серверы, записи и кеширование.
- IPv6: адреса и заголовок — как записываются 128-битные адреса, какие они бывают и чем заголовок IPv6 отличается от IPv4.
- ICMPv6 и Neighbor Discovery — как в IPv6 без ARP и широковещания находят соседей и роутер.
- SLAAC — как хост собирает себе адрес IPv6 из объявления роутера без всякого сервера.
- DHCPv6 — зачем DHCP, если есть SLAAC, и как провайдер выдаёт домашнему роутеру целый блок сетей.
- VLAN — как один коммутатор и один кабель несут несколько независимых сетей.
- VXLAN — как растянуть сеть Ethernet через роутеры, завернув кадры в UDP.
- IPsec и IKEv2 — как шифруют пакеты на сетевом уровне и договариваются о ключах.
- VPN и прокси — куда уходит каждый пакет при включённом VPN и чем прокси отличается от VPN.
- OSPF — как роутеры одной сети сами строят общую карту и считают по ней кратчайшие пути.
- BGP (эта статья) — как десятки тысяч независимых сетей интернета договариваются о маршрутах.
- TLS и сертификаты — как защищают одно TCP-соединение и откуда браузер знает, что сервер настоящий.
Оставить комментарий могут только зарегистрированные пользователи.
Войдите на сайт или зарегистрируйтесь, чтобы оставить комментарий.