Перейти до вмісту

B3. OSPF і BGP

середнійспирається на модуль 8

Модуль 8 пояснює, чому статичні маршрути не масштабуються й як протоколи маршрутизації самі знаходять обхід, коли ланка гине. Тут ви поставите обидва протоколи на справжній маршрутний демон: BIRD 2, по одному процесу на простір імен. Спочатку OSPF на кільці з чотирьох маршрутизаторів: рвете ланку й міряєте, за скільки секунд мережа знаходить обхід. Потім eBGP між двома автономними системами, в якому одна сторона не приймає чужого зайвого.

Після цієї роботи ви зможете:

  • запустити BIRD у просторі імен зі своїм конфігом і сокетом керування (bird -c ... -s ...) і працювати з ним через birdc;
  • налаштувати OSPF у кільці, прочитати сусідів і базу станів ланок;
  • виміряти час збіжності після розриву ланки й пояснити, від яких таймерів він залежить;
  • налаштувати eBGP-сесію, анонсувати префікси й відфільтрувати імпорт;
  • відрізнити, які маршрути в таблиці ядра прийшли від демона, а які додано руками.

Це основа роботи мережевого інженера: коли обрив кабелю не має зупиняти офіс, а провайдер анонсує зайве, ви шукаєте причину саме тут: у сусідах, таймерах і фільтрах.

Робота має дві незалежні частини. Кожну можна перевірити окремо.

Чотири маршрутизатори 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. Назви інтерфейсів, шляхи до конфігів і сокетів оберіть самі.

Що зробити:

  1. Побудувати кільце й лінк між AS: простори імен, пари veth, адреси з таблиць. Ввімкнути net.ipv4.ip_forward у кожному маршрутизаторі.
  2. Написати конфіг BIRD для кожного маршрутизатора й запустити по одному демону на простір імен, кожен зі своїм -c і -s.
  3. Переконатися, що в кожному маршрутизаторі є по два сусіди OSPF у стані Full, а таблиці ядра містять маршрути до всіх 192.168.255.N від bird.
  4. Розірвати ланку r1–r2 двома способами й виміряти, за скільки секунд зв’язок r1 ↔ r2 відновлюється в обхід.
  5. Підняти eBGP між as1 і as2, анонсувати префікси.
  6. Написати в as1 фільтр імпорту, що пропускає лише 10.2.0.0/16.

Чого робити не треба. Кілька зон OSPF, автентифікація, BFD, iBGP, політики з local_pref та MED не входять. Їх видно в «Далі, якщо цікаво».

Обмеження. Тільки bird (пакет bird2), один процес на простір імен. Статичних маршрутів на маршрутизаторах бути не повинно: усе, що не пряме, має навчитися від BIRD.

Готово, коли sudo ./check.sh не показує жодного «НІ», у вас є виміряний час збіжності в обох випадках і пояснення, чому вони різні.

  • Прочитайте модуль 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: тут лише скелети конфігів.
  1. Кільце.

    Складіть простори імен і з’єднайте їх попарно. Для кожної ланки зручна функція в скрипті:

    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" up
    sudo 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 у кожному маршрутизаторі.

  2. 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.pid
    sudo 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.

  3. Досяжність.

    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 і подивіться, через якого сусіда йде пакет.

  4. Розрив ланки й збіжність.

    Запустіть у 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 cut
    sudo 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 drop
    sudo 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?

  5. 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, а не все підряд?

  6. Фільтр імпорту.

    Поки що 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) покаже його як відкинутий.

    Запишіть: чому в реальних мережах фільтр пишуть на імпорт (і на експорт), а не довіряють сусідові?

Terminal window
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 покажуть, що нічого не залишилося.

Не ввімкнено 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 і час перезавантаження.

Вимкніть check link, а hello залиште маленьким, і подивіться, скільки службового трафіку це дає. Додайте п’яту ланку-діагональ r1–r3 з більшою вартістю (cost) і подивіться, як змінюються маршрути. Перенесіть lo-адреси в OSPF із зовнішньою міткою (stubnet), спробуйте bfd для швидкого виявлення. Для BGP додайте local_pref у політику імпорту й третю AS, щоб побачити вибір шляху за довжиною AS_PATH.