Spusťte službu svého balíčku v jailu: vlastní účet, bez roota, jen povolená síť
Skript služby balíčku QPKG běží jako root. S blokem Start in a jail v editoru služeb běží spouštěné programy pod vlastním účtem v sandboxu: bez capabilities a možnosti je získat, s filtrem nebezpečných systémových volání a s vlastní sítí. Příklad poskytuje stránku, která ukazuje, co sandbox dovoluje.
- Profilco běží a co vidí
- Blokyúčet, složky, jail
- Sestaveníbvs-jail a bwrap jsou součástí
- Podepsánípřípad 1, pak instalace
- Kontrolastránka popisuje své prostředí
Obrázky pocházejí z Bucket & Code Server IDE 1.0.0-49. Příklad byl sestaven, podepsán, nainstalován a ověřen na testovacím NASu s QTS 6.1. Účet se jmenuje ola.
01Co jail poskytuje
- Služby běží pod účtem uvedeným v profilu, nikdy jako root, bez capabilities a s nastaveným
NoNewPrivs. Filtr seccomp odmítá připojování souborových systémů, nové jmenné prostory, moduly jádra,bpf,io_uring,ptracea další volání využívaná exploity jádra. - Vidí aplikaci jen pro čtení, své datové složky pro čtení i zápis, vlastní
/tmp,/proca/deva glibc NASu. Žádnou jinou sdílenou složku, žádné/etc/config, žádný jiný balíček. - Jejich síť má vlastní loopback. Každý port
inboundse přeposílá z NASu na vnitřní port. Odchozí spojení procházejí HTTP proxy, která odmítá soukromé adresy, loopback a vlastní adresy NASu. - Limit paměti, váha CPU a limit procesů platí pro celý jail.
Balíček obsahuje samotný jail: bin/bvs-jail a statický bin/bwrap (bubblewrap), připravené při sestavení pro každou architekturu.
02Než začnete
- Potřebujete projekt QPKG vytvořený přes New project, QDK na stránce Toolchains a prostředí pro sestavení Ubuntu 24.04. Jejich nastavení popisuje Vlastní App Center; příklad používá šablonu služby Empty.
- Certifikát pro podepisování kódu, který vám vystavil QNAP, ve formě souborů. App Center instaluje pouze podepsané balíčky.
03Profil
Profil je soubor JSON v balíčku. Zde je v projektu uložen jako shared/etc/jail/jailbox.json; balíček ho nainstaluje jako etc/jail/jailbox.json do své instalační složky.
# shared/etc/jail/jailbox.json
{
"name": "jailbox",
"user": "jailbox",
"app": "@QPKG_ROOT@",
"data": ["@QPKG_DATA@"],
"services": [
{"name": "checks", "cmd": ["@QPKG_ROOT@/bin/busybox", "sh", "@QPKG_ROOT@/share/jailbox/checks.sh", "@QPKG_ROOT@", "@QPKG_DATA@"], "oneshot": true},
{"name": "web", "cmd": ["@QPKG_ROOT@/bin/busybox", "httpd", "-f", "-p", "127.0.0.1:8080", "-h", "@QPKG_DATA@/www"], "wait_port": 8080}
],
"inbound": [{"listen": "0.0.0.0:19975", "port": 8080}],
"egress": {},
"limits": {"memory_mb": 256},
"stop_seconds": 10
}
@QPKG_ROOT@a@QPKG_DATA@zastupují instalační a datovou složku, jejichž cesty jsou známé až na NASu. Každé spuštění je doplní do kopie, kterou může měnit jen root. Jail používá tuto kopii. Neznámé klíče jsou odmítnuty.appse připojuje jen pro čtení. Zde jde o celou instalační složku, aby služby mohly používat BusyBox z balíčku; skutečná aplikace odkazuje na svůj vlastní strom, například@QPKG_ROOT@/app.servicesse spouštějí postupně. Nejprve doběhneoneshot;wait_portčeká, až služba začne naslouchat, a pak spustí další. Alespoň jedna služba zůstává spuštěná.inboundpřeposílá port 19975 NASu na vnitřní port 8080.egressposkytuje službám proxy na127.0.0.1:3128pro porty 80 a 443 veřejných adres; seznamallowpropouští pojmenované cíle bez ohledu na jejich adresu.limits.memory_mbmá výchozí hodnotu 2048;stop_secondsurčuje, jak dlouho jail čeká na ukončení služeb.
První služba spouští tento skript, který je také součástí balíčku jako shared/share/jailbox/checks.sh. Zapisuje výsledky kontroly sandboxu do složky poskytované druhou službou.
#!/bin/sh # Runs inside the jail and writes what the sandbox allows into the page folder. R=$1 D=$2 B=$R/bin/busybox V=$($B dirname "$D") { $B grep -E '^(Uid|CapEff|NoNewPrivs|Seccomp):' /proc/self/status if $B touch "$R/probe" 2>/dev/null; then echo 'write the install folder: allowed'; else echo 'write the install folder: refused'; fi if $B ls /etc/config >/dev/null 2>&1; then echo 'read /etc/config: allowed'; else echo 'read /etc/config: refused'; fi echo "what $V holds here: $($B ls -A "$V" | $B tr '\n' ' ')" echo "network interfaces: $($B tail -n +3 /proc/net/dev | $B cut -d: -f1 | $B tr -d ' ' | $B tr '\n' ' ')" } >"$D/www/checks.txt" echo 'Served from inside the jail.' >"$D/www/index.html"
04Bloky
Na stránce projektu, karta Service and package, záložka Blocks: použijte Add a block pod At start pětkrát v tomto pořadí.
- Data folder on the volume, název
jailbox: složka$QPKG_DATA. - Create an account, název
jailbox: účet uvedený v profilu. - Create a folder,
$QPKG_DATA/www, vlastníkjailbox:jailbox, režim750: jediná složka, do níž služby zapisují. - Start in a jail, ID
jailbox, profil$QPKG_ROOT/etc/jail/jailbox.json. Čekání při zastavení musí trvat alespoň hodnotustop_secondsz profilu plus 15; výchozích 90 zde stačí.
- Wait for a port,
19975: spuštění skončí, jakmile přeposílaný port odpoví.
Pod At a status check bloky Is it running? s ID jailbox a Is the port open? s 19975 zajistí kontrolu jailu příkazem status skriptu služby. Save zobrazí rozdíly každého souboru a Commit je uloží do repozitáře projektu.
05Sestavení, podepsání, instalace
Build na stránce projektu spustí qbuild z QDK. Log uvádí součásti jailu přibalené do balíčku.
Bez certifikátu se balíček sestaví nepodepsaný a stránka projektu upozorní, že testovací nasazení a repozitář vyžadují podepsaný balíček.
- Umístěte soubory certifikátu
certificate,private_keyaca_certsvedleqpkg.cfgve složce projektu a sestavte znovu: balíček bude podepsaný. Soubor.gitignoreze šablony je vyloučí z gitu. V CI pocházejí z tajných hodnot repozitáře, jak popisuje Vlastní App Center. - Podepsaný balíček nainstalujte přes Test deploy na stránce projektu (admin), Install Manually v App Center nebo vlastní repozitář App Center na NASu.
06Ověření izolace
Otevřete http://<NAS address>:19975/: stránka přes přeposílaný port zobrazí „Served from inside the jail.“. Vedlejší soubor checks.txt obsahuje zjištění první služby:
# http://192.168.1.20:19975/checks.txt
Uid: 222 222 222 222
CapEff: 0000000000000000
NoNewPrivs: 1
Seccomp: 2
write the install folder: refused
read /etc/config: refused
what /share/CACHEDEV1_DATA holds here: .qpkg jailbox
network interfaces: lo
- Složka svazku obsahuje jen složky balíčku: instalační pod
.qpkga datovou složku. Žádnou sdílenou složku ani jiný balíček. - V relaci SSH jako admin ukáže
grep -E '^(Uid|CapEff|NoNewPrivs|Seccomp):' /proc/<pid>/statuspro službu totéž. Dva procesy bubblewrap, které jail hlídají zvenčí, také nemají capabilities a mají nastavenéNoNewPrivs, ale bez filtru. - Log jailu je
log/jailbox.logv datové složce: spuštění každé služby, její port a zastavení. Log zaznamená, když datová složka patří rootovi; služby zapisují jen do složky přidělené účtu blokem Create a folder.
07Zastavení, odstranění a zbývající data
/etc/init.d/jailbox.sh stopnebo zastavení v App Center ukončí služby v opačném pořadí a jail zapíšeended (0)do logu. Nezůstane žádný proces účtu, cgroup ani naslouchající port.- Odstranění balíčku zastaví jail a smaže instalační složku i skript služby. Účet a datová složka zůstanou, protože je žádný blok neodstraňuje: Your own shell lines pod At removal může odstranit i je.
- Běhová složka jailu,
/var/run/bvs-jail/jailbox, zůstane do příštího spuštění, které ji přepíše. Leží v paměťovém souborovém systému QTS a při příštím restartu zmizí.