Жил-был я. И был у этого "я" небольшой пул виртуальных машин. Но пришло время, и появилось осознание, что у моего облачного провайдера (пусть будет С) не все условия мне нравятся. А вот у другого провайдера (путь будет провайдер В) условия для некоторых виртуалок повкуснее. И замыслил я неладное. Я решил разнести инфраструктуру между разными провайдерами. Но эту, так называемую инфру, необходимо скоммутировать между собой, потому что гонять сервисный трафик через интернеты - дурная затея. И родился у меня план. Даже не план, а ПЛААААН!!! И следом эта статья. Предвосхищая вопрос: "Почему не обычный VPN?", отвечу: это, во-первых, скучно, во-вторых, не подлежит публикации, в-третьих, в последнее время VPN нестабилен ввиду блокировок.
Disclaimer! Цель статьи - рассмотреть вариант осуществления связности конкретных элементов инфраструктуры, используя публичные каналы связи. Статья не ставит целью описать способ обхода блокировок и осуждает (хоть и неискренне) подобные статьи.
Итак. Что мы имеем?
Допустим, в ДЦ1 (облачный провайдер С) располагается:
База данных
Бекапы
Внешний ip адрес: 192.0.2.135 на интерфейса eth0
В ДЦ2 (облачный провайдер В) располагается:
Какой-то сайт
Бекапы
Внешний ip адрес: 198.51.100.75 на интерфейсе ens1

Начнём страшную магию. Для начала нужно связать оба ДЦ по внешним каналам связи. Я выбрал vxlan. Чуть попозже расскажу, почему именно его.
ДЦ1:
sudo ip link add vxlan0 type vxlan id 1 dstport 4789 dev eth0 sudo ip link set vxlan0 up sudo ip link set vxlan0 address de:ad:be:ef:00:01 sudo bridge fdb append to 00:00:00:00:00:00 dst 198.51.100.75 dev vxlan0
ДЦ2:
sudo ip link add vxlan0 type vxlan id 1 dstport 4789 dev ens1 sudo ip link set vxlan0 up sudo ip link set vxlan0 address de:ad:be:ef:00:02 sudo bridge fdb append to 00:00:00:00:00:00 dst 192.0.2.135 dev vxlan0
Мак адрес задан просто так, но я очень рекомендую задавать его вручную, чтобы не поиметь веселья в будущем.
Если сейчас назначить на эти интерфейсы ip адреса, то связность можно ощутить совершенно явно. В tcpdump можно будет увидеть явный vxlan траффик:
ICMP:
In IP (tos 0x0, ttl 64, id 28479, offset 0, flags [none], proto UDP (17), length 134) 192.0.2.135.33821 > 198.51.100.75.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 IP (tos 0x0, ttl 64, id 11502, offset 0, flags [DF], proto ICMP (1), length 84) 10.255.255.1 > 10.255.255.2: ICMP echo request, id 4, seq 1, length 64 ... IP (tos 0x0, ttl 63, id 28479, offset 0, flags [none], proto UDP (17), length 134) 192.0.2.135.33821 > 198.51.100.75.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 IP (tos 0x0, ttl 64, id 11502, offset 0, flags [DF], proto ICMP (1), length 84) 10.255.255.1 > 10.255.255.2: ICMP echo request, id 4, seq 1, length 64 ... IP (tos 0x0, ttl 64, id 8166, offset 0, flags [none], proto UDP (17), length 134) 198.51.100.75.52381 > 192.0.2.135.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 IP (tos 0x0, ttl 64, id 48699, offset 0, flags [none], proto ICMP (1), length 84) 10.255.255.2 > 10.255.255.1: ICMP echo reply, id 4, seq 1, length 64 ... IP (tos 0x0, ttl 63, id 8166, offset 0, flags [none], proto UDP (17), length 134) 198.51.100.75.52381 > 192.0.2.135.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 IP (tos 0x0, ttl 64, id 48699, offset 0, flags [none], proto ICMP (1), length 84) 10.255.255.2 > 10.255.255.1: ICMP echo reply, id 4, seq 1, length 64
SSH:
In IP (tos 0x0, ttl 64, id 33722, offset 0, flags [none], proto UDP (17), length 110) 192.0.2.135.54311 > 198.51.100.75.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 IP (tos 0x10, ttl 64, id 3431, offset 0, flags [DF], proto TCP (6), length 60) 10.255.255.1.52204 > 10.255.255.2.22: Flags [S], cksum 0x2400 (correct), seq 1922400959, win 64860, options [mss 1410,sackOK,TS val 538325349 ecr 0,nop,wscale 7], length 0 Out IP (tos 0x0, ttl 63, id 33722, offset 0, flags [none], proto UDP (17), length 110) 192.0.2.135.54311 > 198.51.100.75.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 IP (tos 0x10, ttl 64, id 3431, offset 0, flags [DF], proto TCP (6), length 60) 10.255.255.1.52204 > 10.255.255.2.22: Flags [S], cksum 0x2400 (correct), seq 1922400959, win 64860, options [mss 1410,sackOK,TS val 538325349 ecr 0,nop,wscale 7], length 0 In IP (tos 0x0, ttl 64, id 19783, offset 0, flags [none], proto UDP (17), length 110) 198.51.100.75.48800 > 192.0.2.135.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) 10.255.255.2.22 > 10.255.255.1.52204: Flags [S.], cksum 0x645e (correct), seq 2242386131, ack 1922400960, win 64308, options [mss 1410,sackOK,TS val 1891742331 ecr 538325349,nop,wscale 7], length 0 Out IP (tos 0x0, ttl 63, id 19783, offset 0, flags [none], proto UDP (17), length 110) 198.51.100.75.48800 > 192.0.2.135.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto TCP (6), length 60) 10.255.255.2.22 > 10.255.255.1.52204: Flags [S.], cksum 0x645e (correct), seq 2242386131, ack 1922400960, win 64308, options [mss 1410,sackOK,TS val 1891742331 ecr 538325349,nop,wscale 7], length 0

Всё выглядит хорошо. Связность есть... Но только как-то не очень безопасно. Мне это не нравится. Можно обмазаться до ушей TLS, но это не наш метод. Ведь не наш же, да? Значит, надо шифровать. На ум пришло простое решение: MacSec. Чем протокол хорош? Тем, что он не сильно накладный по ресурсам, прикрепляется MAC адресу, а значит более-менее безопасен. В чём идея? Построенный vxlan туннель закрыть именно им. Приступаем:
ДЦ1:
sudo ip link add link vxlan0 macsec0 type macsec encrypt on sudo ip macsec add macsec0 tx sa 0 pn 1 on key 01 0123456789abcdef0123456789abcdef sudo ip link set macsec0 up sudo ip macsec add macsec0 rx address de:ad:be:ef:00:02 port 1 sudo ip macsec add macsec0 rx address de:ad:be:ef:00:02 port 1 sa 0 pn 1 on key 02 fedcba9876543210fedcba9876543210 sudo ip address add 192.168.255.1/24 dev macsec0
ДЦ2:
sudo ip link add link vxlan0 macsec0 type macsec encrypt on sudo ip macsec add macsec0 tx sa 0 pn 1 on key 02 fedcba9876543210fedcba9876543210 sudo ip link set macsec0 up sudo ip macsec add macsec0 rx address de:ad:be:ef:00:01 port 1 sudo ip macsec add macsec0 rx address de:ad:be:ef:00:01 port 1 sa 0 pn 1 on key 01 0123456789abcdef0123456789abcdef sudo ip address add 192.168.255.2/24 dev macsec0
Что мы имеем?
Весь траффик, который идёт по vxlan у нас надёжно защищён шифрованием. Хорошо же! Даже tcpdump радует:
In IP (tos 0x0, ttl 64, id 52234, offset 0, flags [none], proto UDP (17), length 166) 192.0.2.135.48609 > 198.51.100.75.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 de:ad:be:ef:00:01 > de:ad:be:ef:00:02 802.1AE MACsec, an 0, pn 21, flags ECI, sci deadbeef00010001, 0x0000: 72d9 d31f ade5 9be7 25e3 f9d0 06e5 0774 r.......%......t 0x0010: 7f90 41e7 bf12 b12c 9bd9 06b8 7fde 27c2 ..A....,......'. 0x0020: 1672 3666 9f1b f43f 5dc1 92ca 39c3 bbc5 .r6f...?]...9... 0x0030: 8f27 e3ea 810c 9394 99a5 edc6 64ea 446c .'..........d.Dl 0x0040: 12ed 6eaa e467 aa2c 751d 4afc 88f4 fcbd ..n..g.,u.J..... 0x0050: 29ab 1748 0510 c1cd 32a8 3fa8 499b 9f3a )..H....2.?.I..: 0x0060: 3e32 aec3 1b63 >2...c Out IP (tos 0x0, ttl 63, id 52234, offset 0, flags [none], proto UDP (17), length 166) 192.0.2.135.48609 > 198.51.100.75.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 de:ad:be:ef:00:01 > de:ad:be:ef:00:02 802.1AE MACsec, an 0, pn 21, flags ECI, sci deadbeef00010001, 0x0000: 72d9 d31f ade5 9be7 25e3 f9d0 06e5 0774 r.......%......t 0x0010: 7f90 41e7 bf12 b12c 9bd9 06b8 7fde 27c2 ..A....,......'. 0x0020: 1672 3666 9f1b f43f 5dc1 92ca 39c3 bbc5 .r6f...?]...9... 0x0030: 8f27 e3ea 810c 9394 99a5 edc6 64ea 446c .'..........d.Dl 0x0040: 12ed 6eaa e467 aa2c 751d 4afc 88f4 fcbd ..n..g.,u.J..... 0x0050: 29ab 1748 0510 c1cd 32a8 3fa8 499b 9f3a )..H....2.?.I..: 0x0060: 3e32 aec3 1b63 >2...c In IP (tos 0x0, ttl 64, id 22307, offset 0, flags [none], proto UDP (17), length 166) 198.51.100.75.56215 > 192.0.2.135.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 de:ad:be:ef:00:02 > de:ad:be:ef:00:01 802.1AE MACsec, an 0, pn 25, flags ECI, sci deadbeef00020001, 0x0000: 5852 16a6 d772 da3a 96cc 04ce ebe9 06e0 XR...r.:........ 0x0010: bf31 f5c2 3c8b 798e 05e8 5bc4 b9a7 5d7d .1..<.y...[...]} 0x0020: 1911 9a79 a339 1fbf 49b9 7833 858b a76a ...y.9..I.x3...j 0x0030: 910c 8a56 8811 ba0b 61d9 d38f a17a 73f6 ...V....a....zs. 0x0040: 843d 5e5b 2df8 57d8 3713 8381 890a da79 .=^[-.W.7......y 0x0050: e073 75cc cfab 3ab2 0991 1684 72fe 743a .su...:.....r.t: 0x0060: a75c fe36 266e .\.6&n Out IP (tos 0x0, ttl 63, id 22307, offset 0, flags [none], proto UDP (17), length 166) 198.51.100.75.56215 > 192.0.2.135.4789: [udp sum ok] VXLAN, flags [I] (0x08), vni 1 de:ad:be:ef:00:02 > de:ad:be:ef:00:01 802.1AE MACsec, an 0, pn 25, flags ECI, sci deadbeef00020001, 0x0000: 5852 16a6 d772 da3a 96cc 04ce ebe9 06e0 XR...r.:........ 0x0010: bf31 f5c2 3c8b 798e 05e8 5bc4 b9a7 5d7d .1..<.y...[...]} 0x0020: 1911 9a79 a339 1fbf 49b9 7833 858b a76a ...y.9..I.x3...j 0x0030: 910c 8a56 8811 ba0b 61d9 d38f a17a 73f6 ...V....a....zs. 0x0040: 843d 5e5b 2df8 57d8 3713 8381 890a da79 .=^[-.W.7......y 0x0050: e073 75cc cfab 3ab2 0991 1684 72fe 743a .su...:.....r.t: 0x0060: a75c fe36 266e .\.6&n
То есть мы видим, что что-то ходит, а что - не ясно. Ясно только, что это macsec. И, плюсом, это L2!

А дальше что? А если добавим новый ДЦ? Например, домашнюю инфру?
В ДЦ3 (домашняя лаба) располагается:
Мониторинг
Бекапы
Внешний ip адрес: 203.0.113.52 на интерфейсе enp3s0
Что ж. Тут раскрывается прелесть vxlan. Нет нужды строить ещё один туннель в каждом ДЦ! Достаточно добавить пира к существующему vxlan интерфейсу, а также добавить всем участникам необходимые ключи шифрования:
ДЦ3
sudo ip link add vxlan0 type vxlan id 1 dstport 4789 dev enp3s0 sudo ip link set vxlan0 up sudo bridge fdb append to 00:00:00:00:00:00 dst 198.51.100.75 dev vxlan0 sudo bridge fdb append to 00:00:00:00:00:00 dst 192.0.2.135 dev vxlan0 sudo ip link add link vxlan0 macsec0 type macsec encrypt on sudo ip macsec add macsec0 tx sa 0 pn 1 on key 03 abcdef0123456789abcdef0123456789 sudo ip link set macsec0 up sudo ip macsec add macsec0 rx address de:ad:be:ef:00:01 port 1 sa 0 pn 1 on key 01 0123456789abcdef0123456789abcdef sudo ip macsec add macsec0 rx address de:ad:be:ef:00:01 port 1 sudo ip macsec add macsec0 rx address de:ad:be:ef:00:01 port 1 sa 0 pn 1 on key 01 0123456789abcdef0123456789abcdef sudo ip macsec add macsec0 rx address de:ad:be:ef:00:02 port 1 sudo ip macsec add macsec0 rx address de:ad:be:ef:00:02 port 1 sa 0 pn 1 on key 02 fedcba9876543210fedcba9876543210 sudo ip address add 192.168.255.3/24 dev macsec0
ДЦ1
sudo bridge fdb append to 00:00:00:00:00:00 dst 203.0.113.52 dev vxlan0 sudo ip macsec add macsec0 rx address de:ad:be:ef:00:03 port 1 sudo ip macsec add macsec0 rx address de:ad:be:ef:00:03 port 1 sa 0 pn 1 on key 03 abcdef0123456789abcdef0123456789
ДЦ2
sudo bridge fdb append to 00:00:00:00:00:00 dst 203.0.113.52 dev vxlan0 sudo ip macsec add macsec0 rx address de:ad:be:ef:00:03 port 1 sudo ip macsec add macsec0 rx address de:ad:be:ef:00:03 port 1 sa 0 pn 1 on key 03 abcdef0123456789abcdef0123456789
И - ТАДАМ! Всё работает! Получается, что можно в связку добавить достаточно большое число узлов без серьёзных заморочек!

Пойдём дальше! А теперь я хочу, чтобы база данных в ДЦ1 была доступна без дополнительных маршрутов, просто по сетевому адресу. Попробуем! Пусть в ДЦ1 есть внутренняя изолированная сеть. Ничего страшного. Это решается достаточно просто: в ДЦ1 объединим локальную сеть и зашифрованную в один бридж:
ДЦ1
sudo ip link add name bridge0 type bridge sudo ip link set eth1 down sudo ip link set eth1 master bridge0 sudo ip link set eth1 up sudo ip address flush macsec0 sudo ip link set macsec0 master bridge0 sudo ip link set bridge0 up sudo ip address add 192.168.255.1/24 dev bridge0
Всё! Если назначить DB серверу адрес из нужной сети (macsec), связность будет работать сама!
Вот такой весёлый эксперимент на коленке.
Если кому интересно, оставляю ссылку на hh
