Unofficial
Op deze pagina
  1. 01Wat de jail biedt
  2. 02Voordat u begint
  3. 03Het profiel
  4. 04De blokken
  5. 05Bouwen, ondertekenen, installeren
  6. 06De afscherming controleren
  7. 07Stoppen, verwijderen en wat overblijft

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.

  1. Profielwat draait en wat het ziet
  2. Blokkenaccount, mappen, jail
  3. Bouwenbvs-jail en bwrap worden meegeleverd
  4. Ondertekenengeval 1, daarna installeren
  5. 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 NoNewPrivs ingesteld. Een seccomp-filter weigert mounts, nieuwe namespaces, kernelmodules, bpf, io_uring, ptrace en andere aanroepen die kernelexploits gebruiken.
  • Ze zien de app alleen-lezen, hun datamappen met lees- en schrijftoegang, eigen /tmp, /proc en /dev en 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.
  • app wordt 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.
  • services starten op volgorde. Een oneshot draait eerst helemaal af; wait_port wacht tot de dienst luistert voordat de volgende start. Minstens één dienst blijft draaien.
  • inbound stuurt poort 19975 van de NAS door naar interne poort 8080. egress biedt de diensten een proxy op 127.0.0.1:3128 voor poorten 80 en 443 van openbare adressen; een allow-lijst laat genoemde bestemmingen ongeacht hun adres door.
  • limits.memory_mb is standaard 2048; stop_seconds bepaalt 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.

Een blok toevoegen, groep The program: Create a group, Create an account, Owner and mode, Start the program, Start in a jail, Wait for a port, Wait for a socket
  1. Data folder on the volume, naam jailbox: de map $QPKG_DATA.
  2. Create an account, naam jailbox: het account uit het profiel.
  3. Create a folder, $QPKG_DATA/www, eigenaar jailbox:jailbox, modus 750: de enige map waarin de diensten schrijven.
  4. Start in a jail, ID jailbox, profiel $QPKG_ROOT/etc/jail/jailbox.json. De wachttijd bij stoppen moet minstens stop_seconds van het profiel plus 15 zijn; de standaardwaarde 90 volstaat hier. The Start in a jail block: ID jailbox, Profile $QPKG_ROOT/etc/jail/jailbox.json, Seconds to wait at stop 90, Restart it when it stops off, Undo it at stop on, and the lines it writes: qpkg_jail and, at stop, qpkg_daemon_stop with bin/bvs-jail
  5. 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.

Wijzigingen vastleggen: service.json met de startblokken en shared/jailbox.sh met de regels qpkg_data_dir, qpkg_user, qpkg_dir, qpkg_jail en qpkg_wait_port

05Bouwen, ondertekenen, installeren

Build op de projectpagina voert qbuild van QDK uit. Het log vermeldt welke onderdelen voor de jail in het pakket zitten.

Bouwlog: x86_64-pakket met bin/busybox, bin/chpst, share/busybox/, bin/bvs-jail, bin/bwrap en share/bubblewrap/; gebouwd: build/jailbox_0.1.0_x86_64.qpkg, zonder codehandtekening

Zonder certificaat wordt het pakket ongetekend gebouwd. De projectpagina vermeldt dat de testinstallatie en de repository een ondertekend pakket nodig hebben.

Projectpijplijn: Build voltooid; Test deploy vereist een pakket met codehandtekening; Publish: ongetekend, de repository accepteert alleen ondertekende pakketten
  1. Zet de certificaatbestanden certificate, private_key en ca_certs naast qpkg.cfg in de projectmap en bouw opnieuw: het pakket is dan ondertekend. De .gitignore van de sjabloon houdt de bestanden buiten git. In CI komen ze uit de secrets van de repository, zoals Uw eigen App Center laat zien.
  2. 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 .qpkg en de datamap. Geen gedeelde map, geen ander pakket.
  • In een SSH-sessie als admin toont grep -E '^(Uid|CapEff|NoNewPrivs|Seccomp):' /proc/<pid>/status voor de dienst hetzelfde. Ook de twee bubblewrap-processen die de jail van buiten bewaken hebben geen capabilities en hebben NoNewPrivs ingesteld, zonder het filter.
  • Het log van de jail staat als log/jailbox.log in 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 logt ended (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.