Клиент се свързва със сървъра OpenVPN на VM в Compute Engine, прозорецът за състояние казва свързано, а ping до хост вътре във VPC все още не стига никъде. Първият импулс е да се добави още един push ред и това никога не помага. Compute Engine решава накъде отиват пакетите по собствената си таблица за маршрутизиране и по адресите, които интерфейсът на VM действително държи, затова pool на тунел, който VM не притежава, е pool, до който никой не доставя.

Следвайте падащия пакет вместо конфигурационния файл и липсващите части ще се появят по ред.

Започнете от умиращия пакет

SYN напуска клиента, влиза в тунела и достига до VM като инкапсулиран пакет към дестинация във VPC. OpenVPN го декапсулира и се опитва да го препрати през eth0, където fabric задава един въпрос преди всичко друго: притежава ли този инстанс адреса на дестинацията. Pool на тунел, изрязан от чужда подмрежа, се проваля на този въпрос и пакетът се изхвърля, преди да бъде прегледан какъвто и да е маршрут или правило на firewall.

Значи посоката от клиента към VPC има две отделни изисквания и нито едно от тях не е директива push. На VM ѝ трябва диапазон alias, който покрива pool-а на тунела, и точно това я прави законен собственик на тези адреси. На VPC му трябва маршрут, който именува VM като next hop за всеки защитен префикс. Липсва ли едно, пакетът умира на друго място, докато клиентът вижда същата тишина.

Четете отказа в този ред, защото от страната на клиента двете условия изглеждат еднакво. Тунел, който съобщава свързано, докато нищо не отговаря, е признак за проблем с топологията, а не за лош шифър.

Притежава ли инстансът pool-а на тунела

Дайте на VM вторичен диапазон вътре в собствената ѝ подмрежа, после накарайте OpenVPN да раздава адреси точно от този диапазон. На инстанс, чийто основен адрес е 10.156.0.10/20, alias /28 държи pool-а отделен от адресите, които други инстанси вече държат:

gcloud compute instances network-interfaces update openvpn-vm \
  --zone=europe-west1-b \
  --aliases=eth0:10.156.1.0/28

Тогава директивата server трябва да описва същия блок. Първият ѝ адрес става gateway на тунела, а останалите адреси се раздават на клиентите. Тук две числа описват един блок, мрежа и маска, и това е синтаксисът на pool, който OpenVPN все още очаква.

server 10.156.1.0 255.255.255.240

Уверете се, че адресът наистина е попаднал на интерфейса, а не само в конфигурацията на OpenVPN. Fabric препраща това, което NIC съобщава, а не това, в което вярва демонът. Една команда решава въпроса:

ip -4 addr show dev eth0

Вторичен адрес, който така и не достига до eth0, или pool, който се припокрива с друга подмрежа, по-късно се проявява като периодични загуби, а не като грешка при стартиране. Демонът стартира, клиентите се свързват и само някои дестинации се държат неправилно. Дръжте диапазона alias малък, за да е лесно pool-ът да се разпознае в таблица за маршрути. Никога не го изрязвайте от подмрежа, която друг инстанс вече използва.

Дайте на обратния трафик next hop

Отговор от хост във VPC е адресиран до клиентски адрес в pool-а на тунела, който не принадлежи на никоя подмрежа, известна на VPC. Без маршрут за този pool отговорът спира на първия hop без съвпадение, а заявката може съвсем да е успяла в другия край.

gcloud compute routes create openvpn-return \
  --network=prod-vpc \
  --destination-range=192.168.127.0/24 \
  --next-hop-instance=openvpn-vm \
  --next-hop-instance-zone=europe-west1-b \
  --priority=800

Същият маршрут е нужен за всеки префикс, който стои зад клиент, а не във VPC. Тези префикси се нуждаят и от запис iroute в ccd файла на този клиент. Този запис е счетоводство от страна на сървъра: казва на сървъра кой клиент притежава префикса и не инсталира нищо на самия клиент.

Запазете push списъка за клиентската страна на разговора, защото той само добавя маршрути към свързващата се машина. Push ред за подмрежа във VPC и маршрут на VPC обратно към pool-а са две половини от един и същ път и всяка половина сама по себе си дава тунел, който носи заявки, но не отговори.

Firewall, препращане и междинните hop-ове

Firewall на VPC оценява декапсулирания пакет, затова правило ingress трябва да допуска pool-а на тунела и всеки префикс на сайт, който достига до VM по този път. Позицията default-deny се проваля тихо тук: пакетът се изхвърля след декапсулация и журналът на OpenVPN показва здравословна сесия.

На всеки Linux хост, който препраща, вместо да завършва, проверете дали net.ipv4.ip_forward е включен. Правилото за собственост важи и там: машина, която препраща за подмрежа, която не притежава, изхвърля пакета точно както би направила VM. Прочетете стойността, преди да обвините тунела.

Когато се провали точно един префикс

Частичният отказ се чете най-лесно, защото всичко останало по пътя вече е доказано. Започнете със списъка с маршрути и прочетете диапазона на дестинацията и next hop на записа, който би трябвало да покрива префикса, после прочетете описанието на инстанса и сравнете неговия диапазон alias с pool-а, който сървърът раздава.

gcloud compute routes list --filter=destination-range~10.164.0.0
 gcloud compute instances describe openvpn-vm --format=get(networkInterfaces[0].aliasIpRanges)

Липсващ маршрут се проявява като липса на next hop за префикса, докато липсващ alias се проявява като пакет, изхвърлен на интерфейса; от страна на клиента двете изглеждат подобно, а в тези два изхода са напълно различни. Ако са налице и двете, останалият заподозрян е iroute в ccd на клиента, който претендира за префикса.

Запишете четирите стойности до тунела: диапазон alias, pool на сървъра, push-нати префикси, маршрути на VPC. Остарелият alias чупи всеки адрес в pool-а, остарелият маршрут чупи една посока, липсващият push скрива префикса от клиента, а грешният iroute изпраща префикса към грешен peer. Следващият човек, който добави подмрежа, се нуждае от четирите на едно място и бележката е по-евтина от вечерта.

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