Subnet
Una subnet lega un range CIDR a un profilo. È il fallback che cattura ogni host che non hai fissato individualmente.
Cos’è
Una subnet è un insieme nominato di uno o più blocchi CIDR (IPv4, IPv6, o misti) che mappano a un profilo. Quando il resolver riceve una query e l’IP sorgente non corrisponde ad alcuna riga [[devices]], percorre le subnet configurate dalla più specifica alla meno specifica e applica il profilo della subnet che matcha. Una subnet è la strada che prendi quando hai categorie di host — una VLAN ospite, un range IoT, un /8 aziendale — che devono condividere un profilo senza essere enumerati uno per uno.
Questa pagina copre ogni dimensione che puoi mettere in una voce [[subnets]], le superfici CLI / TUI / API che le leggono e le scrivono, come una subnet matcha all’interno della catena del resolver a 5 livelli, e il confine di sicurezza attorno all’identità basata su IP sorgente. Per la catena vera e propria vedi profili; per l’ACL di rete che decide se il daemon risponde a una sorgente (un concetto separato), vedi [server].allow_from in globali del server.
Quando ti serve
Aggiungi o modifichi una subnet quando:
- Hai una VLAN. Wi-Fi ospiti, VLAN IoT, VLAN bambini, VLAN aziendale — ognuna è un CIDR che vuole il proprio profilo.
- Non vuoi enumerare ogni host. Un
/24di stampanti e tablet sconosciuti va benissimo lasciato non mappato se una subnet lega l’intero range a un profilo sensato. - Un intero range di indirizzi serve un default diverso. Un rack di test su
10.99.0.0/16, un /22 di sede remota, un range CGNAT Tailscale. - Stai ritagliando un’eccezione stretta da un range più ampio. Due subnet con prefissi diversi: il prefisso più lungo vince dove si sovrappongono.
Non ti serve [[subnets]] quando vuoi:
- Limitare a chi il daemon risponde. Quello è
[server].allow_from— un’ACL CIDR separata, a livello di daemon. Una sorgente fuori daallow_fromviene rifiutata prima ancora che si consulti una subnet. Vedi note di sicurezza. - Legare un profilo a un singolo host. Usa
[[devices]]— è al livello 1 della catena del resolver (le subnet sono al livello 4) e porta gli overlay di regole per dispositivo. - Esprimere cambi di profilo guidati da pianificazione. Vivono su
[[schedules]], non sulle subnet.
Schema
Una subnet è una riga di array-of-tables — [[subnets]], ripetibile. Ogni riga richiede un id, un nome leggibile, almeno un CIDR, e un profilo a cui legarsi.
[[subnets]]
id = "vlan-iot"
display_name = "VLAN IoT"
cidrs = ["10.10.50.0/24"]
profile = "iot-strict"
priority = 100Dimensioni
Una subnet è un vettore piccolo, deliberatamente chiuso: solo identità, copertura di indirizzi, e binding del profilo. Lo schema impone #[serde(deny_unknown_fields)] — non c’è notes, non c’è description, non c’è ACL per subnet, non c’è enforcement MAC per subnet. Se cerchi una di queste cose, vive altrove (admin rules, globali del server, dispositivi).
| Gruppo | Dimensione | Campo TOML | Cosa regola |
|---|---|---|---|
| Identità | id | id | Riferimento incrociato stabile. I verbi CLI e l’audit log puntano la subnet con questo id. Charset [a-z0-9-], ≤64 caratteri, niente - iniziali o finali. |
| Nome leggibile | display_name | Etichetta operatore mostrata in warden subnet list / show e nella master list della TUI. Non può essere vuoto. | |
| Copertura | Lista di CIDR | cidrs | Uno o più blocchi CIDR. IPv4 (10.0.0.0/8), IPv6 (fd00::/8), e misti nella stessa riga sono tutti accettati. Un indirizzo nudo è parsato come /32 (v4) o /128 (v6). Non può essere vuota. |
| Binding del profilo | Profilo legato | profile | Id del profilo applicato agli IP sorgenti che cadono in uno qualsiasi dei blocchi cidrs e non sono altrimenti mappati ai livelli 1–3. Verificato per riferimento incrociato al caricamento. |
| Tie-break | Priorità | priority | Default 0. Usata per rompere i pareggi quando due subnet condividono lo stesso prefisso più lungo; vince la priorità più alta, poi l’id ASCII più piccolo. Non può sovrascrivere il match a prefisso più lungo — un /24 vince sempre su un /16 indipendentemente dalla priorità. |
| Riferimenti (esterno) | Profilo a cui questa subnet si lega | [profiles.<id>] | Il profilo legato è referenziato; la subnet non referenzia indietro. Rimuovere un profilo referenziato è rifiutato finché ogni entità che lo referenzia non è riassegnata. |
Cose che sembrano dimensioni della subnet ma non lo sono:
- ACL di rete (quali sorgenti il daemon risponde) è
[server].allow_from, non un campo per subnet. Unallow_fromvuoto significa “nessuna ACL” ed è rifiutato dal validator nelle build di produzione — esporrebbe un open resolver. - Enforcement MAC è
[server].enforce_device_mac, a livello di daemon. Le subnet non portano flag di enforcement per riga. (L’alias legacyenforce_client_macresta accettato con nota di deprecazione.) - Risposta di blocco o TTL per subnet — vivono sul profilo a cui la subnet si lega.
- Description / notes — non nello schema. Il
deny_unknown_fieldschiuso le rifiuta. I tag invece sono un campo della subnet — vedi la riga qui sotto.
Riferimento dei campi
| Campo | Tipo | Obbligatorio | Default | Scopo |
|---|---|---|---|---|
id | stringa, [a-z0-9-], ≤64 caratteri | sì | — | Riferimento incrociato stabile. |
display_name | stringa, non vuota | sì | — | Etichetta operatore. |
cidrs | array di stringhe CIDR, non vuoto | sì | — | Blocchi IPv4 e/o IPv6; indirizzi nudi accettati come /32 o /128. |
profile | id di profilo | sì | — | Profilo legato; deve esistere in [profiles.*]. |
priority | i32 | no | 0 | Tie-breaker a prefisso uguale. La più alta vince. |
tags | lista di slug di tag, ^[a-z][a-z0-9-]{0,31}$ | no | [] | Aree tematiche contribuite alle sorgenti dentro cidrs che non hanno una riga [[devices]]. Una sorgente con riga device esplicita prende device.tags ∪ profile.tags ∪ group.tags e la subnet non contribuisce nulla, anche se il suo IP cade nell’intervallo. |
#[serde(deny_unknown_fields)] è attivo. Il campo legacy enforce_client_mac su [server] è ancora accettato tramite alias serde (rinominato in enforce_device_mac); non è un campo per subnet. Fonte: src/config/schema/subnet.rs:35-55, src/config/schema/mod.rs:101-136.
I tag della subnet hanno uno scrittore di prima classe: warden subnet tag add|remove <id> <tag> (idempotente — riaggiungere un tag che la subnet ha già, o rimuoverne uno che non ha, stampa una riga no-op e salta la scrittura; lo slug è validato al confine della CLI; una modifica reale attiva un hot reload). Ciò che warden subnet set non tocca sono i tag — accetta solo display_name, profile, priority e cidrs. Vedi tag per il modello completo e profili per come l’intersezione decide quali blocklist si applicano.
Input CIDR — forme strict e friendly
Il TOML su disco porta sempre CIDR canonici (network/prefix). La CLI e la TUI accettano un superset friendly in input, normalizzato in forma canonica prima della scrittura:
| Forma input | Esempio | Memorizzato come | Note |
|---|---|---|---|
| CIDR semplice | 10.14.0.0/24, 2001:db8::/32 | passthrough | IPv4 e IPv6. |
| Indirizzo nudo | 10.14.0.5, ::1 | 10.14.0.5/32, ::1/128 | Entrambe le famiglie. |
| Wildcard suffix | 10.14.0.*, 10.14.*.*, 10.*.*.* | /24, /16, /8 | Solo IPv4. |
| Range CIDR-allineato | 10.14.0.0-10.14.0.255 | 10.14.0.0/24 | Solo IPv4. La dimensione deve essere una potenza di due e lo start allineato al prefisso risultante. |
Forme friendly che vengono rifiutate con errori descrittivi: wildcard non contigui (10.*.0.*), numero di ottetti sbagliato, tutti wildcard, mix di wildcard + range, range disallineati (10.14.0.5-10.14.0.30), range invertiti, IPv6 con wildcard. Il TOML su disco porta sempre la forma canonica strict. Fonte: src/config/cidr.rs:37-313.
Match per famiglia di indirizzi
Un CIDR v4 non matcherà mai un IP sorgente v6, e viceversa — non c’è alcun trattamento speciale per IPv4-mapped-IPv6 (::ffff:10.0.0.1 è trattato come solo v6). Se ti serve coprire entrambe le famiglie con la stessa subnet, elenca entrambi i CIDR in cidrs:
[[subnets]]
id = "corp"
display_name = "Corp"
cidrs = ["10.0.0.0/8", "fd00::/8"]
profile = "corp"Fonte: src/config/cidr.rs:148-162, test schema multiple_cidrs_ok in src/config/schema/subnet.rs:60-74.
Esempi
Una catch-all della LAN domestica più un’eccezione IoT — il prefisso più lungo vince dove si sovrappongono:
[[subnets]]
id = "lan-home"
display_name = "LAN domestica (catch-all)"
cidrs = ["10.10.0.0/16"]
profile = "default"
priority = 0
[[subnets]]
id = "vlan-iot"
display_name = "VLAN IoT"
cidrs = ["10.10.50.0/24"]
profile = "iot-strict"
priority = 100Un client a 10.10.50.42 matcha entrambe le righe. vlan-iot vince perché /24 è più specifico di /16. I numeri di priority non decidono questo match — conterebbero solo se due subnet condividessero lo stesso prefisso più lungo.
Una VLAN ospiti multi-range su due /24 adiacenti:
[[subnets]]
id = "vlan-guest"
display_name = "Wi-Fi ospiti"
cidrs = ["10.10.200.0/24", "10.10.201.0/24"]
profile = "guest"Una regola larga con un’eccezione stretta, utile per addomesticare un blocco upstream rumoroso:
[[subnets]]
id = "range-74"
display_name = "Range 74.x — default"
cidrs = ["74.0.0.0/8"]
profile = "range-default"
[[subnets]]
id = "range-74-28"
display_name = "74.28.x — eccezione"
cidrs = ["74.28.0.0/16"]
profile = "range-exception"Una subnet aziendale dual-stack che copre sia IPv4 sia IPv6:
[[subnets]]
id = "corp"
display_name = "Corp"
cidrs = ["10.0.0.0/8", "fd00::/8"]
profile = "corp"
priority = 5subnets.d/<tema>.toml (home.toml, guest.toml, office.toml). Il config.toml master li include tramite includes. I verbi della CLI accettano --into <file> per instradare le scritture nel frammento giusto.CLI
Ogni sottocomando di scrittura attiva un hot reload (swap atomico della config, niente restart del daemon). I sottocomandi di sola lettura funzionano anche senza il daemon.
| Comando | Cosa fa |
|---|---|
warden subnet list | Una riga per subnet: <id> "<display_name>" cidrs=[...] profile=<id> priority=<n>. Una lista vuota stampa un suggerimento con la sintassi di add. |
warden subnet show <id> | Dump di dettaglio campo per campo. Errore subnet not found: <id> se manca. |
warden subnet add <id> --cidrs <csv> --profile <id> [--display-name --priority --into <file>] | Aggiunge una nuova subnet. I CIDR sono separati da virgola, accettano forme strict e friendly, e sono canonicalizzati a strict in scrittura. Rifiutato se l’id esiste già, se --cidrs è vuoto, o se il profilo referenziato è indefinito. |
warden subnet set <id> <campo> <valore> | Modifica un singolo campo. Supportati: display_name, profile, priority, cidrs (separati da virgola). Non i tag — quelli hanno il proprio verbo tag. I controlli di riferimento incrociato avvengono al reload post-scrittura. |
warden subnet tag add|remove <id> <tag> [--into <file>] | Aggiunge o rimuove un tag di area tematica sulla subnet. Idempotente — riaggiungere un tag esistente o rimuoverne uno assente stampa una riga no-op e salta la scrittura. Lo slug è validato al confine della CLI; una modifica reale attiva un hot reload. |
warden subnet remove <id> [--into <file>] | Rimuove la voce. Errore subnet "<id>" not found in <path> con suggerimento di usare --into se vive in un altro frammento. |
warden subnet allow <subnet-or-cidr> <dominio> [--id <rule_id>] [--remove] [--into <file>] | Aggiunge un dominio al profilo a cui la subnet si lega. Il primo argomento accetta o l’id della subnet o una qualsiasi stringa CIDR nel suo array cidrs. Se una stringa CIDR matcha più di una subnet, la CLI dà errore e dice di usare l’id. |
warden subnet deny <subnet-or-cidr> <dominio> [...stessi flag] | Simmetrico per il deny. |
warden resolve <ip> | Sola lettura. Percorre la catena a 5 livelli per un IP sorgente e stampa quale livello ha matchato, incluso Via subnet: <id> quando scatta il livello 4. Il modo più rapido per debuggare un mistero di profilo sbagliato. |
Pattern comuni:
# Aggiungi una VLAN IoT, legata a un profilo strict
sudo warden subnet add vlan-iot \
--cidrs 10.10.50.0/24 \
--profile iot-strict \
--display-name "VLAN IoT" \
--priority 100
# Input friendly — scritto canonicamente su disco
sudo warden subnet add lan-guest --cidrs 10.10.1.200-10.10.1.207 --profile guest
# memorizzato come 10.10.1.200/29
# Sostituisci la lista dei CIDR (mantiene id + profilo + priorità)
sudo warden subnet set vlan-iot cidrs 10.10.50.0/24,10.10.51.0/24
# Riassegna una subnet a un profilo diverso
sudo warden subnet set vlan-iot profile iot-strictest
# Ispeziona cosa succederebbe per una sorgente — senza toccare il daemon
warden resolve 10.10.50.42
# → Match level: 4 (subnet longest-prefix)
# → Via subnet: vlan-iot
# → Active profile: iot-strict
# Blocca un singolo dominio per ogni dispositivo che matcha i CIDR della subnet
sudo warden subnet deny vlan-guest gambling.exampleDopo ogni modifica con hot-reload, viene stampato esattamente uno di quattro messaggi — gli stessi usati da ogni percorso di scrittura della CLI:
daemon reloaded — change is livedaemon not running — change will take effect on next startnote: change landed on disk but no admin token is available to request a daemon reload. Run warden token generate or restart the daemon to activate.warning: change landed on disk but the daemon rejected the reload (<msg>). Check journalctl -u purge-warden and consider systemctl restart purge-warden.
Fonte: src/cli/mod.rs:162-167, 674-741, src/cli/commands/subnets.rs, src/cli/commands/rules.rs:645-731.
TUI
La tab Subnets vive sotto la sezione Network. Raggiungila con g s da qualsiasi posto, o con il numero di sezione (4 dalla barra delle tab in alto). Layout master / detail (la card di dettaglio collassa sotto le 110 colonne).
| Elemento | Cosa mostra | Tasti utili |
|---|---|---|
| Master list (sinistra) | Subnet [[subnets]] configurate prima, poi candidate auto-rilevate marchiate [suggested]. I bucket raggruppano gli IP non mappati in /24 (v4) o /64 (v6) e fanno emergere i range con ≥2 host distinti, ordinati popolosi-prima. | j / k / ↑ / ↓ scorre |
| Card di dettaglio (destra) | Linechart di traffico orario su 24h, pannello KV a 7 metriche (profilo, file sorgente, dispositivi online + totali, query oggi + 1h, conteggio bloccati + percentuale, top vendor), lista client per subnet. | — |
| Modal di Add | Form vuoto per una nuova subnet. | a apri; Tab / Shift-Tab muove tra i campi; ← / → cicla la dropdown del profilo; Enter su Submit applica. |
| Modal di Edit | Pre-compilato con la subnet configurata in evidenza. | e apri; stessa navigazione tra campi. |
| Modal di Delete | Conferma single-key y / n — le subnet sono a scope ristretto, niente frase tipata richiesta. | d / Delete apri. |
| Promote-from-suggestion | Enter su una riga candidata [suggested] apre Add pre-compilato col CIDR canonico e un display name sintetizzato (lan-10-10-50 per v4, lan6-2001-db8-0-0 per v6). L’id resta vuoto perché tu scelga consapevolmente. | Enter su una riga candidata. |
I modal condividono lo stesso core di validate-or-revert + TOCTOU + scrittura atomica della CLI — inviare un form della TUI fa girare gli stessi add_inner / set_inner / remove_inner di warden subnet add / set / remove. Fonte: src/tui/tabs/subnets.rs, src/tui/subnet_modal.rs, src/tui/mod.rs:519-562.
Il modal Resolver (raggiungibile da qualsiasi vista con s) è il modo più rapido di confermare “perché questo client riceve quel profilo?”. Per un IP sorgente stampa la stessa catena a 5 livelli di warden resolve, con Via subnet: <id> quando scatta il livello 4.
API REST
Nessuna route per le subnet. La superficie REST (/api/*) non espone alcun endpoint di lettura o scrittura per le subnet — subnet non compare in src/api/routes.rs o src/api/handlers.rs. L’authoring delle subnet passa per la CLI (o per la TUI), che scrive il TOML e attiva un Reload generico via IPC.
IPC
Il socket Unix non ha nessun verbo specifico per le subnet. Le modifiche alle subnet seguono lo stesso percorso di ogni altro cambio di configurazione: scrittura CLI → validate_or_revert → IpcCommand::Reload { token } → il daemon prende le nuove [[subnets]] da disco al prossimo reload. Fonte: src/ipc/protocol.rs.
Ordine di precedenza
Una subnet contribuisce al filtro solo come livello 4 della catena del resolver. La catena completa (documentata in profili):
- Pianificazione attiva che riguarda il dispositivo abbinato o il suo gruppo.
- Profilo diretto del dispositivo (
[[devices]].profile). - Gruppo a priorità più alta a cui il dispositivo appartiene.
- Match della subnet a prefisso più lungo. ← questa pagina.
[server].default_profile. Se non impostato, la risposta èREFUSED.
Dentro il livello 4 — match a prefisso più lungo
Il resolver costruisce una lista ordinata di ogni CIDR di ogni subnet — ordinata per lunghezza di prefisso DESC, poi priority DESC, poi id ASC — e la percorre linearmente. Il primo match vince. Quindi:
- Un
/24batte sempre un/16indipendentemente dapriority. Il prefisso più lungo è sovrano. - Due subnet alla stessa lunghezza di prefisso: vince la
prioritypiù alta. A parità di priorità: vince l’id lessicograficamente più piccolo. Il validator non segnala CIDR sovrapposti a parità di prefisso — l’ordinamento deterministico ne sceglie silenziosamente uno. - Un CIDR v4 non matcherà mai un IP sorgente v6, e viceversa.
- L’attribuzione del match è registrata come
Via subnet: <id>, esposta dawarden resolvee dal modal Resolver della TUI.
Fonte: src/profiles/resolver.rs:456-476, 859-902.
Downgrade per discrepanza MAC
Quando [server].enforce_device_mac = true (default) e il dispositivo abbinato fissa un MAC, il resolver consulta lo snapshot ARP live prima di rispondere. Se ARP mostra un MAC diverso da quello fissato, il dispositivo è declassato: i livelli 1, 2, 3 vengono saltati e la risoluzione continua al livello 4 (subnet).
Un dispositivo sotto sospetto MAC perde i suoi override diretti, di gruppo e di pianificazione — ma non è auto-bloccato. L’operatore decide cosa lo cattura al livello 4 / 5. L’audit log registra il downgrade come riga tracing::warn!(target = "audit", ...): MAC mismatch — dropping device / group / schedule levels, falling through to subnet / default. Fonte: src/profiles/resolver.rs:343-376.
Nessun match di subnet e default_profile non impostato
Il livello 5 restituisce REFUSED — il resolver non produce alcun profilo e il daemon risponde RCODE=REFUSED a ogni query da quella sorgente. Sintomo: un laptop ospite sulla LAN viene rifiutato per ogni nome. warden resolve <ip> esce con codice 1 e stampa:
Match level: <REFUSED — no level 1-5 matched> This source would be REFUSED by the daemon. To resolve it, either map the IP to a [[devices]] row, wire a [[subnets]] that covers it, or set server.default_profile to a fallback profile.
È intenzionale — il ritiro SN3 di block_unmapped_clients esprime “nega i client non mappati” proprio attraverso questo percorso. Fonte: src/profiles/resolver.rs:478-491, src/cli/commands/resolve.rs:90-96.
priority è perlopiù informativo
Il commento dello schema chiama priority “informational only”, e in senso lato è vero: non può sovrascrivere il match a prefisso più lungo. Però rompe silenziosamente i pareggi quando due subnet coprono CIDR sovrapposti alla stessa lunghezza di prefisso. Se l’intento è “la subnet A vince sulla subnet B per 10.10.50.0/24”, meglio rendere i prefissi diversi — spezza A in 10.10.50.0/25 + 10.10.50.128/25 se necessario — invece che affidarsi a priority. L’intento è più chiaro al prossimo operatore.
Note di sicurezza
Le subnet NON sono l’ACL di rete
È la distinzione più importante di questa pagina. Due concetti separati:
[server].allow_fromè unVec<CIDR>piatto di range di sorgenti a cui il daemon risponde affatto. Una sorgente fuori daallow_fromviene rifiutata prima ancora che il resolver giri. È la tua ACL di rete.[[subnets]]decide quale profilo ottiene una query a cui si risponde. Gira solo dopo cheallow_fromha accettato la sorgente.
Se un client di una VLAN ospite viene rifiutato senza traccia di un match di subnet, la causa è quasi sempre allow_from, non [[subnets]]. Il gestore incrementa tracking.engine.refused_acl per i rifiuti ACL; le miss di subnet non compaiono affatto nel contatore ACL perché succedono più avanti nel pipeline. Fonte: src/config/schema/mod.rs:120-123, src/cli/commands/start.rs:539-577, src/tracking/engine.rs:32.
L’identità per IP sorgente si fida del confine L2/L3
Un binding di subnet assume che il confine di rete (VLAN, ACL di switch, 802.1X) sia fatto rispettare a monte. Se il layer-2 è aperto, chiunque sulla LAN può asserire qualsiasi IP, e un’identità basata su subnet non è più forte dell’IP che il client dichiara. Verbatim dal threat model upstream:
Spoofing dell’indirizzo MAC sulla LAN — qualsiasi dispositivo nello stesso segmento layer-2 può presentare qualsiasi MAC. L’identità basata su MAC in purge-warden è ergonomica, non di sicurezza.
Spoofing dell’IP su una LAN piatta — preoccupazione simile. L’identità basata su subnet assume che il confine di rete (VLAN, ACL di switch, 802.1X) sia fatto rispettare a monte. Se il layer-2 è aperto, l’identità di subnet è asseribile da chiunque sul L2.
Il downgrade per discrepanza MAC sopra fa parte di questa storia: è difesa in profondità, non autenticazione. Non affidarti al binding profilo-per-subnet per un isolamento reale tra livelli di trust — usa VLAN e indirizzi di bind per VLAN per quello. Fonte: DOCUMENTATION.md:2467-2468.
IPv6 link-local, ULA, loopback
Sono perfettamente accettabili in [[subnets]].cidrs — fd00::/8, fe80::/10, ::1/128 parsano e matchano tutti. La guardia SSRF su host riservati che rifiuta [[blocklists]].url = "http://10.0.0.5/foo" è un sandbox separato per le URL delle blocklist e non si applica ai CIDR delle subnet. I CIDR delle subnet riguardano chi mappi, non da chi scarichi. Fonte: src/config/cidr.rs:382-406.
Audit log
Le mutazioni delle subnet atterrano sull’audit log accanto a ogni altro cambio di configurazione:
warden subnet add / set / removescrivono ciascuno un recordCliMutationsubnet.add/subnet.set/subnet.removeconscope = "subnet"(src/cli/commands/subnets.rs:196-200, 246-250, 298-302); il reload accettato aggiunge anche una rigaReloadcon un nuovopost_hash— ogni modifica è recuperabile dalla traccia di audit.warden subnet allow / denyregistrascope = "subnet",target_id = "<id-subnet-o-cidr>",action = "rule.add"/"rule.remove"— la stessa forma del allow/deny scope-profilo.warden subnet tag add / removeregistra un’azione di auditsubnet.tag_add/subnet.tag_remove— le modifiche ai tag sono sulla traccia, una modifica a mano del TOML no.- Il downgrade per discrepanza MAC emette una riga
tracing::warn!(target = "audit", ...).
warden audit tail [-n N] stampa le righe di audit recenti. Il path dell’audit log è /var/lib/purge-warden/audit/audit.log. Fonte: src/config/audit.rs:81, 194-201.
RRL non c’entra
Il runtime traccia le query-per-sorgente in bucket fissi /24 (v4) e /48 (v6) per la mitigazione di amplificazione. Quelle sono lunghezze di prefisso hardcoded, non le tue [[subnets]] configurate. Non provare a tunare RRL modificando le righe di subnet. Fonte: src/security/rrl.rs:3.
Risoluzione problemi
Un reload fallisce con subnets[i] "<id>".profile "<p>" is not defined. La subnet si lega a un profilo che non esiste. Il validator rifiuta il reload e il daemon resta sulla configurazione precedente. O crea il profilo prima (warden profile create <p> ...) o correggi il typo (warden subnet set <id> profile <corretto>).
Un reload fallisce con subnets[i] "<id>".cidrs[j] "<c>" is not a valid CIDR. Drift da modifica a mano. La CLI canonicalizza in scrittura, quindi questo arriva quasi sempre da una modifica manuale. Esegui warden config lint per vedere ogni diagnostica in una sola volta.
Un reload fallisce con subnets[i] "<id>".cidrs must not be empty. Una riga cidrs = [] non ha senso. warden subnet remove <id> è la mossa giusta.
warden subnet set <id> cidrs "" viene rifiutato con cidrs cannot be empty — remove the subnet instead. La CLI rifiuta di scrivere un cidrs vuoto. O passa una lista non vuota o rimuovi la riga.
warden subnet add <id> dice subnet "<id>" already exists. O modifichi quella esistente (warden subnet set ...) o scegli un id nuovo. C’è una verifica TOCTOU sul percorso post-scrittura che cattura le aggiunte concorrenti dello stesso id, con la stessa stringa di errore.
warden subnet allow <CIDR> <dominio> dà errore CIDR "<c>" matches N subnets. Due o più subnet elencano la stessa stringa CIDR nei loro array cidrs. La CLI rifiuta di indovinare. Passa l’id della subnet invece della stringa CIDR.
Un dispositivo riceve il profilo sbagliato — ti aspettavi il livello 3 (gruppo), hai ricevuto il livello 4 (subnet). Esegui warden resolve <ip>. L’output nomina il livello che ha matchato, il via-id, e il profilo attivo. I due colpevoli più comuni:
- La riga del dispositivo non ha alcun gruppo con
profileimpostato, quindi il livello 3 non restituisce nulla e scatta il livello 4. Soluzione: imposta un profilo sul gruppo, o assegnane uno direttamente sul dispositivo. - Il dispositivo è stato declassato per MAC. L’audit log porta la riga di warn
MAC mismatch — dropping device / group / schedule levels, falling through to subnet / default. O correggi il MAC fissato o accetta il fallback alla subnet come policy sotto sospetto.
warden subnet remove <id> dice subnet "<id>" not found in <path>. La voce vive in un frammento diverso. Passa --into <path> puntando al file giusto, o cercala con grep:
grep -RnE 'id\s*=\s*"<id>"' /etc/purge-warden/subnets.dUn laptop ospite non mappato riceve RCODE=REFUSED per ogni nome. Nessun livello 1–4 ha matchato e [server].default_profile non è impostato. O configuri una [[subnets]] che copre il range ospite con un profilo sensato, imposti default_profile su un fallback, oppure accetti la policy (almeno impedisce al daemon di forwardare per gli sconosciuti).
Due subnet si sovrappongono e quella sbagliata continua a vincere. Stessa lunghezza di prefisso → controlla priority e l’ordinamento per id. Lunghezze di prefisso diverse → vince il prefisso più lungo, è il design. Se vuoi davvero che una regola larga sovrascriva una stretta, la regola larga deve avere un prefisso più lungo per farlo — ristruttura i CIDR invece di combattere il resolver.
Per altro, vedi risoluzione problemi.
Vedi anche
- Profili — a cosa una subnet si lega; la catena del resolver a 5 livelli per intero.
- Dispositivi — livello 1 della catena; il modo per fissare un singolo host sopra il livello di subnet.
- Gruppi — livello 3; insiemi nominati di dispositivi che condividono un profilo.
- Pianificazioni — livello 2 (pianificazione attiva); cambi di profilo basati sull’orario che sovrascrivono il binding device / subnet dentro una finestra.
- Globali del server —
[server].allow_from(l’ACL di rete),default_profile(livello 5),enforce_device_mac(il trigger del downgrade per discrepanza MAC). - Riferimento TOML — ogni campo, ogni vincolo.
- Riferimento CLI — la superficie completa di
warden subnet …ewarden resolve.