Ruli VPN-agadon post konekto kiel la uzanto, ne kiel la demono
Medivariablo diranta USER=alice ne ŝanĝas, sub kiu konto hoko ruliĝas. Apartigu la eventon, la ekigilon kaj la agon, poste pruvu la UID-on.
La konektaj hokoj de VPN-demono ruliĝas kiel la demono, kaj kutime tio signifas, ke ili ruliĝas kiel root. En la momento, kiam unu el tiuj hokoj skribas en ies hejman dosierujon aŭ restartigas labortablan helpanton, vi donis al reta evento la kapablon agi kiel arbitra loka uzanto. La kutima mallongigo, legi uzantnomon el medivariablo kaj transdoni ĝin, ne riparas tion. Ĝi renomigas la agon sen ŝanĝi, kiu konto plenumas ĝin. Tio, kio funkcias, estas triparta transdono, en kiu la privilegia paŝo diras, kio okazis, kaj aparta unuo plenumas la agon sub la ĝusta identeco.
Uzantnomo en la medio ne estas identeca ŝaltilo
Unikso decidas, kion procezo rajtas tuŝi, laŭ sia efektiva uzanta ID, ne laŭ la ĉenoj en sia medio. Agordi USER=alice aŭ eksporti LOGNAME ŝanĝas, kion senzorga programaro presas en sia eligo; ĝi ŝanĝas nenion en dosierposedaj kontroloj. Hoko ruliĝanta kiel root kun tiu variablo agordita ankoraŭ malfermas la dosierojn de Alice kiel root.
Ankaŭ la nomoj ne estas la sama nomo. La salutnomo por fora aliro, la loka Uniksa konto kaj la komuna nomo de la atestilo estas tri identigiloj, kiuj ofte koincidas kaj foje ne. Uzanto, kiu aŭtentikiĝas kiel a.smith, eble tute ne havas lokan konton, aŭ eble mapiĝas al asmith per adresara servo. Ajna dezajno, kiu supozas, ke unu ĉeno servas al ĉiuj tri roloj, rompiĝos ĉe la unua kontraktisto.
Do la unua demando ne estas «kiu uzanto estas konektita» sed «kiu loka konto rajtas plenumi ĉi tiun agon». Respondu tion el via propra konta datumbazo, ne el tio, kion la kliento sendis:
id -u alice
getent passwd alice | cut -d: -f1,3,6
stat -c '%U:%G %a %n' /home/alice/.local/state/vpn-status.json
La tria komando estas tiu, kiun homoj preterlasas. Se la cela dosiero posedatas de root ĉar la antaŭa hoko kreis ĝin, ĝuste agordita uzanta ago malsukcesos kun permesa eraro, kiu aspektas kiel problemo de systemd kaj ne estas.
La demono restas tie, kie ĝi estas
Ŝanĝi la propran User= de la VPN-servo al Alice estas la malĝusta levilo. Ĝi ŝanĝas, kiel la demono ligas interfacojn, legas ŝlosilojn, skribas sian statan dosieron kaj administras itinerojn, kaj ĝi movas tiun tutan riskon en unuon, kiu funkciis. La demono bezonas siajn privilegiojn; la sekva ago ne.
Rigardu, kion la unuo efektive faras, antaŭ ol tuŝi ĝin. Du komandoj diras al vi la plenumidenton kaj la precizajn komandliniojn en valido, inkluzive de ĉio aldonita de superskribo:
systemctl show -p User -p Group -p ExecStart openvpn-server@server
systemctl cat openvpn-server@server
Ĉe defaŭlta paketa instalo la demono estas root, kaj la skripto --up heredas tion. Konfirmu tion anstataŭ supozi, ĉar hardita distribuo eble movis ĝin al dediĉita konto, kaj permane skribita drop-in eble rulas la hokon tra ĉirkaŭvolvaĵo kun aliaj reguloj.
Tri nomitaj partoj, unu mallarĝa ekigilo
La aranĝo, kiu postvivas prizorgadon, havas eventon, ekigilon kaj agon. La demono raportas, ke nomita sesio leviĝis. Ekigilo akceptas tiun malgrandan fakton kaj petas unu fiksan agon. La ago ruliĝas sub la loka konto, kiu posedas la dosierojn, kiujn ĝi tuŝas. Nenio en la ĉeno akceptas arbitran komandan vojon.
La ago mem estas ordinara serva unuo, kaj la identeco estas unu direktivo interne de ĝi:
[Service]
Type=oneshot
User=alice
Group=alice
ExecStart=/usr/local/bin/refresh-vpn-status --slot %i
Rimarku, ke User=alice validas por la tuta unuo, kaj systemd dokumentas unu escepton indan je atento: komando kun la prefikso + ruliĝas kun plenaj privilegioj sendepende. Tiu prefikso estas legitima ilo por unu privilegia paŝo kaj oportuna maniero nuligi la apartigon, kiun vi ĵus konstruis, do traktu ajnan + en tiu unuo kiel ion, kion oni devas pravigi en revizio.
Tenu la enigon de la ekigilo minimuma kaj nesecret. La sesia identigilo, la mapita konto kaj tempindiko kutime estas ĉio bezonata. Neniam transdonu ŝel-fragmenton, plenumeblan vojon aŭ klientan mediblokon trans la limon, ĉar la ricevanta flanko ne havas manieron distingi legitiman valoron de enĵetita.
Kontrolu la identecon, kiu efektive ruliĝis
Konfigura revizio ne estas pruvo. Post aprobita testa konekto, konfirmu la UID-on, kiu tuŝis la dosieron, kaj la UID-on, kiun la demono ankoraŭ uzas:
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
La unua linio devus montri Alice kaj tempindikon ene de via testa fenestro. La dua devus ankoraŭ montri root aŭ la pakan servokonton, kio pruvas, ke la demono ne moviĝis. La tria estas la plej malmultekosta maniero testi la permesojn de la ago sen atendi veran rekonekton.
Se la posedanto de la dosiero estas Alice sed ĝia grupo aŭ reĝimo ŝanĝiĝis inter ruloj, serĉu UMask= aŭ dosierujan permesodiferencon anstataŭ logikan eraron. Se la tempindiko tute ne moviĝis, la ekigilo neniam ekagis, kaj la utila sekva paŝo estas journalctl -u por la aga unuo anstataŭ plia klienta rekonekto.
Kion konekta evento ankoraŭ ne pruvas
Establita tunelo estas unu fakto. Ĝi ne signifas, ke la labortabla sesio estas malŝlosita, ke la sesia buso atingeblas, aŭ ke la privata rimedo, kiun la ago volas, jam haveblas. oneshot-unuo sub la UID de Alice havas ŝian identecon kaj nenion de ŝia sesio, do ĉio, kio postulas grafikan buson, devas iri tra la subtenata uzantsesia mekanismo kaj difini, kio okazas, kiam ŝi estas elsalutinta.
Rekonektoj ankaŭ ripetiĝas. Tekkomputilo, kiu dormas en trajno, povas produkti dekduon da konektaj eventoj en horo, kaj hoko, kiu ĉiufoje aldonas linion, transformas statan dosieron en protokolon, kiun neniu povas legi. Faru la agon idempotenta, aŭ lasu ĝin anstataŭigi unu rikordon ŝlositan laŭ sesio.
Fine, limigu la difuzradiuson en la unuo mem: nurlega dosiersistema vido aparte de la stata dosierujo, neniuj novaj privilegioj, kaj eksplicita tempolimo. La apartigo inter demono kaj uzanta ago valoras per si mem, sed ĝi valoras multe pli, kiam la ago povas fari nenion krom la unu afero, kiun vi aprobis.