BGP для начинающих с использованием zebra на базе FreeBSD

Thursday, 30 March 2006

На первый взгляд типичная задача обеспечения бесперебойной связи меджу удаленными точками при глубинном изучении выявила несколько различных по степени сложности подходов. Надо отметить что готовых и "родных" методов для решения этой проблемы ни в одной системе я не увидел. А зачастую задача усугубляется еще и требованиями к балансировке нагрузки, что тоже является очень непростой задачей, например, исходя из каких условий установить приоритеты использования каналов? А требования к балансировке могут быть самыми разными, например, стоимость трафика, ширина и скорость каналов, латентность(пинг). С честной балансировкой нагрузки во FreeBSD очень плохо в связи с отсутствием фичи "поддержка multi route path", это когда непосредственно в ядре хранится несколько записей для одного и того же хоста, с заданием приоритетов. А в Линуксе есть, ага.

Но вернемся к нашей теме.

Условно к решению задачи динамического переключения каналов есть два подхода. Первый, любительский, переключение каналов пингующими скриптами. Второй промышленный, настройкой и использованием bgp протокола динамической маршрутизации. Первый метод достаточно прост, и в этой заметке рассматриваться не будет, суть в двух словах: пингуем шлюзы, при отсутствии пинга прописываем default route на второй шлюз. Но мы же эта, конечно, легких путей не ищем :)

В моем хитром случае (который подойдет далеко не всем) имеется: две площадки, которые нужно связать между собой бесперебойными каналами связи, сервер на площадке провайдера (он же главный роутер) в дальнейшем - colo (195.202.61.146, 195.202.61.164, 195.202.61.165), через который и проходит весь внешний трафик (самые недорогие тарифы). Одна площадка (в дальнейшем HQ - head quarter) имеет прямой канал на colocation (195.202.61.106-195.202.61.105) и два запасных провайдера (85.171.240.233, 215.36.171.94), другая площадка (в дальнейшем - склад), также имеет прямой канал к серверу на colocation (195.202.61.101-195.202.61.102) плюс дополнительный канал к резервному провайдеру (шлюз 195.29.234.110).

Задача: динамическое переключение на резервные каналы при падении любого основного.

Первое, с чего хотелось бы начать, так это с необходимости создания туннелей через шлюзы резервных провайдеров к colo серверу. Для чего? А очень просто, так нам не прийдется руками переписывать таблицы маршрутизации на складе для сетей расположенных в HQ (и к тому же в HQ не нужно будет переписывать таблицы для сетей склада, не говоря уже о сервере colo). Пробрасываем туннели к colo через резервных провайдеров через специальные FreeBSD теннельные gif интерфейсы. Тут есть небольшая загвоздка, для корректного проброса туннелей через резервных провайдеров нам необходимы дополнительные IP адреса на colo сервере, к которым мы пропишем пути через шлюзы резервных провайдеров. Для складского роутера, например, так:

----- gate-stock rc.conf ---- (FreeBSD 5.3) -

## резервный канал

ifconfig_ste1="inet 195.29.234.110 netmask 255.255.255.252"

## основной канал к colo

ifconfig_rl0="inet 195.202.61.102 netmask 255.255.255.252"

## локальная сеть

ifconfig_ste0="inet 192.168.3.2 netmask 255.255.255.0"

## шлюз через неосновгого провайдера к colo

route_165="195.202.61.165/32 195.29.234.109"

static_routes="165"

## непосредственно проброс туннеля к colo

gif_interfaces="gif0"

gifconfig_gif0="195.29.234.110 195.202.61.165"

## виртуальная сеть

ifconfig_gif0="192.168.8.10 netmask 255.255.255.252 192.168.8.9 netmask 255.255.255.252"

------------------------------

----- gate-hq /etc/rc.conf -- (FreeBSD 5.4) -

## локальная сеть

ifconfig_ste0="inet 192.168.0.1 netmask 255.255.255.0"

## один провайдер

ifconfig_xl0="inet 215.36.171.94 netmask 255.255.255.240"

## основной канал

ifconfig_fxp0="inet 195.202.61.106 netmask 255.255.255.252"

## статический маршрут через шлюз резервного провайдера

route_164="195.202.61.164/32 215.36.171.93"

static_routes="164"

## туннель через резервный маршрут

gif_interfaces="gif0"

gifconfig_gif0="215.36.171.94 195.202.61.164"

ifconfig_gif0="inet 192.168.8.14 netmask 255.255.255.252 192.168.8.13 netmask 255.255.255.252"

------------------------------

----- colo server /etc/rc.conf -- (в FreeBSD 4.11 отличается синтаксис gif от 5.3 !) -

ifconfig_fxp0="inet 195.202.61.146 netmask 255.255.255.252"

## алиас 1

ifconfig_fxp0_alias0="inet 195.202.61.164 netmask 255.255.255.255"

## алиас 2

ifconfig_fxp0_alias1="inet 195.202.61.165 netmask 255.255.255.255"

### туннели к hq и склад

gif_interfaces="gif0 gif1"

gifconfig_gif0="195.202.61.165 195.29.234.110"

gifconfig_gif1="195.202.61.164 215.36.171.94"

ifconfig_gif0="inet 192.168.8.9 netmask 255.255.255.252 192.168.8.10 netmask 255.255.255.252"

ifconfig_gif1="inet 192.168.8.13 netmask 255.255.255.252 192.168.8.14 netmask 255.255.255.252"

---------------------------------

Внимание! Маршрутизацией, т.е. получением и передачей маршрутов заниматься у нас будет специальный демон: zebra. И у нас не будет явным образом задан default route! (look ma, no default route!)

Подготовительные работы будем считать выполнеными. Да, скажете вы, а секурность? А вам, отвечу я, ничто не мешает повесить поверх туннелей ipsec криптование, но это уже тема для отдельной статьи.

Перейдем к матчасти.

Default route мы будем получать от colo сервера, который, в свою очередь, возьмет его у провайдера (Михайлову респект ;). Роутеры на складе и HQ будут автоматически пинговать по маршрутам, и анонсировать живые маршруты далее по цепочке соседских роутеров. Пару слов о BGP (в моем холопском понимании). Единицей, с которой работает BGP является запись о известном маршруте, который роутер может передавать соседнему роутеру. Область, в которой объединены роутеры под управлением одного администратора называется AS (автономная система). AS диапазоны выдаются провайдерам организацией RIPE и берут за это деньги :) Существует специальный AS номер для приватных сетей 65001, который мы и будем использовать в нашем примере, это наподобие зарезервированных частных сетей 127.0.0 и 192.168.0. :) Когда анонс внутреннего машршута (iBGP) выходит за пределы своей AS он становится "внешним" (eBGP). Работа с внешними маршрутами имеет свои нюансы, в которые мы пока вдаваться не будем.

Подготовим зебру к запуску при загрузке, для чего у каждого сервера укажем в rc.conf

router_enable="YES"

router="/usr/local/sbin/zebractl"

router_flags="start"

И перейдем к фазе конфигурации. Настроим colo сервер на дружбу с соседскими роутерами и беспрепятственным получением маршрутов.

---- colo сервер /usr/local/etc/zebra/bgpd.conf ---

## приватный диапазон

router bgp 65001

bgp router-id 195.202.61.146

## соседний роутер в той же AS

neighbor 195.202.61.106 remote-as 65001

## заменяем провайдерский default route на свой

neighbor 195.202.61.106 next-hop-self

## необходимо указывать в internal bgp непосредственно для передачи маршрутов от роутера

neighbor 195.202.61.106 route-reflector-client

neighbor 195.202.61.102 remote-as 65001

neighbor 195.202.61.102 next-hop-self

neighbor 195.202.61.102 route-reflector-client

## предпочтительный канал с весом 2000 (этой штукой мы задаем используемы канал по умолчанию как основной)

neighbor 195.202.61.102 weight 2000

neighbor 192.168.8.14 remote-as 65001

neighbor 192.168.8.14 next-hop-self

neighbor 192.168.8.14 route-reflector-client

neighbor 192.168.8.10 remote-as 65001

neighbor 192.168.8.10 next-hop-self

neighbor 192.168.8.10 route-reflector-client

## резервный канал с весом 1000, тот, на который мы переключимся при падении основного

neighbor 192.168.8.10 weight 1000

## передавать маршруты со статусом CONNECTED

redistribute connected

## получение default route из провайдерского BGP и его AS

neighbor 195.202.61.145 remote-as 24995

neighbor 195.202.61.145 prefix-list DENYALL out

neighbor 195.202.61.145 ebgp-multihop 3

ip prefix-list DENYALL deny 0.0.0.0/0

log stdout

-------------------------------------------------

Роутер на складе.

--- gate-stock /usr/local/etc/zebra/bgpd.conf ---

## тот же приватный AS

router bgp 65001

bgp router-id 195.202.61.102

network 192.168.3.0/24

## его непосредственный сосед - colo сервер

neighbor 195.202.61.101 remote-as 65001

neighbor 195.202.61.101 next-hop-self

neighbor 195.202.61.101 route-reflector-client

neighbor 195.202.61.101 distribute-list 1 out

## задаем основной канал

neighbor 195.202.61.101 weight 2000

neighbor 192.168.8.9 remote-as 65001

neighbor 192.168.8.9 next-hop-self

neighbor 192.168.8.9 route-reflector-client

neighbor 192.168.8.9 distribute-list 1 out

## задаем резервный канал

neighbor 192.168.8.9 weight 1000

## разрешаем передавать свои маршруты

redistribute connected

## не анонсируем маршруты через другого провайдера

access-list 1 deny 195.29.234.0 0.0.0.255

access-list 1 permit any

log file bgpd.log

log stdout

------------------------------------------

Роутер в HQ

--- gate-hq /usr/local/etc/zebra/bgpd.conf ---

router bgp 65001

bgp router-id 195.202.61.106

neighbor 195.202.61.105 remote-as 65001

neighbor 195.202.61.105 next-hop-self

neighbor 195.202.61.105 route-reflector-client

neighbor 195.202.61.105 distribute-list 1 out

neighbor 192.168.8.13 weight 2000

!redistribute connected

neighbor 192.168.8.13 remote-as 65001

neighbor 192.168.8.13 next-hop-self

neighbor 192.168.8.13 route-reflector-client

neighbor 192.168.8.13 weight 1000

access-list 1 deny 215.36.171.0 0.0.0.255

access-list 1 permit any

access-list all permit any

log stdout

----------------------------------------------

Демоном зебры мы можем управлять через zebractl [start|stop|restart]

Кончено, с первого раза врядли у вас все пойдет как по маслу, поэтому для отладки bgp задайте в обязательном порядке пароль для соединения с консолью зебры

password xxxxx

enable password yyyyy

Для просмотра и отладки таблицы маршрутизации роутеров запускаем телнет и коннектимся к складскому роутеру на порт 2601

>telnet gate-stock 2601

оказываемся в консоли:

gate-stock> show ip rou

Codes: K - kernel route, C - connected, S - static, R - RIP, O - OSPF,

B - BGP, > - selected route, * - FIB route

## машрут по умолчанию, B указывает на то, что он получен по протоколу BGP

B>* 0.0.0.0/0 [200/0] via 195.202.61.101, rl0, 3d01h38m

## модем 1

B>* 10.1.0.104/29 [200/0] via 195.202.61.101, rl0, 3d01h38m

## модем 2

B>* 10.1.0.112/29 [200/0] via 195.202.61.101, rl0, 3d01h38m

C>* 127.0.0.0/8 is directly connected, lo0

C>* 192.168.3.0/24 is directly connected, ste0

C>* 192.168.8.8/30 is directly connected, gif0

## по BGP получием также и другие маршруты, прописанные на colo

B>* 192.168.8.12/30 [200/0] via 195.202.61.101, rl0, 3d01h38m

B>* 192.168.26.104/32 [200/0] via 195.202.61.101, rl0, 02:22:12

C>* 195.29.234.108/30 is directly connected, ste1

C>* 195.202.61.100/30 is directly connected, rl0

B>* 195.202.61.104/30 [200/0] via 195.202.61.101, rl0, 3d01h38m

B>* 195.202.61.144/30 [200/0] via 195.202.61.101, rl0, 3d01h38m

B>* 195.202.61.164/30 [200/0] via 195.202.61.101, rl0, 3d01h38m

S>* 195.202.61.164/32 [1/0] via 195.29.234.109, ste1

## вот она, заветная строчка, > указывает на то, что маршрут в данный момент не выбран, и является бекапным

B 195.202.61.165/32 [200/0] via 195.202.61.101, rl0, 3d01h38m

K>* 195.202.61.165/32 via 195.29.234.109, ste1

Для просмотра и отладки работы BGP протокола запускаем телнет и коннектимся к зебре на порт 2605

>telnet gate-stock 2605

bgpd> show ip bgp

BGP table version is 0, local router ID is 195.202.61.102

Status codes: s suppressed, d damped, h history, * valid, > best, i - internal

Origin codes: i - IGP, e - EGP, ? - incomplete

Network Next Hop Metric LocPrf Weight Path

## два маршрута по умолчанию :) сейчас выбран гейт с наибольшим приоритетом

* i0.0.0.0 192.168.8.9 100 1000 24995 i

*>i 195.202.61.101 100 2000 24995 i

## резервный гейт, неактивен

* i10.1.0.104/29 192.168.8.9 0 100 1000 ?

*>i 195.202.61.101 0 100 2000 ?

* i10.1.0.112/29 192.168.8.9 0 100 1000 ?

*>i 195.202.61.101 0 100 2000 ?

* i192.168.0.0 195.202.61.106 0 100 1000 i

* i 195.202.61.106 0 100 2000 i

* 192.168.3.0 0.0.0.0 0 32768 ?

*> 0.0.0.0 0 32768 i

* i192.168.5.0 195.202.61.106 0 100 1000 i

* i 195.202.61.106 0 100 2000 i

* i192.168.6.0 195.202.61.106 0 100 1000 i

* i 195.202.61.106 0 100 2000 i

* i192.168.7.0 195.202.61.106 0 100 1000 i

* i 195.202.61.106 0 100 2000 i

* i192.168.8.8/30 192.168.8.9 0 100 1000 ?

* i 195.202.61.101 0 100 2000 ?

* i192.168.8.12/30 192.168.8.9 0 100 1000 ?

*>i 195.202.61.101 0 100 2000 ?

* i192.168.26.104/32

192.168.8.9 0 100 1000 ?

*>i 195.202.61.101 0 100 2000 ?

*> 195.29.234.108/30

0.0.0.0 0 32768 ?

* i195.202.61.100/30

192.168.8.9 0 100 1000 ?

* i 195.202.61.101 0 100 2000 ?

*> 0.0.0.0 0 32768 ?

* i195.202.61.104/30

192.168.8.9 0 100 1000 ?

*>i 195.202.61.101 0 100 2000 ?

* i195.202.61.144/30

192.168.8.9 0 100 1000 ?

*>i 195.202.61.101 0 100 2000 ?

* i195.202.61.164/30

192.168.8.9 0 100 1000 ?

*>i 195.202.61.101 0 100 2000 ?

* i195.202.61.165/32

192.168.8.9 0 100 1000 ?

*>i 195.202.61.101 0 100 2000 ?

* i195.202.61.184/29

195.202.61.106 0 100 1000 ?

* i 195.202.61.106 0 100 2000 ?

Total number of prefixes 18

Стоит отметить, что BGP протокол достаточно неторопливый, смена маршрутов иногда занимает несколько минут, но тем не менее, работает!

по моей просьбе были даны дельные комментарии от гуру:

---

neighbor 1.2.3.4 fall-over

bgp fast-external-fallover

timers bgp 5 15

будет быстрее...

кроме того можно заюзать механизм "bgp dampening" дабы не переключатся на хлопающий канал...

---

Для перехода на следующий уровень медитаций над BGP рекомендуется получить свой личный AS у RIPE и договориться с провайдрами об анонсах своих маршрутов на пограничные роутеры, и тогда мы имеем шанс погрузиться в окончательную нирвану с оптимизированной маршрутизацией к вашим сетям на уровне интернет-провайдеров!

http://www.rostovlinux.ru/content/view/727/56/

Обновлено: 12.03.2015