Дорогие читатели, добрый день. На связи Николай Едомский, руководитель группы сетевых инженеров компании Единый ЦУПИС.

Продолжаем наш практикум! В предыдущей статье мы подготовили базовую конфигурацию для интерфейсов концентратора. Теперь нам предстоит организовать маршрутизацию и зашифровать трафик до филиала.

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

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

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

Рис 1. Схема движения трафика.
Рис 1. Схема движения трафика.

Организовать динамическую маршрутизацию нам поможет известный деймон 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 будет несколько.

Получаем вот такое (внимание на маршрутизатор филиала):

Рис 3. Стыковка с филиалом по BGP
Рис 3. Стыковка с филиалом по BGP

И теперь свяжем 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

Вот что получили:

Рис 4. Донастройка BGP на контуре.
Рис 4. Донастройка BGP на контуре.

После того, как пиринг успешно установился, нам нужно озаботиться распространением суррогатных подсетей в нашем контуре. Создадим маршруты и начнем их распределение в 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.1
address-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.1
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

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_addr
ip 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 первой фазы.

dpdaction=clear

Для клиента же она должна запустить процедуру перезапуска SA первой фазы. 

dpdaction=restart

keyingtries=%forever

Такая конфигурация позволяет избежать дублей при создании 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. Первая версия может выполнять рекиинг первой фазы через реаутентификацию или без нее. Предпочтительно не делать реаутентификацию, тк она иногда может давать флапы связности. Это менее безопасно, разумеется. Директива:

       reauth="no"

При этом для второй версии IKE эта директива не работает. Там рекиинг первой фазы всегда проходит без реаутентифицации.

Время рекиинга первой и второй фазы сответственно:

        ikelifetime=1d

        lifetime=6h

Настройка должна быть симметрична на концентраторе и клиентах для избежания зависших SA второй фазы.

Криптосеты

По умолчанию деймон будет принимать все криптосеты, предложенные пиром. Сам же будет пытаться инициировать обмен с теми криптосетами, которые указаны у него в конфигурации. Если требуется строгая проверка криптосетов, то следует использовать "!". Если используется modp-функция (Диффи-Хеллман), то нормальной будет ситуация, когда modp2048 будет использоваться только при первом рекиинге, и при этом ее не будет при самой первой сборке SA.

        esp=aes256-sha256!

        ike=aes256-sha256-modp2048!

Прочее

  • Следует также выставлять mobike=no. Эта функция позволяет изменять src ip в SA первой фазы без разрушения самой SA. Функция отрабатывает нежелательным образом при рестарте netplan (меняет P-адрес на локальный адрес), поэтому ее следует отключать.

  • Иногда также требуется ограничить протоколы, подлежащие шифрованию: 

       leftprotoport="gre"

       rightprotoport="gre"

  • Директива "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 1320

    ip netns exec ipsecTo iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1320

    ip netns exec site1_int iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1320

    ip netns exec site1_ext iptables -A FORWARD -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --set-mss 1320

    ip 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+ пока что завершен.

Навигация по циклу:

  1. Обзор IPsec

  2. Сегментирование на IPsec-хабе

  3. Эскалаторная топология

  4. Сложные сценарии

  5. Отказоустойчивость и динамическая маршрутизация

  6. Масштабирование и распределение нагрузки

  7. Практикум. Интерфейсы

  8. Практикум. Деймоны

Комментарии (0)