Kako otkriti koja je systemd sandbox odbila vaš OpenVPN hook
Hook radi kao root, a pod systemd-om pada jer unit zadržava manje sposobnosti, manji /dev i staze samo za čitanje.
Hook radi kada ga pokrenete ručno kao root i vraća Operation not permitted u trenutku kada ga servis pokrene. Datoteka se između tih pokretanja nije promijenila; okruženje jest. systemd daje procesu manji svijet: manje sposobnosti, drugačiji /dev, staze datotečnog sistema samo za čitanje i plafon zadataka. Čitajte neuspjeh kao granicu koja je odbila jednu konkretnu operaciju, a ne kao skriptu koja se pokvarila.
Krenite od operacije koja je odbijena
Linija dnevnika koja kaže da je unit pao ne govori vam gotovo ništa. Korisna linija imenuje poziv koji je odbijen: čvor uređaja koji se nije mogao otvoriti, direktorij u koji se nije moglo pisati, imenski prostor koji se nije mogao stvoriti. Nađite taj poziv prije nego što dotaknete i jednu direktivu, jer svaka odgovara drugom ograničenju. Zatim čitajte unit koji je zaista radio, uključujući drop-in datoteke, a ne datoteku koju je paket isporučio.
Upit ispod ispisuje putanju fragmenta, direktorije za drop-in i svojstva koja su važna za odbijanje uređaja ili datotečnog sistema. Pročitajte ih sve prije nego što odlučite koja je granica relevantna:
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'Ništa u tom bloku ne piše. Ako odbijeni poziv nedostaje u dnevniku, podignite detaljnost klijenta za jedno pokretanje umjesto da nagađate direktive. Proces koji radi dokazuje da je unit startovao, a ne da je hook radio s privilegijama koje su mu trebale.
Imenski prostor traži prava montiranja koja TUN uređaj nikada ne koristi
Dvije operacije koje unutar jednog hooka izgledaju isto imaju različite profile dozvola. Otvaranje /dev/net/tun i stvaranje interfejsa traži mrežnu administraciju plus pristup tom čvoru. Stvaranje imenovanog mrežnog imenskog prostora također traži rad na montiranju, jer alat za imenske prostore montira svjež /sys pogled i veže direktorij stanja na mjesto. klijentski unit uzvodno namjerno ostavlja administraciju montiranja izvan svog skupa granica, pa se korak s imenskim prostorom odbija dok bi sam tunel radio.
Zato davanje čvora uređaja ne spašava skriptu. Dozvola za uređaj odgovara na jedno pitanje, smije li ovaj proces otvoriti ovaj čvor, a pitanje imenskog prostora je drugo. Uparite poziv koji pada s njegovom sposobnošću prije nego što bilo šta proširite.
Test u vašem shellu nasljeđuje svaku sposobnost koju ima neograničeni root, a unit nasljeđuje ono što je njegov skup granica zadržao. Ta dva pokretanja su različiti eksperimenti čak i kada je binarna datoteka identična.
Uređaji, zaštićene staze i plafoni zadataka
Kada je odbijena operacija poznata, tri grupe direktiva objašnjavaju većinu padova. Pristup uređajima uređuje PrivateDevices, koji zamjenjuje /dev minimalnim skupom pseudo-uređaja, i DevicePolicy sa DeviceAllow, koji odlučuju šta cgroup dopušta. /dev/net/tun nije dio tog minimalnog skupa, pa unit sa PrivateDevices=yes ne može ga otvoriti šta god kaže politika uređaja.
Zaštita datotečnog sistema odgovara na drugo pitanje. ProtectHome=yes čini /home, /root i /run/user nedostupnima, a ProtectSystem=full čini /usr, /boot i /etc samo za čitanje. Zato hook koji piše pored svoje konfiguracijske datoteke radi u vašem shellu i pada pod unitom, s istim oblikom dozvole kao nedostajuća sposobnost. Premjestite upisni ulaz na stazu koju politika dopušta ili dodajte uski ReadWritePaths= zapis.
Ograničenja resursa su treća grupa i najmanje očigledna. TasksMax= ograničava koliko zadataka unit smije stvoriti, a plafon datotečnih deskriptora ponaša se isto za sockete i ručke. Implementacija koja je prerasla plafon pada s greškom resursa, a ne s greškom dozvole, i zato je tačna poruka još uvijek važna.
Izmjestite korak s imenskim prostorom iz hooka
Priprema koja traži privilegiju koju klijent ne smije imati pripada u vlastiti unit. Oneshot koji radi prije klijenta, čuva svoj rezultat i poredan je prije veze daje koraku s imenskim prostorom ono što mu treba, bez predaje tih prava procesu tunela. Klijent se zatim referira na taj unit umjesto da zove skriptu iz svog up hooka.
Šablon ispod je početni oblik, a ne nešto što se primjenjuje nepročitano. Čuva pripremu tamo gdje privilegija živi i ostavlja unit tunela netaknutim:
# /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.targetDodajte redoslijed drop-inom umjesto uređivanja pakiranog unita, da nadogradnja ne može tiho odbaciti vašu promjenu. Direktorij je vezan za ime instance, pa drugi profil treba vlastitu datoteku:
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-reloadPonovite isti poziv nakon promjene
Popravka je potvrđena samo kada isti poziv daje drugačiji rezultat. Restartujte oba unita, izvršite operaciju koja je pala i uporedite njen ishod s linijom dnevnika koju ste sačuvali prije promjene. Unit koji startuje dok hook više ne radi nije popravka.
Slijed ispod čuva poređenje iskrenim, jer provjerava odbijeni poziv, a ne boju unita. Sačuvajte njegov izlaz pored linije dnevnika koju ste uhvatili prije promjene:
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 tun0Brojite odbijanja umjesto da čitate posljednju liniju, jer hook može pasti, pokušati ponovo i uspjeti, i samo broj pokazuje je li se granica pomjerila. Ostavite komentar u drop-inu koji imenuje direktivu koju ste olabavili i razlog, jer sljedeća nadogradnja poredi vašu konfiguraciju s pakiranim zadanim vrijednostima. Unit koji startuje samo nakon što je svaka zaštita isključena nije popravljen.