ROAMSWITCH SERVER 1.10.6 · Ultimo aggiornamento: 2026-09-26

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).

Principio Zero Telemetry (nessuna informazione su di te viene inviata; l'unica comunicazione esterna predefinita è la ricezione di dati firmati)
RoamSwitch non invia gli indirizzi IP del vostro server, le informazioni sulle porte, gli hash dei file, i log di sistema né i risultati diagnostici al produttore o ad alcun cloud. Il binario del demone stesso non contiene alcun client TLS o HTTP. A parte gli aggiornamenti del gestore di pacchetti, l’unico traffico che esce dall’host per impostazione predefinita è il recupero anonimo di dati firmati (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

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
Pacchetto Mutua Esclusione (Conflitti)
L'edizione Client (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
  1. Porte: inserire le porte di manutenzione SSH (predefinita 22) e le porte dei servizi pubblici (predefinite 80,443), separate da virgole.
  2. 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, digita ANYWHERE (in tal caso il percorso SSH di amministrazione resta aperto a tutto il mondo anche durante l'isolamento).
  3. Canali di notifica: abilitare bot Telegram, API di messaggistica LINE e/o un webhook generico (Slack / Discord / Teams).
  4. Risposta a un evento eBPF critico: scegliere isolate (isola l'host), freeze (blocca il processo) o alert_only (solo notifica). Dopo il salvataggio, viene chiesto di inviare una notifica di prova e riavviare il servizio.
  5. 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 uno User-Agent: RoamSwitch-Updater fisso 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; rispondere n la 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 un server.conf esistente, anche la risposta predefinita resta n.
  6. 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.
  7. 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.
  8. 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).
  9. 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.
Nota sull'ID chat di Telegram
L'ID chat di un supergruppo è un numero negativo che inizia con -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:

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).

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.

Garanzia di sicurezza di sola lettura
Per evitare che attacchi di tipo "pronto-iniezione" compromettano l'infrastruttura, l'interfaccia MCP è rigorosamente di sola lettura. Gli agenti AI non possono aprire porte, rimuovere l'isolamento o alterare le configurazioni di sicurezza tramite MCP. La correzione richiede l'accesso autenticato alla shell TTY locale.

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.

Nota sull'iniezione di prompt
L'integrazione investigation passa i dettagli dell'incidente (nomi di processo, percorsi di file e stringhe simili che un attaccante può controllare in parte) al prompt dell'agente di IA come stringhe JSON troncate. Come stringhe JSON, a capo e virgolette non possono servire a simulare una riga di separazione o una falsa sezione di istruzioni. Questo non impedisce che il contenuto di una stringa venga letto come istruzione, quindi l'agente non può essere eseguito come root: una configurazione senza un utente senza privilegi in 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.

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.

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
languagesystem | ja | en | zh-hans | zh-hant | ko | de | fr | es | it | ptjaSì
ssh_portsport list22Sì
allowed_portsport list80,443Sì
whitelist_ipslist—Sì
preserve_ssh_on_isolationbooltrueSì
telegram_enabledboolfalseSì
telegram_bot_tokenstring—Sì
telegram_chat_idstring—Sì
line_enabledboolfalseSì
line_channel_access_tokenstring—Sì
line_user_idstring—Sì
webhook_enabledboolfalseSì
webhook_urlURL—Sì
webhook_block_private_addressesboolfalseSì
webhook_allow_addressesCIDR list—Sì
action_on_criticalisolate | freeze | alert_onlyisolateSì
ebpf_socket_pathabs path/run/roamswitch/events.sockSì
ebpf_heartbeat_interval_secs0 (off) | int 60–86400600Sì
isolation_hard_cap_secsint ≥ 03600Sì
fim_check_interval_secsint ≥ 10300Sì
fim_intrusion_context_enabledbooltrueSì
protect_docker_portsbooltrueSì
dns_sinkhole_enabledboolfalseSì
dns_sinkhole_providerquad9 | cloudflare | adguard | cleanbrowsingquad9Sì
egress_ip_blocklist_enabledbooltrueSì
metadata_watch_enabledbooltrueSì
metadata_watch_allow_userslist—Sì
cve_kernel_map_updates_enabledbooltrueSì
clamav_enabledboolfalseSì
clamav_scan_dirsabs path list—Sì
clamav_scan_interval_secsint ≥ 360086400Sì
clamav_freshclam_interval_secsint ≥ 18007200Sì
lockfile_watch_dirsabs path list—Sì
npm_audit_signatures_enabledboolfalseSì
log_audit_enabledbooltrueSì
log_audit_interval_secsint ≥ 3001800Sì
resource_guard_enabledbooltrueSì
resource_guard_rss_sample_interval_secsint ≥ 1060Sì
resource_guard_rss_window_secsint ≥ 3001800Sì
resource_guard_rss_min_samplesint ≥ 310Sì
resource_guard_rss_min_growth_pctint ≥ 1050Sì
resource_guard_rss_recovery_drop_pctint ≥ 110Sì
resource_guard_rss_min_kbint ≥ 020000Sì
resource_guard_crash_loop_window_secsint ≥ 60300Sì
resource_guard_crash_loop_min_restartsint ≥ 23Sì
resource_guard_correlation_window_secsint ≥ 60600Sì
resource_guard_zombie_min_countint ≥ 020Sì
resource_guard_load_min_normalizedfloat ≥ 0.00.5Sì
resource_guard_load_enabledbooltrueSì
resource_guard_cpu_enabledbooltrueSì
resource_guard_cpu_sample_interval_secsint ≥ 060Sì
resource_guard_cpu_window_secsint ≥ 0600Sì
resource_guard_cpu_min_samplesint ≥ 08Sì
resource_guard_cpu_pct_thresholdfloat 0.0–1000.080.0Sì
container_exec_guard_enabledbooltrueSì
port_scan_detect_enabledbooltrueSì
port_scan_detect_min_distinct_portsint ≥ 015Sì
port_scan_detect_window_secsint ≥ 0300Sì
port_scan_block_enabledbooltrueSì
port_scan_block_duration_secsint ≥ 0600Sì
ssh_guard_enabledbooltrueSì
ssh_guard_block_enabledbooltrueSì
ssh_guard_max_failuresint 2–10006Sì
ssh_guard_window_secsint 10–86400600Sì
ssh_guard_ban_secsint 60–25920003600Sì
ssh_guard_ban_max_secsint 60–31536000604800Sì
ssh_guard_allowIP/CIDR list—Sì
ssh_guard_log_sourceauto | journal | abs pathautoSì
ssh_guard_yield_to_fail2banbooltrueSì
ssh_guard_trust_key_daysint 0–365030Sì
dns_tunnel_detect_enabledbooltrueSì
reverse_shell_watch_enabledbooltrueSì
reverse_shell_watch_include_privateboolfalseSì
reverse_shell_watch_notify_onlyboolfalseSì
sensor_pairing_enabledboolfalseSì
sensor_colocatedboolfalseSì
forward_enabledboolfalseSì
forward_syslog_urlURL—Sì
forward_syslog_formatrfc5424 | cefrfc5424Sì
forward_syslog_framingoctet | lfoctetSì
forward_tls_ca_fileabs path—Sì
forward_file_pathabs path—Sì
forward_file_max_mbint 1–1000050Sì
forward_file_keepint 1–1005Sì
forward_webhook_urlURL—Sì
forward_webhook_secretstring—Sì
forward_webhook_secret_fileabs path—Sì
forward_webhook_block_private_addressesboolfalseSì
forward_webhook_allow_addressesCIDR list—Sì
forward_min_severityinfo | low | medium | high | criticallowSì
forward_queue_max_mbint 1–1000020Sì
forward_queue_max_age_hoursint 1–876072Sì
exec_recorder_enabledbooltrueSì
exec_recorder_retention_mbint 1–100000200Sì
exec_recorder_retention_daysint 1–365014Sì
exec_recorder_hash_chainbooltrueSì
exec_recorder_hash_exebooltrueSì
exec_recorder_cpu_budget_pctint 1–503Sì
exec_rules_enabledbooltrueSì
exec_rules_disabledstring—Sì
exec_rule_service_usersstring—Sì
exec_rule_window_secsint 5–3600120Sì
exec_rules_isolation_optinboolfalseSì
honeytokens_enabledbooltrueSì
honeytokens_homeabs path/rootSì
harden_userns_enabledbooltrueSì
dns_tunnel_entropy_allowlistlist—Sì
fleet_forwarding_allowed_hostslist—Sì
fleet_forwarding_allow_plaintextboolfalseSì

18.2 guard.yaml (37 chiavi)

Chiave Tipo / valori Predefinito Riavvio
sensor.typefalco | tetragonfalcoSì
sensor.transportstringunix_socketSì
sensor.socket_pathabs path/run/roamswitch/events.sockSì
sensor.reconnect_interval_msint 100–36000001000Sì
policies.on_warning.actionlog_and_notify | isolate_process | isolate_host_alllog_and_notifySì
policies.on_warning.server_actionlog_and_notify | isolate_process | isolate_host_all—Sì
policies.on_warning.kill_processboolfalseSì
policies.on_warning.freeze_processboolfalseSì
policies.on_warning.fallback_to_host_isolation_after_retriesint 0–1000—Sì
policies.on_error.actionlog_and_notify | isolate_process | isolate_host_allisolate_processSì
policies.on_error.server_actionlog_and_notify | isolate_process | isolate_host_all—Sì
policies.on_error.kill_processboolfalseSì
policies.on_error.freeze_processboolfalseSì
policies.on_error.fallback_to_host_isolation_after_retriesint 0–1000—Sì
policies.on_critical.actionlog_and_notify | isolate_process | isolate_host_allisolate_processSì
policies.on_critical.server_actionlog_and_notify | isolate_process | isolate_host_all—Sì
policies.on_critical.kill_processbooltrueSì
policies.on_critical.freeze_processboolfalseSì
policies.on_critical.fallback_to_host_isolation_after_retriesint 0–10003Sì
policies.on_emergency.actionlog_and_notify | isolate_process | isolate_host_allisolate_host_allSì
policies.on_emergency.server_actionlog_and_notify | isolate_process | isolate_host_all—Sì
policies.on_emergency.kill_processbooltrueSì
policies.on_emergency.freeze_processboolfalseSì
policies.on_emergency.fallback_to_host_isolation_after_retriesint 0–1000—Sì
server_safeguards.allow_established_connectionsbooltrueSì
server_safeguards.maintenance_ssh_portsport list22Sì
server_safeguards.whitelist_cidrslist—Sì
server_safeguards.whitelist_dns_serverslist—Sì
server_safeguards.safety_timer_secsint ≥ 0300Sì
adaptive_security.enabledbooltrueSì
adaptive_security.untrusted_network_actions.elevate_falco_profilestring—Sì
adaptive_security.untrusted_network_actions.auto_enable_userns_restrictionboolfalseSì
investigation.enabledboolfalseSì
investigation.commandabs path—Sì
investigation.argslist—Sì
investigation.run_asstring—Sì
investigation.timeout_secsint 1–86400180Sì

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.

ChiaveSignificato (predefinito)
quarantineLivello 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_actionIndica 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_uidaccount_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_secsscan_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.

← Whitepaper di Server Edition Alla pagina di installazione Linux →