Bazy leżą na udziale osiągalnym z całej sieci — to najkrótsza droga do wycieku, z pominięciem logowania, limitów, audytu i canary. Runbook zawęża udział `astrololo` do trzech węzłów k3s, ustawia tylko odczyt i root_squash. Krok po kroku, komenda po komendzie: rozpoznanie → dowód dziury (montowanie z maszyny spoza klastra) → kopia konfiguracji → zmiana → cztery testy weryfikacyjne → ścieżka wycofania. Dwie zasady wynikające z tego, że Tank1 obsługuje CAŁY homelab (Proxmox, conjurer z zapisem, media, LXC-e, stacja robocza): - ruszamy WYŁĄCZNIE udział astrololo, nigdy globalnych ustawień usługi NFS — inaczej padną VM-y, bot i biblioteka mediów; - w TrueNAS SCALE nie edytuje się /etc/exports ręcznie (middleware nadpisze) — wszystko przez midclt albo GUI. Runbook każe też sprawdzić nazwy pól w API PRZED zapisem, bo middleware zmieniało je między wersjami SCALE (path vs paths). Opisane pułapki: hookscript Proxmoxa czekający na showmount przed startem VM; utrata możliwości wgrywania baz przez NFS po ro=true; lista IP to nie uwierzytelnianie (docelowo NFSv4+Kerberos, jak mówi samo wymaganie). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.5 KiB
DAN-25 — zamknięcie dostępu do baz na NFS (TrueNAS SCALE)
Bazy interpretacyjne leżą na 192.168.1.34:/mnt/Tank1/astrololo. Dziś udział jest
osiągalny z całej sieci, więc kto ma dostęp do LAN, bierze kompletne bazy
w oryginale — z pominięciem logowania, limitów, audytu i canary. Żadne
zabezpieczenie w kodzie tego nie zamyka: to najkrótsza droga do wycieku.
Cel: udział astrololo widoczny tylko dla trzech węzłów k3s, tylko do
odczytu, z root_squash.
⚠️ Zasada nadrzędna: ruszamy WYŁĄCZNIE udział astrololo
Tank1 obsługuje cały homelab — Proxmox (proxmox-NFS), conjurera (conjurer_swap,
z zapisem), media, LXC-e, stację roboczą. Nie dotykamy globalnych ustawień
usługi NFS ani innych udziałów — inaczej wywalimy VM-y, bota i bibliotekę mediów.
Każda komenda niżej celuje w jeden konkretny udział.
Druga zasada: w TrueNAS SCALE nie edytuje się /etc/exports ręcznie. Plik
generuje middleware i nadpisze każdą ręczną zmianę. Wszystko robimy przez midclt
(albo GUI: Shares → Unix (NFS) Shares).
Ustalone dane
| Co | Wartość |
|---|---|
| NAS | 192.168.1.34 (TrueNAS SCALE / Community Edition) |
| Udział do zamknięcia | /mnt/Tank1/astrololo |
| Węzły k3s (jedyni uprawnieni) | 192.168.1.73 (server), 192.168.1.80 (agent2), 192.168.1.81 (agent1) |
| Kto montuje astrololo | wyłącznie pod data w ns astrololo, read-only |
Faza 0 — rozpoznanie (nic nie zmienia)
ssh admin@192.168.1.34
Wersja systemu (potwierdza, że komendy niżej pasują):
midclt call system.version
Lista udziałów NFS z ich obecnymi ustawieniami — stąd bierzemy ID udziału astrololo:
midclt call sharing.nfs.query | python3 -m json.tool
W wyniku poszukaj wpisu ze ścieżką
/mnt/Tank1/astrololoi zapamiętaj jegoid. Sprawdź też, jak nazywają się pola (pathvspaths,hosts,networks,ro,maproot_user,mapall_user) — middleware zmieniało ich nazwy między wersjami SCALE. Dalsze komendy używają nazw z Twojego wyniku.
Kto jest teraz podłączony (żeby nie odciąć czegoś w trakcie pracy):
ss -tn state established '( sport = :2049 )'
Faza 1 — dowód dziury (zrób PRZED zmianą)
Na stacji roboczej (Mac mini, czyli host spoza klastra):
mkdir -p /tmp/nfs-test && sudo mount -t nfs -o ro,vers=3 192.168.1.34:/mnt/Tank1/astrololo /tmp/nfs-test
ls -la /tmp/nfs-test | head
Jeśli widzisz pliki baz — to jest dokładnie problem, który zamykamy. Odmontuj:
sudo umount /tmp/nfs-test
Faza 2 — kopia obecnej konfiguracji (możliwość cofnięcia)
Na NAS-ie, podstaw <ID> z Fazy 0:
midclt call sharing.nfs.query '[["id","=",<ID>]]' > /root/astrololo-nfs-share.backup.json && cat /root/astrololo-nfs-share.backup.json
Faza 3 — zawężenie udziału
Jedna komenda ustawia wszystkie trzy zabezpieczenia naraz: listę hostów, tylko
odczyt i root_squash. Podstaw <ID>:
midclt call sharing.nfs.update <ID> '{"hosts": ["192.168.1.73", "192.168.1.80", "192.168.1.81"], "ro": true, "maproot_user": null, "maproot_group": null, "mapall_user": null, "mapall_group": null}'
Co robi każdy element:
| Ustawienie | Znaczenie |
|---|---|
hosts |
eksport tylko dla trzech węzłów k3s — reszta LAN przestaje widzieć udział |
ro: true |
tylko odczyt; aplikacja i tak montuje read-only, więc niczego nie łamie |
maproot_*, mapall_* = null |
root_squash: root z klienta nie jest rootem na udziale |
Zastosuj i sprawdź, że middleware przepisał eksporty:
midclt call service.reload nfs && exportfs -v | grep -A1 astrololo
Jeśli Twoja wersja nie ma
service.reload, użyj GUI (Shares → NFS → zapisz), co wymusi to samo.
Faza 4 — weryfikacja (wszystkie cztery testy)
1. Spoza klastra ma NIE działać. Na Macu:
sudo mount -t nfs -o ro,vers=3 192.168.1.34:/mnt/Tank1/astrololo /tmp/nfs-test
Oczekiwane: access denied / Operation not permitted. Jeśli montuje się dalej —
zmiana nie zadziałała, nie idź dalej.
2. Z węzła klastra ma działać.
ssh 192.168.1.73 'sudo mount -t nfs -o ro 192.168.1.34:/mnt/Tank1/astrololo /mnt/test && ls /mnt/test | head -3 && sudo umount /mnt/test'
3. Aplikacja żyje. Pody muszą wstać i realnie czytać bazy:
kubectl -n astrololo rollout restart deploy/data && kubectl -n astrololo rollout status deploy/data
kubectl -n astrololo exec deploy/data -- ls /app/data_files | head -3
4. Reszta homelabu nietknięta — conjurer (zapis!) i pozostałe udziały:
kubectl -n conjurer get pods
midclt call sharing.nfs.query | python3 -c "import sys,json;[print(s.get('path') or s.get('paths'), '| hosts:', s.get('hosts'), '| ro:', s.get('ro')) for s in json.load(sys.stdin)]"
Oczekiwane: tylko astrololo ma zawężone hosts i ro: true; reszta bez zmian.
Faza 5 — wycofanie (gdyby coś padło)
midclt call sharing.nfs.update <ID> '{"hosts": [], "ro": false}'
midclt call service.reload nfs
To przywraca poprzedni stan (pełna kopia w /root/astrololo-nfs-share.backup.json).
Pułapki, o których warto wiedzieć
Hookscript Proxmoxa. Na Proxmoxie działa wait-truenas.sh, który przed startem
VM czeka w pętli na showmount -e 192.168.1.34. Zawężamy tylko udział astrololo,
więc showmount nadal zwróci pozostałe eksporty i pętla przejdzie. Mimo to sprawdź
po zmianie:
ssh root@pve2 'showmount -e 192.168.1.34'
Aktualizacja baz przestanie działać przez NFS. Po ro: true nikt nie wgra
nowych plików baz przez ten udział — również Ty. Do wgrywania użyj GUI TrueNAS,
SMB albo SSH bezpośrednio na NAS-ie. To celowe: udział ma być drogą tylko do
czytania przez aplikację.
hosts przyjmuje adresy IP, nie nazwy — świadomie, żeby dostęp nie zależał od
DNS-u (AdGuard na .57). Gdyby doszedł czwarty węzeł k3s, trzeba dopisać jego IP,
inaczej pod data na nim nie wstanie.
To nie jest uwierzytelnianie. Lista IP zatrzymuje przypadkowy i oportunistyczny dostęp, ale adres da się podszyć w tej samej sieci. Docelowo (poza zakresem tego kroku): NFSv4 + Kerberos albo przeniesienie plików na wolumen nieosiągalny poza klastrem — tak mówi samo wymaganie DAN-25.
Po wykonaniu
Zaktualizuj status DAN-25 w docs/astrololo_wymagania.xlsx na Zrobione (albo
W trakcie, jeśli zostawiasz Kerberosa jako etap docelowy).