Hooki povezave pri demonu VPN tečejo kot demon, kar običajno pomeni, da tečejo kot root. V trenutku, ko eden od teh hookov zapiše v nečijev domači imenik ali znova zažene pomočnika namizja, ste omrežnemu dogodku dali zmožnost delovati kot kateri koli lokalni uporabnik. Običajna bližnjica, brati uporabniško ime iz okoljske spremenljivke in ga posredovati, tega ne odpravi. Dejanje le preoznači, ne da bi spremenila, kateri račun ga izvaja. Kar deluje, je tridelna predaja, pri kateri privilegirani korak pove, kaj se je zgodilo, ločena enota pa dejanje izvede pod pravo identiteto.

Uporabniško ime v okolju ni stikalo identitete

Unix odloča, česa se lahko proces dotakne, po svojem efektivnem uporabniškem ID, ne po nizih v svojem okolju. Nastavitev USER=alice ali izvoz LOGNAME spremeni, kaj nepreviden program izpiše v svojem izhodu; pri preverjanjih lastništva datotek ne spremeni ničesar. Hook, ki teče kot root s to spremenljivko, še vedno odpira Alicine datoteke kot root.

Tudi imena niso isto ime. Prijava za oddaljeni dostop, lokalni račun Unix in skupno ime potrdila so trije identifikatorji, ki se pogosto ujemajo in včasih ne. Uporabnik, ki se preverja kot a.smith, morda nima nobenega lokalnega računa ali pa se prek imeniške storitve preslika v asmith. Vsaka zasnova, ki predpostavlja, da en niz služi vsem trem vlogam, se bo zlomila pri prvem izvajalcu.

Prvo vprašanje torej ni „kateri uporabnik je povezan“, ampak „kateremu lokalnemu računu je dovoljeno izvesti to dejanje“. Odgovorite na to iz lastne zbirke računov, ne iz tega, kar je poslal odjemalec:

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

Tretji ukaz je tisti, ki ga ljudje preskočijo. Če je ciljna datoteka v lasti roota, ker jo je ustvaril prejšnji hook, bo pravilno nastavljeno uporabniško dejanje spodletelo z napako dovoljenja, ki je videti kot težava systemd in ni.

Demon ostane tam, kjer je

Spreminjanje lastnega User= storitve VPN v Alico je napačna ročica. Spremeni, kako demon veže vmesnike, bere ključe, piše svojo datoteko stanja in upravlja poti, ter ves to tveganje prestavi v enoto, ki je delovala. Demon potrebuje svoje pravice; naslednje dejanje ne.

Poglejte, kaj enota v resnici počne, preden se je dotaknete. Dva ukaza vam povesta identiteto izvajanja in natančne veljavne ukazne vrstice, vključno z vsem, kar je dodala preglasitev:

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

Pri privzeti namestitvi iz paketa je demon root in skript --up to podeduje. Potrdite to, namesto da predpostavljate, ker je utrjena distribucija morda premaknila v namenski račun, ročno napisan drop-in pa lahko hook zažene prek ovoja z drugimi pravili.

Tri imenovani deli, en ozek sprožilec

Razporeditev, ki preživi vzdrževanje, ima dogodek, sprožilec in dejanje. Demon sporoči, da se je imenovana seja dvignila. Sprožilec sprejme to majhno dejstvo in zahteva eno fiksno dejanje. Dejanje teče pod lokalnim računom, ki je lastnik datotek, ki se jih dotika. Nič v verigi ne sprejme poljubne poti ukaza.

Dejanje samo je običajna storitvena enota, identiteta pa je ena direktiva v njej:

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

Upoštevajte, da User=alice velja za celotno enoto, in systemd dokumentira eno izjemo, ki se jo je vredno zavedati: ukaz s predpono + teče s polnimi pravicami ne glede na to. Ta predpona je zakonito orodje za en sam privilegiran korak in priročen način za razveljavitev ločitve, ki ste jo pravkar zgradili, zato vsak + v tej enoti obravnavajte kot nekaj, kar je treba v pregledu utemeljiti.

Vhod sprožilca naj bo minimalen in ne-tajen. Identifikator seje, preslikan račun in časovni žig so običajno vse, kar je potrebno. Nikoli ne pošiljajte čez mejo fragmenta lupine, poti do izvršljive datoteke ali okoljskega bloka, ki ga je zagotovil odjemalec, ker prejemna stran ne more ločiti zakonite vrednosti od vbrizgane.

Preverite identiteto, ki je v resnici tekla

Pregled konfiguracije ni dokaz. Po odobreni preskusni povezavi potrdite UID, ki se je dotaknil datoteke, in UID, ki ga demon še uporablja:

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

Prva vrstica bi morala pokazati Alico in časovni žig v vašem preskusnem oknu. Druga bi morala še vedno kazati root ali servisni račun paketa, kar dokazuje, da se demon ni premaknil. Tretja je najcenejši način za preizkus dovoljenj dejanja brez čakanja na pravo ponovno povezavo.

Če je lastnik datoteke Alica, vendar sta se njena skupina ali način med zagoni spremenila, iščite UMask= ali razliko v dovoljenjih imenika, ne logične napake. Če se časovni žig sploh ni premaknil, sprožilec ni bil nikoli sprožen, in koristen naslednji korak je journalctl -u za enoto dejanja, ne še ena ponovna povezava odjemalca.

Česa dogodek povezave še vedno ne dokaže

Vzpostavljen tunel je eno dejstvo. Ne pomeni, da je seja namizja odklenjena, da je sejno vodilo dosegljivo ali da je zasebni vir, ki ga dejanje želi, že na voljo. Enota oneshot pod Alicinim UID ima njeno identiteto in ničesar iz njene seje, zato mora vse, kar zahteva grafično vodilo, iti skozi podprti mehanizem uporabniške seje in določiti, kaj se zgodi, ko je odjavljena.

Ponovne povezave se tudi ponavljajo. Prenosnik, ki spi na vlaku, lahko v eni uri ustvari ducat dogodkov povezave, hook, ki vsakič doda vrstico, pa spremeni statusno datoteko v dnevnik, ki ga nihče ne more brati. Naredite dejanje idempotentno ali mu dovolite, da zamenja en zapis, ključan po seji.

Nazadnje omejite polmer škode v sami enoti: pogled na datotečni sistem samo za branje zunaj statusnega imenika, brez novih pravic in z izrecnim časovnim omejitvijo. Ločitev demona in uporabniškega dejanja je vredna sama po sebi, a veliko več velja, ko dejanje ne more storiti ničesar drugega kot tisto eno, kar ste odobrili.

Sorodni članki