VPN-i deemoni ühenduse hookid töötavad deemonina, ja tavaliselt tähendab see, et need töötavad rootina. Hetkel, mil üks neist hookidest kirjutab kellegi kodukataloogi või taaskäivitab töölaua abilise, olete andnud võrgusündmusele võime tegutseda suvalise kohaliku kasutajana. Tavaline otsetee, lugeda kasutajanimi keskkonnamuutujast ja see edasi anda, ei paranda seda. See nimetab toimingu ümber, muutmata seda, milline konto seda täidab. See, mis töötab, on kolmeosaline üleandmine, kus privilegeeritud samm ütleb, mis juhtus, ja eraldi üksus teostab toimingu õige identiteedi all.

Kasutajanimi keskkonnas ei ole identiteedilüliti

Unix otsustab, mida protsess puutuda tohib, oma efektiivse kasutaja-ID järgi, mitte keskkonnas olevate stringide järgi. USER=alice seadmine või LOGNAME eksportimine muudab seda, mida hooletu tarkvara oma väljundisse prindib; faili omandiõiguse kontrollides ei muuda see midagi. Rootina töötav hook, millel see muutuja on seatud, avab ikkagi Alice’i failid rootina.

Ka nimed ei ole sama nimi. Kaugjuurdepääsu login, kohalik Unixi konto ja sertifikaadi üldnimi on kolm identifikaatorit, mis sageli kattuvad ja mõnikord mitte. Kasutajal, kes autendib end a.smith-na, ei pruugi kohalikku kontot üldse olla, või vastendub see kataloogiteenuse kaudu kontole asmith. Iga disain, mis eeldab, et üks string teenib kõiki kolme rolli, puruneb esimese töövõtja peale.

Seega esimene küsimus ei ole „milline kasutaja on ühendatud“, vaid „millisel kohalikul kontol on lubatud seda toimingut teha“. Vastake sellele omaenda kontode andmebaasist, mitte sellest, mille klient saatis:

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

Kolmas käsk on see, mille inimesed vahele jätavad. Kui sihtfail kuulub rootile, sest eelmine hook selle lõi, siis korrektselt seadistatud kasutajatoiming ebaõnnestub õiguste veaga, mis näeb välja nagu systemd probleem ja ei ole seda.

Deemon jääb sinna, kus ta on

VPN-teenuse enda User= muutmine Alice’iks on vale hoob. See muudab, kuidas deemon liidestab liideseid, loeb võtmeid, kirjutab oma olekufaili ja haldab marsruute, ning viib kogu selle riski üksusesse, mis töötas. Deemon vajab oma privileege; järeltoiming mitte.

Vaadake, mida üksus tegelikult teeb, enne kui seda puudutate. Kaks käsku ütlevad teile täitmisidentiteedi ja kehtivad täpsed käsuread, sealhulgas kõik, mille on lisanud ülekirjutusfail:

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

Vaikimisi paketi paigaldusel on deemon root ja --up skript pärib selle. Kinnitage seda, selle asemel et eeldada, sest karastatud distributsioon võis selle viia eraldi kontole, ja käsitsi kirjutatud drop-in võib hooki käivitada teistsuguste reeglitega ümbrise kaudu.

Kolm nimetatud osa, üks kitsas päästik

Paigutus, mis hoolde üle elab, on sündmus, päästik ja toiming. Deemon teatab, et nimetatud sessioon tuli üles. Päästik võtab selle väikese fakti vastu ja küsib ühte fikseeritud toimingut. Toiming töötab selle kohaliku konto all, kellele kuuluvad failid, mida see puudutab. Midagi ahelas ei võta vastu suvalist käsuteed.

Toiming ise on tavaline teenuseüksus ja identiteet on üks direktiiv selle sees:

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

Pange tähele, et User=alice kehtib kogu üksuse kohta, ja systemd dokumenteerib ühe erandi, mida tasub teada: prefiksiga + käsk töötab täisprivileegidega olenemata sellest. See prefiks on seaduslik tööriist ühe privilegeeritud sammu jaoks ja mugav viis tühistada äsja ehitatud eraldus, seega käsitlege mis tahes + selles üksuses asjana, mida tuleb ülevaatusel põhjendada.

Hoidke päästiku sisend minimaalne ja mitte-salajane. Sessiooni identifikaator, vastendatud konto ja ajatempel on tavaliselt kõik, mida vaja. Ärge kunagi laske üle piiri shell-fragmenti, käivitatava faili teed ega kliendi antud keskkonnaplokki, sest vastuvõtval poolel pole võimalust eristada seaduslikku väärtust süstitust.

Kontrollige identiteeti, mis tegelikult töötas

Konfiguratsiooni ülevaatus ei ole tõend. Pärast kinnitatud testühendust kinnitage UID, mis faili puudutas, ja UID, mida deemon ikka kasutab:

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

Esimene rida peaks näitama Alicet ja ajatemplit teie testiakna sees. Teine peaks näitama ikka rooti või paketi teenusekontot, mis tõestab, et deemon ei liikunud. Kolmas on odavaim viis toimingu õiguste testimiseks ilma tõelist taasühendust ootamata.

Kui faili omanik on Alice, aga selle grupp või režiim muutus käivituste vahel, otsige pigem UMask= või kataloogi õiguste erinevust kui loogikaviga. Kui ajatempel ei liikunud üldse, ei vallandunud päästik kunagi, ja kasulik järgmine samm on journalctl -u toimingu üksuse jaoks, mitte veel üks kliendi taasühendus.

Mida ühendussündmus ikka veel ei tõesta

Loodud tunnel on üks fakt. See ei tähenda, et töölaua sessioon on lukust lahti, sessioonisiin on kättesaadav või toimingu soovitud privaatne ressurss on juba saadaval. oneshot-üksusel Alice’i UID all on tema identiteet ja mitte midagi tema sessioonist, seega kõik, mis nõuab graafilist siini, peab minema toetatud kasutajasessiooni mehhanismi kaudu ja määratlema, mis juhtub, kui ta on välja logitud.

Taasühendused kordavad end ka. Rongis magav sülearvuti võib tunnis tekitada tosinat ühendussündmust, ja hook, mis iga kord rea lisab, muudab olekufaili logiks, mida keegi lugeda ei saa. Tehke toiming idempotentseks või laske sellel asendada üks sessiooni järgi võtmestatud kirje.

Lõpuks piirake kahjuraadiust üksuses endas: kirjutuskaitstud failisüsteemi vaade väljaspool olekukataloogi, uusi privileege pole ja selgesõnaline ajalõpp. Deemoni ja kasutajatoimingu eraldamine on iseenesest väärtuslik, aga see on palju väärtuslikum, kui toiming ei saa teha midagi muud kui see üks asi, mille te heaks kiitsite.

Seotud artiklid