Die verbindingshooks op ’n VPN-daemon loop as die daemon, en dit beteken gewoonlik dat hulle as root loop. Sodra een van daardie hooks in iemand se tuisgids skryf of ’n lessenaarhulp herbegin, het jy ’n netwerkgebeurtenis die vermoë gegee om as ’n willekeurige plaaslike gebruiker op te tree. Die gewone kortpad, om ’n gebruikersnaam uit ’n omgewingsveranderlike te lees en dit deur te gee, los dit nie op nie. Dit hernoem die aksie sonder om te verander watter rekening dit uitvoer. Wat werk, is ’n drieledige oorhandiging waarin die bevoorregte stap sê wat gebeur het en ’n aparte eenheid die handeling onder die regte identiteit doen.

’n Gebruikersnaam in die omgewing verander nie die rekening nie

Unix besluit wat ’n proses mag aanraak op grond van sy effektiewe gebruikers-ID, nie op grond van die stringe in sy omgewing nie. Om USER=alice te stel of LOGNAME uit te voer, verander wat sorgelose sagteware in sy uitset druk; dit verander niks aan lêereienaarskapkontroles nie. ’n Hook wat as root loop met daardie veranderlike gestel, maak steeds Alice se lêers as root oop.

Die name is ook nie dieselfde naam nie. Die afstandtoegang-aanmelding, die plaaslike Unix-rekening en die sertifikaat se algemene naam is drie identifiseerders wat dikwels saamval en soms nie. ’n Gebruiker wat as a.smith aanmeld, het dalk glad geen plaaslike rekening nie, of word dalk deur ’n gidsdiens na asmith gekarteer. Enige ontwerp wat aanneem dat een string al drie rolle dien, sal by die eerste kontrakteur breek.

Die eerste vraag is dus nie “watter gebruiker is gekoppel” nie, maar “watter plaaslike rekening mag hierdie aksie uitvoer”. Beantwoord dit uit jou eie rekeningdatabasis, nie uit wat die kliënt ook al gestuur het nie:

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

Die derde opdrag is die een wat mense oorslaan. As die teikenlêer deur root besit word omdat die vorige hook dit geskep het, sal ’n korrek opgestelde gebruikersaksie misluk met ’n toestemmingsfout wat soos ’n systemd-probleem lyk en nie een is nie.

Die daemon bly waar hy is

Om die VPN-diens se eie User= na Alice te verander, is die verkeerde hefboom. Dit verander hoe die daemon koppelvlakke bind, sleutels lees, sy statuslêer skryf en roetes bestuur, en dit skuif al daardie risiko in ’n eenheid wat gewerk het. Die daemon het sy voorregte nodig; die opvolgende aksie het dit nie.

Kyk wat die eenheid werklik doen voordat jy daaraan raak. Twee opdragte vertel jou die uitvoeringsidentiteit en die presiese opdragreëls wat geld, insluitend enigiets wat ’n oorheersing bygevoeg het:

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

Op ’n standaard pakketinstalllasie is die daemon root en die --up-skrip erf dit. Bevestig dit eerder as om dit te aanvaar, want ’n geharde verspreiding het dit dalk na ’n toegewyde rekening geskuif, en ’n handgeskrewe drop-in laat die hook dalk deur ’n wikkel met ander reëls loop.

Drie benoemde dele, een nou sneller

Die reëling wat instandhouding oorleef, het ’n gebeurtenis, ’n sneller en ’n aksie. Die daemon rapporteer dat ’n benoemde sessie opgekom het. ’n Sneller aanvaar daardie klein feit en vra vir een vaste aksie. Die aksie loop onder die plaaslike rekening wat die lêers besit wat dit aanraak. Niks in die ketting aanvaar ’n willekeurige opdragpad nie.

Die aksie self is ’n gewone dienseenheid, en die identiteit is een riglyn daarbinne:

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

Let daarop dat User=alice op die hele eenheid van toepassing is, en systemd dokumenteer een uitsondering wat die moeite werd is om te ken: ’n opdrag met die voorvoegsel + loop nietemin met volle voorregte. Daardie voorvoegsel is ’n wettige hulpmiddel vir een enkele bevoorregte stap en ’n gerieflike manier om die skeiding wat jy pas gebou het, ongedaan te maak, so behandel enige + in daardie eenheid as iets wat jy in hersiening moet regverdig.

Hou die sneller se invoer minimaal en nie-geheim. Die sessie-identifiseerder, die gekarteerde rekening en ’n tydstempel is gewoonlik al wat nodig is. Moet nooit ’n skulfragment, ’n uitvoerbare pad of ’n kliëntverskafde omgewingsblok oor die grens stuur nie, want die ontvangende kant het geen manier om ’n wettige waarde van ’n ingevoegde een te onderskei nie.

Verifieer die identiteit wat werklik geloop het

Konfigurasiehersiening is nie bewyse nie. Bevestig ná ’n goedgekeurde toetsverbinding die UID wat die lêer aangeraak het en die UID wat die daemon steeds gebruik:

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

Die eerste reël moet Alice wys en ’n tydstempel binne jou toetsvenster. Die tweede moet steeds root of die verpakte diensrekening wys, wat bewys die daemon het nie geskuif nie. Die derde is die goedkoopste manier om die aksie se toestemmings te toets sonder om vir ’n werklike herverbinding te wag.

As die lêer se eienaar Alice is maar sy groep of modus het tussen lopies verander, soek na ’n UMask= of ’n gidsregteverskil eerder as na ’n logikafout. As die tydstempel glad nie beweeg het nie, het die sneller nooit gevuur nie, en die nuttige volgende stap is journalctl -u vir die aksie-eenheid eerder as nog ’n kliëntherverbinding.

Wat ’n verbindingsgebeurtenis steeds nie bewys nie

’n Gevestigde tonnel is een feit. Dit beteken nie die lessenaarsessie is ontsluit, die sessiebus is bereikbaar, of die privaat hulpbron wat die aksie wil hê, is al beskikbaar nie. ’n Oneshot-eenheid onder Alice se UID het haar identiteit en niks van haar sessie nie, so enigiets wat ’n grafiese bus vereis, moet deur die ondersteunde gebruikersessie-meganisme gaan en definieer wat gebeur wanneer sy afgemeld is.

Herverbindings herhaal ook. ’n Skootrekenaar wat op ’n trein slaap, kan ’n dosyn verbindingsgebeurtenisse in ’n uur produseer, en ’n hook wat elke keer ’n reël byvoeg, verander ’n statuslêer in ’n log wat niemand kan lees nie. Maak die aksie idempotent, of laat dit ’n enkele rekord vervang wat deur sessie gesleutel is.

Laat uiteindelik die skadeomvang in die eenheid self begrens: ’n alleenlees-lêerstelsel-aansig buiten die staatgids, geen nuwe voorregte nie, en ’n uitdruklike tydperk. Die skeiding tussen daemon en gebruikersaksie is op sigself die moeite werd, maar dit is baie meer werd wanneer die aksie niks anders kan doen as die een ding wat jy goedgekeur het nie.

Verwante artikels