Скрипта која покрене OpenVPN и никада се не повеже обично није мрежни проблем: клијент седи на захтеву без терминала на коме би га нацртао. OpenVPN има тачно два подржана начина да одговори на тај захтев без човека, датотеку акредитива иза auth-user-pass и контролни сокет, и они нису заменљиви. Датотека кошта једну директиву и одговара на један захтев; сокет одговара на сваки захтев и свему што може да отвори loopback порт даје неаутентификован контролни канал. Која припада вашем распоређивању зависи од тога који захтев заиста блокира и коју тајну можете да приуштите да оставите на миру.

Именујте захтев пре него што изаберете механизам

Четири захтева изгледају исто на терминалу. Пар за налог долази из подешавања PAM или auth-user-pass-verify на серверу и на њега одговара auth-user-pass. Лозинка приватног кључа припада датотеци кључа и чита се преко --askpass или се уноси ручно. Пакет PKCS#12 тражи сопствену лозинку. Прокси аутентикација користи auth датотеку коју узима --http-proxy, а не акредитиве налога.

Када OpenVPN ради као дете systemd-а, PHP-а или Node-а нема терминала, па сваки од њих блокира тихо. Процес седи тамо, дневник се зауставља после линије шифре и јединица на крају истекне; та тишина је разлог зашто људи додају петљу понављања или sleep уместо да погледају који захтев чека. Само контролни сокет може да одговори на сва четири. Датотека акредитива одговара на први и ни на шта друго.

auth-user-pass: једна датотека, један захтев

Датотека садржи корисничко име у првом реду и лозинку у другом, и ништа друго: без наводника, без имена кључева, без коментара. Поставите режим 600 и учините власником налог који покреће openvpn, што је за услугу често посебан корисник, а не ваша пријава. Датотека у власништву root-а под /root је разлика између наредбе која ради у вашој љусци и јединице која не успева при подизању.

Два детаља претварају исправну датотеку у захтев. Уређивач који чува CRLF оставља враћање карета залепљено за лозинку, па сервер одбија лозинку која у датотеци изгледа исправно; проверите са cat -A или od -c, а не оком. А auth-user-pass без аргумента унутар профила по дизајну значи «питај корисника», што друга директива на командној линији можда неће надјачати, јер се профил парсира тамо где се налази.

Редослед опција је трећа замка и зависи од верзије. Неке градње OpenVPN-а 2.4 игноришу --auth-user-pass када се појави пре --config, па се исте две опције у другом редоследу повезују. Ставите директиву у профил или после --config на командној линији и пре било какве друге измене претражите профил за свако појављивање.

auth-nocache припада овом механизму али ништа не даје. Ограничава колико дуго клијент држи акредитиве у меморији, што помаже после пада и нимало када датотека недостаје. Поновно повезивање после истека сесије на страни сервера поново чита датотеку, па акредитиви који су радили при подизању могу ипак истећи усред дана.

Контролни сокет: сваки захтев, више површине

Покрените клијент са слушачем и изричито наведите да ће захтеви бити пријављивани на њему, користећи директиве документоване у приручнику OpenVPN-а 2.6:

management 127.0.0.1 3030
management-query-passwords

Из bash-а држите везу на слободном описнику датотеке и одговарајте по имену захтева, а не по позицији, јер поновно повезивање може да пита у другом редоследу:

exec 3<>/dev/tcp/127.0.0.1/3030
while read -r -u 3 line; do
  case "$line" in
    *"Need 'Auth' username/password"*)
      echo 'username "Auth" alice' >&3
      echo 'password "Auth" secret' >&3 ;;
    *"Need 'Private Key' password"*)
      echo 'password "Private Key" secret' >&3 ;;
  esac
done

Граница је транспорт. Контролни протокол је отворен текст преко TCP-а на loopback-у, па се слушач не сме објављивати на LAN или тунелској адреси да би га даљински контролер достигао; даљински контролер значи SSH прослеђивање, не шире повезивање. Демон заједнице прима и само једног контролног клијента истовремено, па GUI или монитор не могу да деле сокет са вашом скриптом. Друга веза се одбија, не ставља у ред, и квар изгледа као скрипта која је оглувела.

Тај сокет је и контролни канал. Без контролне лозинке све што може да се повеже на 127.0.0.1:3030 може да чита стање, убије тунел или само одговори на захтев. Контролна лозинка и датотека акредитива су тајне исте класе и обе заслужују исту пажњу.

Која одговара распоређивању

Изаберите датотеку акредитива када је једини захтев пар за налог, клијент ради као услуга са стабилним власником и можете да држите датотеку 600 изван резервних копија које не контролишете. Изаберите контролни сокет када је у игри лозинка кључа или лозинка PKCS#12, када омот већ надгледа процес или када треба да посматрате стање и захтеве док отклањате грешке при поновном повезивању.

Два услова померају одлуку. Ако је омот /bin/sh, јединица systemd-а која директно позива бинарну датотеку или минимални контејнер, лепак за сокет само за bash није доступан и датотека је јефтинији одговор. Ако се тајна често ротира, ниједна датотека није добар дом за њу: затражите привезак за кључеве из малог омота и пустите јединицу да позива омот, што држи ротацију на једном месту и лозинку изван историје љуске.

Замена процеса стоји између оба и не припада ниједном. Једноредни пример испод ради зато што га bash проширује пре него што openvpn почне, а не зато што клијент разуме синтаксу:

openvpn --config client.ovpn --auth-user-pass <(printf "%s
%s
" "$USER" "$PASS")

Ломи се под /bin/sh, у јединици која заобилази љуску и у сликама без bash-а или /dev/fd. Чувајте је за интерактивно тестирање, никада као уговор од кога зависи услуга.

Заштитите тајну, затим проверите из дневника

Оба механизма остављају тајну читљиву за процес OpenVPN-а. Никада не стављајте лозинку на командну линију или у датотеку јединице, где је ps и systemctl показују сваком локалном кориснику; предајте путању до датотеке, не вредност у њој. Тамо где сертификати могу да замене пар за налог, то уклања категорију захтева уместо да је скрива.

Исправан рад показује завршетак низа захтева и сесију која достиже «Initialization Sequence Completed». Ако се клијент заустави на истом захтеву, поклапање није успело: испишите тачне линије које је сокет послао, проверите наводнике и име захтева и поправите шаблон уместо да додате sleep. Тунел који извештава успех и не носи ништа је проблем рутирања или push-а, не акредитива.

Затим тестирајте поновно повезивање, не само прво покретање. Прекините сесију на страни сервера или сачекајте њен истек; клијент поново пита, и управо тамо датотека која је при подизању изгледала исправно показује да ли је још читљива налогу који се поново повезује.

Повезани чланци