Дорогие читатели, добрый день. На связи Николай Едомский, руководитель группы сетевых инженеров компании Единый ЦУПИС.
Продолжаем наш практикум! В предыдущей статье мы подготовили базовую конфигурацию для интерфейсов концентратора. Теперь нам предстоит организовать маршрутизацию и зашифровать трафик до филиала.
Маршрутизация
Давайте разберемся с маршрутизацией. Разумеется, смаршрутизировать трафик можно и при помощи статических маршрутов, но я предлагаю сразу настроить BGP внутри всего контура.
Позвольте напомнить направления трафика, которые нужно выстроить при помощи маршрутизации. Подробнее про эскалаторную топологию можно прочитать тут.

Организовать динамическую маршрутизацию нам поможет известный деймон FRR. Он поддерживает namespace и позволяет создавать привязки вида namespace-VRF.
Файл /etc/frr/daemons
Включить поддержку namespace в FRR можно следующим образом. В файле /etc/frr/daemons добавляем к строке zebra_options= опцию -n, это поддержка namespace в FRR.
zebra_options=" -A 127.0.0.1 -s 90000000-n"
Деймон будет анализировать созданные в системе namespace, после чего в конфигурацию добавляются конструкции вида:
vrf site1 netns /run/netns/site1_ext
Также включим поддержку BGP:
bgpd=yes
Конфигурация через vtysh
Далее организуем BGP-пиринг между всеми нашими veth-интерфейсами, а также между с филиалом через GRE. Это можно сделать в интерактиве через vtysh - при помощи этой команды оказываемся в Cisco-like CLI. Для персистентности конфига делаем классический wr mem, и конфигурация сохраняется в файл.
Структура конфигурации BGP тоже CIsco-like. Мы настраиваем BGP-instance в рамках VRF, который ранее был привязан к namespace.
router bgp 65511 vrf site1_ext
bgp router-id 10.90.2.1 #такой router-id будет уникален на всем концентраторе
bgp graceful-restart stalepath-time 1 bgp graceful-restart restart-time 1 bgp bestpath as-path multipath-relax
#группа с настройками для филиалов neighbor Sites peer-group
neighbor Sites bfd neighbor Sites bfd profile CommonBfd neighbor Sites remote-as 65521
#слушаем все запросы от филиалов (passive BGP) bgp listen range 172.16.4.0/24 peer-group Sites
И в корне конфига добавим профиль BFD:
exit bfd profile CommonBfd detect-multiplier 5 transmit-interval 500 receive-interval 500
Через директиву listen вы переводим концентратор в пассивный режим и слушаем все запросы от филиалов. Это позволит минимизировать количество конфигурации, если филиалов у нас в namespace будет несколько.
Получаем вот такое (внимание на маршрутизатор филиала):

И теперь свяжем BGP-пирингом namespace site1_int и site1_ext:
router bgp 65511 vrf site1_ext neighbor 10.90.2.0 bfd neighbor 10.90.2.0 bfd profile CommonBfd neighbor 10.90.2.0 remote-as 65511
router bgp 65511 vrf site1_int neighbor 10.90.2.1 bfd neighbor 10.90.2.1 bfd profile CommonBfd neighbor 10.90.2.1 remote-as 65510
Теперь организуем при помощи veth связность namespace site1_int с namespace ipsecTo и ipsecFrom. Сделаем через peer-group, так как мы предполагаем, что site1 - это не единственный наш филиал. В этой peer-group будут заданы общие настройки для стыковок ipsecTo и ipsecFrom с другими филиалами.
router bgp 65511 vrf site1_int#листенер для запросов из ipsecFrom neighbor IpsecTo peer-group neighbor IpsecTo remote-as 65509 neighbor IpsecTo bfd neighbor IpsecTo bfd profile CommonBfd bgp listen range 10.90.1.0/24 peer-group IpsecFrom
#листенер для запросов из ipsecTo neighbor IpsecTo peer-group neighbor IpsecTo remote-as 65508 neighbor IpsecTo bfd neighbor IpsecTo bfd profile CommonBfd bgp listen range 10.90.0.0/24 peer-group IpsecTo
Теперь можно настроить пиры в ipsecTo и ipsecFrom:
router bgp 65508 vrf ipsecTo bgp router-id 172.16.2.2 bgp graceful-restart stalepath-time 1 bgp graceful-restart restart-time 1 bgp bestpath as-path multipath-relax neighbor IpsecTo peer-group neighbor IpsecTo remote-as 65510 neighbor IpsecTo bfd neighbor IpsecTo bfd profile CommonBfd neighbor 10.90.0.1 peer-group IpsecTo neighbor 10.90.0.1 description to_site1
router bgp 65509 vrf ipsecFrom bgp router-id 172.16.3.2 bgp graceful-restart stalepath-time 1 bgp graceful-restart restart-time 1 bgp bestpath as-path multipath-relax neighbor IpsecFrom peer-group neighbor IpsecFrom remote-as 65510 neighbor IpsecFrom bfd neighbor IpsecFrom bfd profile CommonBfd neighbor 10.90.1.1 peer-group IpsecFrom neighbor 10.90.1.1 description from_site1
Вот что получили:

После того, как пиринг успешно установился, нам нужно озаботиться распространением суррогатных подсетей в нашем контуре. Создадим маршруты и начнем их распределение в BGP.
Мы заблэкхолим сеть 100.64.0.0/24, так как она существует только в качестве сущности внутри NAT-правил. Статический маршрут нужен только для того, чтобы распределить его по BGP и притянуть тем самым трафик в namespace site1_ext. Аналогично поступим с 100.65.0.0/24.
vrf site1_ext netns /run/netns/site1_ext
ip route 100.64.0.0/24 blackhole #притягиваем суррогат филиала address-family ipv4 unicast redistribute static
vrf site1_int netns /run/netns/site1_int ip route 100.65.0.0/24 blackhole #притягиваем суррогат ЦОДaddress-family ipv4 unicast redistribute static
Не забудем смаршрутизировать реальную подсеть ЦОД в ipsecFrom, направив ее на межсетевой экран. Я сделаю это через статический маршрут, но можно, конечно, сделать это и более элегантными способами.
vrf ipsecFrom netns /run/netns/ipsecFrom ip route 192.168.0.0/24 172.16.3.1address-family ipv4 unicast redistribute static
Все, что нам осталось - это ограничить обмен префиксами между site1_int и site1_ext. Это нужно, чтобы не случился конфликт маршрутизации между пересекающимися подсетями 192.168.0.0/24.
vrf site1_ext netns /run/netns/site1_ext ip route 100.64.0.0/24 blackhole address-family ipv4 unicast redistribute static
vrf ipsecFrom netns /run/netns/ipsecFrom ip route 192.168.0.0/24 172.16.3.1address-family ipv4 unicast redistribute static
vrf site1_int netns /run/netns/site1_int ip route 100.65.0.0/24 blackholeaddress-family ipv4 unicast redistribute static
router bgp 65511 vrf site1_ext address-family ipv4 unicast neighbor 10.90.2.0 route-map rmap-deny-local in
router bgp 65511 vrf site1_int address-family ipv4 unicast neighbor 10.90.2.1 route-map permit_nat_addr in
route-map rmap-permit_nat_addr permit 5 match ip address prefix-list pfxl-permit_nat_addrip prefix-listpfxl-permit_nat_addr seq 5 permit 100.65.0.0/24 eq 24ip prefix-listpfxl-permit_nat_addr seq 10 permit 100.64.0.0/24 eq 24
Также не забываем написать соответствующие маршруты на межсетевом экране. Трафик до 100.64.0.0/24 нужно будет завернуть на 172.16.2.2. Это интерфейс концентратора в ipsecTo.
Итоговый конфиг для FRR:
Скрытый текст
bfd profile CommonBfd
detect-multiplier 5
transmit-interval 500
receive-interval 500
router bgp 65511 vrf site1_ext
bgp router-id 10.90.2.1
bgp graceful-restart stalepath-time 1
bgp graceful-restart restart-time 1
bgp bestpath as-path multipath-relax
neighbor Sites peer-group
neighbor Sites bfd
neighbor Sites bfd profile CommonBfd
neighbor Sites remote-as 65521
bgp listen range 172.16.4.0/24 peer-group Sites
neighbor 10.90.2.0 bfd
neighbor 10.90.2.0 bfd profile CommonBfd
neighbor 10.90.2.0 remote-as 65511
ip route 100.64.0.0/24 blackhole
address-family ipv4 unicast
redistribute static
neighbor 10.90.2.0 route-map rmap-deny-local in
router bgp 65511 vrf site1_int
neighbor 10.90.2.1 bfd
neighbor 10.90.2.1 bfd profile CommonBfd
neighbor 10.90.2.1 remote-as 65510
neighbor IpsecTo peer-group
neighbor IpsecTo remote-as 65509
neighbor IpsecTo bfd
neighbor IpsecTo bfd profile CommonBfd
bgp listen range 10.90.1.0/24 peer-group IpsecFrom
neighbor IpsecTo peer-group
neighbor IpsecTo remote-as 65508
neighbor IpsecTo bfd
neighbor IpsecTo bfd profile CommonBfd
bgp listen range 10.90.0.0/24 peer-group IpsecTo
ip route 100.65.0.0/24 blackhole
address-family ipv4 unicast
redistribute static
neighbor 10.90.2.1 route-map permit_nat_addr in
router bgp 65508 vrf ipsecTo
bgp router-id 172.16.2.2
bgp graceful-restart stalepath-time 1
bgp graceful-restart restart-time 1
bgp bestpath as-path multipath-relax
neighbor IpsecTo peer-group
neighbor IpsecTo remote-as 65510
neighbor IpsecTo bfd
neighbor IpsecTo bfd profile CommonBfd
neighbor 10.90.0.1 peer-group IpsecTo
neighbor 10.90.0.1 description to_site1
router bgp 65509 vrf ipsecFrom
bgp router-id 172.16.3.2
bgp graceful-restart stalepath-time 1
bgp graceful-restart restart-time 1
bgp bestpath as-path multipath-relax
neighbor IpsecFrom peer-group
neighbor IpsecFrom remote-as 65510
neighbor IpsecFrom bfd
neighbor IpsecFrom bfd profile CommonBfd
neighbor 10.90.1.1 peer-group IpsecFrom
neighbor 10.90.1.1 description from_site1
ip route 192.168.0.0/24 172.16.3.1
address-family ipv4 unicast
redistribute static
ip route 192.168.0.0/24 172.16.3.1
address-family ipv4 unicast
redistribute static
route-map rmap-permit_nat_addr permit 5
match ip address prefix-list pfxl-permit_nat_addr
ip prefix-listpfxl-permit_nat_addr seq 5 permit 100.65.0.0/24 eq 24
ip prefix-listpfxl-permit_nat_addr seq 10 permit 100.64.0.0/24 eq 24
Шифрование
Все, что нам осталось - это зашифровать трафик между филиалом и концентратором. Сделаем это при помощи деймона Strongswan. Конфигурация достаточно простая, находиться она будет в файле /etc/ipsec.conf.
conn site1 keyingtries=%forever closeaction=clear
inactivity=60s
authby=psk
auto=add
type=tunnel
esp=aes256-sha256!
ike=aes256-sha256-modp2048!
keyexchange=ikev2
ikelifetime=1d
lifetime=6h
left=4.4.4.4
right=9.9.9.9
dpdtimeout=10s
mobike=no
leftprotoport="gre"
rightprotoport="gre"
leftsubnet=4.4.4.4/32
rightsubnet=9.9.9.9/32
dpdaction=clear
reauth="no"
PSK для аутентификации кладем в файл /etc/ipsec.secrets в таком виде.
4.4.4.4 9.9.9.9 : PSK "strong_key"
Также можно сделать аутентификацию и по x509, что более предпочтительно, конечно.
Про /etc/ipsec.conf
Тема настройки IPsec очень объемна и требует отдельного рассмотрения, но все-таки я постараюсь кратко прокомментировать приведенные настройки и их особенности.
При настройке BGP мы придерживались топологии hub and spoke, где hub у нас находится в пассивном режиме. С IPsec постараемся сделать то же самое. Лучше избегать состояния, когда и hub, и его клиенты находятся в active режиме. Почему это плохо? Допустим, была установлена SA первой фазы, и затем случилось нарушение связности. Что будет происходить?
Оба пира инициируют процесс DPD (если он вообще включен), в результате которого SA первой фазы будут разобраны (если
dpdaction=clear).Далее оба пира инициируют попытки создания первой фазы.
Когда связность будет восстановлена, каждый из пиров обработает запрос соседа на установление SA, и произойдет задвоение.
Трафик будет передаваться только в рамках одной SA, все остальные будут висеть мертвым грузом с вечным рекиингом.
В некоторых сценариях возможны ситуации, когда количество SA постоянно увеличивается до бесконечности, что может в итоге привести к нарушению работоспособности концентратора.
Для минимизации таких рисков лучше использовать active-passive схему, так как ее поведение более управляемо и предсказуемо. За active-passive поведение отвечает директива auto. При состоянии "auto=add"коннекция переходит в пассивный режим.
А выставление "auto=ignore" позволяет вообще временно выключить блок конфигурации.
На клиенте при этом следует в общих случаях использовать настройку "auto=route", так как она будет гарантировать попытку собрать SA в случае, когда на хосте появляется пакет, попадающий под traffic-selector конфигурации (leftsubnet - rightsubnet).
В случае использования директивы "auto=start" клиент попытается установить SA один раз сразу при старте. Но в случае, если SA будет разобрана в дальнейшем при помощи управляющего пакета IKE_DELETE, попытки установить ее снова выполняться не будут.
Поддержание SA первой фазы или настойчивость попыток ее установки может регламентироваться другими способами, такими как:
dpdaction (при потере связности с уже выстроенным SA)
keyingtries (количество попыток установки SA с нуля), но при этом установка SA так или иначе будет выполнена только один раз, при старте деймона.
DPD
Пару слов про DPDaction. В случае разрывов связности между концентратором и удаленными клиентами следует использовать различное значение директивы dpdaction. DPD позволяет выполнить определенные действия в случае, когда на SA наблюдается отсутствие пакетов. Тогда запускается механизм DPD, и если на DPD-keepalive пакеты ответы отсутствуют, то выполняется заданный dpdaction. Конфигурация для концентратора в случае неуспеха DPD должна очищать SA первой фазы.
|
Для клиента же она должна запустить процедуру перезапуска SA первой фазы.
|
|
Такая конфигурация позволяет избежать дублей при создании SA первой фазы при восстановлении связности, тк в случае restart на концентраторе и клиенте обе стороны будут пытаться переустановить SA первой фазы. keyingtries=%forever же позволит выполнять попытки установки SA бесконечно, пока связности не будет восстановлена.
Туннельный и транспортный режимы
Директива type=tunnel в конфигурации означает то, что IPsec полностью зашифрует весь исходный IP пакет и инкапсулирует зашифрованные данные новый IP пакет. По умолчанию лучше использовать эту настройку. Конфигурация должна быть симметрична с обоих сторон.
При type=transport будет зашифрована только полезная нагрузка у исходного IP пакета, а поле "ip type" при этом будет заменен на 50 (ESP). При расшифровке процедура повторится в обратном порядке. Значение поля "ip type" будет возвращено на исходное. Такая настройка обязательна при некоторых сценариях. Например, если клиент находится за 1to1 NAT, имея серые адреса в настройках интерфейсов, и при этом требуется построить с ним GRE-туннель. Тогда NAT должен выполняться не только на IPsec-пакете, но так же и на GRE, что может быть выполнено только в транспорином режиме. Подробнее про такой сценарий можно посмотреть здесь.
Рекиинг
Рекиинг первой и второй фаз происходит по-разному в случае использования IKEv1 и IKEv2. Первая версия может выполнять рекиинг первой фазы через реаутентификацию или без нее. Предпочтительно не делать реаутентификацию, тк она иногда может давать флапы связности. Это менее безопасно, разумеется. Директива:
|
При этом для второй версии IKE эта директива не работает. Там рекиинг первой фазы всегда проходит без реаутентифицации.
Время рекиинга первой и второй фазы сответственно:
|
|
Настройка должна быть симметрична на концентраторе и клиентах для избежания зависших SA второй фазы.
Криптосеты
По умолчанию деймон будет принимать все криптосеты, предложенные пиром. Сам же будет пытаться инициировать обмен с теми криптосетами, которые указаны у него в конфигурации. Если требуется строгая проверка криптосетов, то следует использовать "!". Если используется modp-функция (Диффи-Хеллман), то нормальной будет ситуация, когда modp2048 будет использоваться только при первом рекиинге, и при этом ее не будет при самой первой сборке SA.
|
|
Прочее
Следует также выставлять
mobike=no. Эта функция позволяет изменять src ip в SA первой фазы без разрушения самой SA. Функция отрабатывает нежелательным образом при рестарте netplan (меняет P-адрес на локальный адрес), поэтому ее следует отключать.Иногда также требуется ограничить протоколы, подлежащие шифрованию:
|
|
Директива "
inactivity=<time>" позволяет разобрать SA второй фазы в случае, если на всей SA первой фазы не наблюдается движение пакетов.
Файл /etc/ipsec.conf
Директива "
delete_rekeyed = yes" позволяет удалить те SA второй фазы, которые были успешно пересобраны. Работает только для первой версии IKE, тк она не предусматривает сигнализацию текущей активной SA второй фазы, и пир в теории может использовать любую SA.
Директива "
make_before_break = yes"позволяет для второй версии IKE включить настройку постройки SA первой фазы до того, как она пройдет процедуру рекиинга. Иногда это помогает избежать флапов.
Финализация
В заключении хотелось бы обговорить еще пару важных моментов.
-
Фрагментация. Ввиду того, что в нашем контуре происходит двойная инкапсуляция, нам следует максимально избежать фрагментации, хотя бы для TCP. Для этого на всех namespace нужно создать правило, модифицирующее mss.
ip netns exec ipsecFrom iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1320ip netns exec ipsecTo iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1320ip netns exec site1_int iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1320ip netns exec site1_ext iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1320ip netns exec site1_ext iptables -A OUTPUT -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1320Добавлять понижение mss в OUTPUT для namespace site1_ext нужно для того, чтобы BGP-пакеты, идущие от концентратора до филиала, также создавались бы с учетом инкапсуляций. BGP-апдейты иногда бывают значительны по размеру.
Также стоит помнить, что все то, что мы проделали в bash, не переживет перезагрузку сервиса. У netplan конфигурация хранится в файлах, с этим проблем нет, но конфиг namespace и veth с GRE нам придется запускать при старте системы подручными средствами. Например, можно поместить команды в скрипт и поставить в автозапуск. Важно также соблюсти очередность запуска в этом случае (чтобы этот скрипт выполнялся только после финализации netplan).
На этом наш практикум завершен. На основе приведенной конфигурации есть возможность опробовать все основные идеи концентратора IPsecHub+. Например, автоматизировать добавление стыковки с филиалами или протестировать работу эскалаторной топологии. Ну и, естественно, модифицировать топологию под свои нужды.
Очень надеюсь, что удалось избежать ошибок в приведенных конфигурациях. Если вы нашли таковые, просьба писать комменты, все подправлю.
Спасибо за внимание. На этом наш цикл статей про IPsecHub+ пока что завершен.
Навигация по циклу: