Имена на клиенти на OpenVPN в dnsmasq: скрипт или статични записи?
Адресите на клиентите се променят, имената на услугите — не. Генерирайте имена на клиенти от VPN сесията, фиксирайте имената на услугите в drop-in файл и след това накарайте клиентите да го използват.
Два проблема с имената се появяват на почти всеки малък OpenVPN шлюз. Не можете да достигнете свързан лаптоп по името от сертификата му, а услугите зад тунела нямат никакви имена. Изглеждат като един проблем и изискват противоположни подходи, защото единият адрес се променя с всяка сесия, а другият — не. Решете какъв вид име добавяте, преди да редактирате каквото и да е.
Решавайте за всяко име, не за целия шлюз
Тестът е прост: променя ли се този адрес, когато клиентът се свърже отново? Ако да, името трябва да се генерира от VPN сесията. Ако не, то принадлежи на статичен запис, който можете да прочетете и прегледате.
| Name kind | Source of truth | Where it lives |
|---|---|---|
| Connected client | The address OpenVPN just assigned | Generated hosts file, rewritten per session |
| Service behind the tunnel | A fixed address you chose | Static address= drop-in |
| Anything with a certificate name | The certificate, not the pool | Either, 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
Ако директните заявки отговарят, а приложението — не, проблемът е в предаването към клиента, а не в зоната. Ако името се разрешава и връзката все още се проваля, името е наред и следващото за проверка е маршрутът или защитната стена.
Запишете двете категории до конфигурацията: кои имена се генерират, кои са фиксирани и с кой сертификат трябва да съвпада всяко от тях. Следващият човек, който добави сървър, ще копира първия модел, който намери.