De dienst van uw pakket in een jail uitvoeren: eigen account, geen root, alleen het toegestane netwerk
Het dienstscript van een QPKG-pakket draait als root. Met het blok Start in a jail van de dienstenbouwer draaien de gestarte programma’s onder een eigen account in een sandbox: geen capabilities of mogelijkheid om die te krijgen, een filter voor gevaarlijke systeemaanroepen en een eigen netwerk. Het voorbeeld biedt een pagina aan die laat zien wat de sandbox toestaat.
- Profielwat draait en wat het ziet
- Blokkenaccount, mappen, jail
- Bouwenbvs-jail en bwrap worden meegeleverd
- Ondertekenengeval 1, daarna installeren
- Controlerende pagina beschrijft zijn omgeving
De afbeeldingen komen uit Bucket & Code Server IDE 1.0.0-49. Het voorbeeld is gebouwd, ondertekend, geïnstalleerd en gecontroleerd op een test-NAS met QTS 6.1. Het account heet ola.
01Wat de jail biedt
- De diensten draaien onder het account uit het profiel, nooit als root, zonder capabilities en met
NoNewPrivsingesteld. Een seccomp-filter weigert mounts, nieuwe namespaces, kernelmodules,bpf,io_uring,ptraceen andere aanroepen die kernelexploits gebruiken. - Ze zien de app alleen-lezen, hun datamappen met lees- en schrijftoegang, eigen
/tmp,/procen/deven de glibc van de NAS. Geen andere gedeelde map, geen/etc/config, geen ander pakket. - Hun netwerk heeft een eigen loopback. Elke
inbound-poort wordt van de NAS naar een interne poort doorgestuurd. Uitgaande verbindingen lopen via een HTTP-proxy die privéadressen, loopbackadressen en de eigen adressen van de NAS weigert. - Een geheugenlimiet, een CPU-gewicht en een proceslimiet gelden voor de hele jail.
Het pakket bevat de jail zelf: bin/bvs-jail en een statische bin/bwrap (bubblewrap), tijdens het bouwen voor elke architectuur klaargezet.
02Voordat u begint
- U hebt een met New project gemaakt QPKG-project nodig, QDK op de pagina Toolchains en de bouwomgeving Ubuntu 24.04. Uw eigen App Center beschrijft de inrichting; dit voorbeeld gebruikt de dienstsjabloon Empty.
- Een certificaat voor codeondertekening dat QNAP aan u heeft verstrekt, als bestanden. App Center installeert alleen ondertekende pakketten.
03Het profiel
Het profiel is een JSON-bestand van het pakket. Hier staat het in het project onder shared/etc/jail/jailbox.json; het pakket installeert het als etc/jail/jailbox.json in zijn installatiemap.
# 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@en@QPKG_DATA@staan voor de installatie- en datamap, waarvan de paden pas op de NAS bekend zijn. Bij elke start worden ze ingevuld in een kopie die alleen root kan wijzigen. De jail gebruikt die kopie. Onbekende sleutels worden geweigerd.appwordt alleen-lezen gekoppeld. Hier is dat de hele installatiemap, zodat diensten de eigen BusyBox van het pakket kunnen gebruiken; een echte app verwijst naar zijn eigen mappenstructuur, bijvoorbeeld@QPKG_ROOT@/app.servicesstarten op volgorde. Eenoneshotdraait eerst helemaal af;wait_portwacht tot de dienst luistert voordat de volgende start. Minstens één dienst blijft draaien.inboundstuurt poort 19975 van de NAS door naar interne poort 8080.egressbiedt de diensten een proxy op127.0.0.1:3128voor poorten 80 en 443 van openbare adressen; eenallow-lijst laat genoemde bestemmingen ongeacht hun adres door.limits.memory_mbis standaard 2048;stop_secondsbepaalt hoe lang de jail wacht tot zijn diensten stoppen.
De eerste dienst voert dit script uit, ook opgenomen in het pakket als shared/share/jailbox/checks.sh. Het schrijft wat de sandbox toestaat in de map die de tweede dienst aanbiedt.
#!/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"
04De blokken
Op de projectpagina, kaart Service and package, tabblad Blocks: gebruik Add a block onder At start vijf keer, in deze volgorde.
- Data folder on the volume, naam
jailbox: de map$QPKG_DATA. - Create an account, naam
jailbox: het account uit het profiel. - Create a folder,
$QPKG_DATA/www, eigenaarjailbox:jailbox, modus750: de enige map waarin de diensten schrijven. - Start in a jail, ID
jailbox, profiel$QPKG_ROOT/etc/jail/jailbox.json. De wachttijd bij stoppen moet minstensstop_secondsvan het profiel plus 15 zijn; de standaardwaarde 90 volstaat hier.
- Wait for a port,
19975: de start eindigt zodra de doorgestuurde poort antwoordt.
Onder At a status check controleren Is it running? met ID jailbox en Is the port open? met 19975 de jail voor de opdracht status van het dienstscript. Save toont de wijzigingen per bestand en Commit slaat ze op in de repository van het project.
05Bouwen, ondertekenen, installeren
Build op de projectpagina voert qbuild van QDK uit. Het log vermeldt welke onderdelen voor de jail in het pakket zitten.
Zonder certificaat wordt het pakket ongetekend gebouwd. De projectpagina vermeldt dat de testinstallatie en de repository een ondertekend pakket nodig hebben.
- Zet de certificaatbestanden
certificate,private_keyenca_certsnaastqpkg.cfgin de projectmap en bouw opnieuw: het pakket is dan ondertekend. De.gitignorevan de sjabloon houdt de bestanden buiten git. In CI komen ze uit de secrets van de repository, zoals Uw eigen App Center laat zien. - Installeer het ondertekende pakket via Test deploy op de projectpagina (admin), Install Manually in App Center of de eigen App Center-repository van uw NAS.
06De afscherming controleren
Open http://<NAS address>:19975/: via de doorgestuurde poort toont de pagina “Served from inside the jail.”. Het bestand checks.txt ernaast bevat de bevindingen van de eerste dienst:
# 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
- De volumemap bevat alleen de mappen van het pakket: de installatiemap onder
.qpkgen de datamap. Geen gedeelde map, geen ander pakket. - In een SSH-sessie als admin toont
grep -E '^(Uid|CapEff|NoNewPrivs|Seccomp):' /proc/<pid>/statusvoor de dienst hetzelfde. Ook de twee bubblewrap-processen die de jail van buiten bewaken hebben geen capabilities en hebbenNoNewPrivsingesteld, zonder het filter. - Het log van de jail staat als
log/jailbox.login de datamap: de start van elke dienst, zijn poort en het stoppen. Het vermeldt wanneer root eigenaar van de datamap is; diensten schrijven alleen in de map die het blok Create a folder aan het account gaf.
07Stoppen, verwijderen en wat overblijft
/etc/init.d/jailbox.sh stop, of stoppen in App Center, beëindigt de diensten in omgekeerde volgorde en de jail logtended (0). Er blijven geen processen van het account, cgroup of luisterende poort over.- Het verwijderen van het pakket stopt de jail en verwijdert de installatiemap en het dienstscript. Het account en de datamap blijven bestaan, omdat geen blok ze verwijdert; Your own shell lines onder At removal kan ook die verwijderen.
- De uitvoeringsmap van de jail,
/var/run/bvs-jail/jailbox, blijft staan tot de volgende start die herschrijft. Hij staat op het geheugenbestandssysteem van QTS en verdwijnt bij de volgende herstart.