Ang script na naglulunsad ng OpenVPN at hindi kailanman kumokonekta ay karaniwang hindi problema sa network: nakaupo ang client sa isang prompt na walang terminal na pagguguhitan nito. OpenVPN ay may eksaktong dalawang sinusuportahang paraan para sagutin ang prompt na iyon nang walang tao, isang file ng kredensyal sa likod ng auth-user-pass at ang management socket, at hindi sila mapagpapalit. Ang file ay nagkakahalaga ng isang direktiba at sinasagot ang isang prompt; ang socket ay sinasagot ang bawat prompt at binibigyan ang anumang makakabukas ng loopback port ng hindi awtentikadong control channel. Alin ang nababagay sa deployment mo ay nakasalalay sa kung aling prompt ang talagang humaharang, at kung aling sikreto ang kayang mong iwanang tahimik.

Pangalanan ang prompt bago pumili ng mekanismo

Apat na prompt ang magkamukha sa terminal. Ang pares ng account ay galing sa PAM o auth-user-pass-verify setup ng server at sinasagot ng auth-user-pass. Ang passphrase ng pribadong key ay kabilang sa key file at binabasa sa pamamagitan ng --askpass o kinakalikot. Ang PKCS#12 bundle ay humihingi ng sarili nitong password. Ang proxy authentication ay gumagamit ng auth file na kinukuha ng --http-proxy, hindi ang kredensyal ng account.

Kapag tumatakbo ang OpenVPN bilang anak ng systemd, PHP o Node, walang terminal, kaya alinman sa mga ito ay tahimik na humaharang. Nakaupo lang ang proseso, humihinto ang log pagkatapos ng cipher line, at sa huli ay lumalampas sa oras ang unit; ang katahimikang iyon ang dahilan kung bakit ang mga tao ay nagdaragdag ng retry loop o sleep sa halip na tingnan kung aling prompt ang nakabinbin. Ang management socket lang ang makakasagot sa apat. Ang file ng kredensyal ay sumasagot sa una at wala nang iba.

auth-user-pass: isang file, isang prompt

Ang file ay may username sa unang linya at password sa pangalawa, at wala nang iba: walang quotes, walang pangalan ng key, walang komento. Itakda ang mode 600 at gawing may-ari ang account na nagpapatakbo ng openvpn, na para sa isang serbisyo ay kadalasang dedikadong user at hindi ang iyong login. Ang file na pag-aari ng root sa ilalim ng /root ay ang pagkakaiba ng isang utos na gumagana sa shell mo at isang unit na nabibigo sa boot.

Dalawang detalye ang gumagawa ng tamang file na maging prompt. Ang editor na nagse-save ng CRLF ay nag-iiwan ng carriage return na dumikit sa password, kaya tinatanggihan ng server ang password na mukhang tama sa file; suriin gamit ang cat -A o od -c, hindi sa mata. At ang auth-user-pass na walang argumento sa loob ng profile ay nangangahulugang «tanungin ang user» ayon sa disenyo, na maaaring hindi mapawalang-bisa ng pangalawang direktiba sa command line, dahil ang profile ay pinaparse kung saan ito naroon.

Ang pagkakasunod-sunod ng mga opsyon ay ang ikatlong bitag, at depende ito sa bersyon. Ang ilang OpenVPN 2.4 build ay hindi pinapansin ang --auth-user-pass kapag lumabas bago ang --config, kaya ang parehong dalawang opsyon sa kabilang ayos ay kumokonekta. Ilagay ang direktiba sa loob ng profile, o pagkatapos ng --config sa command line, at i-grep ang profile para sa bawat paglitaw bago baguhin ang iba pa.

auth-nocache ay kabilang sa mekanismong ito ngunit wala itong ibinibigay. Nililimitahan nito kung gaano katagal itinatago ng client ang kredensyal sa memorya, na tumutulong pagkatapos ng crash at hindi tumutulong kapag nawawala ang file. Ang muling pagkonekta pagkatapos ng session timeout sa panig ng server ay muling nagbabasa ng file, kaya ang kredensyal na gumana noong boot ay maaari pa ring mag-expire sa kalagitnaan ng araw.

Ang management socket: bawat prompt, mas maraming surface

Simulan ang client na may listener at tahasang sabihin na ang mga prompt ay iuulat dito, gamit ang mga direktibang nakadokumento sa manual ng OpenVPN 2.6:

management 127.0.0.1 3030
management-query-passwords

Mula sa bash, itago ang koneksyon sa isang ekstrang file descriptor at sumagot ayon sa pangalan ng prompt sa halip na posisyon, dahil ang muling pagkonekta ay maaaring magtanong sa ibang ayos:

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

Ang hangganan ay ang transport. Ang management protocol ay plaintext sa TCP sa loopback, kaya ang listener ay hindi dapat ilathala sa LAN o tunnel address para maabot ito ng remote controller; ang remote controller ay nangangahulugang SSH forwarding, hindi mas malawak na bind. Ang community daemon ay tumatanggap din ng isang management client lamang sa isang pagkakataon, kaya ang GUI o monitor ay hindi makakabahagi ng socket sa iyong script. Ang ikalawang koneksyon ay tinatanggihan, hindi pinipila, at ang pagkasira ay mukhang script na naging bingi.

Ang socket na iyon ay control channel din. Nang walang management password, anumang makakakonekta sa 127.0.0.1:3030 ay makakabasa ng status, makakapatay ng tunnel o sasagot mismo sa isang prompt. Ang management password at ang file ng kredensyal ay parehong klase ng sikreto, at pareho silang karapat-dapat sa parehong pag-iingat.

Alin ang nababagay sa deployment

Piliin ang file ng kredensyal kapag ang tanging prompt ay ang pares ng account, tumatakbo ang client bilang serbisyo na may matatag na may-ari, at kayang itago ang 600 file sa labas ng mga backup na hindi mo kontrolado. Piliin ang management socket kapag may passphrase ng key o password ng PKCS#12, kapag sinusubaybayan na ng wrapper ang proseso, o kapag kailangan mong panoorin ang status at mga prompt habang nagde-debug ng muling pagkonekta.

Dalawang kondisyon ang nagbabago ng desisyon. Kung ang wrapper ay /bin/sh, isang systemd unit na direktang tumatawag sa binary, o minimal na container, ang pandikit ng socket para sa bash lang ay wala, at ang file ang mas murang sagot. Kung madalas umiikot ang sikreto, wala sa mga file ang magandang tahanan para rito: tanungin ang keyring mula sa maliit na wrapper at hayaang tawagin ng unit ang wrapper, na nagpapanatili ng rotasyon sa isang lugar at ng password sa labas ng shell history.

Ang process substitution ay nasa pagitan ng dalawa at hindi kabilang sa alinman. Ang one-liner sa ibaba ay gumagana dahil pinalawak ito ng bash bago magsimula ang openvpn, hindi dahil nauunawaan ng client ang syntax:

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

Nabibigo ito sa ilalim ng /bin/sh, sa unit na lumalampas sa shell, at sa mga image na walang bash o /dev/fd. Itago ito para sa interactive na pagsubok, hindi kailanman bilang kontratang umaasa ang isang serbisyo.

Protektahan ang sikreto, pagkatapos i-verify mula sa log

Parehong mekanismo ay nag-iiwan ng sikretong mababasa ng proseso ng OpenVPN. Huwag kailanman ilagay ang password sa command line o sa unit file, kung saan ipinapakita ito ng ps at systemctl sa bawat lokal na user; ipasa ang path sa file, hindi ang halaga sa loob nito. Kung saan maaaring palitan ng mga sertipiko ang pares ng account, inaalis nito ang kategorya ng prompt sa halip na itago ito.

Ang tamang pagtakbo ay nagpapakita ng pagkumpleto ng sequence ng prompt at ng session na umabot sa «Initialization Sequence Completed». Kung hihinto ang client sa parehong prompt, nabigo ang pagtutugma: i-print ang eksaktong linya na ipinadala ng socket, suriin ang quotes at pangalan ng prompt, at ayusin ang pattern sa halip na magdagdag ng sleep. Ang tunnel na nag-uulat ng tagumpay at walang dinadala ay problema sa routing o push, hindi sa kredensyal.

Pagkatapos subukan ang muling pagkonekta, hindi lang ang unang pagsisimula. Ihulog ang session sa panig ng server o hintayin ang timeout nito; magtatanong muli ang client, at doon ipinapakita ng file na mukhang tama noong boot kung nababasa pa ito ng account na muling kumokonekta.

Kaugnay na mga artikulo