FreeBSD: Создание VPN между офисами по схеме 2x2

схема объединения сетей двух офисов

Все названия компаний, мест, адресов, условий организации каналов связи и прочие "персонифицированные" данные, приведенные в данном тексте являются вымыслом и приведены здесь только для удобства понимания ситуации. Более того, описанный здесь пример был собран в лабораторных условиях, что называется "на столе". Однако, это не значит, что такой ситуации не может встретиться в реальности. К слову сказать, примерно подобная схема организации связи между офисами внедряется сейчас мной у одного из клиентов.

Имеется:
Два офиса, каждый имеющий по два выхода в интернет через различных провайдеров. Офис "Тула" выходит в интернет через провайдеров "Девятый этаж" и "Инвест-ком". Офис "Удаленный склад" имеет связь с интернет через провайдеров "Инвест-ком" и "Радио-нет".
Задача:
Объединить локальные сети двух офисов в единую сеть с максимальной надежностью (в плане уменьшения времени простоя).

Дополнительные "вводные" данные

Для дальнейшего удобства, дадим интерфейсам имена и присвоим им IP-адреса. Чтобы "за деревьями не потерять леса" будем считать, что все интерфейсы до провайдеров это Ethernet-интерфейсы с маской /24 (и вообще, ситуация обкатывается "на столе", так что мы имеем полное право создать свой Интернет как нам заблагорассудится и задать ему какие угодно адреса).

Названия интерфесов и их адреса
Хост Интерфейс Краткое имя IP
IP Хост
Tula 9floor t9 11.2/24 11.1/24 Inet
InvestCom ti 12.2/24 12.1/24
LAN tl 8.1/24


pptp Sklad → Tula ST



Sklad RadioNet sr 111.2/24 111.1/24 Inet
InvestCom si 112.2/24 112.1/24
LAN sl 9.1/24


pptp Sklad → Tula ST



Исходя из тарифных планов и прочих "вводных данных", нам задано, что в каждый конкретный момент VPN должна образовываться только между двумя внешними интерфейсами офисов Tula и Sklad. Ну например, трафик внутри сети провайдера InvestCom практически бесплатный, а между различными провайдерами стоит денег, канал от офиса Tula к провайдеру 9 Этаж очень тонкий и не надежный. Подобные "вводные данные" имеются и по отношению к тому, что является default gateway на каждом из настраиваемых хостов, (или иначе, через кого ходим в интернет в каждом из офисов).

схема организации PPtP Link-ов

в сухом остатке, имеем (на входе задачи) следующие комбинации организации каналов связи между офисами (в порядке уменьшения их приоритета).

  1. si → ti = Sklad.InvestCom-Tula.InvestCom
  2. sr → ti = Sklad.Radionet-Tula.InvestCom
  3. sr → t9 = Sklad.Radionet-Tula.9floor
  4. si → t9 = Sklad.InvestCom-Tula.9floor

А также, приоритетность линий для выхода в Интернет в офисе Tula:

  1. t9 = Tula.9floor
  2. ti = Tula.InvestCom

... и в офисе Sklad:

  1. sr = Sklad.RadioNet
  2. si = Sklad.InvestCom

Решение

В качестве граничных маршрутизаторов будем использовать компьютеры с ОС FreeBSD 6.3. Будем использовать статическую маршрутизацию. В качестве фаервола будем использовать ipfw. На внешних интерфейсах будем исползовать NAT: natd. Связь между офисами организуем с помощью Multilink PPtP канала, организованного на обоих концах с помощью mpd5.

Подготовка

После установки FreeBSD сразу поставим следующие приложения из пакаджей:

... из портов:

Обновляем коллекцию портов. Обновляем установленные пакеты: portupgrade -a.
В описываемом опыте я обновление портов сделал на более быстром компе. На слабом компьютере мне это делать не захотелось :)

Так как нам понадобится команда fwd в ipfw, то придется пересобирать ядро, так как такого модуля ядра вроде нет :(.

Пересоберем ядро на более быстром компьютере.

Копируем ядро на более слабый комп:

  1. На первом компе архивируем каталог ядра:
    cd /boot/kernel
    tar cf k.tar
    
  2. На втором компьютере:
    mv /boot/kernel /boot/kernel.old
    mkdir /boot/kernel
    
  3. Копируем в каталог /boot/kernel файл k.tar с первого компа и разархивируем его там: tar xf k.tar

MPD5

Канал связи между офисами организуем с помощью Multilink PPtP состоящего из четырех возможных pptp Link-ов (см. рисунок 2). Таким образом мы защищаемся от падения любого из каналов связи до провайдеров на любой из сторон; и, даже, от некоторых вариантов одновременного падения двух каналов (о надежности получившегося канала смотри ниже).

Итак имеем на стороне Tula следующий файл /usr/local/etc/mpd5/mpd.conf.
(чтобы не усложнять, в приведенных конфигах опущено все, что касается управления mpd с консоли и web и все что касается сжатия и шифрования трафика)

На стороне Sklad соответственно имеем файл /usr/local/etc/mpd5/mpd.conf.

Заметим, что так как нам не выгодно распределять трафик по всем Link-ам, в том числе и финансово, то в каждый конкретный момент (в зависимости от ситуации) активным должен быть только один из Link-ов, остальные три Link-а должны гасится (об этом см ниже).

Маршрутизация и FireWall

Определим через какой интерфейс выходить в интернет в зависимости от текущего состояния каналов связи

Default Gateway на хосте Tula
Состояние интерфейсов Мощность множества вариантов Маршрут до defaultgw через
t9 ti
1 x 2 t.9floor
0 1 1 t.invest
0 0 1 t.9floor

Default Gateway на хосте Sklad
Состояние интерфейсов Мощность множества вариантов Маршрут до defaultgw через
sr si
1 x 2 s.radio
0 1 1 s.invest
0 0 1 s.radio

Комментарий к предыдущим двум таблицам: какой-то defgw должен быть определен всегда, иначе не работает наш скрипт "ping-овалка" (см. ниже) (ОС не знает через какой интерфейс слать пакеты в МИР) и дело не доходит даже до ipfw.

Заметим, что в зависимости от ситуации, организация VPN может быть более выгодной совсем не по тем каналам связи, на которые настроены Default Gateway. Чтобы "исправить" это будем исправлять таблицу маршрутизации, добавляя или убирая "уточненный" маршрут до другого офиса. Определим через какие пару интерфейсов должна обеспечиваться связь между офисами (какой из Link-ов мультилинкового канала должен быть активным) в зависимости от текущего состояния каналов связи.

Маршрутизация Sklad → Tula на хосте Sklad
Работоспособность канала Мощность множества вариантов "Уточненный" маршрут
si-ti sr-ti sr-t9 si-t9 to t.invest to t.9floor
1 x x x 8 over si_gw delete
0 1 x x 4 over sr_gw delete
0 0 1 x 2 delete over sr_gw
0 0 0 1 1 delete over si_gw
0 0 0 0 1 delete delete

Неправильные маршруты PPtP link-ов

Обратную маршрутизацию: Tula → Sklad - настраивать не надо, достаточно обеспечить то, чтобы сервисы на внешних интерфейсах хоста Tula отвечали в тот же канал связи, из которого они получают запрос. Об этом подробно написано тут. Нас, в контексте данной статьи, интересуют "правильная" маршрутизация пакетов ICMP эхо-ответ, PPtP и GRE.

Как было сказано выше, нам необходимо ограничивать количество Link-ов из которых в каждый конкретный момент времени состоит наш канал VPN. Если мы не будем ограничивать количество Link-ов PPtP между хостами, то в самой вероятностной ситуации мы получим Multilink из 4-х link-ов PPtP, конфигурация которых отображена на рисунке 3.В результате трафик VPN вместо того, чтобы сосредоточится в Link-е si-ti (а это самый выгодный для нас Link (см. вводные данные)), будет равномерно распределен по всем четырем Link-ам.

Чтобы "побороть" эту ситуацию, нами на хосте Sklad будут использоваться специальные "запретительные" наборы правил в ipfw.

Скрипты и конфигурационные файлы

На обоих хостах настраиваем скрипты /etc/rc.d/ipfw, /etc/rc.d/natd1 и /etc/rc.d/natd2 для применения NAT на двух внешних интерфейсах.

Следующие файлы используются на обоих хостах и содержат полезные функции, включаемые в другие скрипты includ-ами.

Прочие файлы используемые на обоих хостах:

Скрипты хоста Tula:

Скрипты хоста Sklad:

Настройка CRON

Скрипт set_st_vpn.sh в mpd.conf у нас прописан как скрипт, который вызывается в случае, если интерфейс VPN переходит в состояние CLOSE (т.е. по сути когда падает текущий PPtP link). Если бы интерфейсы для подключения к провайдеру интернет у нас тоже формировались демоном mpd, то аналогично можно было бы прописать в mpd.conf и скрипты set_defgw.sh

Однако нам недостаточно производить действия по определению (настройке) каналов связи только в случае падения оных. Необходимо иметь возможность реагировать и на "улучшение" ситуации (например, поднялся более дешевый канал). Для этого будем вызывать эти скрипты из cron.

На хосте Tula добавим в файл /etc/crontab:

#KMN added
*/1	*	*	*	*	root	/AnyDir/set_defgw.sh 2> /dev/null > /dev/null

а на хосте Sklad:

#KMN added
*/1	*	*	*	*	root	/AnyDir/set_defgw.sh 2> /dev/null > /dev/null
*/1	*	*	*	*	root	/AnyDir/set_st_vpn.sh 2> /dev/null > /dev/null

Дольше всего вышеуказанные скрипты выполняются тогда, когда все возможные четыре канала выключены. Поэтому, если у Вас слабый компьютер, то выключите все интерфейсы и через некоторое время посмотрите не станут ли плодится процессы ping. Если станут, то это будет говорить о том, что интервал c которым запускается скрипт в crontab надо увеличить.


Проверка

Состояние интерфейсов (код Грея) PPtP multilinks состоит из Link-ов Ping -S 192.168.8.1 192.168.9.1 DefGW на хосте Sklad DefGW на хосте Tula
sr si t9 ti
0 0 0 0 - 0 111.1 11.1
0 0 0 1 - 0 111.1 12.1
0 0 1 1 - 0 111.1 11.1
0 0 1 0 - 0 111.1 11.1
0 1 1 0 SI_T9 1 112.1 11.1
0 1 1 1 SI_TI 1 112.1 11.1
0 1 0 1 SI_TI 1 112.1 12.1
0 1 0 0 - 0 112.1 11.1
1 1 0 0 - 0 111.1 11.1
1 1 0 1 SI_TI 1 111.1 12.1
1 1 1 1 SI_TI 1 111.1 11.1
1 1 1 0 SR_T9 1 111.1 11.1
1 0 1 0 SR_T9 1 111.1 11.1
1 0 1 1 SR_TI 1 111.1 11.1
1 0 0 1 SR_TI 1 111.1 12.1
1 0 0 0 - 0 111.1 11.1

Все замечательно - работает так как мы и хотели.

Теоретический расчет надежности канала

Посчитаем надежность нашего VPN. Да простят меня математики, за дилетанство (ну не математик я :). Если я тут сильно накосячил, то прошу сообщить ⇒ немедленно исправлю или уберу, дабы не засорять интернет :)

Допустим надежность каждого интернет-канала = 90%, т.е. вероятность сбоя одного канала p(1chann)= 0,1

В дальнейшем будем предполагать, что падение каналов это события не зависящие друг от друга.

Событие 0 "работают все четыре канала": лень считать вероятность этого события, главное, что связь VPN при этом есть всегда ⇒ вероятность сбоя VPN p(vpn)=0.

Событие 1 "лежит один канал": p(1chann)=0,1. Связь есть всегда ⇒ вероятность сбоя VPN p(vpn)=0.

Событие 2 "лежат два канала": p(2chann)=0,01. VPN не работает только в 2-х случаях из 6-ти ⇒ вероятность сбоя VPN p(vpn)=0,01/3.

Событие 3 "лежат три канала": p(3chann)=0,001. VPN никогда не работает ⇒ p(vpn)=0,001.

Событие 4 "лежат четыре канала": p(4chann)=0,0001. VPN никогда не работает ⇒ p(vpn)=0,0001.

Результирующее событие "Не работает VPN": Событие0 ∪ Событие1 ∪ Событие2 ∪ Событие3 ∪ Событие4 ⇒ p(VPN)=0,01/3+0,001+0,0001=0,0044(3).

Итого получаем, что даже при надежности каналов интернет всего 90% мы имеем VPN с вероятностью сбоя всего 0,44(3)%.


Дата документа: 11.08.09