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

INFO

Carpe diem — латинское выражение, в данном случае означающее «Будь счастлив в ту секунду, когда интернет-шлюз выйдет из строя» :).
 

Введение

Чтобы не перенастраивать маршруты клиентов в случае выхода из строя основного шлюза, можно пойти двумя путями: перестроить таблицы маршрутизации или отдать IP-адрес отказавшего шлюза другому узлу. Каждый способ имеет свои плюсы и минусы. Протоколы динамической маршрутизации, вроде RIP, OSPF, EIGRP или BGP, требуют поддержки со стороны роутеров, плюс придется повозиться с настройками. Для простых сетей второй вариант реализовать на порядок проще, к тому же он имеет свои плюсы.

Сетевой протокол дупликации общего адреса CARP (Common Address Redundancy Protocol) позволяет использовать один IP-адрес несколькими хостами, работающими в пределах одного сегмента сети и имеющими один виртуальный MAC (link layer). Этот IP-адрес клиенты и устанавливают в маршруте по умолчанию, поэтому изменять сетевые настройки в случае выхода из строя мастер-шлюза нет необходимости. Настроив CARP, затем можно смело проводить обслуживание одного из узлов шлюзового кластера (изменять конфигурацию с перезагрузкой, обновлять ПО, проводить плановую модернизацию), не беспокоясь, что офис на какое-то время останется без интернета.

 

OpenBSD/FreeBSD CARP

Впервые CARP появился в 2003 году в ОС OpenBSD 3.5 как ответ на патентование компанией Cisco протоколов VRRP (Virtual Router Redundancy Protocol) и HSRP (Hot Standby Router Protocol). Впоследствии поддержка протокола была портирована в FreeBSD, NetBSD, DragonFly BSD и реализована для Linux-систем.

WWW

Сайт проекта UCARP: pureftpd.org/project/ucarp

Работает CARP следующим образом. В случае выхода главного узла из состава redundancy group (группа избыточности) его IP и идентификатор подхватывает один из резервных узлов, имеющий более высокий приоритет. Для определения своей работоспособности главный узел использует объявления (IP Protocol 112, защищены при помощи SHA-1 HMAC), как только они прекращаются, делается вывод о сбое. Резервный узел, взяв на себя IP, начинает рассылать объявления. Выбирается такой узел просто: кто быстрее начнет рассылать объявления, тот и главный. Для этого в настройках каждого роутера используются параметры advbase и advskew. Интервал рассылки рассчитывается по формуле advbase + advskew/255, то есть чем меньше значения, тем чаще узел рассылает объявления, а значит, вероятность того, что он станет мастером, выше. Когда мастер-шлюз восстанавливает работоспособность, управление снова переходит к нему (это необязательно, и в некоторых реализациях такое поведение можно отключить).

Схема сети
Схема сети

Самое главное — при выходе из строя главного узла все существующие подключения сохраняются и работа клиентов продолжается как ни в чем не бывало. Хотя для некоторых приложений потребуется согласование настроек и, как результат, переподключение. Для устранения этих неудобств используют дополнительные механизмы, вроде pfsync, синхронизирующие состояния соединений, рассылая сообщения (IP protocol 240) на другие устройства, которые затем импортируют полученные таблицы. Данные, передаваемые pfsync, не шифруются, поэтому для обмена таблицами соединений рекомендуется использовать выделенную физическую сеть.

INFO

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

Обычно CARP используется для обеспечения отказоустойчивости роутеров и брандмауэров, хотя в некоторых реализациях он позволяет распределять нагрузку посредством балансировки ARP (arpbalance).

Конфигурирование CARP в OpenBSD и FreeBSD, по сути, ничем не отличается, только используются разные файлы. Текущие установки можно просмотреть при помощи команды

# sysctl -a | grep "net.inet.carp"

Разрешаем форвардинг и включаем CARP:

# vi /etc/sysctl.conf
net.inet.ip.forwarding=1
# Разрешаем принимать CARP-пакеты
net.inet.carp.allow=1
net.inet.carp.preempt=1
net.inet.carp.log=2

Активированный параметр net.inet.carp.preempt позволит узлу участвовать в выборе мастера, при этом если откажет хотя бы один из CARP-интерфейсов, то advskew автоматически устанавливается в 240 и инициируются выборы мастер-шлюза. В случае если необходима балансировка, используем net.inet.carp.arpbalance, указав режим балансировки: arp, ip, ip-stealth или ip-unicast.

INFO

CARP позволяет разделить нагрузку между узлами.

CARP-интерфейс создается на лету при помощи команды ifconfig carp create. Для постоянных установок директивы прописываются в /etc/rc.conf (FreeBSD) или /etc/hostname.* (OpenBSD). Помимо стандартных для сетевых интерфейсов параметров, необходимо указать пароль, установить группу vhid и расставить приоритеты advskew.

Предположим, что имеется три сети: 192.168.0.0 (WAN), 192.168.100.0 (LAN) и 172.16.0.0 (между роутерами для pfsync). Виртуальный IP, создаваемый CARP, будет оканчиваться на 1. Нам требуется, чтобы на WAN и LAN «висел» постоянный IP, это позволит не менять настройки шлюза по умолчанию на компьютерах клиентов и подключаться к сервисам, расположенным внутри. Кстати, возможно использование уже имеющегося физического адреса хоста в качестве виртуального адреса.

Настраиваем параметры CARP
Настраиваем параметры CARP

Интерфейсы конфигурируются как обычно (это можно сделать во время установки OC), разберем только то, что относится непосредственно к CARP и pfsync. В FreeBSD:

# vi /etc/rc.conf
network_interfaces="lo0 em0 em1 em2 pfsync0"
cloned_interfaces="carp0 carp1"
ifconfig_carp0="vhid 1 pass <password> 192.168.0.1/24"
ifconfig_carp1="vhid 2 pass <password> 192.168.100.1/24"
# Включаем pfsync
ifconfig_pfsync0="up syncif em2"

По окончании проверяем работу интерфейсов командой ifconfig carp.

Есть еще один момент, о котором стоит упомянуть. Все интерфейсы CARP разделены на группы (по умолчанию группа carp, ifconfig -g), каждой можно назначать счетчик demotion counter, позволяющий задавать некоторые ограничения: устанавливать master при загрузке, ограничивать число отказоустойчивых carp.

На резервном узле настройки полностью аналогичны, только в вызов ifconfig добавляем значение advskew. Покажу на примере OpenBSD:

# vi /etc/hostname.carp0
inet 192.168.0.1 255.255.255.0 192.168.0.255 vhid 1 carpdev em0 advskew 100 pass <password>

Параметр carpdev можно не указывать, в этом случае CARP использует физический интерфейс, который соответствует той же подсети, что и назначенный IP для виртуального интерфейса.

И второй:

# vi /etc/hostname.carp0
inet 192.168.100.1 255.255.255.0 192.168.100.255 vhid 2 carpdev em1 advskew 100 pass <password>

Теперь настала очередь псевдоинтерфейса pfsync:

# vi /etc/hostname.pfsync0
up syncdev em2

Такой вариант удобен в том случае, когда шлюзов несколько, так как для передачи используется мультикаст. Как вариант, можно указать конкретный IP:

up syncdev em2 syncpeer 172.16.0.2

На данный момент пакетный фильтр блокирует передачу служебной информации, необходимо добавить пару разрешающих правил в /etc/pf.conf:

# vi /etc/pf.conf
pass quick on { em2 } proto pfsync keep state (no-sync)
pass on { em0 em1 } proto carp keep state (no-sync)

Это минимум. При желании правила можно развивать, принудительно перенаправлять все запросы с физического интерфейса на carp или добавить фильтры, разрешающие подключения по pfsync и carp только с определенных IP.

Теперь можно проверять. Выключаем основной шлюз, IP и МАС подхватывает резервный шлюз, при этом существующие соединения не обрываются. Хотя в случае активных VPN-туннелей есть свои особенности.

Настройка CARP в интерфейсе pfSense
Настройка CARP в интерфейсе pfSense
Устанавливаем виртуальный IP в pfSense
Устанавливаем виртуальный IP в pfSense

 

Монитор интерфейсов ifstated

Демон ifstated(8) — еще одно интересное дополнение, которое может с успехом использоваться вместе с CARP. Контролируя состояние интерфейсов и сервисов сети, он в ответ на изменившиеся условия выполняет определенные команды. Это может быть что угодно: принудительная смена мастера в CARP, изменение таблицы маршрутизации и правил pf, контроль доступности сервисов и так далее. При этом логику работы админ задает сам, это позволяет автоматизировать действия в ответ практически на любые внештатные ситуации.

Для активации демона при загрузке следует добавить в MARKDOWN_HASH745bb3c68db813fb59fc6fe8d144ffa2MARKDOWN_HASHстроку MARKDOWN_HASHc8a735a8f8116e06505cb1473e48d887MARKDOWN_HASH. Все настройки производятся в MARKDOWN_HASHedc89ceeb4e8b5ca84e62c665d983178MARKDOWN_HASH, в справочной странице ifstated.conf(5) можно найти несколько хороших примеров. После настроек желательно прогнать работу командой MARKDOWN_HASH8943b8c22172c54b5a4fc6dcc77f2faaMARKDOWN_HASH, чтобы посмотреть результат.

 

Сохраняем состояние IPsec VPN

Соединения IPsec, одного из популярных протоколов, используемых для обеспечения VPN, также можно «перекидывать» через CARP. Однако основная трудность заключается в том, что IPsec оперирует механизмами Secure Associations (SA), определяющими, что нужно делать с пакетом (алгоритм шифрования, аутентификация, уникальный номер и прочее). В случае смены шлюза часть данных теряется, поэтому подключение обрывается. Для сохранения состояния VPN-туннелей используется демон sasyncd, также работающий в режиме ведущего или ведомого. Мастер отслеживает состояние локальных IPsec SA и SPD и отправляет изменения (TCP/500) на другие системы. Отказоустойчивость обеспечивается средствами CARP, передаваемая информация защищена при помощи AES и SHA.

Конфигурацию IPsec трогать не будем (демон должен стартовать с опцией -S), остановимся лишь на настройке собственно sasyncd.

# vi /etc/sasyncd.conf
interface carp0
# Группа по умолчанию
group carp
listen on 172.16.0.1 inet
# IP slave роутера, можно указать несколько peer
peer 172.16.0.2
# AES-ключ 'openssl rand -hex 32'
sharedkey /etc/sasyncd.key

Устанавливаем корректные права доступа:

# chown root /etc/sasyncd.conf
# chmod 600 /etc/sasyncd.conf

Настройки на подчиненном шлюзе аналогичны, только в peer указываем IP-адрес основного шлюза (172.16.0.1).

Перезапускаем isakmpd и смотрим результат. Трафик между роутерами у нас разрешен, поэтому обмен должен происходить без проблем.

# pkill isakmpd
# isakmpd -S -K
# sasyncd

Чтобы sasyncd стартовал при загрузке системы, в конфиг /etc/rc.conf.localдобавляем запись:

sasyncd_flags=""
Справочная страница sasyncd
Справочная страница sasyncd
Конфигурационный файл sasyncd.conf
Конфигурационный файл sasyncd.conf
 

А что же Linux?

Для Linux существует два варианта реализации CARP: в виде модуля ядра и пользовательской программы UCARP (http://pureftpd.org/project/ucarp,goo.gl/p4ADwj). Причем оба проекта не полностью совместимы со спецификацией CARP. Первый работает только для ветки 2.4/2.6 и давно не развивается, поэтому его можно встретить только на роутерах, использующих старые ядра. Второй совместим с Linux 2.4+, OS X, OpenBSD, MirBSD и NetBSD (ставить его в последних трех нет смысла). И хотя последние изменения кода датированы 2010 годом, UCARP работает в современных дистрибутивах и доступен в репозиториях. Единственный минус проекта — функция pfsync в UCARP не реализована, поэтому все соединения при переходе на другой роутер будут сброшены. Но стоит пользователям переподключиться, и они сразу получат доступ к требуемому ресурсу.

Итак, ставим UCARP. В Ubuntu и Debian он уже есть в репозитории, поэтому собирать ничего не нужно:

$ sudo apt-get install ucarp

Реализация в виде userspace имеет свои особенности, UCARP, по сути, обычная программа, которую можно запустить любым способом, в том числе из стартовых скриптов. В официальномreadme показан только общий для всех дистрибутивов принцип, помогающий понять, как построен UCARP. Пользователям Ubuntu/Debian повезло больше, поскольку мантейнер положил в пакет все нужные скрипты и предоставил хорошее описание (/usr/share/doc/ucarp).

Прописываем на мастер-сервере:

$ sudo /etc/network/interfaces
iface eth0 inet static
    address 192.168.0.2
    netmask 255.255.255.0
    ucarp-vid 1
    ucarp-vip 192.168.0.1
    ucarp-password password
    ucarp-advskew 0
    ucarp-advbase 1
    ucarp-master yes
iface eth0:ucarp inet static
    address 192.168.0.1
    netmask 255.255.255.0
    ...

Перезапускаем сеть:

$ sudo /etc/init.d/networking restart

Второй интерфейс прописываем по аналогии, изменяем только IP-адрес и значение ucarp-vid.

Теперь резервный роутер:

$ sudo /etc/network/interfaces
iface eth0 inet static
    address 192.168.0.3
    netmask 255.255.255.0
    ucarp-vid 1
    ucarp-vip 192.168.0.1
    ucarp-password password
    ucarp-advskew 100
iface eth0:ucarp inet static
    address 192.168.0.1
    netmask 255.255.255.0

Все готово, можно использовать.

 

Дела виндовые

Использование Windows в качестве маршрутизатора не такая плохая идея, как это кажется на первый взгляд. Тем более что этот вариант предусмотрен самими разработчиками. Достаточно вспомнить большое количество сервисов: VPN, DirectAccess, Remote Desktop Service (RDS), да и собственно сервер маршрутизации и удаленного доступа Windows (RRAS), обеспечивающий подключение клиентов к интернету. Доступность любой из этих ролей потребует наличия второго сервера, а вот инструменты отказоустойчивости придется выбирать в зависимости от сервиса и версии ОС. Служба RRAS и связанные с ней VPN, а также RDS уже давно поддерживают балансировку сетевой нагрузки (NLB, Network Load Balancing), и проблем с их использованием нет никаких. Но например, в Win2k8R2 DirectAccess ограничен развертыванием только на одном сервере, и, чтобы обеспечить резервирование, приходится задействовать отказоустойчивый кластер Hyper-V, настроенный для динамической миграции. В таком сценарии все равно функционирует только один сервер DirectAccess. В Win 2012 роль DirectAccess совместно работает с RRAS и, главное, поддерживает NLB, конфигурацию которой легко настроить прямо в мастере настройки роли. Также можно использовать решения по NLB от сторонних поставщиков.

Сама служба RRAS поддерживает RIP, умеющий динамически обновлять маршрутную информацию. Кроме того, в Win 2012 доступна функция объединения сетевых карт, позволяющая также организовать балансировку нагрузки и обеспечить отказоустойчивость (LBFO).

В Win 2012 DirectAccess интегрирован с RRAS
В Win 2012 DirectAccess интегрирован с RRAS

При настройке сервера RRAS потребуется выбрать топологию
При настройке сервера RRAS потребуется выбрать топологию

 

WARNING

В документации Microsoft можно встретить упоминание о протоколе CARP. Это одноименный протокол, который позволяет выдавать клиенту содержимое с определенного сайта.

 

Настройка CARP в pfSense

Один из самых популярных дистрибутивов-роутеров — построенный на FreeBSD pfSense, поэтому нелишним будет разобрать, как настроить в нем CARP. Переходим в Firewall -> Virtual IPs -> CARP settings -> Synchronize Enabled и начинаем заполнять поля. Активируем Synchronize States, выбираем нужный интерфейс в Synchronize Interface. По умолчанию таблица синхронизируется при помощи мультикаста, но можно отправлять по конкретному IP, указав его в pfsync Synchronize Peer IP. Это достаточный минимум.

Разработчики pfSense пошли дальше, и c резервным роутером можно синхронизировать все настройки сервера (учетные записи, сертификаты, правила, задания, установки сервисов и прочее). Для этого в Configuration Synchronization Settings (XMLRPC Sync) следует указать логин и пароль админа второго роутера и отметить флажками данные, которые необходимо отправлять.

Теперь переходим во вкладку Virtual IPs, нажимаем + и конфигурируем виртуальный IP. Выбираем в Type -> CARP и далее заполняем все предложенные поля: IP-адрес, пароль, номер VHID и значения частоты синхронизации (Advertising Frequency, на основном — 0).

Включаем NAT, переходим в Firewall -> NAT -> Outbound, выбираем Automatic outbound NAT rule generation и нажимаем Save, это автоматически создаст правила для LAN, которые нужно отредактировать под IP CARP. В Firewall -> Rules добавляем правило, разрешающее подключения для pfsync-интерфейса (add allow all from any to any).

В Status -> CARP failover показывается статус работы CARP, здесь же можно быстро включить и выключить эту функцию. В случае ошибки синхронизации XMLRPC Sync вверху страницы появится сообщение.

 

Заключение

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

 

1 комментарий

  1. 06.10.2014 at 18:30

    Спасибо тебе, мил человек-автор. Бью челом…

Оставить мнение

Check Also

Мошенничество по воздуху. Разбираем возможность Cryptogram Replay Attack в Apple Pay

Задача платежной системы — списать нужную сумму в пользу продавца со счета верное число ра…