OpenVPN auth-user-pass: файл, stdin или подкана? Как да изберете
Изберете между подканата в конзолата, файл с идентификационни данни, поток и интерфейса за управление, после отстранете грешките, които само изглеждат като грешна парола.
Три неща определят кой източник на идентификационни данни да използвате: дали човек седи на конзолата, дали тайната може да живее на диска и дали друг процес трябва да отговаря на подканата. Сгрешете ли избора, клиентът съобщава за проблем със stdin, докато паролата е напълно валидна, което изпраща повечето хора към сървъра без причина. Изберете пътя първо; съобщенията за грешка имат смисъл само след като знаете кой път ги е създал.
Трите условия, които решават въпроса
Подканата в конзолата е единственият път, който се нуждае от човек, затова е единственият, който се проваля тихо в systemd unit или контейнер. Ако човек стартира клиента и въведе паролата, не участва файл и нищо чувствително не попада на диска. Ако клиентът стартира при зареждане, същата подкана се превръща в забиване и изтичането на времето обикновено изглежда като обща грешка на връзката, а не като грешка в идентификационните данни.
Файлът с идентификационни данни е правилният отговор, когато процесът стартира без надзор и тайната може да остане на диска при контролиран набор от права. Когато тайната не бива да се записва изобщо - политика само на трезор, краткотраен токен - ви трябва поток, който клиентът може да отвори, което на практика означава заместване на процес или помощник, който пише във файлов дескриптор. Интерфейсът за управление покрива четвъртия случай: контролер, който вече управлява жизнения цикъл на тунела и може да отговаря на въпроси през сокет.
- Човек на конзолата, без автоматизация: интерактивна подкана.
- Стартиране без надзор, тайната може да се съхранява: файл с идентификационни данни с режим 0600.
- Стартиране без надзор, тайната не може да се съхранява: заместване на процес или fd, в който пише агент за тайни.
- Друг процес притежава клиента: интерфейс за управление.
Когато два отговора пасват, предпочитайте този, който държи тайната извън argv и извън историята на shell. Парола, подадена като аргумент на програма, е четима от всеки локален потребител през списъка с процеси и това излагане е трудно за отмяна.
Какво всъщност прави всеки път за въвеждане
--auth-user-pass сам по себе си иска потребителско име и парола на конзолата. При зададено име на файл клиентът приема първия ред за потребителско име, а втория за парола; нищо не поддържа кавички, коментари или синтаксис ключ-стойност. Това е целият формат, затова всеки, който го редактира с очакване за INI файл, го разваля. Вграденият блок <auth-user-pass> държи същите два реда в профила, което прави самия профил тайна и го поставя в същия клас на работа като частен ключ.
Другите два пътя са поток и сокет. OpenVPN се нуждае само от четим файлов дескриптор, затова ще приеме заместване на процес, запис /dev/fd зад канал или име на файл, който всъщност е FIFO. Интерфейсът за управление е различен по същност: клиентът пита надзорен процес за стойностите вместо да ги чете сам. Тази разлика е важна при повторно свързване: файл с идентификационни данни, FIFO, в който помощник за тайни може да пише отново, и интерфейсът за управление могат да доставят отново без човек; заместването на процес не може, защото дескрипторът се изразходва при първото четене.
Файлът трябва да е точно два реда
Два режима на отказ покриват повечето повредени файлове с идентификационни данни. Редактор на Windows оставя CRLF окончания, връщането на каретката става част от паролата и сървърът отхвърля стойност, която изглежда правилна на екрана. Празен втори ред - празен ред там, където трябва да е паролата - оставя клиента с празна парола, която сървърът отхвърля, въпреки че стойността на екрана изглежда правилна. Допълнителен нов ред след паролата е безвреден. Записвайте файла от shell, не от редактор, и проверете байтовете:
install -m 600 /dev/null /etc/openvpn/client.creds
printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS" > /etc/openvpn/client.creds
od -c /etc/openvpn/client.creds | head -3Пътят е също толкова важен, колкото съдържанието. Относителният път се разрешава спрямо работната директория на процеса, която за услуга рядко е директорията, в която сте тествали. Използвайте абсолютен път, направете файла собственост на акаунта, който пуска клиента, и пазете режим 0600, за да не могат групата и останалите да го четат. Ръководството на OpenVPN 2.6 изброява приетите форми на директивата; проверете го, преди да изобретите трета.
Тествайте файла, преди да обвинявате сървъра. Изпълнението на openvpn --config client.ovpn --auth-user-pass /etc/openvpn/client.creds --verb 4 отпечатва дали файлът е отворен и по-късно дали идентификационните данни са приети, което ви казва кой слой да смените след това.
Потоци, stdin и грешките, които те произвеждат
Подаването на паролата през канал е първото, което повечето хора опитват, и пътят с най-много изненади. Заместването на процес работи, защото на клиента му трябва само четим дескриптор: openvpn --config client.ovpn --verb 3 --auth-user-pass <(printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS"). Подаването на /dev/stdin работи само когато stdin е още отворен и четим в момента, в който клиентът пита, което не е вярно в конвейер, който вече го е изразходвал.
ERROR: could not read Auth username from stdin има две различни причини. При някои клиенти 2.3.x съобщението идваше от дефект в обработката на stdin, който по-късните издания 2.3 поправиха, затова толкова стар клиент се подобрява само с надграждане. При съвременен клиент същият текст означава, че клиентът е поискал конзолен вход и stdin не е бил терминал - точно ситуацията в systemd unit, задача на cron или контейнер, стартиран без -t.
auth-nocache добавя трети цикъл, който изглежда като счупена парола. Той изхвърля идентификационните данни от паметта след употреба, затова повторното свързване, предизвикано от промяна в мрежата, няма какво да преиграе и подканата се връща. Това е директивата, работеща както е проектирана. auth-nocache променя това, което клиентът пази в паметта, а не това, което сървърът или доставчикът на идентичност мисли за акаунта, затова цялата поправка е повторно подаване на същия файл, прочетен отново при рестарт - а при управлявана връзка това подаване трябва да идва от одобреното хранилище за тайни, не от парола в скрипт.
Интерфейсът за управление, когато друг процес притежава подканата
Контролер, който вече наблюдава тунела, може също да отговаря на въпросите му. Стартирайте клиента с --management 127.0.0.1 7505, четете редовете за състояние и следете за >PASSWORD:Need 'Auth' username/password. Контролерът отговаря с username "Auth" alice, последван от password "Auth" ... на отделни командни редове. Токенът 'Auth' повтаря идентификатора от заявката и трябва да съвпада, иначе отговорът се игнорира и клиентът чака.
Цената е машина на състоянията, която сега притежавате: ред на свързване, рестартиране на клиента и локален сокет, до който други потребители на хоста не трябва да достигат. Това, което купувате, е идентификационни данни, подадени по време на изпълнение, без файл на диска и без подкана, която може да забие. Ако нищо друго в стека ви вече не говори протокола, този път добавя компонент за поддръжка.
Провали, които изглеждат като проблеми с идентификационните данни
TLS ръкостискане, което никога не завършва, или VERIFY ERROR: depth=0, error=certificate signature failure, е проблем с доверието и се случва преди да бъде прочетено каквото и да е потребителско име. Клиент proto tcp, насочен към UDP слушател, се проваля на същото място: пакетите така и не достигат до етапа на удостоверяване, затова всяка парола изглежда грешна по асоциация. Пазете проверката на сертификата включена, преди идентификационните данни да бъдат изпратени; позната подкана не казва нищо за това кой получава паролата. Проверете веригата от сертификати, общото име и транспорта, преди да пипате идентификационните данни.
Грешки в shell в скрипта, който сглобява профила, са другата фалшива следа. Липсващ интервал вътре в [ ! -f "$file" ] произвежда command not found, скриптът спира рано, профилът никога не се преизгражда и клиентът стартира с предишния. Тази грешка принадлежи на shell, не на удостоверяването, и никакво преписване на паролата няма да я изчисти.
Не всяка подкана в този поток е тези идентификационни данни. Паролата за частен ключ, входът през HTTP прокси и паролата на услугата са три различни тайни, искани в различни фази, а паролата за ключ обикновено се обработва от клиента или агент, а не от auth-user-pass. Ако подканата се появи преди TLS сесията да е установена, отговаряте на грешния въпрос и нулиране на акаунта няма да помогне. След като грешната подкана бъде изключена, останалите проверки започват от най-ранния слой:
- Четете първата грешка на протокола, не последния ред за идентификационни данни: TLS, после удостоверяване, после push.
- Потвърдете, че файлът е два реда, няма връщания на каретката и е посочен с абсолютен път.
- Потвърдете, че профилът и командният ред не се разминават относно директивата.
- Отделете "идентификационните данни са приети" от "трафикът тече" - маршрутизацията и DNS са по-късен слой.
Щом клиентът стигне фазата push, спрете да гледате идентификационните данни и започнете да четете маршрутите и DNS сървърите, които сървърът е изпратил. Това е следващият проблем и няма нищо общо с паролата, която току-що поправихте.