Майже на кожному невеликому шлюзі OpenVPN виникають дві проблеми з іменами. До підключеного ноутбука не дістатися за іменем із його сертифіката, а служби за тунелем узагалі не мають імен. Вони виглядають як одна проблема й потребують протилежного підходу, бо одна адреса змінюється з кожним сеансом, а інша ні. Вирішіть, який тип імені ви додаєте, перш ніж щось редагувати.

Вирішуйте за іменем, а не за шлюзом

Перевірка проста: чи змінюється ця адреса, коли клієнт перепідключається? Якщо так, ім'я потрібно створювати із сеансу VPN. Якщо ні, воно належить статичному запису, який можна прочитати й переглянути.

Name kindSource of truthWhere it lives
Connected clientThe address OpenVPN just assignedGenerated hosts file, rewritten per session
Service behind the tunnelA fixed address you choseStatic address= drop-in
Anything with a certificate nameThe certificate, not the poolEither, but the name must match the certificate

Їх змішування — звичайна помилка. Служба, закріплена у створеному файлі, зникає під час першого перезапису скриптом, а клієнт, записаний у статичний запис, указує на того, хто мав цю адресу останнім. Обидві помилки залишаються непомітними, доки ім'я не розв'яжеться на неправильну машину. На той момент людина, яка це налагоджує, вважає, що зламано DNS, а не файл.

Динамічний шлях: learn-address і пул

OpenVPN знає призначення, тож нехай він вам його скаже. Ці параметри сервера роблять призначення стійким і придатним для скриптів:

client-config-dir /etc/openvpn/ccd
ifconfig-pool-persist /etc/openvpn/ip-pool 60
script-security 2
learn-address /etc/openvpn/learn-address.sh

learn-address запускає ваш скрипт щоразу, коли адресу додають, оновлюють або видаляють, і передає операцію, адресу та спільне ім'я. Мінімальний скрипт додає один рядок на клієнта й прибирає його під час видалення:

#!/bin/sh
HOSTS=/etc/openvpn/hosts.lan
case "$1" in
  add|update) echo "$2 $3" >> "$HOSTS" ;;
  delete)     sed -i "/^$2 /d" "$HOSTS" ;;
esac
kill -HUP $(cat /var/run/dnsmasq.pid)

На пристрої tun другий аргумент — це тунельна адреса клієнта, тому рядок можна використовувати напряму. На пристрої tap OpenVPN натомість передає MAC-адресу клієнта, бо сегмент tap може нести й інші протоколи, крім IPv4, і тоді адресу треба знайти у файлі пулу за спільним іменем, перш ніж щось записувати.

Будьте чіткими щодо того, що таке створений файл: знімок того, хто підключений просто зараз. Імена зникають під час відключення, і це саме те, що потрібно для ноутбуків, які переміщаються між мережами, і саме те, чого не потрібно для сервера, що працює всю ніч.

Статичний шлях: address= і розширення домену

Спрямуйте dnsmasq на створений файл замість системного файлу hosts і дайте йому домен, щоб короткі імена розгорталися в повні:

domain=corp.example
no-hosts
addn-hosts=/etc/openvpn/hosts.lan
listen-address=127.0.0.1,10.8.0.1
bind-interfaces

Коли domain задано, рядок на кшталт 10.8.0.6 alice відповідає і для alice, і для alice.corp.example. Тримайте listen-address лише на шлюзі тунелю та loopback, бо резолвер, випадково опублікований на інтерфейсі LAN, — це служба, яку ви не збиралися пропонувати.

Служби, які ніколи не надходять із пулу, отримують власні записи. Помістіть їх в окремий drop-in файл у каталозі конфігурації дистрибутива, щоб оновлення пакета не могло їх перезаписати:

address=/files.corp.example/10.8.0.20
address=/db.corp.example/10.9.0.5

Передайте резолвер, інакше нічого не станеться

Резолвер, який ніхто не запитує, нічого не змінює. Сервер має його оголосити:

push "dhcp-option DNS 10.8.0.1"
push "dhcp-option DOMAIN corp.example"

Клієнти Windows застосовують обидва параметри самі. Більшість клієнтів Linux — ні: їм потрібна підтримувана інтеграція з резолвером, наприклад гачок update-resolv-conf дистрибутива або обробка DNS у NetworkManager, або вручну задані домен пошуку й сервер імен. Перевіряйте фактичний резолвер клієнта, а не припускайте, що push дотримано, бо проігнорований push виглядає точно так само, як сервер, що не відповідає.

Перевірте на трьох рівнях

Спершу запитайте сервер напряму, потім клієнт, потім застосунок:

dig +short @10.8.0.1 alice.corp.example
getent hosts files.corp.example

Якщо прямі запити відповідають, а застосунок ні, винна передача клієнтові, а не зона. Якщо ім'я розв'язується, а з'єднання все одно не встановлюється, ім'я гаразд, і наступне, на що варто подивитися, — маршрут або міжмережевий екран.

Запишіть обидві категорії поруч із конфігурацією: які імена створюються, які закріплені та з яким сертифікатом кожне має збігатися. Наступна людина, яка додасть сервер, скопіює перший знайдений шаблон.

Схожі статті