Pull to refresh

Route-based VPN между Linux StrongSwan и Cisco ISR

Reading time4 min
Views8.1K

Всем доброго времени суток!

Захотелось поделиться реализацией Hub-and-Spoke VPN между Cisco ISR (в качестве споков) и Linux+StrongSwan (в качестве хабов).

Небольшая предыстория.

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

Хабы располагаются в ДЦ в виде Cisco CSR. И вот с ними и была основная проблема, так как отечественные решения не могут пока предложить что-то наподобие полностью готового виртуального роутера (поправьте в комментариях, если я ошибаюсь).
В итоге, пока остановились на решении Linux+StrongSwan+FRR.

И первая задача, которую пришлось решить, это как переводить текущую инфраструктуру споков на новый виртуальный роутер, в части построения туннелей.

Все туннели у нас строятся поверх интернета.

На стороне CSR используются virtual-template с шифрованием IKEv2+IPSec, и так-же с помощью IKEv2 пушим ip в сторону споков. Соответственно, эту схему хотелось сохранить.

Для того, чтобы воспроизвести похожий функционал на Linux воспользуемся StrongSwan и утилитой swanctl, так как ipsec.conf самим StrongSwan считается устаревшим методом. Будем делать route-based VPN на базе XFRM интерфейсов.

Нам понадобится, по рекомендациям StrongSwan:

  1. Версия StrongSwan не ниже 5.8.0;

  2. Linux Kernel начиная с 4.19;

  3. Iproute2 версии с 5.1.0+

У меня:

  1. Strongswan - 5.9.6;

  2. Linux kernel - 5.4.17;

  3. Iproute2 - 5.12.0;

Будем считать, что у вас уже открыты порты 500,4500 udp и разрешен протокол ESP (50)

Заливаем конфиг swanctl.conf:

swanctl.conf
connections {
        dmvpn {
                include /etc/strongswan/swanctl/conf.d/ike_sa_default.conf # Можно включать элементы конфигурации
                pools = dmvpn       # Пул для "пушинга" адресов на удаленные узлы
                keyingtries = 1     # Кол-во попыток установить соединение при первоначальном конекте
                mobike = no         # Выключаем mobike, во избежание !возможных! проблем. Клиенты у нас статичны
                version = 2         # Версия IKE
                remote_addrs = %any # Разрешаем коннект с любых адресов
                remote-all {        # Указываем метод аутентификации удаленной стороны
                        auth = psk
                }
                local_addrs = 198.51.100.1 # Указываем наш паблик адрес для данного конекшена
                local-dmvpn {              # Указываем метод аутентификации нашей стороны
                        auth = psk
                }
                proposals = aes256-sha512-modp2048, default # Proposal для постороение IKE туннеля
                dpd_delay = 10s     # Переодичность проверки, что пир "живой"
                children {
                        dmvpn {
                                include /etc/strongswan/swanctl/conf.d/child_sa_default.conf # Можно включать элементы конфигурации
                                updown = /etc/strongswan/swanctl/scripts/auto-interface-xfrm # Указываем директорию где лежит скрипт, который будет выполняться по событию CHILD_SA up и down
                                start_action = start  # Сразу активируем соединение
                                esp_proposals = aes256-sha512, default # Proposal для постороение ipsec
                                local_ts = 0.0.0.0/0  # Указываем трафик-селекторы для построения route-based VPN.
                                remote_ts = 0.0.0.0/0 # Указываем трафик-селекторы для построения route-based VPN.
                                if_id_out = %unique   # Для того, чтобы создавались интерфейсы с уникальными xfrm политиками
                                if_id_in = %unique    # Для того, чтобы создавались интерфейсы с уникальными xfrm политиками
                                dpd_action = clear    # Что делать, когда срабатывает DPD. В данном случае, закрывать коннект
                        }
                }
        }
}
pools { # Создание пулов
        dmvpn {
                addrs = 192.0.2.2-192.0.2.255
        }
}
authorities {
}
secrets { # Создание типов аутентификации
        ike-dmvpn {
                secret = "VERY-STRONG-PSK"
        }
}

Для того, чтобы интерфейсы создавались и удалялись автоматически и им присваивались уникальные идентификаторы IPSec политик, воспользуемся встроенным функционалом swanctl — updown. Он срабатывает на событие CHILD_SA up или down. Скрипт будет вызываться автоматически. Кладем его в директорию, например, /etc/strongswan/swanctl/scripts/auto-interface-xfrm и делаем исполняемым.

Сам скрипт:

auto-interface-xfrm
#!/bin/bash

# set charon.install_virtual_ip = no to prevent the daemon from also installing the VIP

set -o nounset
set -o errexit

VTI_IF="Virtual-Access${PLUTO_IF_ID_OUT}" # Лучше использовать id xfrm interface, чтобы уникальные идентификаторы не слетали. И демон не терял менеджмент над интерфейсами

case "${PLUTO_VERB}" in
    up-client)
        ip link add "${VTI_IF}" type xfrm dev uplink-1 \
            if_id "${PLUTO_IF_ID_OUT%%/*}"
        ip addr add 192.0.2.1/32 dev "${VTI_IF}"
        ip link set "${VTI_IF}" up
        ip route add "${PLUTO_PEER_SOURCEIP}" dev "${VTI_IF}" # Прописываем маршрут до клиента
        sysctl -w "net.ipv4.conf.${VTI_IF}.disable_policy=1"  # По рекомендациям strongswan, для избежания дублирующихся лукапов к политикам
        ;;
    down-client)
        ip link del "${VTI_IF}"
        ;;
esac

Со стороны Cisco isr все стандартно:

Cisco ISR
crypto ikev2 proposal IKE2-PROPOSAL 
 encryption aes-cbc-256
 integrity sha512
 group 14

crypto ikev2 policy IKE2-POLICY 
 proposal IKE2-PROPOSAL 

crypto ikev2 keyring FLEX-KEYIRING-FRR
 peer HUB-FRR-01
  address 198.51.100.1
  pre-shared-key VERY-STRONG-PSK

crypto ikev2 profile FLEX-PROFILE-FRR
 match identity remote address 198.51.100.1 255.255.255.255 
 authentication remote pre-share
 authentication local pre-share
 keyring local FLEX-KEYIRING-FRR
 dpd 10 3 on-demand

crypto ipsec transform-set TSET-FRR esp-aes 256 esp-sha512-hmac 
 mode tunnel

crypto ipsec profile FLEX-IPSEC-FRR
 set transform-set TSET-FRR 
 set ikev2-profile FLEX-PROFILE-FRR

interface Tunnel32
 description HUB-FRR-01-TEST
 ip address negotiated
 ip mtu 1300
 ip tcp adjust-mss 1260
 tunnel source GigabitEthernet0/0/0
 tunnel mode ipsec ipv4
 tunnel destination 198.51.100.1
 tunnel protection ipsec profile FLEX-IPSEC-FRR
 
ip route 192.0.2.1 255.255.255.255 Tunnel32

Установку IKE и IPSec туннелей можно проверить командой swanctl -l

Командой ip xfrm policy можно проверить какие политики, к каким идентификаторам интерфейсов привязаны

ip xfrm policy
ip xfrm policy

Команда ip -d link поможет проверить и соотнести политику xfrm к интерфейсу

ip -d link
ip -d link

Теперь туннели на хабе будут создаваться и удаляться автоматически, после установки IPSec. Останется только поднять FRR, настроить BGP dynamic neighbors и часть рутинных операций мы решили.

Готов услышать ваши предложения, комментарии, опыт, конструктивную критику.

И может кому окажется полезен данный небольшой how-to.

UPD: В скрипте "updown" необходимо уменьшить название создаваемого интерфейса xfrm, так как Linux позволяет использовать только 15 символов. Как пример, использовать "vti-${PLUTO_IF_ID_OUT}"

Ссылки

Tags:
Hubs:
Total votes 6: ↑5 and ↓1+4
Comments1

Articles