Kabliukas veikia, kai paleidžiate jį rankiniu būdu kaip root, ir grąžina Operation not permitted tą akimirką, kai paslauga jį paleidžia. Failas tarp šių paleidimų nepasikeitė; pasikeitė aplinka. systemd duoda procesui mažesnį pasaulį: mažiau galimybių, kitokį /dev, tik skaitymui skirtus failų sistemos kelius ir užduočių lubas. Skaitykite gedimą kaip ribą, kuri atmetė vieną konkrečią operaciją, o ne kaip sudužusį scenarijų.

Pradėkite nuo operacijos, kuri buvo atmesta

Žurnalo eilutė, sakanti, kad unit nepavyko, beveik nieko nepasako. Naudinga eilutė įvardija iškvietimą, kuris buvo atmestas: įrenginio mazgas, kurio nepavyko atidaryti, katalogas, į kurį nepavyko įrašyti, vardų erdvė, kurios nepavyko sukurti. Raskite tą iškvietimą prieš paliesdami bent vieną direktyvą, nes kiekviena atitinka skirtingą apribojimą. Tada skaitykite unit, kuris iš tikrųjų veikė, įskaitant drop-in, o ne failą, kurį pateikė paketas.

Toliau pateikta užklausa išspausdina fragmento kelią, drop-in katalogus ir savybes, kurios svarbios atmetant įrenginį ar failų sistemą. Perskaitykite visas prieš nuspręsdami, kuri riba svarbi:

systemctl show "[email protected]" -p FragmentPath -p DropInPaths -p PrivateDevices -p DevicePolicy -p DeviceAllow -p ProtectHome -p ProtectSystem -p TasksMax
journalctl -u "[email protected]" -b --no-pager | grep -iE 'operation not permitted|permission denied|cannot open|failed'

Tame bloke nieko nerašoma. Jei atmesto iškvietimo žurnale nėra, vienam paleidimui padidinkite kliento išsamumą, o ne spėliokite direktyvas. Veikiantis procesas įrodo, kad unit paleistas, o ne kad kabliukas veikė su reikiamomis teisėmis.

Vardų erdvei reikia mount teisių, kurių TUN įrenginys niekada nenaudoja

Dvi operacijos, kurios viename kabliuke atrodo vienodai, turi skirtingus leidimų profilius. Atidarant /dev/net/tun ir kuriant sąsają reikia tinklo administravimo bei prieigos prie to mazgo. Pavadintos tinklo vardų erdvės kūrimas taip pat reikalauja mount darbo, nes vardų erdvės įrankis mountina naują /sys vaizdą ir pririša būsenos katalogą į jo vietą. pirminį kliento unit sąmoningai palieka mount administravimą už savo ribų rinkinio, todėl vardų erdvės žingsnis atmetamas, nors pats tunelis būtų veikęs.

Štai kodėl įrenginio mazgo suteikimas neišgelbsti scenarijaus. Įrenginio leidimas atsako į vieną klausimą, ar šis procesas gali atidaryti šį mazgą, o vardų erdvės klausimas yra kitas. Prieš ką nors plėsdami, priskirkite nepavykusį iškvietimą jo galimybei.

Testas jūsų shell paveldi visas galimybes, kurias turi neribotas root, o unit paveldi tai, ką išlaikė jo ribų rinkinys. Tie du paleidimai yra skirtingi eksperimentai net kai dvejetainis failas identiškas.

Įrenginiai, apsaugoti keliai ir užduočių lubos

Kai atmesta operacija žinoma, trys direktyvų grupės paaiškina daugumą gedimų. Prieigą prie įrenginių reguliuoja PrivateDevices, kuris pakeičia /dev minimaliu pseudoįrenginių rinkiniu, ir DevicePolicy su DeviceAllow, kurie nusprendžia, ką leidžia cgroup. /dev/net/tun nėra to minimalaus rinkinio dalis, todėl unit su PrivateDevices=yes negali jo atidaryti, ką bebūtų sakoma įrenginių politikoje.

Failų sistemos apsauga atsako į antrą klausimą. ProtectHome=yes padaro /home, /root ir /run/user neprieinamus, o ProtectSystem=full padaro /usr, /boot ir /etc tik skaitymui skirtais. Todėl kabliukas, kuris rašo šalia savo konfigūracijos failo, veikia jūsų shell ir žlunga po unit, su ta pačia leidimo forma kaip trūkstama galimybė. Perkelkite rašomą įvestį į kelią, kurį politika leidžia, arba pridėkite siaurą ReadWritePaths= įrašą.

Išteklių limitai yra trečioji grupė ir mažiausiai akivaizdi. TasksMax= riboja, kiek užduočių unit gali sukurti, o failų deskriptorių lubos elgiasi taip pat socket ir rankenų atžvilgiu. Diegimas, kuris išaugo virš lubų, žlunga su išteklių klaida, o ne su leidimo klaida, todėl tiksli žinutė vis dar svarbi.

Iškelkite vardų erdvės žingsnį iš kabliuko

Paruošimas, kuriam reikia privilegijos, kurios klientas neturi turėti, priklauso jo paties unit. Oneshot, kuris veikia prieš klientą, išsaugo savo rezultatą ir yra išdėstytas prieš ryšį, duoda vardų erdvės žingsniui tai, ko reikia, neperduodamas tų teisių tunelio procesui. Tada klientas nurodo tą unit, o ne kviečia scenarijų iš savo up kabliuko.

Žemiau pateiktas šablonas yra pradinė forma, o ne kažkas, ką taikote neperskaitę. Jis laiko paruošimą ten, kur gyvena privilegija, ir palieka tunelio unit neliestą:

# /etc/systemd/system/[email protected]
[Unit]
Description=Namespace preparation for %i
Before=openvpn-client@%i.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/netns-up.sh %i
CapabilityBoundingSet=CAP_NET_ADMIN CAP_SYS_ADMIN
[Install]
WantedBy=multi-user.target

Pridėkite tvarką su drop-in, o ne redaguokite supakuotą unit, kad atnaujinimas negalėtų tyliai numesti jūsų pakeitimo. Katalogas susietas su egzemplioriaus vardu, todėl antram profiliui reikia savo failo:

sudo mkdir -p /etc/systemd/system/[email protected]
sudo tee /etc/systemd/system/[email protected]/10-namespace.conf >/dev/null <<'CONF'
[Unit]
[email protected]
[email protected]
CONF
sudo systemctl daemon-reload

Pakartokite tą patį iškvietimą po pakeitimo

Taisymas patvirtinamas tik tada, kai tas pats iškvietimas duoda kitokį rezultatą. Paleiskite iš naujo abu unit, atlikite operaciją, kuri nepavyko, ir palyginkite jos rezultatą su žurnalo eilute, kurią išsaugojote prieš pakeitimą. Unit, kuris paleidžiamas, kai kabliukas niekada nebepaleidžiamas, nėra taisymas.

Žemiau pateikta seka išlaiko palyginimą sąžiningą, nes tikrina atmestą iškvietimą, o ne unit spalvą. Išsaugokite jos išvestį šalia žurnalo eilutės, kurią užfiksavote prieš pakeitimą:

sudo systemctl restart "[email protected]" "[email protected]"
systemctl status "[email protected]" --no-pager
journalctl -u "[email protected]" -b --no-pager | grep -c 'Operation not permitted'
ip -brief addr show tun0

Skaičiuokite atmetimus, o ne skaitykite paskutinę eilutę, nes kabliukas gali nepavykti, bandyti dar kartą ir pavykti, ir tik skaičius parodo, ar riba pasislinko. Palikite drop-in komentarą, kuriame nurodyta atlaisvinta direktyva ir priežastis, nes kitas atnaujinimas lygina jūsų konfigūraciją su supakuota numatytąja. Unit, kuris paleidžiamas tik išjungus visą apsaugą, nėra sutaisytas.

Susiję straipsniai