Unofficial
På den här sidan
  1. 01Vad jailen ger
  2. 02Innan du börjar
  3. 03Profilen
  4. 04Blocken
  5. 05Bygg, signera, installera
  6. 06Kontrollera avskärmningen
  7. 07Stopp, borttagning och det som blir kvar

Kör paketets tjänst i en jail: eget konto, utan root, bara det nätverk du tillåter

Ett QPKG-pakets tjänsteskript körs som root. Med tjänstbyggarens block Start in a jail körs programmen det startar under ett eget konto i en sandlåda: inga capabilities, ingen möjlighet att få dem, ett filter för farliga systemanrop och ett eget nätverk. Exemplet visar en webbsida som redovisar vad sandlådan tillåter.

  1. Profilvad som körs och vad det ser
  2. Blockkonto, mappar, jail
  3. Byggbvs-jail och bwrap följer med
  4. Signerafall 1, installera sedan
  5. Kontrollerasidan beskriver sin miljö

Bilderna kommer från Bucket & Code Server IDE 1.0.0-49. Exemplet byggdes, signerades, installerades och kontrollerades på en test-NAS med QTS 6.1. Kontot heter ola.

01Vad jailen ger

  • Tjänsterna körs under kontot i profilen, aldrig som root, utan capabilities och med NoNewPrivs satt. Ett seccomp-filter nekar monteringar, nya namnrymder, kärnmoduler, bpf, io_uring, ptrace och andra anrop som kärnexploits använder.
  • De ser appen skrivskyddad, sina datamappar läs- och skrivbara, egna /tmp, /proc och /dev samt NAS:ens glibc. Ingen annan delad mapp, ingen /etc/config, inget annat paket.
  • Nätverket har en egen loopback. Varje inbound-port vidarebefordras från NAS:en till en intern port. Utgående anslutningar går genom en HTTP-proxy som nekar privata adresser, loopbackadresser och NAS:ens egna adresser.
  • En minnesgräns, en CPU-vikt och en processgräns gäller för hela jailen.

Paketet innehåller själva jailen: bin/bvs-jail och en statisk bin/bwrap (bubblewrap), som byggsteget förbereder för varje arkitektur.

02Innan du börjar

  • Du behöver ett QPKG-projekt skapat med New project, QDK på sidan Toolchains och byggmiljön Ubuntu 24.04. Eget App Center beskriver installationen; exemplet använder tjänstemallen Empty.
  • Ett kodsigneringscertifikat som QNAP har utfärdat till dig, som filer. App Center installerar bara signerade paket.

03Profilen

Profilen är en JSON-fil i paketet. Här ligger den som shared/etc/jail/jailbox.json i projektet, och paketet installerar den som etc/jail/jailbox.json i installationsmappen.

# 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@ och @QPKG_DATA@ står för installations- och datamapparna, vars sökvägar blir kända först på NAS:en. Varje start skriver in dem i en kopia som bara root kan ändra; jailen använder kopian. Okända nycklar nekas.
  • app monteras skrivskyddad. Här är det hela installationsmappen, så tjänsterna kan använda paketets egen BusyBox; en riktig app pekar på sitt eget katalogträd, till exempel @QPKG_ROOT@/app.
  • services startar i ordning. En oneshot körs först färdigt; wait_port väntar tills tjänsten lyssnar innan nästa startar. Minst en tjänst fortsätter att köras.
  • inbound vidarebefordrar NAS:ens port 19975 till port 8080 inuti. egress ger tjänsterna en proxy på 127.0.0.1:3128 för portarna 80 och 443 på offentliga adresser; en allow-lista släpper igenom namngivna mål oavsett adress.
  • limits.memory_mb är 2048 om du inte anger något annat; stop_seconds är hur länge jailen väntar på att tjänsterna ska stanna.

Den första tjänsten kör detta skript, som också ingår i paketet som shared/share/jailbox/checks.sh. Det skriver vad sandlådan tillåter i mappen som den andra tjänsten visar.

#!/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"

04Blocken

På projektsidan, kortet Service and package, fliken Blocks: använd Add a block under At start fem gånger, i denna ordning.

Lägg till ett block, gruppen 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, namn jailbox: mappen $QPKG_DATA.
  2. Create an account, namn jailbox: kontot i profilen.
  3. Create a folder, $QPKG_DATA/www, ägare jailbox:jailbox, läge 750: den enda mapp tjänsterna skriver till.
  4. Start in a jail, ID jailbox, profil $QPKG_ROOT/etc/jail/jailbox.json. Väntetiden vid stopp måste vara minst profilens stop_seconds plus 15; standardvärdet 90 räcker här. 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: starten slutförs när den vidarebefordrade porten svarar.

Under At a status check gör Is it running? med ID jailbox och Is the port open? med 19975 att tjänsteskriptets kommando status kontrollerar jailen. Save visar varje fils ändringar och Commit sparar dem i projektets arkiv.

Bekräfta ändringarna: service.json med startblocken och shared/jailbox.sh med raderna qpkg_data_dir, qpkg_user, qpkg_dir, qpkg_jail och qpkg_wait_port

05Bygg, signera, installera

Build på projektsidan kör QDK:s qbuild. Loggen anger vad paketet innehåller för jailen.

Byggloggen: x86_64-paket med bin/busybox, bin/chpst, share/busybox/, bin/bvs-jail, bin/bwrap och share/bubblewrap/; byggt: build/jailbox_0.1.0_x86_64.qpkg, utan kodsignatur

Utan certifikat byggs paketet osignerat. Projektsidan anger att testinstallation och arkivet kräver ett signerat paket.

Projektets pipeline: Build klart; Test deploy kräver ett kodsignerat paket; Publish: osignerat, arkivet tar bara emot signerade paket
  1. Lägg certifikatfilerna certificate, private_key och ca_certs bredvid qpkg.cfg i projektmappen och bygg igen: paketet blir signerat. Mallens .gitignore håller filerna utanför git. I CI kommer de från arkivets hemligheter, som Eget App Center visar.
  2. Installera det signerade paketet: Test deploy på projektsidan (admin), Install Manually i App Center eller NAS:ens eget App Center-arkiv.

06Kontrollera avskärmningen

Öppna http://<NAS address>:19975/: sidan visar ”Served from inside the jail.” via den vidarebefordrade porten. Filen checks.txt bredvid sidan innehåller den första tjänstens resultat:

# 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
  • Volymmappen innehåller bara paketets egna mappar: installationsmappen under .qpkg och datamappen. Ingen delad mapp, inget annat paket.
  • I en SSH-session som admin visar grep -E '^(Uid|CapEff|NoNewPrivs|Seccomp):' /proc/<pid>/status för tjänsten samma sak. De två bubblewrap-processerna som bevakar jailen utifrån saknar också capabilities och har NoNewPrivs satt, utan filtret.
  • Jailens logg är log/jailbox.log i datamappen: varje tjänsts start, dess port och stoppet. Loggen anger när datamappen tillhör root; tjänsterna skriver bara i mappen som blocket Create a folder gav kontot.

07Stopp, borttagning och det som blir kvar

  • /etc/init.d/jailbox.sh stop, eller stopp i App Center, avslutar tjänsterna i omvänd ordning och jailen loggar ended (0). Ingen process för kontot, cgroup eller lyssnande port blir kvar.
  • När paketet tas bort stoppas jailen och installationsmappen samt tjänsteskriptet tas bort. Kontot och datamappen blir kvar eftersom inget block tar bort dem; Your own shell lines under At removal kan ta bort även dem.
  • Jailens körmapp, /var/run/bvs-jail/jailbox, finns kvar tills nästa start skriver om den. Den ligger på QTS:s minnesfilsystem och försvinner vid nästa omstart.