B3. OSPF і BGP
Модуль 8 пояснює, чому статичні маршрути не масштабуються й як протоколи маршрутизації самі знаходять обхід, коли ланка гине. Тут ви поставите обидва протоколи на справжній маршрутний демон: BIRD 2, по одному процесу на простір імен. Спочатку OSPF на кільці з чотирьох маршрутизаторів: рвете ланку й міряєте, за скільки секунд мережа знаходить обхід. Потім eBGP між двома автономними системами, в якому одна сторона не приймає чужого зайвого.
Після цієї роботи ви зможете:
- запустити BIRD у просторі імен зі своїм конфігом і сокетом керування
(
bird -c ... -s ...) і працювати з ним черезbirdc; - налаштувати OSPF у кільці, прочитати сусідів і базу станів ланок;
- виміряти час збіжності після розриву ланки й пояснити, від яких таймерів він залежить;
- налаштувати eBGP-сесію, анонсувати префікси й відфільтрувати імпорт;
- відрізнити, які маршрути в таблиці ядра прийшли від демона, а які додано руками.
Це основа роботи мережевого інженера: коли обрив кабелю не має зупиняти офіс, а провайдер анонсує зайве, ви шукаєте причину саме тут: у сусідах, таймерах і фільтрах.
Завдання
Section titled “Завдання”Робота має дві незалежні частини. Кожну можна перевірити окремо.
Частина 1. OSPF у кільці
Section titled “Частина 1. OSPF у кільці”Чотири маршрутизатори r1–r4 сполучені кільцем. Кожна ланка має
власну підмережу /30, а на lo кожного маршрутизатора стоїть адреса
192.168.255.N/32, яку OSPF має розповісти всім.
r1 ─── 10.0.12.0/30 ─── r2 │ │ 10.0.41.0/30 10.0.23.0/30 │ │ r4 ─── 10.0.34.0/30 ─── r3| Ланка | Підмережа | Адреси |
|---|---|---|
r1–r2 |
10.0.12.0/30 |
.1 у r1, .2 у r2 |
r2–r3 |
10.0.23.0/30 |
.1 у r2, .2 у r3 |
r3–r4 |
10.0.34.0/30 |
.1 у r3, .2 у r4 |
r4–r1 |
10.0.41.0/30 |
.1 у r4, .2 у r1 |
lo у rN: 192.168.255.N/32 (тобто r1 має 192.168.255.1, r4 має
192.168.255.4).
Частина 2. eBGP між двома AS
Section titled “Частина 2. eBGP між двома AS”| Простір імен | AS | Адреси | Анонсує |
|---|---|---|---|
as1 |
65001 | 172.16.0.1/30 на лінку, 10.1.0.1/32 на lo |
10.1.0.0/16 |
as2 |
65002 | 172.16.0.2/30 на лінку, 10.2.0.1/32 і 10.99.0.1/32 на lo |
10.2.0.0/16 і 10.99.0.0/16 |
as1 має приймати від as2 лише 10.2.0.0/16. Префікс 10.99.0.0/16
as2 анонсує, а as1 його відкидає фільтром імпорту.
Назви просторів імен і адреси зафіксовані, їх перевіряє check.sh.
Назви інтерфейсів, шляхи до конфігів і сокетів оберіть самі.
Що зробити:
- Побудувати кільце й лінк між AS: простори імен, пари
veth, адреси з таблиць. Ввімкнутиnet.ipv4.ip_forwardу кожному маршрутизаторі. - Написати конфіг BIRD для кожного маршрутизатора й запустити по одному
демону на простір імен, кожен зі своїм
-cі-s. - Переконатися, що в кожному маршрутизаторі є по два сусіди OSPF у стані
Full, а таблиці ядра містять маршрути до всіх192.168.255.Nвідbird. - Розірвати ланку
r1–r2двома способами й виміряти, за скільки секунд зв’язокr1↔r2відновлюється в обхід. - Підняти eBGP між
as1іas2, анонсувати префікси. - Написати в
as1фільтр імпорту, що пропускає лише10.2.0.0/16.
Чого робити не треба. Кілька зон OSPF, автентифікація, BFD, iBGP,
політики з local_pref та MED не входять. Їх видно в «Далі, якщо цікаво».
Обмеження. Тільки bird (пакет bird2), один процес на простір імен.
Статичних маршрутів на маршрутизаторах бути не повинно: усе, що не пряме,
має навчитися від BIRD.
Готово, коли sudo ./check.sh не показує жодного «НІ», у вас є
виміряний час збіжності в обох випадках і пояснення, чому вони різні.
Перед початком
Section titled “Перед початком”- Прочитайте модуль 8: розділи про OSPF, базу станів ланок, таймери й про BGP (сесія, анонси, політики).
- Встановіть інструменти:
sudo bash setup/provision.sh(потрібніbird2,iproute2,nftables,tcpdump). Службуbirdсистемного рівня provision вимикає: у цій роботі ви запускаєте демони самі. - Потрібні права root. Працюйте в каталозі
labs/b3-dynamic-routing. - Прочитайте
man birdабо розділи «OSPF» і «BGP» на сайті документації BIRD 2: тут лише скелети конфігів.
-
Кільце.
Складіть простори імен і з’єднайте їх попарно. Для кожної ланки зручна функція в скрипті:
Terminal window link() { # лівий правий мережаsudo ip link add "to-$2" netns "$1" type veth peer name "to-$1" netns "$2"sudo ip netns exec "$1" ip addr add "$3.1/30" dev "to-$2"sudo ip netns exec "$2" ip addr add "$3.2/30" dev "to-$1"sudo ip netns exec "$1" ip link set "to-$2" upsudo ip netns exec "$2" ip link set "to-$1" up}link r1 r2 10.0.12Не забудьте
lo(піднята, з адресою192.168.255.N/32) іsysctl -w net.ipv4.ip_forward=1у кожному маршрутизаторі. -
BIRD у просторі імен.
Мінімальний конфіг
r1(кожному маршрутизатору потрібен свійrouter id):router id 192.168.255.1;protocol device { }protocol kernel {ipv4 { export all; };}protocol ospf v2 {ipv4 { import all; export all; };area 0 {interface "lo" { stub yes; };interface "to-*" { type ptp; };};}Запуск: кожному процесу свій конфіг, сокет і pid-файл.
Terminal window sudo ip netns exec r1 bird -c ~/b3/r1.conf -s /tmp/r1.ctl -P /tmp/r1.pidsudo ip netns exec r1 birdc -s /tmp/r1.ctl show protocolsПеревірте:
show ospf neighborsу кожному демоні показує двох сусідівFull/PtP,show ospf topologyзнає всі чотири маршрутизатори, аip route show proto birdуr1містить маршрути до192.168.255.2,.3і.4.Запишіть: чому до
192.168.255.3уr1два однакових за вартістю шляхи? Яку вартість (cost) дає BIRD ланці за замовчуванням? Подивіться вshow ospf interface. -
Досяжність.
Terminal window sudo ip netns exec r1 ping -c1 -I 192.168.255.1 192.168.255.3-Iробить відправником адресуlo: так відповідь повертається за маршрутами, а не за прямою підмережею. Пропінгуйте всі пари. Запустітьtraceroute -n -s 192.168.255.1 192.168.255.3уr1і подивіться, через якого сусіда йде пакет. -
Розрив ланки й збіжність.
Запустіть у
r1безперервнийping, що показує час кожної відповіді:Terminal window sudo ip netns exec r1 ping -D -i 0.2 -I 192.168.255.1 192.168.255.2і в іншому вікні розірвіть ланку
r1–r2двома способами.Перший: вимкнути інтерфейс.
Terminal window sudo ip netns exec r1 ip link set to-r2 downЯдро й BIRD одразу знають, що ланки немає. Подивіться на проріху у відповідях: скільки секунд
pingмовчав?Другий: «мовчазний» розрив. Ланка формально цілком жива, але пакети зникають. Так ламається ланка, що йде через проміжний комутатор чи оптичний перетворювач: інтерфейс лишається
UP, жодного сигналу про аварію. Змоделюйте це правилом, що відкидає весь трафік на інтерфейсі:Terminal window sudo ip netns exec r1 nft add table inet cutsudo ip netns exec r1 nft add chain inet cut pre \'{ type filter hook prerouting priority -300; }'sudo ip netns exec r1 nft add chain inet cut post \'{ type filter hook postrouting priority 300; }'sudo ip netns exec r1 nft add rule inet cut pre iifname to-r2 dropsudo ip netns exec r1 nft add rule inet cut post oifname to-r2 dropТепер нікого не сповіщено. Сусід зникає лише тоді, коли спливає
dead interval. Заміряйте час ще раз, відновіть ланку (nft delete table inet cut) і порівняйте.Тепер підберіть таймери. У блоці
interfaceєhello,deadіcheck link:interface "to-*" { type ptp; hello 1; dead 4; check link yes; };Повторіть обидва досліди зі значеннями за замовчуванням і з цими. Зробіть так, щоб збіжність у обох випадках вкладалася в 20 секунд (це й перевіряє
check.sh).Запишіть: у таблиці «спосіб розриву × таймери» чотири виміряні числа. Чому в першому досліді таймери майже не впливають? Яка ціна дуже малого
hello? -
eBGP.
Скелет конфігу
as1:router id 172.16.0.1;protocol device { }protocol static own {ipv4;route 10.1.0.0/16 blackhole;}protocol kernel {ipv4 { import none; export where source = RTS_BGP; };}protocol bgp as2 {local 172.16.0.1 as 65001;neighbor 172.16.0.2 as 65002;ipv4 { import all; export where source = RTS_STATIC; };}Статичний маршрут
blackholeлише дає BIRD що оголошувати: префікс10.1.0.0/16як таке в ядро не потрапляє (експортується лишеRTS_BGP). Складіть дзеркальний конфіг дляas2із двома префіксами:10.2.0.0/16і10.99.0.0/16.Перевірте:
birdc show protocols all as2уas1кажеEstablishedіNeighbor AS: 65002.ip route show proto birdуas1містить10.2.0.0/16. Пропінгуйте10.2.0.1із10.1.0.1:Terminal window sudo ip netns exec as1 ping -c1 -I 10.1.0.1 10.2.0.1Запишіть: що робить
export where source = RTS_STATICу каналі BGP і чому в ядро експортують лишеRTS_BGP, а не все підряд? -
Фільтр імпорту.
Поки що
as1прийняла й10.99.0.0/16. Напишіть фільтр і підставте його вimport:filter from_as2 {if net = 10.2.0.0/16 then accept;reject;}Перезавантажте конфіг без розриву сесії:
birdc -s /tmp/as1.ctl configure. Перевірте:birdc show routeуas1більше не містить10.99.0.0/16, аshow route protocol as2 filtered(якщо ввімкнулиimport keep filtered) покаже його як відкинутий.Запишіть: чому в реальних мережах фільтр пишуть на імпорт (і на експорт), а не довіряють сусідові?
Перевірка
Section titled “Перевірка”sudo ./check.sh # обидві частиниsudo ./check.sh ospf # лише кільцеsudo ./check.sh bgp # лише eBGPСкрипт нічого не будує. Інтерфейси він знаходить за адресами, а сокет
керування BIRD бере з командного рядка процесу (-s ...), тож усі
назви й шляхи ваші. Перевіряється:
- адреси на всіх маршрутизаторах і їх
lo; - що в кожному просторі працює
bird, у кільці по два сусідиFull, а сесії BGP в станіEstablishedіз правильними номерами AS; - що в ядрі маршрути до чужих
192.168.255.N(та10.2.0.0/16,10.1.0.0/16) маютьproto bird; - що всі пари
loдосяжні, аas1іas2пінгують одна одну з адресlo; - що
10.99.0.0/16не потрапив вas1ні в таблицю ядра, ні в таблицю BIRD, хочаas2його має й анонсує; - розрив ланки: скрипт сам вимикає інтерфейс
r1доr2і вимикає його ж мовчки (правиломnftables), чекає відновлення зв’язкуr1↔r2в обхід (черезr4) і вимірює час; ліміт 20 с можна змінити:CONVERGE_MAX=30 sudo ./check.sh ospf. Потім ланка відновлюється, і скрипт чекає, поки маршрут знов піде напряму.
Чекер завжди повертає ланку на місце, навіть якщо його перервати
(Ctrl-C). Якщо сумніваєтеся, ip netns exec r1 ip link show і
ip netns exec r1 nft list tables покажуть, що нічого не залишилося.
Часті помилки
Section titled “Часті помилки”Не ввімкнено ip_forward. Описано в етапі 1. Симптом: сусіди є,
маршрути є, ping до сусіда проходить, а через сусіда ні.
Демони ділять сокет чи pid-файл. Якщо всі копії BIRD отримали
один -s /run/bird.ctl, другий процес не запуститься. Кожному
простору імен свій сокет і свій -P.
Системна служба bird. Якщо ви ставили пакет без setup/provision.sh,
служба bird могла запуститися в основному просторі імен. Вона не заважає
процесам у просторах, але birdc без -s заговорить саме з нею.
Завжди вказуйте -s.
OSPF не піднімається на veth. Тип ланки за замовчуванням —
broadcast, і вибори DR можуть довго тривати. Для двоточкових ланок
задавайте type ptp.
interface "to-*" не збігається з назвами. Шаблон у BIRD — це
маска назв інтерфейсів. Якщо ваші інтерфейси називаються інакше,
змініть шаблон, інакше OSPF не запуститься ні на одному.
BGP-сесія не доходить до Established. Подивіться
birdc show protocols all <ім'я>: там видно причину (Connection refused, Hold timer expired, невідповідність AS). Перевірте, що
local/neighbor не переплутано й що номер AS сусіда збігається
з його конфігом.
Фільтр «нічого не зробив». Правка конфігу без birdc configure
на демон не діє. Перевірте birdc show protocols і час перезавантаження.
Далі, якщо цікаво
Section titled “Далі, якщо цікаво”Вимкніть check link, а hello залиште маленьким, і подивіться,
скільки службового трафіку це дає. Додайте п’яту ланку-діагональ
r1–r3 з більшою вартістю (cost) і подивіться, як змінюються
маршрути. Перенесіть lo-адреси в OSPF із зовнішньою міткою
(stubnet), спробуйте bfd для швидкого виявлення. Для BGP додайте
local_pref у політику імпорту й третю AS, щоб побачити вибір
шляху за довжиною AS_PATH.