Manuale operativo di RoamSwitch Server Edition
Installazione, distribuzione e riferimenti operativi ufficiali per Cloud VPS (AWS, GCP, Azure, Linode, DigitalOcean), data center bare metal e host container.
1. Panoramica e requisiti
RoamSwitch Server Edition è una suite di difesa autonoma e monitoraggio dell'integrità headless (zero dipendenze GUI) progettata per server Linux esposti a Internet pubblico.
A differenza dell'edizione client che cambia dinamicamente i profili in base allo stato Wi-Fi, l'edizione server applica Inbound Default Drop, monitoraggio dell'integrità dei file (FIM) del percorso critico, mitigazione LPE preventiva del kernel (Frag Gap), rilevamento delle minacce runtime eBPF, prevenzione del blocco SSH e avvisi di emergenza multicanale automatizzati (Telegram / LINE / Webhook).
cve_kernel_map_updates_enabled, attivo per impostazione predefinita). Sono i dati CVE del kernel, le regole web e, sui server Ubuntu, i dati CVE dei pacchetti Ubuntu usati dal controllo CVE dei pacchetti di sistema. roamswitch-updater riceve, tramite HTTPS GET da lafine.net, dati con firma Ed25519 (il manifest firmato viene controllato ogni giorno, i dati CVE veri e propri circa ogni 30 giorni e le regole web solo quando il manifest ha una versione più recente), senza query string né cookie, con uno User-Agent: RoamSwitch-Updater fisso come unico header che nomina il software, e non invia nulla su questo host. Si disattiva con roamswitch server config set cve_kernel_map_updates_enabled false (oppure con la procedura guidata di configurazione o la TUI del server), e l’audit continua a funzionare con la baseline integrata, anche se il controllo CVE dei pacchetti di sistema su un server Ubuntu segnalerà allora «nessun dato CVE locale». Ogni altro traffico che esce dall’host si limita a quanto segue, abilitato esplicitamente dall’operatore: notifiche (Telegram / LINE / webhook), verifica delle firme npm (npm_audit_signatures_enabled, solo quando il comando viene eseguito) e inoltro degli eventi (forward_enabled, disattivato per impostazione predefinita; §16). L’inoltro degli eventi va solo verso le destinazioni che indicate voi stessi (un SIEM, syslog, un webhook); syslog su TLS è inviato tramite openssl di sistema e il webhook strutturato tramite un sottoprocesso curl. Inoltre, l'abbinamento del Sensor (sensor_pairing_enabled, disattivato per impostazione predefinita) e l'integrazione LLM dello strumento separato incluso accessscope (disattivata per impostazione predefinita; da riga di comando, solo quando si specifica --llm) si connettono all'esterno solo quando l'operatore li attiva. L'elenco delle eccezioni è nella sezione Zero Telemetry del documento di progettazione della sicurezza della Server Edition.Requisiti di sistema
- Distribuzioni supportate: Ubuntu 22.04 / 24.04 LTS, Debian 12+, AlmaLinux / Rocky Linux / RHEL 9+, Fedora 39+, openSUSE Leap 15.5+, sistema operativo Raspberry Pi (64 bit)
- Architetture:
x86_64(amd64) oaarch64(arm64) - Kernel: Linux 5.10+ (
nftables,cgroups v2, eBPF BTF consigliato) - Footprint: 20–30 MB di memoria residente, <0,1% CPU durante carichi di lavoro inattivi/normali
2. Procedure di installazione
L'utilizzo dei repository ufficiali firmati garantisce la risoluzione automatica delle dipendenze e aggiornamenti continui tramite il gestore di pacchetti di sistema standard.
2.1 APT (sistema operativo Ubuntu/Debian/Raspberry Pi)
# 1. Registrare la chiave di firma del repository
curl -fsSL https://lafine.net/apt/roamswitch-archive-keyring.asc \
| sudo gpg --dearmor -o /usr/share/keyrings/roamswitch-archive-keyring.gpg
# 2. Aggiungere il repository
echo "deb [arch=amd64,arm64 signed-by=/usr/share/keyrings/roamswitch-archive-keyring.gpg] https://lafine.net/apt stable main" \
| sudo tee /etc/apt/sources.list.d/roamswitch.list
# 3. Installare
sudo apt update && sudo apt install roamswitch-server
2.2 DNF/RPM (Fedora/RHEL/AlmaLinux/Rocky Linux)
# 1. Importare la chiave GPG
sudo rpm --import https://lafine.net/rpm/RPM-GPG-KEY-roamswitch
# 2. Aggiungere il file di configurazione del repository
sudo curl -fsSL -o /etc/yum.repos.d/roamswitch.repo https://lafine.net/rpm/fedora/roamswitch.repo
# 3. Installare
sudo dnf install roamswitch-server
2.3 openSUSE (zypper)
sudo rpm --import https://lafine.net/rpm/RPM-GPG-KEY-roamswitch
sudo zypper addrepo https://lafine.net/rpm/opensuse/roamswitch.repo
sudo zypper refresh && sudo zypper install roamswitch-server
roamswitch) e l'edizione Server (roamswitch-server) dichiarano conflitti di pacchetti reciproci. Seleziona sempre roamswitch-server negli ambienti server headless.3. Configurazione iniziale e verifica del servizio
3.1 Stato del servizio
Dopo l'installazione, roamswitch-server.service si avvia immediatamente e viene abilitato all'avvio del sistema.
sudo systemctl status roamswitch-server.service
3.2 Procedura guidata di configurazione interattiva
Eseguire la procedura guidata di configurazione interattiva con il comando seguente per configurare in modo interattivo porte, IP di origine per la manutenzione, canali di notifica e azione di contenimento (premere Invio per accettare ciascun valore predefinito).
sudo roamswitch server setup
- Porte: inserire le porte di manutenzione SSH (predefinita
22) e le porte dei servizi pubblici (predefinite80,443), separate da virgole. - IP di origine per la manutenzione: IP o CIDR di un bastion SSH o del monitoraggio (ad es.
203.0.113.50/32). La procedura guidata richiede una risposta e non accetta un valore vuoto. Per consentire SSH da qualsiasi origine, digitaANYWHERE(in tal caso il percorso SSH di amministrazione resta aperto a tutto il mondo anche durante l'isolamento). - Canali di notifica: abilitare bot Telegram, API di messaggistica LINE e/o un webhook generico (Slack / Discord / Teams).
- Risposta a un evento eBPF critico: scegliere
isolate(isola l'host),freeze(blocca il processo) oalert_only(solo notifica). Dopo il salvataggio, viene chiesto di inviare una notifica di prova e riavviare il servizio. - Aggiornamento automatico dei dati CVE (predefinito
y): scegliete se il database delle CVE del kernel usato dall’audit di isolamento dei container, le regole web e, sui server Ubuntu, i dati CVE dei pacchetti Ubuntu usati dal controllo CVE dei pacchetti di sistema vengano scaricati in forma anonima da lafine.net (il manifest firmato viene controllato ogni giorno, i dati CVE veri e propri circa ogni 30 giorni e le regole web solo quando il manifest ha una versione più recente; solo HTTPS GET, senza query string né cookie, con unoUser-Agent: RoamSwitch-Updaterfisso come unico header che nomina il software, con firma Ed25519 verificata). Non viene inviato nulla su questo host. È l’unica comunicazione esterna attiva per impostazione predefinita nella Server Edition; risponderenla ferma (l’audit stesso continua a funzionare con la baseline integrata, ma il controllo CVE dei pacchetti di sistema su un server Ubuntu segnalerà allora «nessun dato CVE locale»). Se è già disattivata in unserver.confesistente, anche la risposta predefinita restan. - Impostazioni di File Scan Guard: scegliere se abilitare la scansione antivirus per relay di posta, cartelle condivise e destinazioni di caricamento (§13) e impostare le directory di destinazione. Opzionale, disattivato per impostazione predefinita.
- Impostazioni di Resource Guard: abilitare la protezione da esaurimento delle risorse che rileva una crescita costante della RSS (memory leak/DoS) o cicli di crash nei servizi esposti in rete.
- Panoramica delle protezioni principali sempre attive: mostra le difese principali che funzionano sempre indipendentemente dalla procedura guidata — drop predefinito in ingresso, FIM, integrazione eBPF, ecc. (nessun input richiesto).
- Impostazioni di delega all'agente investigativo (investigation): scegliere se delegare automaticamente l'indagine preliminare — per eventi eBPF critici, o rilevamenti di manomissione di FIM Critical-Path/file di lock delle dipendenze, quando classificati come solo notifica — a una CLI di agente IA esterno (Claude Code / agy / Codex CLI / OpenCode, o un comando personalizzato) (§10.1). Disattivato per impostazione predefinita.
-100 (es. -1001234567890). Verificare il valore corretto nel campo "chat":{"id":...} della risposta di curl -s "https://api.telegram.org/bot<token>/getUpdates".3.3 Controllo di sicurezza del server in 34 elementi
sudo roamswitch status --server
Esegue un audit istantaneo di 34 controlli delle regole del firewall, della mitigazione del Frag Gap, delle restrizioni Yama LSM, delle autorizzazioni e dell'esposizione delle porte Docker, producendo un punteggio e un grado di sicurezza compreso tra 0 e 100 (da S a C).
Ogni voce di controllo è ora contrassegnata anche, ai fini della rendicontazione di conformità, con una funzione/categoria NIST CSF 2.0 (sempre presente quando applicabile) e, solo quando esiste una mappatura affidabile, con un numero di controllo CIS Controls v8.
4. Regole firewall e porte
Il file di configurazione /etc/roamswitch/server.conf richiede obbligatoriamente i permessi 0600 (lettura/scrittura solo per root) per proteggere le informazioni sensibili. Il formato è chiave=valore piatto; le intestazioni di sezione come [network] vengono ignorate.
# --- Firewall ---
ssh_ports=22 # Porta di gestione SSH (mantenuta anche durante l'isolamento di emergenza)
allowed_ports=80,443 # Porte dei servizi pubblici
whitelist_ips=203.0.113.10/32 # IP/CIDR di origine per la manutenzione (vuoto = consenti tutto, in passato admin_source_ips)
protect_docker_ports=true # Protezione DOCKER-USER (impedisce ai container di aggirare il firewall)
preserve_ssh_on_isolation=true # Mantiene il percorso di gestione SSH anche durante l'isolamento di emergenza (false = blocco totale)
# --- Guardia di runtime eBPF ---
action_on_critical=isolate # isolate | freeze (SIGSTOP+blocco rete) | alert_only
ebpf_socket_path=/run/roamswitch/events.sock
# --- Blocco Egress/C2 e DNS sinkhole ---
egress_ip_blocklist_enabled=true # Predefinito true. Il seed incluso nel pacchetto contiene solo i tre server di attacco pubblicati da JPCERT/CC; nient'altro viene bloccato finché non si installa un feed
metadata_watch_enabled=true # Predefinito true. Avvisa quando un programma non root/container contatta i metadati cloud (solo registro, non blocca; rileva SSRF)
metadata_watch_allow_users= # Account che usano legittimamente il servizio di metadati (nomi o id numerici, separati da virgole; root è sempre escluso)
dns_sinkhole_enabled=false # Predefinito false (per non compromettere DNS interni/configurazioni split-horizon)
dns_sinkhole_provider=quad9 # quad9 | cloudflare | adguard | cleanbrowsing
# --- Dati CVE di isolamento container (attivi per impostazione predefinita) ---
cve_kernel_map_updates_enabled=true # Predefinito true. L'unica comunicazione esterna attiva per impostazione predefinita (dati CVE del kernel firmati, regole web e, sui server Ubuntu, dati CVE dei pacchetti Ubuntu; manifest ogni giorno, dati CVE circa ogni 30 giorni; anonima, solo ricezione, firma verificata). false la ferma
# --- Notifiche ---
telegram_enabled=false
telegram_bot_token=
telegram_chat_id=
line_enabled=false
webhook_enabled=false
webhook_url=
webhook_block_private_addresses=false # opt-in SSRF guard
webhook_allow_addresses=
# --- Sistema ---
language=ja
fim_check_interval_secs=300 # In precedenza chiamato scan_interval
isolation_hard_cap_secs=3600 # Secondi prima che un isolamento ad alta affidabilità passi alla modalità DEGRADED (0 = mantieni fino al rilascio)
Dopo aver modificato il file direttamente, riavviare il servizio per applicare le modifiche (roamswitch-server non supporta il reload):
sudo roamswitch server restart
4.1 Policy per livello di gravità (guard.yaml, opzionale)
Se action_on_critical da solo non offre sufficiente granularità, creare /etc/roamswitch/guard.yaml (un modello è disponibile in /etc/roamswitch/guard.yaml.example). Se assente, viene sintetizzata automaticamente una policy equivalente a partire da action_on_critical in server.conf, senza impatti sulle installazioni esistenti.
policies:
on_warning:
action: log_and_notify
on_critical:
server_action: isolate_process
kill_process: true
fallback_to_host_isolation_after_retries: 3 # Passa automaticamente all'isolamento dell'host se lo stesso processo si ripresenta
on_emergency:
action: isolate_host_all
kill_process: true
server_safeguards:
maintenance_ssh_ports: [22]
safety_timer_secs: 300 # Secondi prima che un isolamento a bassa affidabilità venga ripristinato automaticamente (0 lo disattiva). Non si applica agli isolamenti ad alta affidabilità (vedere sotto)
Rilascio automatico di un isolamento (in base all’affidabilità): rilasciare solo con un timer fisso permette a un attaccante paziente di limitarsi ad aspettare, quindi il trigger di ogni isolamento è classificato in base all’affidabilità. (1) Bassa affidabilità (eBPF Error / Warning e inferiori, anomalie di porta generiche): ripristinato completamente dopo un breve timer (safety_timer_secs, 300 s per impostazione predefinita). (2) Alta affidabilità (manomissione del canary, riscrittura massiva in stile ransomware, eBPF Critical / Emergency / Alert, escalation ripetuta della stessa regola): non viene mai ripristinato in silenzio. Dopo il breve timer la causa continua a essere ricontrollata, e l’isolamento viene rilasciato con una notifica solo quando si verifica che la causa è stata rimossa. Se ciò non può essere confermato, nessuno lo ha riconosciuto (ack) e si raggiunge il limite massimo (isolation_hard_cap_secs in server.conf, 3600 s per impostazione predefinita, 0 = nessun limite), passa alla modalità DEGRADED. (3) La modalità DEGRADED continua a bloccare il nuovo traffico diverso dai percorsi di gestione (le porte SSH di manutenzione e gli IP in whitelist) e non si apre mai su timer. Viene rilasciata solo da un ricontrollo che verifichi la rimozione della causa, da un ack esplicito (un ack in DEGRADED significa rilascio) o da sudo roamswitch emergency-restore. In ogni isolamento le connessioni stabilite diverse dai percorsi di gestione (un canale C2 o una reverse shell che l’attaccante ha già aperto) vengono interrotte. Ogni transizione è registrata nella timeline degli incidenti e notificata in 10 lingue.
sudo roamswitch server ack
roamswitch server ack riconosce un isolamento FULL mantenendolo rigido (l’operatore se ne è fatto carico, quindi nessun passaggio a DEGRADED e nessun rilascio automatico) e rilascia uno in DEGRADED.
4.2 Blocco Egress/C2 e DNS sinkhole
Con egress_ip_blocklist_enabled=true (predefinito), le connessioni in uscita verso IP malevoli noti vengono bloccate con nftables. Il feed è /var/lib/roamswitch/threatfeed/malicious_ips.txt (gestito dal meccanismo di aggiornamento) se esiste, altrimenti il seed incluso nel pacchetto (/usr/share/roamswitch/threatfeed/); si usa l'uno al posto dell'altro, non vengono uniti. Il seed contiene solo i tre indirizzi di server di attacco pubblicati da JPCERT/CC nel suo rapporto del 15/10/2026 sugli attacchi a servizi web e API (210.149.87.120, 118.26.36.16, 69.10.51.162). Gli indirizzi dei server a noleggio possono essere riassegnati ad altri; se una destinazione legittima smette di funzionare, controlla la riga corrispondente in quel file.
Impostare dns_sinkhole_enabled=true forza la risoluzione tramite un resolver DNS di filtraggio (Quad9 / Cloudflare / AdGuard / CleanBrowsing), bloccando la risoluzione di domini noti come malevoli. È disattivato (false) per impostazione predefinita poiché può interferire con DNS interni o configurazioni split-horizon.
Con metadata_watch_enabled attivo (predefinito), la tabella nftables inet roamswitch_metadata_watch scrive una riga nel log del kernel solo quando un programma non root o un container apre una nuova connessione verso un indirizzo di metadati cloud (169.254.169.254, 169.254.170.2, 100.100.100.200, fd00:ec2::254); il demone del server notifica una volta al giorno per account (per indirizzo di origine nel caso di un container). Registra e notifica soltanto, non blocca mai. Quando un aggressore passa all'applicazione l'URL del proprio server, che reindirizza (302) verso un indirizzo interno, il log di accesso mostra solo l'URL esterno; solo questo traffico in uscita rivela il secondo passaggio. Viene segnalata anche un'applicazione che usa legittimamente il proprio ruolo cloud: aggiungi il suo account a metadata_watch_allow_users per escluderla (un container non può essere escluso).
4.3 Protezione di rilevamento delle scansioni delle porte in ingresso
Rileva gli IP di origine che si sono connessi a numerose porte distinte in breve tempo, correlando le regole di log di nftables con journald (abilitato per impostazione predefinita). Le fonti di scansione ad alta affidabilità possono essere bloccate automaticamente per una durata prestabilita. Se utilizzato insieme a RoamSwitch Sensor (una funzione diversa dal §10.1 — le sonde di controllo completo delle porte di un Sensor associato vengono escluse come mitigazione dei falsi positivi), l'IP dello stesso Sensor viene escluso automaticamente.
# --- Rilevamento delle scansioni delle porte in ingresso (abilitato per impostazione predefinita) ---
port_scan_detect_enabled=true # false per disattivare
port_scan_detect_min_distinct_ports=15 # Considerato una scansione quando le connessioni raggiungono questo numero di porte distinte
port_scan_detect_window_secs=300 # Finestra di aggregazione per il rilevamento (secondi)
port_scan_block_enabled=true # Blocca automaticamente l'IP di origine della scansione rilevata
port_scan_block_duration_secs=600 # Durata del blocco automatico (secondi)
È possibile consultare la cronologia di rilevamento con il comando roamswitch port-scan.
4.4 Protezione di rilevamento dei tunnel DNS
Ispeziona esclusivamente il traffico DNS in uscita proprio di questo host (porta UDP/TCP 53) tramite un consumer NFQUEUE dedicato. Una query è considerata sospetta se la lunghezza dell'etichetta supera i 40 byte E la sua entropia di Shannon supera 3,8, oppure se il suo qtype è TXT/NULL; un avviso viene emesso non appena negli ultimi 60 secondi si rilevano 10 o più query di questo tipo (un periodo di raffreddamento di 300 secondi evita avvisi ripetuti per la stessa condizione). L'obiettivo è rilevare i pattern di query tipici degli strumenti di tunneling/esfiltrazione DNS come iodine e dnscat2. La regola nftables sottostante porta lo stesso flag bypass delle altre protezioni DNS di questo demone, quindi la risoluzione dei nomi DNS non viene mai compromessa anche se questa protezione è ferma o non risponde. È una funzione solo di notifica: non blocca mai automaticamente. Come per ogni altra impostazione, una modifica a dns_tunnel_detect_enabled ha effetto solo dopo un riavvio del servizio.
# --- Rilevamento tunnel DNS (abilitato per impostazione predefinita) ---
dns_tunnel_detect_enabled=true # false per disattivare
4.5 Guardia contro la forza bruta SSH
La guardia legge i login falliti di sshd nell'istante in cui vengono scritti nel log e li conta per indirizzo di origine (attiva per impostazione predefinita). Per un'origine che raggiunge il numero di fallimenti configurato (di default 6 in 600 secondi), la tabella nftables inet roamswitch_sshguard scarta solo le nuove connessioni verso le porte SSH. Il primo ban dura 1 ora, si quadruplica a ogni recidiva della stessa origine e ha un tetto di 7 giorni. Al momento del ban vengono interrotte anche le connessioni che quell'origine aveva già aperto verso SSH (si eliminano le sue voci conntrack e una regola scarta i pacchetti della direzione di risposta). Viene bannita solo un'origine senza sessione autenticata, senza login a chiave pubblica registrato e senza esenzione, e lo si ricontrolla subito prima di interrompere: una sessione autenticata e un'origine esente non vengono quindi mai interrotte. Non viene inviato nulla all'esterno; in locale vengono eseguiti solo comandi come journalctl, nft e loginctl.
Il log viene seguito con journalctl -f. journald registra quale processo ha scritto ogni riga, quindi le righe scritte da qualcosa che non sia sshd vengono ignorate. Senza journald la guardia segue /var/log/auth.log o /var/log/secure, ma in quei file qualsiasi utente locale autorizzato a usare syslog può falsificare righe e far bannare un terzo; dove journald è disponibile, lasciate ssh_guard_log_source al valore predefinito auto. I fallimenti contati sono password errata, utente inesistente, disconnessione prima dell'autenticazione dopo aver indicato un nome utente, superamento del numero di tentativi e fallimenti di autenticazione PAM. Un fallimento di chiave pubblica (Failed publickey) non viene contato, perché un client legittimo con più chiavi ne produce uno a ogni connessione. L'indirizzo di origine viene letto dalla fine della riga, in from <IP> port <N>. Un attaccante può inserire qualsiasi testo nel nome utente, ma un indirizzo di origine falso scritto lì non fa bannare un terzo. L'IPv6 viene contato per /64 e anche il ban vale per il /64 (solo per l'indirizzo di origine se quel /64 contiene un indirizzo che deve restare raggiungibile, come il gateway).
Non vengono mai bannati: il gateway, i resolver DNS, il server stesso, il loopback, whitelist_ips, ssh_guard_allow, l'origine di una sessione SSH aperta e già autenticata, qualsiasi indirizzo che abbia effettuato l'accesso con chiave pubblica negli ultimi 30 giorni (ssh_guard_trust_key_days; un accesso riuscito con password non conta) e un Sensor associato. Se una di queste origini accumula fallimenti, la guardia si limita a registrarlo. Gli indirizzi privati non sono esentati, perché anche un dispositivo compromesso all'interno della rete può essere l'origine di un attacco a forza bruta. Non è esentata nemmeno un'origine che si limita a tenere aperta una connessione prima dell'autenticazione.
Quando fail2ban (con una jail sshd attiva) o CrowdSec (con un firewall bouncer in esecuzione) protegge già sshd, la guardia gli lascia il ban per non bannare due volte lo stesso indirizzo e si limita a rilevare e notificare (ssh_guard_yield_to_fail2ban, true per impostazione predefinita). Con ssh_guard_block_enabled=false si limita anch'essa a rilevare e notificare. Notifica quando banna (in modalità di sola rilevazione, quando viene raggiunta la soglia) e quando un login riesce da un'origine che aveva accumulato fallimenti (critico: un attacco a forza bruta potrebbe essere riuscito; la sessione non viene interrotta). Non notifica ogni singolo fallimento, e le origini oltre 10 all'ora vengono raggruppate in un'unica notifica.
L'elenco dei ban si vede con roamswitch server bans (supporta --json; l'elenco è leggibile solo da root, quindi con sudo) e un ban si rimuove con sudo roamswitch server unban <IP | /64 IPv6 | --all>; rimuovendo un ban si azzera anche il contatore dei fallimenti di quell'origine. I ban vengono ripristinati con il tempo residuo dopo un riavvio del server. roamswitch emergency-restore non rimuove i ban SSH (ripristinare la rete non è un motivo per riammettere chi stava indovinando le password); il menu di ripristino (roamswitch recover) e la disinstallazione eliminano l'intera tabella. Lo strumento MCP get_ssh_guard_incidents è in sola lettura e non esiste alcuno strumento per rimuovere un ban. Nella TUI Server, la sezione «Forza bruta SSH» della schermata degli incidenti elenca i ban e permette di rimuoverli (se avviata come root; §17).
roamswitch server bans
sudo roamswitch server unban 203.0.113.9
sudo roamswitch server unban --all
Le impostazioni sono 10, tutte con il prefisso ssh_guard_ (§18.1). Se ne modifica una, per esempio, con sudo roamswitch server config set ssh_guard_max_failures 10 e la si applica con sudo roamswitch server restart. Imposta ssh_guard_enabled=false per fermare del tutto la guardia, oppure ssh_guard_block_enabled=false perché si limiti a rilevare e notificare. Anche la voce «Protezione dalla forza bruta SSH» della diagnostica a 34 voci risulta superata finché questa guardia è attiva e banna.
Limiti: i tentativi che falliscono solo con la chiave pubblica non vengono contati. Un attacco a forza bruta distribuito su molte origini viene contato per origine, quindi non viene fermato finché una singola origine non raggiunge la soglia. Il rimedio di fondo è disattivare l'autenticazione con password e consentire solo le chiavi pubbliche.
5. Failsafe di prevenzione del blocco SSH
Il blocco accidentale tramite un'errata configurazione del firewall è un disastro operativo intollerabile. RoamSwitch Server Edition incorpora protezioni a più livelli:
- ESTABLISHED / RELATED Passaggio incondizionato: le sessioni attive non vengono mai eliminate durante i ricaricamenti delle regole.
- SSH mantenuto attivo durante l’isolamento Air-Gap: anche quando un’anomalia innesca un isolamento di emergenza,
preserve_ssh_on_isolation = truemantiene il traffico nuovo e stabilito solo sui percorsi di gestione (le porte SSH di manutenzione e gli IP di origine degli amministratori,whitelist_ips), così potete indagare e ripristinare senza recarvi sul posto. Tutte le altre connessioni stabilite (C2, esfiltrazione di dati o una reverse shell che l’attaccante ha già aperto) vengono interrotte. Se non è indicata alcuna sorgente di amministrazione (whitelist_ipse gli indirizzi consentiti di guard.yaml sono vuoti), le porte SSH di manutenzione continuano ad accettare nuove connessioni da qualsiasi origine durante l'isolamento e il server emette un avviso all'avvio. Conpreserve_ssh_on_isolation=false, l'isolamento interrompe anche l'SSH. L'edizione server fino alla 1.10.4 presentava un difetto. Le regole di isolamento scartavano le risposte SSH, quindi l'SSH dell'operatore non funzionava durante l'isolamento. È stato corretto nella 1.10.5. - Caricamento di Atomic nftables con rollback: gli errori di sintassi delle regole attivano immediatamente un rollback senza tempi di inattività al set di regole verificato precedente.
6. Protezione del contenitore (Docker/Podman)
Il comportamento predefinito di Docker crea regole iptables personalizzate che aggirano i firewall host standard, esponendo le porte del contenitore (ad esempio -p 8080:8080) direttamente a Internet.
Con protect_docker_ports=true (predefinito), RoamSwitch si adatta al backend firewall di Docker in modo che anche il traffico verso i container non sia raggiungibile dall’esterno, a meno che non sia diretto a una porta elencata in ssh_ports o allowed_ports. Con il backend iptables / iptables-nft inserisce una regola di ispezione in testa alla catena DOCKER-USER (per IPv4, e anche tramite ip6tables quando IPv6 di Docker è abilitato). Con il backend nftables nativo di Docker (Docker 29 e successivi, dove DOCKER-USER non esiste) crea una propria tabella inet roamswitch_docker_guard sull’hook forward, prima delle catene di Docker (una tabella inet copre sia IPv4 sia IPv6). La decisione usa la porta di destinazione originale prima del DNAT (ctorigdstport) e si applica solo al traffico in arrivo sull’interfaccia esterna, quindi il traffico in uscita dei container e quello tra container non sono toccati. Previene l’esposizione accidentale di, ad esempio, un container di database di sviluppo.
La protezione è idempotente e si auto-ripristina ogni minuto: se dockerd si avvia dopo RoamSwitch, se un riavvio o ricaricamento di Docker riscrive le regole, o dopo un nft flush manuale o la perdita della tabella nftables, viene riapplicata, mentre una protezione già aggiornata viene lasciata intatta.
Una protezione in tempo reale che monitora docker events rileva anche i container avviati con --privileged o con /var/run/docker.sock montato (rischio di container escape) subito dopo l’avvio e vi avvisa. Inoltre la protezione dell’esecuzione nei container (container_exec_guard_enabled, attiva per impostazione predefinita) ispeziona con YARA i binari eseguiti all’interno dei container (anche un’evasione che elimina il file dopo l’esecuzione viene ispezionata, perché il contenuto è letto dal descrittore di file già aperto). La protezione contrassegna inoltre i container già in esecuzione all’avvio e segue automaticamente i nuovi container. Entrambe sono solo notifica e non bloccano mai automaticamente. Funziona anche con Docker 29 (dalla 1.11.1). Quando la sottoscrizione agli eventi continua a fallire, l’intervallo di riconnessione aumenta da 5 secondi fino a un massimo di 5 minuti.
7. Monitoraggio dell'integrità dei file del percorso critico (FIM)
Più di 150 file critici (binari critici come /bin/login, /usr/bin/sudo e /usr/sbin/sshd, configurazioni di autenticazione come /etc/shadow e /etc/sudoers, e unit di systemd) sono monitorati tramite SHA-256.
L’ambito non si limita ai singoli file. Nelle directory critiche (/etc/pam.d, /etc/sudoers.d, /etc/ssh/sshd_config.d, /etc/cron.*, /etc/systemd/system, /etc/ld.so.conf.d, /etc/profile.d e /root/.ssh (tranne known_hosts)) viene rilevata anche la comparsa di un nuovo file, e sono coperti anche gli authorized_keys di ogni account che può effettuare l’accesso, /etc/ld.so.preload (normalmente non esiste; la sua comparsa è segno di un rootkit locale) e i binari di RoamSwitch stessi. Le unit temporanee generate da snapd (snap-*.mount e simili) sono escluse. Il rilevamento dei nuovi file funziona solo rispetto a una baseline che includa questo ambito, quindi eseguite sudo roamswitch fim update una volta dopo l’aggiornamento. I file che fim verify non riesce a leggere quando eseguito senza root sono segnalati come «saltato, illeggibile», non come manomissione.
7.1 Verifica manuale dell'hash
sudo roamswitch fim verify
7.2 Rilevamento basato su eventi (istantaneo)
I file monitorati vengono osservati singolarmente tramite fanotify (FAN_CLASS_NOTIF, eventi di scrittura completata), così una manomissione viene ri-sottoposta a hash e rilevata nell'istante in cui avviene, senza attendere la scansione periodica successiva. La scansione periodica (predefinita fim_check_interval_secs=300 secondi) resta come backstop per eventuali eventi non intercettati. Vengono rilevate anche le modifiche che collocano un nuovo file con lo stesso nome (install, sed -i e simili), e la notifica indica il processo che ha fatto la modifica e il suo accesso SSH (§7.5).
7.3 Sincronizzazione automatica di base sugli aggiornamenti del sistema operativo
Su Debian/Ubuntu, l'installazione dei pacchetti configura automaticamente l'hook DPkg::Post-Invoke in /etc/apt/apt.conf.d/99roamswitch-fim. Su Fedora/RHEL/Rocky/AlmaLinux/openSUSE, un'unità systemd.path (roamswitch-fim-update.path) che monitora /var/lib/rpm svolge lo stesso ruolo.
Su Debian/Ubuntu, /etc/apt/apt.conf.d/99roamswitch-fim collega un hook DPkg::Post-Invoke. Gli aggiornamenti legittimi dei pacchetti tramite sudo apt upgrade aggiornano automaticamente la baseline FIM, eliminando gli avvisi di falsi positivi.
sudo roamswitch fim update
Quando il demone si avvia per la prima volta e crea la baseline, se un gestore di pacchetti (apt/dpkg, dnf/rpm, zypper o pacman) è al lavoro, attende fino a 120 secondi che termini prima di crearla. Anche installandolo nello stesso apt install di Apache o simili, i file temporanei su cui lavora dpkg (come *.dpkg-new) non finiscono più nella baseline e non sembrano una manomissione alla verifica successiva (dalla 1.11.18). Se dopo 120 secondi è ancora occupato, viene registrato un avviso e la baseline viene creata comunque.
7.4 Honeytoken (esche di credenziali)
All'avvio, sfruttando l'esecuzione come root, il demone distribuisce in modo idempotente tre file di credenziali esca sotto /root: .aws/credentials, .ssh/id_rsa e .docker/config.json (collettivamente, honeytoken). Non sovrascrive mai un file reale già presente in quei percorsi. Un processo di monitoraggio in background utilizza inotify per rilevare qualsiasi accesso in lettura a questi file e lo considera una ricognizione di credenziali post-compromissione (MITRE ATT&CK T1552: Unsecured Credentials), inviando immediatamente una notifica di gravità Critical e registrandola nella timeline degli incidenti. La funzione è attiva per impostazione predefinita e si regola con le chiavi honeytokens_enabled (false ferma la collocazione e il monitoraggio; le esche già collocate restano) e honeytokens_home (dove vengono collocate le esche; predefinito /root). I pacchetti fino alla 1.10.4 non includevano roamswitch-honeytokens, necessario per questa funzione, che quindi non veniva eseguita nelle installazioni dai pacchetti. È incluso dalla 1.10.5, e il problema della sandbox di systemd che bloccava le scritture in /root nell'edizione server è stato corretto nella 1.10.10. Dalla 1.11.1, i comandi docker eseguiti da RoamSwitch stesso vengono avviati con una directory dedicata vuota (/run/roamswitch/docker-config come root) come DOCKER_CONFIG, quindi non fanno scattare l'esca .docker/config.json (prima, il monitoraggio del demone e roamswitch status --server potevano leggere l'esca e generare un falso rilevamento). La lettura da parte di qualsiasi altro programma viene rilevata come prima.
Se viene rilevato un accesso reale a una delle honeytoken, prevedendo che l'attaccante continuerà a esplorare, RoamSwitch distribuisce fino a due esche aggiuntive tematicamente correlate per ogni trigger (ad esempio, raggiungere .aws/credentials distribuisce anche .aws/config; raggiungere .ssh/id_rsa distribuisce .ssh/config; raggiungere .docker/config.json distribuisce .kube/config), fino a un massimo di sei in totale tra tutti i trigger. Se durante un'indagine su un incidente si nota un accumulo di questi file sconosciuti sotto /root, si tratta di un comportamento previsto.
7.5 Percorso di intrusione (chi ha fatto la modifica e tramite quale accesso SSH)
Le notifiche su un file modificato (FIM dei percorsi critici e FIM dei lockfile) riportano ora il processo che ha fatto la modifica (account, eseguibile, comando) e l'accesso SSH a cui appartiene (IP e porta di origine, ora di accesso, metodo di autenticazione e impronta della chiave pubblica). È attivo per impostazione predefinita (fim_intrusion_context_enabled). Nel momento in cui un evento viene letto, il daemon scatta un'istantanea di /proc/<pid> del processo che scrive (eseguibile, utente, loginuid, sessionid, cgroup, catena dei genitori), perché un processo come tee o sed scompare un millisecondo dopo. Un processo già terminato viene integrato dal registratore di esecuzioni (se attivo). Il collegamento a un accesso usa prima la tabella delle sessioni della guardia SSH e, in mancanza, le righe Accepted di logind e journald. Funziona anche con la guardia SSH disattivata. Non viene inviato nulla all'esterno.
Ci si fida solo dei valori riportati dal kernel: l'eseguibile viene da /proc/<pid>/exe (non da argv[0]), l'accesso da loginuid (impostato una sola volta al login e ereditato attraverso sudo e su) e dal session-N.scope del cgroup, il resto dalla catena dei genitori. I valori che un processo può cambiare da sé, come comm, la riga di comando e l'ambiente, vengono mostrati ma non usati mai per decidere; un processo che si limita a chiamarsi sshd non viene scambiato per un accesso SSH. Una notifica tiene distinte tre risposte: trovato (origine, ora, metodo, chiave); «Non è stato trovato alcun accesso SSH» (il controllo ha mostrato un servizio systemd, un container, una sessione di login locale o un processo senza sessione di login); e «Non è stato possibile determinare il percorso di accesso» (il processo non c'era già più e non è nel registratore di esecuzioni, logind non ha risposto, la modifica è stata trovata dalla scansione periodica e il processo è sconosciuto, e così via). Ciò che non si è potuto verificare non viene mai riportato come «non è un accesso». La notifica parte anche se la ricerca fallisce.
/etc/ssh/sshd_config: modified
Processo: root (ha effettuato l'accesso come admin) / /usr/bin/tee / comando: tee /etc/ssh/sshd_config (pid 4121)
Accesso SSH: la sessione aperta da admin da 203.0.113.25:51544 alle 2026-10-17 03:12:08 (autenticazione: publickey, chiave SHA256:AbCdEf0123456789)
/etc/sudoers: modified
Non è stato possibile determinare il percorso di accesso (la modifica è stata trovata dalla scansione periodica, quindi il processo responsabile non è noto)
Vengono ora rilevate anche le modifiche che collocano un nuovo file con lo stesso nome: install, sed -i e cp seguito da mv nella stessa directory. Il contrassegno per file è legato all'inode, perciò questo tipo di modifica prima non generava alcun evento. Ora il daemon contrassegna anche le directory che contengono file sorvegliati e, quando in quella stessa directory viene chiuso un file con un altro nome, ricerca di nuovo il nome pochi millisecondi dopo. Limite: un file scritto in un'altra directory e spostato con mv viene trovato solo dalla scansione periodica (fim_check_interval_secs). In quel caso il processo che ha scritto non è noto, e la notifica lo dice.
Oltre alla notifica, il rilevamento viene conservato nella cronologia degli incidenti (tipo fim) e in /var/lib/roamswitch/fim_intrusions.json (solo root, gli ultimi 100). Lo strumento MCP verify_fim lo restituisce in un campo aggiunto, recentIntrusionContext (solo se eseguito come root). Il verdetto su una manomissione del file non cambia. Limiti: con il registratore di esecuzioni disattivato e un processo scrivente che vive solo un istante, l'eseguibile non è noto e vengono mostrati l'eseguibile e la riga di comando del processo padre. Le notifiche della sorveglianza della persistenza (persistence_watch) non contengono informazioni sul processo e non ricevono quindi il percorso di intrusione. Il percorso mostra il processo che ha fatto la modifica e il suo accesso, non oltre: la porta d'ingresso in sé (la vulnerabilità sfruttata o il modo in cui una chiave è stata rubata) non viene mostrata. Per disattivarlo, imposta fim_intrusion_context_enabled=false.
8. eBPF Runtime Guard e integrazione Falco
Si collega agli eventi eBPF dello spazio kernel (Falco/Tetragon) per rilevare l'escalation dei privilegi del kernel Frag Gap, gli escape dei contenitori e le shell inverse non autorizzate.
8.1 Architettura anti-gonfiamento
Per evitare il «syslog bloat» e la pressione sul disco che affliggono gli strumenti di sicurezza convenzionali, RoamSwitch si collega a Falco direttamente tramite il socket di dominio UNIX /run/roamswitch/events.sock. Il socket è creato accessibile solo a root (0600), quindi solo Falco eseguito come root può scriverci (non serve alcuna configurazione aggiuntiva dei permessi).
- Il pacchetto
/etc/falco/config.d/99-roamswitch-optimized.yamltrasmette gli eventi direttamente nel demone con zero I/O del disco. L’output di Falco viene passato al socket consocatall’interno di questa configurazione, quindi i pacchetti deb / rpm dell’edizione Server installanosocatcome pacchetto raccomandato (Recommends); non serve se non si usa Falco. /etc/logrotate.d/roamswitch-falcogarantisce una rotazione giornaliera pulita per qualsiasi output di file di fallback.
8.2 Contenimento autonomo
Dopo aver rilevato un attacco critico, RoamSwitch emette immediatamente SIGSTOP per congelare il PID del processo offensivo e applica l'isolamento Air-Gap di nftables.
8.3 Conservazione automatica delle prove forensi (Forensic Evidence Capture)
Un pacchetto di prove viene creato automaticamente ogni volta che la Guardia di runtime eBPF esegue un'azione di contenimento per processo (congelamento tramite SIGSTOP più interruzione della rete). Secondo la policy predefinita del §4.1, gli eventi di gravità Critical seguono questo percorso; gli eventi di gravità Emergency, che isolano l'intero host, al momento non producono un pacchetto. Un pacchetto contiene una cattura di pacchetti limitata, al meglio delle possibilità, di circa 30 secondi sull'interfaccia di routing predefinita (saltata silenziosamente, con l'omissione registrata, se tshark non è installato) e, quando il PID responsabile è noto, uno snapshot di /proc/<pid>: status, cmdline, maps, environ (i valori il cui nome contiene KEY/TOKEN/SECRET/PASSWORD vengono sostituiti con [REDACTED]), un elenco delle destinazioni dei file descriptor aperti e la catena dei processi antenati fino al PID 1. Un manifest.json che registra l'hash SHA-256 di ogni file acquisito è incluso per una successiva verifica di manomissione.
I pacchetti vengono archiviati in /var/lib/roamswitch/incident-evidence/<timestamp>-<ID>/. Non vengono mai eliminati automaticamente. Per liberare spazio su disco, rimuovere esplicitamente i pacchetti più vecchi del periodo di conservazione (30 giorni per impostazione predefinita) con:
sudo roamswitch-incident-capture prune [--keep-days N]
È inoltre possibile acquisire uno snapshot manuale in qualsiasi momento, senza attendere un'azione di contenimento, con:
sudo roamswitch-incident-capture snapshot [--pid PID] [--reason TEXT] [--json]
8.4 Misurazione della rapidità dell'isolamento e heartbeat del percorso degli avvisi
La precisione e la rapidità dell'isolamento eBPF dipendono dalle regole del sensore (Falco o Tetragon). In effetti, le regole standard di Falco 0.45.0 (29 in tutto) non ne includono nessuna che rilevi una reverse shell sull'host: le regole per le reverse shell valgono solo per i container e alcune vengono scartate dalla condizione priority: warning di RoamSwitch. RoamSwitch non dà per scontata la bontà delle regole; compensa in tre modi: misura quanto dura l'isolamento, verifica regolarmente che il percorso degli avvisi sia vivo e rileva da sé le reverse shell.
Misurazione della latenza dell'isolamento: per ogni incidente eBPF il daemon registra il tempo che passa dal rilevamento di Falco alla lettura dell'avviso (detect_to_receive_ms), dalla lettura al termine della risposta (receive_to_action_ms, misurato dopo il ritorno della chiamata di isolamento; per l'Air-Gap dell'host, fino al caricamento del ruleset) e la loro somma (detect_to_action_ms). I valori compaiono come campi aggiunti in ebpf_incidents.json e nello strumento MCP get_ebpf_incidents. La notifica di un processo isolato riporta una riga «dal rilevamento alla risposta: N ms». Misurato su una VM Ubuntu 24.04 (Falco 0.45.0, modern eBPF): da 1 a 2 ms dal rilevamento alla ricezione, da 41 a 62 ms dalla ricezione all'isolamento del processo più SIGKILL (da 42 a 64 ms in totale) e 109 ms in totale per l'Air-Gap dell'host (entro l'obiettivo di 150 ms). I valori sono di quella VM. Tetragon applica l'orario alla ricezione, quindi non ha detect_to_receive_ms.
Heartbeat (ebpf_heartbeat_interval_secs; 600 secondi per impostazione predefinita, 0 lo disattiva, altrimenti da 60 a 86400): il pacchetto include una regola Falco propria di RoamSwitch, 96-roamswitch-heartbeat.yaml. A ogni intervallo il daemon apre un percorso usa e getta che solo root può usare (un nome casuale sotto /run/roamswitch/heartbeat/) e misura quanto tempo impiega l'avviso di quella regola a tornare dall'output di Falco. Un solo andata e ritorno mostra insieme che la regola è caricata, che Falco funziona e che il percorso di output è vivo. Solo quando due controlli di fila non tornano (il secondo un minuto dopo il primo) avvisa: «le regole non sono caricate o l'output non arriva», al massimo una volta ogni 24 ore. Una riga di heartbeat viene scartata senza raggiungere isolamento, notifica, allowlist o registro degli incidenti. Non viene inviato nulla all'esterno. Gli andata e ritorno misurati sono stati di 2-6 ms; togliendo la regola l'avviso è arrivato dopo circa 164 secondi e, ripristinandola, lo stato è tornato normale in circa 75 secondi.
Lo stato è conservato in /var/lib/roamswitch/ebpf_heartbeat.json e viene letto dal campo heartbeat dello strumento MCP get_ebpf_incidents e dalla diagnostica K-04 (agente runtime eBPF; il numero di voci diagnostiche resta 34). Anche se Falco è in esecuzione, K-04 non passa se l'heartbeat non torna. Limiti: si verifica un solo andata e ritorno di una sola regola (le chiamate di sistema della famiglia open); non si può sapere se un'altra regola sia rotta per conto suo. Ciò che si rompe tra due controlli (10 minuti per impostazione predefinita) non si vede fino al successivo. Non viene eseguito per Tetragon. Su un host in cui Falco non è in esecuzione o manca il file della regola, non si controlla nulla e non si avvisa di nulla (se ne occupa la notifica esistente «guardia arrestata»). Falco scrive una riga di avviso nel syslog a ogni controllo (144 righe al giorno con l'impostazione predefinita).
8.5 Rilevamento delle reverse shell (proprio di RoamSwitch)
Senza affidarsi alle regole di Falco, RoamSwitch legge da sé /proc ogni 2 secondi e cerca una shell o un interprete (sh, bash, python, perl, ruby, php, node e simili) il cui input e output standard siano un'unica connessione TCP che questo host ha aperto verso un indirizzo esterno. Sono coperti bash -i >& /dev/tcp/…, python, perl, nc -e e socat exec:. Viene segnalato solo ciò che si vede due volte di fila, una volta per processo. Per impostazione predefinita contano solo gli indirizzi esterni pubblici; quelli privati (RFC 1918, CGNAT, link-local) contano solo con reverse_shell_watch_include_private=true, perché il ProxyCommand di ssh, i container e lo sviluppo locale li rendono comuni e legittimi. Il loopback non viene mai sorvegliato. Anche le connessioni accettate dall'host (da inetd o socat TCP-LISTEN) non sono coperte. Misurato su una VM Ubuntu 24.04, bash /dev/tcp, python, perl, nc -e e socat exec: sono stati rilevati ciascuno circa 2,4 secondi dopo la connessione. Non vengono rilevati ssh, ssh con ProxyCommand, git su ssh e un client nc.
Un rilevamento segue lo stesso percorso di un avviso di Falco (allowlist, raffreddamento delle notifiche, azioni per gravità di guard.yaml, registro degli incidenti) come evento eBPF Critical chiamato RoamSwitch Reverse Shell. Per impostazione predefinita isola il processo e lo termina (kill). Una reverse shell di proprietà di root non può essere isolata per processo; come per ogni evento Critical, si passa quindi all'Air-Gap dell'intero host. Ci sono due vie d'uscita se si teme che un programma legittimo venga segnalato per errore: reverse_shell_watch_notify_only=true (un Warning con sola notifica; non si isola né si termina nulla; false per impostazione predefinita) e una voce nella allowlist, sudo roamswitch server allowlist add "RoamSwitch Reverse Shell" <nome del processo>. Le tre chiavi di impostazione sono reverse_shell_watch_enabled (true per impostazione predefinita), reverse_shell_watch_include_private (false) e reverse_shell_watch_notify_only (false).
Limiti: il filtro avviene per nome (nome del processo e dell'eseguibile), perciò un binario fatto in casa con un nome diverso da quello di una shell o di un interprete che leghi input e output standard a un socket non viene trovato. Le connessioni via loopback (come il ritorno di ssh -R) e quelle più brevi di 2 secondi non si vedono, né si vedono i processi non visibili dallo spazio dei processi dell'host. Questo rilevamento esiste solo nella Server Edition; il Mac e il client Linux non lo hanno.
9. Avvisi di emergenza (Telegram / LINE / Webhook)
Invia avvisi immediati a canali di notifica esterni quando si verificano anomalie delle porte, manomissioni FIM o eventi di contenimento eBPF:
[notifications]
language = ja
# Telegram: token del bot e ID chat
telegram_bot_token = "123456789:ABCdefGHIjklMNOpqrSTUvwxYZ"
telegram_chat_id = "-1001234567890"
# LINE: token di accesso al canale Messaging API e ID utente
line_channel_access_token = "YOUR_LINE_ACCESS_TOKEN"
line_user_id = "U1234567890abcdef1234567890abcdef"
# Webhook generico (Slack, Discord, Teams, la propria piattaforma di monitoraggio)
webhook_url = "https://hooks.slack.com/services/T00/B00/XXXXX"
Anche senza configurare questi canali esterni, ogni avviso inviato viene comunque conservato localmente per gli ultimi 7 giorni. Consultalo con roamswitch notifications.
Rifiutare destinazioni webhook interne (opt-in): con webhook_block_private_addresses=true (predefinito false = invariato), un webhook di notifica viene rifiutato se la sua destinazione — per un nome host basta un solo indirizzo risolto — è loopback, privata (10/8, 172.16/12, 192.168/16), link-local (169.254/16, incluso l'endpoint di metadati cloud 169.254.169.254), ULA (fc00::/7) o CGNAT (100.64/10). Il motivo compare nel log e nell'errore di roamswitch notify-test. Anche le grafie alternative come 2130706433 o 0x7f.1 e l'IPv6 IPv4-mapped vengono classificate, e gli indirizzi verificati vengono fissati in curl, così il DNS rebinding non può cambiare il bersaglio. Le destinazioni interne legittime, come un SIEM aziendale, si consentono con webhook_allow_addresses=10.20.0.0/16,fd00::/8 (CIDR separati da virgole). I webhook di inoltro eventi hanno la stessa coppia: forward_webhook_block_private_addresses e forward_webhook_allow_addresses. Anche con l'opzione su false, se la destinazione è un indirizzo di metadati cloud viene registrato un avviso (l'invio non viene fermato). Se è impostata una variabile d'ambiente di proxy HTTP, risoluzione e connessione avvengono sul proxy e sono fuori da questo controllo.
10. Integrazione agente AI/MCP (protocollo contesto modello)
RoamSwitch Server Edition include roamswitch-mcp, consentendo agli agenti AI (Claude, Gemini, Cursor) di monitorare l'integrità e la postura dell'infrastruttura.
Esempio di configurazione (`claude_desktop_config.json`)
{
"mcpServers": {
"roamswitch": {
"command": "/usr/bin/roamswitch-mcp",
"args": []
}
}
}
10.1 Delega all'agente investigativo (investigation — delega dell'indagine automatizzata preliminare a un agente IA)
Mentre roamswitch-mcp del §10 gestisce le query provenienti dal client IA di un essere umano, la delega investigation è un meccanismo separato in cui il demone stesso avvia autonomamente una CLI di agente IA esterno, attivata da un evento di rilevamento. Riguarda gli eventi eBPF critici classificati come solo notifica (che non hanno attivato l'isolamento automatico o il blocco del processo), oltre ai rilevamenti di manomissione di FIM Critical-Path e file di lock delle dipendenze. Una volta abilitata, il demone genera prima un report di triage preliminare euristico locale (probabilità di falso positivo, motivazione, prossimi passi suggeriti), quindi avvia la CLI di agente IA configurata come sottoprocesso con tale report allegato, delegando ulteriori indagini e riepilogo. Disattivato per impostazione predefinita.
# Da aggiungere a /etc/roamswitch/guard.yaml (un file separato da server.conf)
investigation:
enabled: true
command: "claude" # "claude" | "agy" | "codex" | "opencode" | qualsiasi comando personalizzato
args: ["-p"] # Il prompt viene aggiunto automaticamente come ultimo argomento
timeout_secs: 180
Le stesse impostazioni possono essere configurate anche dalla procedura guidata interattiva di sudo roamswitch server setup (§3.2, ultimo passaggio). Scegliere tra i preset per Claude Code (claude -p), agy (agy -p --dangerously-skip-permissions), Codex CLI (codex exec), OpenCode (opencode run), oppure un comando personalizzato. In una nuova esecuzione, il preset corrispondente viene selezionato automaticamente in base alla configurazione salvata.
run_as non viene salvata dalla procedura guidata (CLI e TUI) e il demone non la avvia. Avviare lo strumento in una modalità che salta le conferme dei permessi, come --dangerously-skip-permissions, aumenta il rischio che un input malevolo induca l'agente ad azioni non volute. La procedura mostra questo avviso quando si sceglie agy. Dove esistono percorsi di input di log non attendibili, si consiglia una configurazione dello strumento che non salti le conferme dei permessi.La delega investigation non viene mai richiamata mentre la rete è isolata (ad esempio durante un Air-Gap attivo, o qualsiasi stato equivalente a isolate_host_all).
11. Foglio informativo dei comandi CLI
| Comando | Privilegi | Descrizione |
|---|---|---|
sudo roamswitch status --server |
root | Mostra il punteggio di sicurezza del server a 34 voci e lo stato (--json stampa lo stesso report come JSON) |
sudo roamswitch ports |
root | Controlla le porte di ascolto aperte e i processi associati |
sudo roamswitch fim verify |
root | Verificare l'integrità SHA-256 dei file di sistema del percorso critico |
roamswitch notifications |
Utente | Mostra la cronologia delle notifiche dell’ultima settimana (ogni avviso inviato); sono supportati --json e --export FILE |
sudo roamswitch server setup |
root | Avvia la procedura guidata di configurazione iniziale interattiva |
sudo roamswitch fim update |
root | Aggiorna il database di base FIM SHA-256 |
sudo roamswitch server config set <key> <value> |
root | Modifica e salva una singola chiave di configurazione (elenco al §18) |
sudo roamswitch emergency-restore |
Radice | Disattiva completamente l'isolamento eBPF/firewall e ripristina la baseline iniziale |
roamswitch port-scan |
Utente | Mostra la cronologia di rilevamento della protezione di rilevamento delle scansioni delle porte in ingresso (§4.3) (IP di origine, se bloccato automaticamente e durata del blocco) |
roamswitch sensor [key|list|pair|unpair|request-audit|results] |
Utente/root | Fiducia reciproca con un RoamSwitch Sensor tramite codici di abbinamento. pair --addr <IP> --code <code> --fingerprint <SHA-256> abbina (l’impronta digitale è il valore mostrato sullo schermo del Sensor), repin aggiorna il pin dopo che il Sensor ha rigenerato il proprio certificato, e request-audit richiede un audit attivo delle vulnerabilità (recuperate il risultato con results). Richiede sensor_pairing_enabled: true (disattivato per impostazione predefinita). Per i dettagli consultate il Manuale operativo del Sensor |
roamswitch server tui |
Utente/root | Avvia la TUI che copre ogni funzione (sola lettura per gli utenti normali, controllo completo come root; §17) |
sudo roamswitch server ack |
root | Riconosce l’isolamento di emergenza corrente (mantiene rigido un isolamento FULL e rilascia uno in DEGRADED; §4.1) |
roamswitch server ebpf |
Utente | Mostra lo stato di contenimento corrente della protezione runtime eBPF e la cronologia degli incidenti rilevati |
roamswitch server bans [--json] |
Utente/root | Mostra la guardia contro la forza bruta SSH (§4.5): il suo stato e le origini bannate al momento con il tempo residuo. Supporta --json. L'elenco dei ban è leggibile solo da root |
sudo roamswitch server unban <IP | IPv6 /64 | --all> |
root | Rimuove un ban della guardia SSH e azzera il contatore dei fallimenti di quell'origine (indica un'origine IPv6 con il suo /64; --all rimuove tutti i ban) |
sudo roamswitch server allowlist [list|add <rule> <process> [--exe <path>]|remove <rule> <process>] |
root | Gestisce l’allowlist permanente dei falsi positivi. Con --exe la voce è legata al percorso reale dell’eseguibile, così un processo rinominato non può usarla (una voce solo per nome può essere falsificata, e viene stampato un avviso) |
roamswitch frozen [list|resume <PID>|resume all] |
Utente/root | Elenca i processi che le protezioni mantengono in SIGSTOP e rilascia uno che era un falso positivo (SIGCONT); resume all li rilascia tutti |
sudo roamswitch events search|tree|export|verify|status |
root | Cerca nel registratore delle esecuzioni (--since 2h --pid --exe --user --parent --text --json), stampa un albero dei processi, esporta, verifica la catena di hash e mostra lo stato (§15) |
sudo roamswitch forward status|test|queue |
root | Mostra lo stato dell’inoltro degli eventi, invia un evento di test ed elenca la coda di ritentativi (§16) |
roamswitch timeline / notifications [--json] [--export FILE] |
Utente | Mostra la timeline unificata degli incidenti (sperimentale) o la cronologia delle notifiche; --json stampa un array JSON e --export FILE scrive JSON Lines |
roamswitch audit-agent-setup [--json] |
Utente | Controllo in sola lettura dei file di istruzioni, delle skill e delle impostazioni OpenClaw dati agli agenti IA alla ricerca di contenuti a rischio (solo la cartella home, senza rete; --json stampa JSON). Disponibile anche in «Strumenti» del Server TUI |
12. Risoluzione dei problemi e domande frequenti
Q1. RoamSwitch disconnetterà inaspettatamente la mia sessione SSH?
No. In funzionamento normale RoamSwitch consente incondizionatamente gli stati di connessione established/related e ssh_ports (22 per impostazione predefinita). Anche quando un attacco grave innesca un isolamento di emergenza Air-Gap, preserve_ssh_on_isolation=true (il valore predefinito) mantiene le sessioni di gestione sulle porte SSH di manutenzione e sugli IP di amministrazione (tutte le altre connessioni stabilite vengono interrotte). L'edizione server fino alla 1.10.4 presentava un difetto. Le regole di isolamento scartavano le risposte SSH, quindi l'SSH dell'operatore non funzionava durante l'isolamento. È stato corretto nella 1.10.5.
Q2. Come posso riottenere l'accesso se bloccato accidentalmente?
Accedere tramite la console web del proprio provider cloud (VNC / console seriale) ed eseguire sudo roamswitch emergency-restore per disattivare l'isolamento, oppure sudo systemctl stop roamswitch-server per arrestare il servizio.
Q3. Come posso esporre le porte per i servizi web appena aggiunti (ad esempio Nginx)?
Eseguire sudo roamswitch server config set allowed_ports 80,443,3000 (oppure modificare direttamente /etc/roamswitch/server.conf), quindi sudo roamswitch server restart.
13. File Scan Guard (protezione di relay di posta, cartelle condivise e endpoint di upload)
Funzionalità opzionale rilevante solo se questo host dispone di una directory che conserva file destinati ad altri: un relay di posta, una condivisione Samba/NFS, un endpoint di upload di file. Il motore YARA integrato analizza sempre clamav_scan_dirs senza dipendenze esterne; impostando clamav_enabled=true si aggiunge ClamAV come seconda opinione. Le minacce confermate vengono automaticamente messe in quarantena in /var/lib/roamswitch/quarantine e l'operatore viene notificato.
# --- File Scan Guard (ClamAV, opt-in) ---
# Il motore YARA integrato analizza sempre clamav_scan_dirs incondizionatamente.
clamav_enabled=false # true abilita il controllo aggiuntivo tramite clamdscan
clamav_scan_dirs= # Percorsi assoluti da analizzare (separati da virgola)
clamav_scan_interval_secs=86400 # Intervallo di scansione (secondi, minimo 3600)
clamav_freshclam_interval_secs=7200 # Intervallo di aggiornamento automatico del database delle firme (secondi, minimo 1800)
Configurabile anche tramite la procedura guidata interattiva sudo roamswitch server setup; è possibile verificarne la configurazione e lo stato della quarantena con lo strumento MCP get_file_scan_guard_status.
14. Log Audit (rilevamento e notifica delle anomalie nei pattern dei log)
Una scansione periodica di journalctl trasforma i messaggi di log in modelli per rilevare pattern nuovi (forme di log mai viste prima) e anomalie di frequenza (un picco statistico, Z-score > 3.0). Si tratta di un meccanismo leggero che non richiede alcun daemon aggiuntivo né dipendenze esterne, quindi è abilitato per impostazione predefinita. Le rilevazioni vengono inviate tramite gli stessi canali di notifica di File Scan Guard e FIM (Telegram / LINE / Webhook). Eventuali chiavi API o token che potrebbero comparire in una riga di log vengono mascherati automaticamente prima di essere inclusi nella notifica.
# --- Log Audit (abilitato per impostazione predefinita) ---
log_audit_enabled=true # false per disabilitare
log_audit_interval_secs=1800 # Intervallo di scansione in secondi (minimo 300)
Può anche essere configurato dalla procedura guidata interattiva sudo roamswitch server setup, e i risultati di rilevamento più recenti possono essere consultati tramite il comando CLI roamswitch audit-logs o lo strumento MCP audit_security_logs.
AccessScope, uno strumento di diagnosi dei log di accesso (strumento separato): il deb / rpm della Server Edition include il comando accessscope di uno strumento separato che diagnostica i log di accesso dei server web e di SSH (l'app con finestra non è inclusa). È in sola lettura, e la sua analisi non usa né un LLM né la rete. L'analisi con un LLM è facoltativa e disattivata per impostazione predefinita (quando è attivata, può funzionare anche come root, ma l'LLM gira allora con i privilegi di root; si consiglia un utente senza privilegi). accessscope scan --auto diagnostica i log di questo host e accessscope discover elenca dove si trovano i log. Per i dettagli, consulta la pagina di AccessScope. I deb / rpm della Server Edition includono anche i comandi personalsoc e pathscope di altri due strumenti separati, PersonalSOC (controlla i log e le difese di questo host) e PathScope (analizza i percorsi di escalation dei privilegi); le app con finestra non sono incluse. I comandi stessi non effettuano comunicazioni di rete. L'analisi LLM di PersonalSOC viene eseguita solo se si specifica --llm.
15. Registratore delle esecuzioni e regole di correlazione (locale, solo notifica)
Le esecuzioni dei processi (exec) sono registrate tramite il proc connector di netlink: eseguibile, argomenti, discendenza dei processi padre, UID, cwd, ID del container e SHA-256. È attivo per impostazione predefinita, e i record sono salvati nella directory di questo host accessibile solo a root /var/lib/roamswitch/exec_log come JSON Lines segmentati e concatenati tramite hash (0600, 200 MB / 14 giorni per impostazione predefinita) e non vengono mai inviati altrove. Il registro è a evidenza di manomissione (tamper-evident; events verify), non a prova di manomissione. Se il proc connector non può essere aperto, degrada a una scansione di /proc a bassa frequenza. La registrazione gira su thread propri, separati dal ciclo degli eventi di permesso di fanotify, e mantiene il proprio uso della CPU entro un budget (3% per impostazione predefinita).
Cercate ed esportate in locale (il registro è accessibile solo a root, quindi normalmente è necessario sudo).
sudo roamswitch events status
sudo roamswitch events search --since 2h --exe curl
sudo roamswitch events tree 4242
sudo roamswitch events export --since 1d > exec-events.jsonl
sudo roamswitch events verify
Regole di correlazione da EXR-001 a EXR-007 (solo notifica, ciascuna con un ID di tecnica MITRE ATT&CK): EXR-001 una shell generata da un servizio web / EXR-002 esecuzione da /tmp, da un file eliminato o da memfd / EXR-003 esecuzione subito dopo un download / EXR-004 una one-liner di un interprete che usa base64 o eval / EXR-005 ottenimento di uid 0 senza setuid / EXR-006 esecuzione di un binario appena collocato da cron o systemd / EXR-007 esecuzione dopo la modifica di ld.so.preload. Ogni regola ha un valore predefinito volutamente silenzioso e non isola mai da sola. Silenziate le singole regole con exec_rules_disabled (ad esempio EXR-003,EXR-004) e regolate gli utenti monitorati da EXR-001 con exec_rule_service_users.
Solo se impostate esplicitamente exec_rules_isolation_optin (predefinito false) su true, le regole di gravità alta sono trattate come trigger di isolamento ad alta affidabilità (§4.1). Per impostazione predefinita le regole si limitano a notificare. I record possono essere letti anche tramite gli strumenti MCP di sola lettura search_exec_events e get_process_tree.
16. Inoltro degli eventi (SIEM / syslog / webhook, opt-in)
Gli eventi di rilevamento possono essere inoltrati verso le destinazioni che specificate nella vostra organizzazione. È disattivato per impostazione predefinita: non viene inviato nulla finché non impostate forward_enabled=true e configurate almeno una destinazione, e non c’è alcuna destinazione del produttore incorporata. Vengono inoltrati la timeline degli incidenti, la cronologia delle notifiche, la protezione eBPF, le transizioni di stato dell’isolamento e gli avvisi di FIM, canary e regole di esecuzione; il log grezzo delle esecuzioni non viene inoltrato. Esistono tre tipi di destinazione.
- syslog (
forward_syslog_url:udp://host:514/tcp://host:port/tls://host:port): RFC 5424 o CEF (forward_syslog_format). Il framing TCP / TLS èoctet(RFC 6587, il predefinito) olf. Potete indicare una CA per la verifica TLS conforward_tls_ca_file, e la connessione è delegata aopenssl s_clientdi sistema. - File JSON Lines (
forward_file_path): un evento per riga, ruotato in base aforward_file_max_mb(50 per impostazione predefinita) eforward_file_keep(5 per impostazione predefinita). - Webhook strutturato (
forward_webhook_url): un POST JSON firmato con HMAC-SHA256 tramite un segreto condiviso (forward_webhook_secret, oppureforward_webhook_secret_fileche punta a un file0600), trasportato nell’headerX-RoamSwitch-Signature. La consegna è eseguita da un sottoprocessocurl, e il segreto non viene mai messo nella riga di comando.
Gli eventi che non è stato possibile consegnare (TCP / TLS / webhook) vengono messi in una coda di ritentativi su disco (0600, limitata da forward_queue_max_mb, 20 per impostazione predefinita, e forward_queue_max_age_hours, 72 per impostazione predefinita) e ritentati con backoff esponenziale, anche dopo un riavvio. forward_min_severity (predefinito low) imposta la gravità minima inviata. La consegna gira su un thread dedicato così nessun percorso critico viene bloccato, e quando la coda trabocca gli elementi più vecchi vengono scartati per primi.
Verificate lo stato, testate la connettività e ispezionate la coda di ritentativi con i comandi seguenti (riavviate il servizio dopo aver modificato le impostazioni).
# /etc/roamswitch/server.conf
forward_enabled=true
forward_syslog_url=tls://siem.example.org:6514
forward_syslog_format=rfc5424
forward_tls_ca_file=/etc/ssl/certs/corp-ca.pem
forward_min_severity=medium
sudo roamswitch server restart
sudo roamswitch forward status
sudo roamswitch forward test
sudo roamswitch forward queue
17. TUI del server (un’interfaccia da terminale per ogni funzione)
roamswitch-server-tui (avviabile anche con roamswitch server tui) è una TUI che raggiunge ogni funzione di Server Edition, distribuita tra i verbi della CLI e i due file di configurazione (server.conf e guard.yaml), con la sola tastiera via SSH (funziona a 80x24, in 10 lingue). I test di sviluppo falliscono ogni volta che un verbo della CLI o una chiave di configurazione non ha un corrispettivo nella TUI.
- Modalità dei permessi: avviata come utente normale è in sola lettura (le modifiche e le azioni privilegiate sono disabilitate, e viene invece mostrato il comando
sudo roamswitch …che servirebbe). Avviata come root può agire; le operazioni ad alto impatto mostrano prima cosa faranno, e le più pericolose richiedono di digitareyes. Non avvia mai il demone e non apre alcun socket di rete proprio. - Schermate (si cambia con i tasti numerici):
1Dashboard (stato di salute, stato dell’isolamento) /2Protezione (isolamento eBPF, canary, FIM, Docker, egress e DNS, registratore delle esecuzioni, regole e ricerca eventi, feed, gate XDP) /3Incidenti (tutti i tipi di incidente, compreso l'elenco dei ban SSH e la loro rimozione, timeline, cronologia delle notifiche, processi congelati, deposito di quarantena, allowlist) /4Notifiche e inoltro /5Sensor /6Configurazione /7Servizio /8Strumenti /9Audit dei log /0Informazioni e guida.?mostra i tasti della schermata corrente,Lscorre le 10 lingue,rricarica eqesce (chiedendo prima conferma se ci sono modifiche di configurazione non salvate). - Editor di configurazione: generato da uno schema, modifica tutte le 146 chiavi di
server.confeguard.yaml(§18) con validazione di tipo, intervallo e valori consentiti. Rivedete un diff (con i segreti mascherati) prima di salvare, e il salvataggio crea un backup con timestamp e scrive in modo atomico. Le chiavi che richiedono riavvio, e quelle in cui un valore errato può tagliarvi fuori o indebolire la protezione, sono contrassegnate. Si può scrivere anche la configurazione dell’agente di indagine (§10.1), dopo aver scelto un preset e visualizzato l’anteprima.
Avviatela con:
sudo roamswitch-server-tui # full control
roamswitch-server-tui # read-only
roamswitch server tui # same as roamswitch-server-tui
18. Riferimento delle chiavi di configurazione (server.conf / guard.yaml)
roamswitch-server non supporta il ricaricamento della configurazione: ogni chiave richiede il riavvio del servizio per avere effetto (sudo roamswitch server restart). Modificate le chiavi di server.conf con roamswitch server config set <key> <value> o con l’editor del §17; modificate guard.yaml con l’editor o a mano.
18.1 server.conf (109 chiavi)
| Chiave | Tipo / valori | Predefinito | Riavvio |
|---|---|---|---|
language | system | ja | en | zh-hans | zh-hant | ko | de | fr | es | it | pt | ja | Sì |
ssh_ports | port list | 22 | Sì |
allowed_ports | port list | 80,443 | Sì |
whitelist_ips | list | — | Sì |
preserve_ssh_on_isolation | bool | true | Sì |
telegram_enabled | bool | false | Sì |
telegram_bot_token | string | — | Sì |
telegram_chat_id | string | — | Sì |
line_enabled | bool | false | Sì |
line_channel_access_token | string | — | Sì |
line_user_id | string | — | Sì |
webhook_enabled | bool | false | Sì |
webhook_url | URL | — | Sì |
webhook_block_private_addresses | bool | false | Sì |
webhook_allow_addresses | CIDR list | — | Sì |
action_on_critical | isolate | freeze | alert_only | isolate | Sì |
ebpf_socket_path | abs path | /run/roamswitch/events.sock | Sì |
ebpf_heartbeat_interval_secs | 0 (off) | int 60–86400 | 600 | Sì |
isolation_hard_cap_secs | int ≥ 0 | 3600 | Sì |
fim_check_interval_secs | int ≥ 10 | 300 | Sì |
fim_intrusion_context_enabled | bool | true | Sì |
protect_docker_ports | bool | true | Sì |
dns_sinkhole_enabled | bool | false | Sì |
dns_sinkhole_provider | quad9 | cloudflare | adguard | cleanbrowsing | quad9 | Sì |
egress_ip_blocklist_enabled | bool | true | Sì |
metadata_watch_enabled | bool | true | Sì |
metadata_watch_allow_users | list | — | Sì |
cve_kernel_map_updates_enabled | bool | true | Sì |
clamav_enabled | bool | false | Sì |
clamav_scan_dirs | abs path list | — | Sì |
clamav_scan_interval_secs | int ≥ 3600 | 86400 | Sì |
clamav_freshclam_interval_secs | int ≥ 1800 | 7200 | Sì |
lockfile_watch_dirs | abs path list | — | Sì |
npm_audit_signatures_enabled | bool | false | Sì |
log_audit_enabled | bool | true | Sì |
log_audit_interval_secs | int ≥ 300 | 1800 | Sì |
resource_guard_enabled | bool | true | Sì |
resource_guard_rss_sample_interval_secs | int ≥ 10 | 60 | Sì |
resource_guard_rss_window_secs | int ≥ 300 | 1800 | Sì |
resource_guard_rss_min_samples | int ≥ 3 | 10 | Sì |
resource_guard_rss_min_growth_pct | int ≥ 10 | 50 | Sì |
resource_guard_rss_recovery_drop_pct | int ≥ 1 | 10 | Sì |
resource_guard_rss_min_kb | int ≥ 0 | 20000 | Sì |
resource_guard_crash_loop_window_secs | int ≥ 60 | 300 | Sì |
resource_guard_crash_loop_min_restarts | int ≥ 2 | 3 | Sì |
resource_guard_correlation_window_secs | int ≥ 60 | 600 | Sì |
resource_guard_zombie_min_count | int ≥ 0 | 20 | Sì |
resource_guard_load_min_normalized | float ≥ 0.0 | 0.5 | Sì |
resource_guard_load_enabled | bool | true | Sì |
resource_guard_cpu_enabled | bool | true | Sì |
resource_guard_cpu_sample_interval_secs | int ≥ 0 | 60 | Sì |
resource_guard_cpu_window_secs | int ≥ 0 | 600 | Sì |
resource_guard_cpu_min_samples | int ≥ 0 | 8 | Sì |
resource_guard_cpu_pct_threshold | float 0.0–1000.0 | 80.0 | Sì |
container_exec_guard_enabled | bool | true | Sì |
port_scan_detect_enabled | bool | true | Sì |
port_scan_detect_min_distinct_ports | int ≥ 0 | 15 | Sì |
port_scan_detect_window_secs | int ≥ 0 | 300 | Sì |
port_scan_block_enabled | bool | true | Sì |
port_scan_block_duration_secs | int ≥ 0 | 600 | Sì |
ssh_guard_enabled | bool | true | Sì |
ssh_guard_block_enabled | bool | true | Sì |
ssh_guard_max_failures | int 2–1000 | 6 | Sì |
ssh_guard_window_secs | int 10–86400 | 600 | Sì |
ssh_guard_ban_secs | int 60–2592000 | 3600 | Sì |
ssh_guard_ban_max_secs | int 60–31536000 | 604800 | Sì |
ssh_guard_allow | IP/CIDR list | — | Sì |
ssh_guard_log_source | auto | journal | abs path | auto | Sì |
ssh_guard_yield_to_fail2ban | bool | true | Sì |
ssh_guard_trust_key_days | int 0–3650 | 30 | Sì |
dns_tunnel_detect_enabled | bool | true | Sì |
reverse_shell_watch_enabled | bool | true | Sì |
reverse_shell_watch_include_private | bool | false | Sì |
reverse_shell_watch_notify_only | bool | false | Sì |
sensor_pairing_enabled | bool | false | Sì |
sensor_colocated | bool | false | Sì |
forward_enabled | bool | false | Sì |
forward_syslog_url | URL | — | Sì |
forward_syslog_format | rfc5424 | cef | rfc5424 | Sì |
forward_syslog_framing | octet | lf | octet | Sì |
forward_tls_ca_file | abs path | — | Sì |
forward_file_path | abs path | — | Sì |
forward_file_max_mb | int 1–10000 | 50 | Sì |
forward_file_keep | int 1–100 | 5 | Sì |
forward_webhook_url | URL | — | Sì |
forward_webhook_secret | string | — | Sì |
forward_webhook_secret_file | abs path | — | Sì |
forward_webhook_block_private_addresses | bool | false | Sì |
forward_webhook_allow_addresses | CIDR list | — | Sì |
forward_min_severity | info | low | medium | high | critical | low | Sì |
forward_queue_max_mb | int 1–10000 | 20 | Sì |
forward_queue_max_age_hours | int 1–8760 | 72 | Sì |
exec_recorder_enabled | bool | true | Sì |
exec_recorder_retention_mb | int 1–100000 | 200 | Sì |
exec_recorder_retention_days | int 1–3650 | 14 | Sì |
exec_recorder_hash_chain | bool | true | Sì |
exec_recorder_hash_exe | bool | true | Sì |
exec_recorder_cpu_budget_pct | int 1–50 | 3 | Sì |
exec_rules_enabled | bool | true | Sì |
exec_rules_disabled | string | — | Sì |
exec_rule_service_users | string | — | Sì |
exec_rule_window_secs | int 5–3600 | 120 | Sì |
exec_rules_isolation_optin | bool | false | Sì |
honeytokens_enabled | bool | true | Sì |
honeytokens_home | abs path | /root | Sì |
harden_userns_enabled | bool | true | Sì |
dns_tunnel_entropy_allowlist | list | — | Sì |
fleet_forwarding_allowed_hosts | list | — | Sì |
fleet_forwarding_allow_plaintext | bool | false | Sì |
18.2 guard.yaml (37 chiavi)
| Chiave | Tipo / valori | Predefinito | Riavvio |
|---|---|---|---|
sensor.type | falco | tetragon | falco | Sì |
sensor.transport | string | unix_socket | Sì |
sensor.socket_path | abs path | /run/roamswitch/events.sock | Sì |
sensor.reconnect_interval_ms | int 100–3600000 | 1000 | Sì |
policies.on_warning.action | log_and_notify | isolate_process | isolate_host_all | log_and_notify | Sì |
policies.on_warning.server_action | log_and_notify | isolate_process | isolate_host_all | — | Sì |
policies.on_warning.kill_process | bool | false | Sì |
policies.on_warning.freeze_process | bool | false | Sì |
policies.on_warning.fallback_to_host_isolation_after_retries | int 0–1000 | — | Sì |
policies.on_error.action | log_and_notify | isolate_process | isolate_host_all | isolate_process | Sì |
policies.on_error.server_action | log_and_notify | isolate_process | isolate_host_all | — | Sì |
policies.on_error.kill_process | bool | false | Sì |
policies.on_error.freeze_process | bool | false | Sì |
policies.on_error.fallback_to_host_isolation_after_retries | int 0–1000 | — | Sì |
policies.on_critical.action | log_and_notify | isolate_process | isolate_host_all | isolate_process | Sì |
policies.on_critical.server_action | log_and_notify | isolate_process | isolate_host_all | — | Sì |
policies.on_critical.kill_process | bool | true | Sì |
policies.on_critical.freeze_process | bool | false | Sì |
policies.on_critical.fallback_to_host_isolation_after_retries | int 0–1000 | 3 | Sì |
policies.on_emergency.action | log_and_notify | isolate_process | isolate_host_all | isolate_host_all | Sì |
policies.on_emergency.server_action | log_and_notify | isolate_process | isolate_host_all | — | Sì |
policies.on_emergency.kill_process | bool | true | Sì |
policies.on_emergency.freeze_process | bool | false | Sì |
policies.on_emergency.fallback_to_host_isolation_after_retries | int 0–1000 | — | Sì |
server_safeguards.allow_established_connections | bool | true | Sì |
server_safeguards.maintenance_ssh_ports | port list | 22 | Sì |
server_safeguards.whitelist_cidrs | list | — | Sì |
server_safeguards.whitelist_dns_servers | list | — | Sì |
server_safeguards.safety_timer_secs | int ≥ 0 | 300 | Sì |
adaptive_security.enabled | bool | true | Sì |
adaptive_security.untrusted_network_actions.elevate_falco_profile | string | — | Sì |
adaptive_security.untrusted_network_actions.auto_enable_userns_restriction | bool | false | Sì |
investigation.enabled | bool | false | Sì |
investigation.command | abs path | — | Sì |
investigation.args | list | — | Sì |
investigation.run_as | string | — | Sì |
investigation.timeout_secs | int 1–86400 | 180 | Sì |
19. Rilevamento di web shell e codice iniettato (Web Rules)
Questa funzione rileva web shell PHP, JavaScript, JSP e ASP e codice iniettato che girano sul tuo web server, PHP nascosto nelle immagini e abusi di .htaccess (da Linux 1.11.23). Non serve alcuna configurazione: trova le document root nella configurazione di Apache, nginx e Caddy e controlla un file subito dopo che è stato scritto e chiuso (con fanotify di sola notifica, che non può mai bloccare un altro processo). Una scansione periodica ogni 6 ore copre gli eventi persi e i file preesistenti. ClamAV non è necessario.
Il comportamento si imposta in /etc/roamswitch/web_rules.conf (proprietario root, modo 0644; un file scrivibile da altri viene ignorato). Applica una modifica con sudo roamswitch server restart. Un modello si ottiene con roamswitch web-rules example conf.
| Chiave | Significato (predefinito) |
|---|---|
quarantine | Livello di quarantena automatica. off non mette mai in quarantena, critical solo critical, high critical e high (predefinito: critical). Un risultato high con il livello critical si limita a notificare e a far partire l'hook; il file non viene toccato. |
account_action | Indica se revocare la shell di login del proprietario di un file rilevato. off / revoke_shell (predefinito: off). Contano solo i risultati critical o high messi in quarantena. Non si tocca mai root, gli UID sotto account_min_uid, gli utenti connessi né l'utente del demone. La shell precedente viene registrata e sudo roamswitch web-rules unlock-account <utente> la ripristina. |
account_min_uid | account_min_uid: l'UID più basso su cui può agire la risposta sugli account (1000 per impostazione predefinita; non scende sotto 100). |
scan_dirs, auto_docroots, watch, scan_interval_secs | scan_dirs (percorsi assoluti separati da virgole), auto_docroots (predefinito true; false ferma il rilevamento automatico dalla configurazione del web server), watch (predefinito true; false disattiva il controllo delle scritture e lascia solo la scansione periodica) e scan_interval_secs (predefinito 21600, minimo 3600). |
# /etc/roamswitch/web_rules.conf
quarantine=critical
account_action=off
account_min_uid=1000
#scan_dirs=/srv/sites/a,/srv/sites/b
auto_docroots=true
watch=true
scan_interval_secs=21600
Un rilevamento invia una notifica (Telegram, LINE, webhook) che nomina la regola e indica se il file è stato messo in quarantena o lasciato. Per guardare senza spostare nulla usa sudo roamswitch web-scan <cartella> (sola lettura; --quarantine per la quarantena) o la schermata Strumenti della TUI server. Le tue regole vanno in /etc/roamswitch/rules.d/*.json. Per chiamare un tuo script dopo un rilevamento, mettilo in /etc/roamswitch/hooks/post-detection (il risultato arriva come JSON sullo standard input; viene eseguito solo un file di proprietà di root, non scrivibile da altri e in una directory sicura; nessuna shell, interruzione dopo 30 secondi). Gli aggiornamenti delle regole viaggiano con l'aggiornamento giornaliero in sola ricezione. Con cve_kernel_map_updates_enabled disattivato non c'è alcun contatto di rete e si usano le regole integrate.