Два провайдера, FreeBSD + bird + проверка канала ping-ом

6th Январь 2013 | Метки: , , ,
Опубликовал: Dmitriy [dk] Kalinin

Захотелось сделать проверку наличия канала связи двух провайдеров, и выбирать шлюз на основании этих данных. У каждого провайдера есть свои подсети, причем оба провайдера между собой дружат и устроили полноценный пиринг.

Небольшой набросок топологии:

топология

топология

Провайдер 1 — Ланта. Подключен к FreeBSD по Ethernet, в отдельном VLAN-e (vlan102). Используется как основной канал.

Провайдер 2 — Ростелеком. Покдлючен к FreeBSD по Ethernet, канал образуется через PPPoE (ng0). Используется как резервный канал.

В сносках указаны пиринговые сети каждого из провайдеров. Розовым цветом выделены совпадающие подсети обоих провайдеров, жирным подсвечены родные подсети провайдеров.

bird, можно сказать, не умеет определять работоспособность канала. Верней он может, путем определения существования и активности интерфейса (да, для Ростелекома это подойдет), но в случае с VLAN-ом это сводится на нет. VLAN всегда активен. Но, даже если бы VLAN отключался синхронно с портом коммутатора провайдера — то определить работоспособность канала невозможно без проверки доступности удаленного хоста (провайдеры не дают клиентом никакой динамической маршрутизации).

В качестве хоста для проверка выбрал публичный DNS-сервер Google — 8.8.8.8. Именно его и буду пинговать для проверти наличия Интернет.

Итак, в наличии есть:

  • Подсети провайдеров;
  • Выбран основной и резервный каналы;
  • Известны родные подсети провайдеры (именно туда желательно отправлять родной.

Что хочется:

  • Отсылать родной трафик как можно ближе к провайдеру;
  • При отсутствии Интернет на одном из провайдеров — перекидывать трафик на другой.

Приведу сразу bird.conf:

log syslog { info, warning, error, fatal, bug };
 
router id 0.0.0.10;
 
table fib0;
table fib2;
table fib3;
 
protocol device {
  scan time 10;
}
 
protocol kernel kernel_fib0 {
  table fib0;
  scan time 20;
  import none;
  export all;
  kernel table 0;
}
 
protocol kernel kernel_fib2 {
  table fib2;
  scan time 20;
  import none;
  export all;
  kernel table 2;
}
 
protocol kernel kernel_fib3 {
  table fib3;
  scan time 20;
  import none;
  export all;
  kernel table 3;
}
protocol static static_fib0_lanta {
  table fib0;
  preference 200;
 
  # default
  route 0.0.0.0/0 via 93.186.105.129;
 
  # ЛанТа
  route 193.203.60.0/22 via 93.186.105.129; # Ланта
  route 93.186.96.0/20 via 93.186.105.129; # Ланта
  route 37.235.128.0/17 via 93.186.105.129; # Ланта
  route 78.132.128.0/17 via 93.186.105.129; # Ростелеком
  route 78.132.128.0/17 via 93.186.105.129; # Ростелеком
  route 213.135.128.0/19 via 93.186.105.129; # Ростелеком
  route 178.75.64.0/18 via 93.186.105.129; # Ростелеком
  route 37.76.160.0/19 via 93.186.105.129; # Ростелеком
}
 
protocol static static_fib0_rt {
  table fib0;
  preference 210;
 
  # Ростелеком
  route 193.33.62.0/23 via "ng0"; # Прокма
  route 91.202.20.0/22 via "ng0"; # Прокма
  route 78.132.128.0/17 via "ng0"; # Ростелеком
  route 213.135.128.0/19 via "ng0"; # Ростелеком
  route 178.75.64.0/18 via "ng0"; # Ростелеком
  route 37.76.160.0/19 via "ng0";; # Ростелеком
}
 
protocol static static_fib0_rt2 {
  table fib0;
  preference 190;
 
  # default
  route 0.0.0.0/0 via "ng0";
 
  # Ростелеком
  route 193.203.60.0/22 via "ng0"; # Ланта
  route 93.186.96.0/20 via "ng0"; # Ланта
  route 37.235.128.0/17 via "ng0"; # Ланта
}
 
protocol static static_fib2 {
  table fib2;
  route 0.0.0.0/0 via 93.186.105.129;
}
 
protocol static static_fib3 {
  table fib3;
  route 0.0.0.0/0 via "ng0";
}

В конфиге:

  • Заведены три таблицы маршрутизации (table fib0, fib2, fib3). Именно эти таблицы будут проецироваться в таблицы маршрутизации системы. fib0 — комбинированный трафик от двух провайдеров, с выбором работающего провайдера, fib2 — Ланта, fib3 — Ростелеком;
  • Заведены три протокола (kernel_fib0, kernel_fib2, kernel_fib3). Экспорт вышеуказанных таблиц в систему.

Теперь разбор статической маршрутизации. Сначала с простых таблиц — fib2 и fib3. В этих таблицах только один маршрут, он же маршрут по умолчанию. static_fib2 — указывает жестко на шлюз Ланты (route 0.0.0.0/0 via 93.186.105.129;), static_fib3 — указывает жестко на шлюз Ростелеком (route 0.0.0.0/0 via «ng0»;). Сделано это для того, чтоб с помощью ping определять работоспособность каждого из провайдеров.

Самое интересное начинается на протоколах static_fib0_*. В соответствии со схемой — прописываем для Ланты (static_fib0_lanta) ее родные подсети + пиринговый подсети (Ростелеком). Ставим preference 200.

Переходим с static_fib0_rt — это резервный канал, но в нем выделены приоритетные подсети для Ростелеком. Поэтому повышаем чуток preference, до 210. Если одновременно доступны оба провайдера — до Ростелеком заберет на себя свои родные подсети (оставив пиринг Ланты с носом), а так же подсети, «недоступные» Ланты. При падении Ланты — Ростелеком так же будет держать свои родные подсети + «недоступные» Ланте. «Недоступные» — имеется в виду доступные, но не с оптимальным маршрутом. Ну и последний вариант — Ланта работает, а Домолинк нет — в этом случае Ланта честно заберет на себя пиринговые подсети.

static_fib0_rt2 — резервный канал, просто резервный канал. Указали какие подсети он обслуживает + шлюз по умолчанию. За  счет пониженного preference до 190 — вступать в силу будет при отсутствии канала Ланты.

С этим разобрались, запускаем bird и смотрим, что получилось:

mira# birdc show route table fib0
BIRD 1.3.8 ready.
0.0.0.0/0          via 93.186.105.129 on vlan102 [static_fib0_lanta 20:55] * (200)
                   dev ng0 [static_fib0_rt2 20:55] (190)
37.235.128.0/17    via 93.186.105.129 on vlan102 [static_fib0_lanta 20:55] * (200)
                   dev ng0 [static_fib0_rt2 20:55] (190)
213.135.128.0/19   dev ng0 [static_fib0_rt 20:55] * (210)
                   via 93.186.105.129 on vlan102 [static_fib0_lanta 20:55] (200)
91.202.20.0/22     dev ng0 [static_fib0_rt 20:55] * (210)
193.33.62.0/23     dev ng0 [static_fib0_rt 20:55] * (210)
37.76.160.0/19     dev ng0 [static_fib0_rt 20:55] * (210)
                   via 93.186.105.129 on vlan102 [static_fib0_lanta 20:55] (200)
193.203.60.0/22    via 93.186.105.129 on vlan102 [static_fib0_lanta 20:55] * (200)
                   dev ng0 [static_fib0_rt2 20:55] (190)
93.186.96.0/20     via 93.186.105.129 on vlan102 [static_fib0_lanta 20:55] * (200)
                   dev ng0 [static_fib0_rt2 20:55] (190)
178.75.64.0/18     dev ng0 [static_fib0_rt 20:55] * (210)
                   via 93.186.105.129 on vlan102 [static_fib0_lanta 20:55] (200)
78.132.128.0/17    dev ng0 [static_fib0_rt 20:55] * (210)
                   via 93.186.105.129 on vlan102 [static_fib0_lanta 20:55] (200)

Маршруты расположились в соответствии с весом (preference) — число в круглых скобках в конце строки (200, 210, 190), а так подсветились резервные маршруты (via).

Теперь перейдем к проверке переключения маршрутов, «отключим» Ланту. Отключать будем путем запрета статического протокола в bird:

mira# birdc
BIRD 1.3.8 ready.
bird> disable "static_fib0_lanta"
static_fib0_lanta: disabled
bird> show route table fib0
0.0.0.0/0          dev ng0 [static_fib0_rt2 20:55] * (190)
37.235.128.0/17    dev ng0 [static_fib0_rt2 20:55] * (190)
213.135.128.0/19   dev ng0 [static_fib0_rt 20:55] * (210)
91.202.20.0/22     dev ng0 [static_fib0_rt 20:55] * (210)
193.33.62.0/23     dev ng0 [static_fib0_rt 20:55] * (210)
37.76.160.0/19     dev ng0 [static_fib0_rt 20:55] * (210)
193.203.60.0/22    dev ng0 [static_fib0_rt2 20:55] * (190)
93.186.96.0/20     dev ng0 [static_fib0_rt2 20:55] * (190)
178.75.64.0/18     dev ng0 [static_fib0_rt 20:55] * (210)
78.132.128.0/17    dev ng0 [static_fib0_rt 20:55] * (210)

Как видно — остались маршруты только на Ростелеком + пиринг на Ланту (все через тот-же Ростелеком).

Поехали дальше, включаем Ланту и отключаем Ростелеком:

bird> enable "static_fib0_lanta"
static_fib0_lanta: enabled
bird> disable "static_fib0_rt*"
static_fib0_rt: disabled
static_fib0_rt2: disabled
bird> show route table fib0
0.0.0.0/0          via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
37.235.128.0/17    via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
213.135.128.0/19   via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
37.76.160.0/19     via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
193.203.60.0/22    via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
93.186.96.0/20     via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
178.75.64.0/18     via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
78.132.128.0/17    via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)

Все с точностью на оборот, теперь Ланта забрала на себя нужные маршруты.

Ну и последнее — включаем обратно и Ланту и Ростелеком:

bird> enable "static_fib0_*"
static_fib0_lanta: already enabled
static_fib0_rt: enabled
static_fib0_rt2: enabled
bird> show route table fib0
0.0.0.0/0          via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
                   dev ng0 [static_fib0_rt2 21:43] (190)
37.235.128.0/17    via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
                   dev ng0 [static_fib0_rt2 21:43] (190)
213.135.128.0/19   dev ng0 [static_fib0_rt 21:43] * (210)
                   via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] (200)
91.202.20.0/22     dev ng0 [static_fib0_rt 21:43] * (210)
193.33.62.0/23     dev ng0 [static_fib0_rt 21:43] * (210)
37.76.160.0/19     dev ng0 [static_fib0_rt 21:43] * (210)
                   via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] (200)
193.203.60.0/22    via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
                   dev ng0 [static_fib0_rt2 21:43] (190)
93.186.96.0/20     via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] * (200)
                   dev ng0 [static_fib0_rt2 21:43] (190)
178.75.64.0/18     dev ng0 [static_fib0_rt 21:43] * (210)
                   via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] (200)
78.132.128.0/17    dev ng0 [static_fib0_rt 21:43] * (210)
                   via 93.186.105.129 on vlan102 [static_fib0_lanta 21:39] (200)

Все маршруты (и основные и резервные вернулись на место).

Маршрутизация закончена, способы воздействия тоже на нее есть. Осталось последнее — написать скрипт, которые с определенной периодичностью будет проверять доступность 8.8.8.8 через каждого провайдера, и включать/выключать нужный протокол. Для этого и были созданы таблицы fib2 и fib3. Сам скрипт:

mira# cat check_isp.sh
#!/bin/sh
 
birdc="/usr/local/sbin/birdc"
host="8.8.8.8"
# Проверяем доступность интернетов через ланту
setfib 2 ping -c 5 -q ${host} > /dev/null
case "$?" in
  0)
    ${birdc} enable static_fib0_lanta > /dev/null
    ;;
  *)
    ${birdc} disable static_fib0_lanta > /dev/null
    ;;
esac
 
# Проверяем доступность интернетов через ростелеком
setfib 3 ping -c 5 -q ${host} > /dev/null
case "$?" in
  0)
    ${birdc} enable \"static_fib0_rt*\" > /dev/null
    ;;
  *)
    ${birdc} disable \"static_fib0_rt*\" > /dev/null
    ;;
esac

Осталось только повесить его в cron с нужной периодичностью, и все.

Пока комментариев нет.
Вы должны авторизоваться для отправки комментария.