Скрипт, който стартира 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, не с идентификационните данни.

След това тествайте повторното свързване, не само първото стартиране. Прекъснете сесията от страна на сървъра или изчакайте изтичането ѝ; клиентът пита отново и точно там файл, който е изглеждал правилен при зареждане, показва дали все още е четим от акаунта, който се свързва отново.

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