OpenVPN на GCE: додайте alias IP, перш ніж пушити маршрути
Запушений маршрут не робить VM next hop. Додайте діапазон alias IP, узгодьте його з пулом сервера та створіть зворотний маршрут у VPC, перш ніж перевіряти клієнтів.
Клієнт підключається до сервера OpenVPN на віртуальній машині Compute Engine, вікно стану повідомляє підключено, а ping до хоста всередині VPC усе одно нікуди не доходить. Перший порив — додати ще один рядок push, і це ніколи не допомагає. Compute Engine вирішує, куди йдуть пакети, за власною таблицею маршрутів і за адресами, які інтерфейс VM справді тримає, тому пул тунелю, яким VM не володіє, — це пул, до якого ніхто не доставляє.
Ідіть за пакетом, що падає, а не за файлом конфігурації, і відсутні частини з'являться по порядку.
Почніть з умираючого пакета
SYN залишає клієнта, потрапляє в тунель і досягає VM як інкапсульований пакет до адресата всередині VPC. OpenVPN розпаковує його і намагається передати через eth0, де fabric ставить одне запитання перед усім іншим: чи володіє цей інстанс адресою призначення. Пул тунелю, вирізаний з чужої підмережі, не проходить це запитання, і пакет відкидається ще до того, як буде перевірено бодай один маршрут чи правило firewall.
Отже, напрямок від клієнта до VPC має дві окремі вимоги, і жодна з них не є директивою push. VM потрібен діапазон alias, що покриває пул тунелю, і саме це робить її законним власником цих адрес. VPC потрібен маршрут, який називає VM наступним переходом для кожного захищеного префікса. Бракує одного — пакет умирає в іншому місці, а клієнт бачить ту саму тишу.
Читайте збій у цьому порядку, бо з боку клієнта обидві умови виглядають однаково. Тунель, який повідомляє про підключення, коли ніхто не відповідає, — ознака проблеми топології, а не поганого шифру.
Чи володіє інстанс пулом тунелю
Дайте VM вторинний діапазон усередині її власної підмережі, а потім змусьте OpenVPN видавати адреси рівно з цього діапазону. На інстансі, чия основна адреса — 10.156.0.10/20, alias /28 відокремлює пул від адрес, які вже тримають інші інстанси:
gcloud compute instances network-interfaces update openvpn-vm \
--zone=europe-west1-b \
--aliases=eth0:10.156.1.0/28Тоді директива server має описувати той самий блок. Її перша адреса стає шлюзом тунелю, а решта адрес роздаються клієнтам. Тут два числа описують один блок, мережу й маску, і це той синтаксис пулу, якого OpenVPN досі чекає.
server 10.156.1.0 255.255.255.240Переконайтеся, що адреса справді потрапила на інтерфейс, а не лише в конфігурацію OpenVPN. Fabric пересилає те, що повідомляє NIC, а не те, у що вірить демон. Одна команда це вирішує:
ip -4 addr show dev eth0Вторинна адреса, яка так і не доходить до eth0, або пул, що перетинається з іншою підмережею, згодом проявляється як періодичні втрати, а не як помилка запуску. Демон стартує, клієнти підключаються, і лише частина призначень поводиться неправильно. Тримайте діапазон alias малим, щоб пул легко впізнавався в таблиці маршрутів. Ніколи не вирізайте його з підмережі, яку вже використовує інший інстанс.
Дайте зворотному трафіку наступний перехід
Відповідь від хоста у VPC адресована клієнтській адресі з пулу тунелю, яка не належить жодній відомій VPC підмережі. Без маршруту до цього пулу відповідь зупиняється на першому переході без збігу, а запит цілком міг успішно виконатися на далекому кінці.
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 назад до пулу — дві половини одного шляху, і будь-яка половина сама по собі дає тунель, який несе запити, але не відповіді.
Firewall, пересилання та проміжні переходи
Firewall VPC оцінює розпакований пакет, тому правило ingress має пропускати пул тунелю й будь-який префікс майданчика, що доходить до VM цим шляхом. Позиція default-deny тихо провалюється тут: пакет відкидається після розпакування, а журнал OpenVPN показує здорову сесію.
На будь-якому хості Linux, який пересилає, а не завершує, перевірте, чи ввімкнено net.ipv4.ip_forward. Правило володіння діє й там: машина, яка пересилає для підмережі, якої вона не має, відкидає пакет так само, як це зробила б VM. Прочитайте значення, перш ніж звинувачувати тунель.
Коли не працює рівно один префікс
Частковий збій читається найлегше, бо все інше на шляху вже доведено. Почніть зі списку маршрутів і прочитайте діапазон призначення та наступний перехід запису, який мав би покривати префікс, потім прочитайте опис інстансу й порівняйте його діапазон alias із пулом, який роздає сервер.
gcloud compute routes list --filter=destination-range~10.164.0.0
gcloud compute instances describe openvpn-vm --format=get(networkInterfaces[0].aliasIpRanges)Відсутній маршрут проявляється як відсутність наступного переходу для префікса, а відсутній alias — як пакет, відкинутий на інтерфейсі; з боку клієнта ці дві речі схожі, а в цих двох виводах зовсім різні. Якщо є і те й те, підозрюваний, що залишився, — iroute у ccd клієнта, який заявляє префікс.
Запишіть чотири значення поряд із тунелем: діапазон alias, пул сервера, запушені префікси, маршрути VPC. Застарілий alias ламає кожну адресу пулу, застарілий маршрут ламає один напрямок, відсутній push ховає префікс від клієнта, а хибний iroute надсилає префікс не тому peer. Наступній людині, яка додасть підмережу, потрібні всі чотири в одному місці, і ця нотатка дешевша за вечір.