Unofficial
Na tej stronie
  1. 01Co zapewnia jail
  2. 02Zanim zaczniesz
  3. 03Profil
  4. 04Bloki
  5. 05Budowanie, podpisanie, instalacja
  6. 06Sprawdzenie izolacji
  7. 07Zatrzymanie, usunięcie i pozostawione dane

Uruchom usługę swojego pakietu w jailu: osobne konto, bez roota, tylko dozwolona sieć

Skrypt usługi pakietu QPKG działa jako root. Blok Start in a jail w edytorze usług uruchamia programy na osobnym koncie w piaskownicy: bez capabilities i możliwości ich uzyskania, z filtrem niebezpiecznych wywołań systemowych oraz własną siecią. Przykład udostępnia stronę, która pokazuje, na co pozwala piaskownica.

  1. Profilco działa i co widzi
  2. Blokikonto, katalogi, jail
  3. Budowaniebvs-jail i bwrap w pakiecie
  4. Podpisanieprzypadek 1, potem instalacja
  5. Sprawdzeniestrona opisuje swoje środowisko

Ilustracje pochodzą z Bucket & Code Server IDE 1.0.0-49. Przykład zbudowano, podpisano, zainstalowano i sprawdzono na testowym NAS-ie z QTS 6.1. Konto nazywa się ola.

01Co zapewnia jail

  • Usługi działają na koncie wskazanym w profilu, nigdy jako root, bez capabilities i z ustawionym NoNewPrivs. Filtr seccomp odrzuca montowanie, nowe przestrzenie nazw, moduły jądra, bpf, io_uring, ptrace i inne wywołania wykorzystywane przez exploity jądra.
  • Widzą aplikację tylko do odczytu, własne katalogi danych do odczytu i zapisu, prywatne /tmp, /proc oraz /dev, a także glibc NAS-a. Żadnego innego udziału, żadnego /etc/config, żadnego innego pakietu.
  • Ich sieć ma własny interfejs loopback. Każdy port inbound jest przekierowany z NAS-a na port wewnętrzny. Połączenia wychodzące przechodzą przez proxy HTTP, które odrzuca adresy prywatne, loopback i własne adresy NAS-a.
  • Limit pamięci, udział CPU i limit procesów obejmują cały jail.

Pakiet zawiera sam jail: bin/bvs-jail i statyczny bin/bwrap (bubblewrap), przygotowywane podczas budowania dla każdej architektury.

02Zanim zaczniesz

  • Potrzebne są projekt QPKG utworzony przez New project, QDK na stronie Toolchains i środowisko budowania Ubuntu 24.04. Ich konfigurację opisuje Własne App Center; ten przykład korzysta z szablonu usługi Empty.
  • Certyfikat podpisywania kodu wydany Ci przez QNAP, w postaci plików. App Center instaluje tylko podpisane pakiety.

03Profil

Profil to plik JSON należący do pakietu. Tutaj znajduje się w projekcie pod shared/etc/jail/jailbox.json; pakiet instaluje go jako etc/jail/jailbox.json w swoim katalogu instalacyjnym.

# 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@ i @QPKG_DATA@ oznaczają katalog instalacyjny i katalog danych, których ścieżki są znane dopiero na NAS-ie. Każdy start wpisuje je do kopii, którą może zmieniać tylko root. Jail używa tej kopii. Nieznane klucze są odrzucane.
  • app jest montowane tylko do odczytu. Tutaj to cały katalog instalacyjny, aby usługi mogły używać BusyBoxa z pakietu; rzeczywista aplikacja wskazuje własne drzewo, na przykład @QPKG_ROOT@/app.
  • services startują po kolei. Najpierw oneshot wykonuje się do końca; wait_port czeka, aż usługa zacznie nasłuchiwać, zanim ruszy następna. Co najmniej jedna usługa działa stale.
  • inbound przekierowuje port 19975 NAS-a na wewnętrzny port 8080. egress udostępnia usługom proxy pod 127.0.0.1:3128 dla portów 80 i 443 adresów publicznych; lista allow przepuszcza wskazane cele niezależnie od ich adresu.
  • limits.memory_mb domyślnie wynosi 2048; stop_seconds określa, jak długo jail czeka na zatrzymanie usług.

Pierwsza usługa uruchamia ten skrypt, również zawarty w pakiecie jako shared/share/jailbox/checks.sh. Zapisuje wyniki sprawdzania piaskownicy w katalogu udostępnianym przez drugą usługę.

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

04Bloki

Na stronie projektu, karta Service and package, zakładka Blocks: użyj Add a block pod At start pięć razy, w tej kolejności.

Dodawanie bloku, grupa 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, nazwa jailbox: katalog $QPKG_DATA.
  2. Create an account, nazwa jailbox: konto wskazane w profilu.
  3. Create a folder, $QPKG_DATA/www, właściciel jailbox:jailbox, tryb 750: jedyny katalog, do którego usługi zapisują.
  4. Start in a jail, ID jailbox, profil $QPKG_ROOT/etc/jail/jailbox.json. Czas oczekiwania przy zatrzymaniu musi wynosić co najmniej stop_seconds z profilu plus 15; domyślne 90 wystarcza. 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: start kończy się, gdy przekierowany port odpowie.

Pod At a status check bloki Is it running? z ID jailbox i Is the port open? z 19975 sprawiają, że polecenie status skryptu usługi sprawdza jail. Save pokazuje różnice każdego pliku, a Commit zapisuje je w repozytorium projektu.

Zatwierdzanie zmian: service.json z blokami startowymi oraz shared/jailbox.sh z wierszami qpkg_data_dir, qpkg_user, qpkg_dir, qpkg_jail i qpkg_wait_port

05Budowanie, podpisanie, instalacja

Build na stronie projektu uruchamia qbuild z QDK. Log wymienia składniki jaila zawarte w pakiecie.

Log budowania: pakiet x86_64 zawiera bin/busybox, bin/chpst, share/busybox/, bin/bvs-jail, bin/bwrap i share/bubblewrap/; zbudowano build/jailbox_0.1.0_x86_64.qpkg, bez podpisu kodu

Bez certyfikatu pakiet jest budowany bez podpisu, a strona projektu informuje, że wdrożenie testowe i repozytorium wymagają podpisanego pakietu.

Potok projektu: Build zakończony; Test deploy wymaga podpisanego pakietu; Publish: bez podpisu, repozytorium przyjmuje tylko podpisane pakiety
  1. Umieść pliki certyfikatu certificate, private_key i ca_certs obok qpkg.cfg w katalogu projektu i zbuduj ponownie: pakiet będzie podpisany. Plik .gitignore z szablonu wyklucza je z gita. W CI pochodzą z sekretów repozytorium, jak opisuje Własne App Center.
  2. Zainstaluj podpisany pakiet przez Test deploy na stronie projektu (admin), Install Manually w App Center albo własne repozytorium App Center na NAS-ie.

06Sprawdzenie izolacji

Otwórz http://<NAS address>:19975/: strona wyświetla „Served from inside the jail.” przez przekierowany port. Plik checks.txt obok niej zawiera wyniki pierwszej usługi:

# 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
  • Katalog woluminu zawiera tylko katalogi pakietu: instalacyjny pod .qpkg i katalog danych. Żadnego udziału ani innego pakietu.
  • W sesji SSH jako admin polecenie grep -E '^(Uid|CapEff|NoNewPrivs|Seccomp):' /proc/<pid>/status dla usługi pokazuje to samo. Dwa procesy bubblewrap nadzorujące jail z zewnątrz także nie mają capabilities i mają ustawione NoNewPrivs, ale bez filtra.
  • Log jaila to log/jailbox.log w katalogu danych: start każdej usługi, jej port i zatrzymanie. Log odnotowuje, gdy katalog danych należy do roota; usługi zapisują tylko w katalogu przydzielonym kontu przez blok Create a folder.

07Zatrzymanie, usunięcie i pozostawione dane

  • /etc/init.d/jailbox.sh stop lub zatrzymanie w App Center kończy usługi w odwrotnej kolejności, a jail zapisuje ended (0) w logu. Nie pozostaje żaden proces konta, cgroup ani port nasłuchujący.
  • Usunięcie pakietu zatrzymuje jail i usuwa katalog instalacyjny oraz skrypt usługi. Konto i katalog danych pozostają, ponieważ żaden blok ich nie usuwa: Your own shell lines pod At removal może usunąć również je.
  • Katalog uruchomieniowy jaila, /var/run/bvs-jail/jailbox, pozostaje do następnego startu, który go nadpisuje. Znajduje się w pamięciowym systemie plików QTS i znika przy ponownym uruchomieniu NAS-a.