Ang mga hook ng koneksyon sa isang daemon ng VPN ay tumatakbo bilang daemon, at karaniwang ibig sabihin nito ay tumatakbo sila bilang root. Sa sandaling ang isa sa mga hook na iyon ay magsulat sa home directory ng isang tao o mag-restart ng desktop helper, nabigyan mo ang isang pangyayari sa network ng kakayahang kumilos bilang sinumang lokal na user. Ang karaniwang shortcut, ang pagbasa ng username mula sa variable ng kapaligiran at pagpapasa nito, ay hindi nag-aayos niyon. Binibigyan lamang nito ng bagong label ang aksyon nang hindi binabago kung aling account ang nagsasagawa nito. Ang gumagana ay isang paghahatid sa tatlong bahagi, kung saan sinasabi ng privileged na hakbang kung ano ang nangyari at isang hiwalay na unit ang nagsasagawa ng aksyon sa ilalim ng tamang pagkakakilanlan.

Ang username sa kapaligiran ay hindi switch ng pagkakakilanlan

Nagpapasya ang Unix kung ano ang maaaring hawakan ng isang proseso batay sa epektibong user ID nito, hindi sa mga string sa kapaligiran nito. Ang pagtatakda ng USER=alice o pag-export ng LOGNAME ay nagbabago kung ano ang ipiniprint ng pabayang software sa output nito; wala itong binabago sa mga pagsusuri ng pagmamay-ari ng file. Ang hook na tumatakbo bilang root na may nakatakdang variable ay binubuksan pa rin ang mga file ni Alice bilang root.

Ang mga pangalan ay hindi rin parehong pangalan. Ang login ng remote access, ang lokal na Unix account at ang karaniwang pangalan ng sertipiko ay tatlong identifier na madalas magtugma at kung minsan ay hindi. Ang user na nagpapatunay bilang a.smith ay maaaring walang lokal na account, o maaaring ma-map sa asmith sa pamamagitan ng serbisyo ng direktoryo. Anumang disenyo na nagpapalagay na isang string ang nagsisilbi sa tatlong papel ay masisira sa unang kontratista.

Kaya ang unang tanong ay hindi «sinong user ang konektado» kundi «aling lokal na account ang pinapayagang magsagawa ng aksyong ito». Sagutin iyon mula sa sarili mong database ng account, hindi mula sa ipinadala ng kliyente:

id -u alice
getent passwd alice | cut -d: -f1,3,6
stat -c '%U:%G %a %n' /home/alice/.local/state/vpn-status.json

Ang ikatlong utos ang hinihintuan ng mga tao. Kung ang target na file ay pag-aari ng root dahil ginawa ito ng nakaraang hook, ang wastong naka-configure na aksyon ng user ay mabibigo nang may error sa pahintulot na mukhang problema sa systemd at hindi naman.

Nananatili ang daemon sa kinalalagyan nito

Ang pagpapalit ng User= ng serbisyo ng VPN mismo kay Alice ay maling lever. Binabago nito kung paano nagbi-bind ng interface ang daemon, nagbabasa ng key, nagsusulat ng status file at namamahala ng ruta, at inililipat ang lahat ng panganib na iyon sa isang unit na gumagana. Kailangan ng daemon ang mga pribilehiyo nito; ang kasunod na aksyon ay hindi.

Tingnan kung ano ang aktwal na ginagawa ng unit bago ito hawakan. Dalawang utos ang nagsasabi sa iyo ng pagkakakilanlan ng pagpapatupad at ng eksaktong mga command line na may bisa, kasama ang lahat ng idinagdag ng override:

systemctl show -p User -p Group -p ExecStart openvpn-server@server
systemctl cat openvpn-server@server

Sa default na pag-install ng pakete, ang daemon ay root at ang script na --up ay nagmamana niyon. Kumpirmahin ito sa halip na ipagpalagay, dahil maaaring inilipat ito ng hardened na distribusyon sa isang dedikadong account, at ang manu-manong isinulat na drop-in ay maaaring magpatakbo ng hook sa pamamagitan ng wrapper na may ibang mga patakaran.

Tatlong pinangalanang bahagi, isang makitid na trigger

Ang kaayusang tumatagal sa maintenance ay may pangyayari, trigger at aksyon. Iniulat ng daemon na umangat ang isang pinangalanang session. Tumatanggap ang trigger sa maliit na katotohanang iyon at humihingi ng isang takdang aksyon. Tumatakbo ang aksyon sa ilalim ng lokal na account na nagmamay-ari ng mga file na hinahawakan nito. Wala sa kadena ang tumatanggap ng di-makatwirang landas ng utos.

Ang aksyon mismo ay isang ordinaryong unit ng serbisyo, at ang pagkakakilanlan ay isang direktiba sa loob nito:

[Service]
Type=oneshot
User=alice
Group=alice
ExecStart=/usr/local/bin/refresh-vpn-status --slot %i

Pansinin na ang User=alice ay nalalapat sa buong unit, at ang systemd ay nagdodokumento ng isang eksepsyon na sulit malaman: ang utos na may prefix na + ay tumatakbo nang may buong pribilehiyo anuman iyon. Ang prefix na iyon ay lehitimong kasangkapan para sa isang privileged na hakbang at maginhawang paraan upang kanselahin ang paghihiwalay na kauuwi mo pa lang, kaya ituring ang anumang + sa unit na iyon bilang bagay na kailangang bigyang-katwiran sa pagsusuri.

Panatilihing minimal at hindi lihim ang input ng trigger. Ang identifier ng session, ang naka-map na account at isang timestamp ay karaniwang sapat na. Huwag kailanman ipasa sa kabila ng hangganan ang isang piraso ng shell, landas ng executable o block ng kapaligiran na ibinigay ng kliyente, dahil walang paraan ang tumatanggap na panig upang makilala ang lehitimong halaga sa isang na-inject.

I-verify ang pagkakakilanlang aktwal na tumakbo

Ang pagsusuri ng configuration ay hindi ebidensya. Pagkatapos ng aprubadong test koneksyon, kumpirmahin ang UID na humawak sa file at ang UID na ginagamit pa rin ng daemon:

stat -c '%U %G %y %n' /home/alice/.local/state/vpn-status.json
ps -o user=,pid=,cmd= -p "$(pgrep -o -f 'openvpn --daemon')"
systemd-run --uid=alice --pipe /usr/local/bin/refresh-vpn-status --dry-run

Ang unang linya ay dapat magpakita kay Alice at isang timestamp sa loob ng iyong test window. Ang pangalawa ay dapat magpakita pa rin ng root o ang service account ng pakete, na nagpapatunay na hindi gumalaw ang daemon. Ang pangatlo ang pinakamurang paraan upang subukan ang mga pahintulot ng aksyon nang hindi naghihintay ng tunay na muling pagkonekta.

Kung ang may-ari ng file ay si Alice ngunit nagbago ang grupo o mode nito sa pagitan ng mga pagpapatakbo, hanapin ang UMask= o pagkakaiba sa pahintulot ng direktoryo sa halip na error sa lohika. Kung hindi gumalaw nang husto ang timestamp, hindi kailanman napaputok ang trigger, at ang kapaki-pakinabang na susunod na hakbang ay journalctl -u para sa unit ng aksyon sa halip na isa pang muling pagkonekta ng kliyente.

Ano ang hindi pa rin pinapatunayan ng pangyayari sa koneksyon

Ang naitatag na tunnel ay isang katotohanan. Hindi ibig sabihin nito na nakabukas ang desktop session, na maaabot ang session bus o na available na ang pribadong resource na gusto ng aksyon. Ang oneshot unit sa ilalim ng UID ni Alice ay may pagkakakilanlan niya at wala mula sa session niya, kaya lahat ng nangangailangan ng graphical bus ay dapat dumaan sa sinusuportahang mekanismo ng user session at tukuyin kung ano ang nangyayari kapag naka-log out siya.

Paulit-ulit din ang muling pagkonekta. Ang laptop na natutulog sa tren ay maaaring gumawa ng dose-dosenang pangyayari sa koneksyon sa isang oras, at ang hook na nagdadagdag ng linya sa bawat pagkakataon ay ginagawang log na walang makababasa ang isang status file. Gawing idempotent ang aksyon, o hayaang palitan nito ang isang rekord na naka-key sa session.

Sa huli, limitahan ang radius ng pinsala sa unit mismo: isang read-only na view ng filesystem sa labas ng status directory, walang bagong pribilehiyo, at isang tahasang timeout. Ang paghihiwalay ng daemon at aksyon ng user ay sulit sa sarili nito, ngunit mas sulit ito kapag ang aksyon ay walang magawa maliban sa isang bagay na inaprubahan mo.

Kaugnay na mga artikulo