Изграждането на втори OpenVPN сървър ви дава второ място за свързване на клиенти и нищо повече. То не поставя тези клиенти в мрежата на първия сървър, а опцията client-to-client променя само препращането в рамките на един сървърен процес. Двата пула стават една мрежа, когато маршрутизирате между тях умишлено, с отговорник за всяка посока. Всичко по-долу предполага режим TUN в потребителско пространство с изключено вътрешно препращане, така че ядрото взема решението.

Митът: един списък с акаунти, една мрежа

Удостоверяването и достижимостта се смесват, защото и двете живеят в конфигурацията на сървъра. Потребител, който може да влезе през който и да е от двата шлюза, отвън изглежда като потребител в една система с две врати. Вътре всеки сървър раздава адреси от своя пул и инсталира маршрути само за клиентите, които обслужва. Затова клиент на шлюз A, който изпрати пакет до клиент на шлюз B, иска дестинация, за която собственият му сървър никога не е чувал. Пакетът тръгва по маршрута по подразбиране на A, напуска тунела и пристига на защитна стена, която никога не е била помолена да го пропусне.

Следователно добавянето на втори сървър не добавя резервиране, откриване или споделен broadcast домейн. То добавя маршрутизирана мрежа, която се нуждае от план, а планът започва с адресиране.

Дайте на всеки шлюз собствен пул и транзитен адрес

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

GatewayClient poolTransit address
gateway-a10.64.10.0/24172.28.44.1/30
gateway-b10.64.20.0/24172.28.44.2/30

Устоявайте на изкушението да дадете на двата сървъра един и същ пул, за да останат профилите идентични. Маршрут в ядрото не може да каже кой от двата хоста в момента притежава произволен адрес в споделен диапазон, затова таблицата за маршрутизация ще сочи към единия шлюз, а клиентът може да е свързан с другия. Имената на интерфейсите са локални конвенции, а не споделено състояние. Двата хоста тук наричат тунелното устройство tun0, а транзитната връзка — transit0, което е наред, защото нито един пакет не носи тези имена.

Инсталирайте маршрута от двете страни

Всеки шлюз се нуждае от маршрут до пула на другия през транзитния адрес, а препращането трябва да е включено, за да действа който и да е като хоп. Първо потвърдете текущата таблица, после добавете записа и го запазете през мрежовия мениджър на хоста, а не чрез hook за повторно свързване.

sysctl net.ipv4.ip_forward
ip route add 10.64.20.0/24 via 172.28.44.2 dev transit0
ip route get 10.64.20.37

Огледално направете същото на другия хост с разменени пулове. Многократното добавяне на същия маршрут от несвързан скрипт е начинът, по който хостът се сдобива с няколко копия и загадъчна промяна следващия път, когато някой прочете таблицата. Ако транзитната връзка сама е тунел, маршрутът сочи към топологията на този тунел и хопът трябва да преживее повторното му свързване. Транзитен адрес, който изчезне за тридесет секунди, отнася със себе си пътя между пуловете, което е свойство на дизайна, което си струва да се заяви, а не да се открие.

Изпратете маршрута на клиента, без да симулирате собственост

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

push "route 10.64.20.0 255.255.255.0"

Поставете огледалния ред в конфигурацията на другия сървър, после свържете отново тестов клиент и прочетете таблицата му. Клиент, който игнорира изтласканите маршрути, се нуждае от собствена одобрена конфигурация, а маршрут, който така и не пристига, не е контрол на достъпа. Не давайте на клиент iroute за целия пул на другия шлюз. Тази директива съществува за подмрежа зад един свързан клиент и използването ѝ, за да се прикрие липсващ маршрут между шлюзовете, създава сървър, който вярва, че притежава адреси, до които не може да достигне.

Докажете една заявка и откажете друга

Изберете реална операция, например HTTPS от клиент на 10.64.10.21 към услуга на 10.64.20.37, и разрешете точно нея на двата хоста. Всяка защитна стена приема заявката от входящата си страна и проследения отговор от страната на връщането; собствената политика на услугата на дестинацията все още трябва да я приеме.

iptables -A FORWARD -i tun0 -o transit0 -s 10.64.10.21 -d 10.64.20.37 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -i transit0 -o tun0 -d 10.64.10.21 -s 10.64.20.37 -p tcp --sport 443 -m conntrack --ctstate ESTABLISHED -j ACCEPT

При взаимни маршрути NAT на източника е ненужен и тук активно вреден: транслирането на източника скрива кой клиент е направил заявката и осуетява политиката, базирана на източник, от страната на дестинацията. Проверете дали съществуващо правило за маскарад за изход към интернет не хваща и този път. След това тествайте отказа. Услуга, която трябва да остане локална за пул B, трябва да остане недостъпна от пул A, а двойките клиенти на един и същ шлюз също трябва да се тестват, тъй като политиката за препращане, която току-що променихте, се отнася и за тях.

Още една корекция на мисловния модел: транзитната връзка носи дешифрирани вътрешни пакети, така че е граница на доверие, а не частна гаранция. Ако пресича мрежа, която не контролирате, защитете този хоп с одобрен криптиран тунел и маршрутизирайте през реалната му топология. Крайното TLS все още удостоверява приложението само по себе си, затова вътрешната услуга трябва да продължи да го използва.

Подобни статии