IT

Subnet

Work in progress — content may be incomplete.

Una subnet lega un range CIDR a un profilo. È il fallback che raccoglie ogni host che non hai fissato uno per uno.

Cos’è

Una subnet è un insieme con nome di uno o più blocchi CIDR (IPv4, IPv6 o misti) che corrispondono a un profilo. Quando il resolver riceve una query e nessuna pianificazione, nessun profilo del dispositivo e nessun gruppo la decide, percorre le subnet configurate dal prefisso più lungo in giù e applica il profilo della subnet che corrisponde. Questo copre le sorgenti senza riga [[devices]], i dispositivi senza profilo, gruppo o pianificazione, e i dispositivi esclusi dal controllo del MAC (vedi declassamento per MAC non corrispondente). Una subnet è la strada da prendere quando hai categorie di host (una VLAN ospiti, un range IoT, un /8 aziendale) che devono condividere un profilo senza essere elencati uno per uno.

Questa pagina copre ogni dimensione che puoi mettere su una voce [[subnets]], le superfici CLI, TUI e API che le leggono e le scrivono, come una subnet viene abbinata dentro la catena a 5 livelli del resolver, e il confine di sicurezza attorno all’identità basata sull’IP sorgente. Per la catena vedi profili; per l’ACL di rete che decide se il daemon risponde a una sorgente (un concetto separato) vedi allow_from nella tabella [server].

Quando ti serve

Aggiungi o modifica una subnet quando:

  • Hai una VLAN. Wi-Fi ospiti, VLAN IoT, VLAN dei bambini, VLAN aziendale: ognuna è un CIDR che vuole il suo profilo.
  • Non vuoi elencare ogni host. Un /24 di stampanti e tablet sconosciuti può restare non mappato, se una subnet lega l’intero range a un profilo sensato.
  • Un intero range di indirizzi ha bisogno di un default diverso. Un rack di test su 10.99.0.0/16, un /22 di un ufficio remoto, un range CGNAT di Tailscale.
  • Stai ritagliando un’eccezione stretta in un range più ampio. Due subnet con lunghezze di prefisso diverse: dove si sovrappongono vince il prefisso più lungo.

Non ti serve [[subnets]] quando vuoi:

  • Limitare a chi risponde il daemon. Quello è [server].allow_from, un’ACL CIDR separata e valida per tutto il daemon. Una sorgente fuori da allow_from viene rifiutata prima che si consulti qualsiasi subnet. Vedi le note di sicurezza.
  • Legare un profilo a un singolo host. Usa [[devices]]: nella catena del resolver sta sopra le subnet (le subnet sono al livello 4). Un dispositivo non porta regole proprie; punta a un profilo.
  • Esprimere cambi di profilo legati all’orario. Quelli stanno su [[schedules]], non sulle subnet.

Schema

Una subnet è una riga array-of-tables: [[subnets]], ripetibile. Ogni riga richiede un id, un nome visualizzato, almeno un CIDR e un profilo a cui legarsi.

toml
[[subnets]]
id           = "vlan-iot"
display_name = "VLAN IoT"
cidrs        = ["10.10.50.0/24"]
profile      = "iot-strict"
priority     = 100

Dimensioni

Una subnet è un vettore piccolo e chiuso di proposito: solo identità, copertura degli indirizzi e legame con il profilo. Lo schema impone #[serde(deny_unknown_fields)]: non c’è notes, né description, né un’ACL per subnet, né un controllo del MAC per subnet. Se ti serve una di queste cose, sta altrove (Custom List sul profilo, impostazioni globali del server, dispositivi).

AreaDimensioneCampo TOMLCosa regola
IdentitàididRiferimento stabile. I comandi della CLI e l’audit log indicano la subnet con questo id. Caratteri [a-z0-9-], al massimo 64, senza - iniziale o finale.
Nome visualizzatodisplay_nameEtichetta per l’operatore, mostrata in warden subnet list / show e nell’elenco principale della TUI. Non può essere vuoto.
Copertura degli indirizziElenco CIDRcidrsUno o più blocchi CIDR. Sono accettati IPv4 (10.0.0.0/8), IPv6 (fd00::/8) e i due mescolati nella stessa riga. Un indirizzo semplice viene letto come /32 (v4) o /128 (v6). Non può essere vuoto.
Legame con il profiloProfilo legatoprofileId del profilo applicato agli IP sorgente che cadono in uno dei blocchi cidrs e non sono mappati ai livelli 1–3. Il riferimento viene controllato al caricamento della config.
SpareggioPrioritàpriorityVale 0 se non indicata. Serve a decidere tra due subnet con lo stesso prefisso più lungo: vince la priorità più alta, poi l’id più piccolo in ordine ASCII. Non può scavalcare il match a prefisso più lungo: un /24 vince sempre su un /16, qualunque sia la priorità.
Riferimento incrociato (esterno)Profilo a cui la subnet si lega[profiles.<id>]Il profilo legato viene referenziato; la subnet non viene referenziata a sua volta. La rimozione di un profilo referenziato viene rifiutata finché ogni entità che lo usa non è stata riassegnata.

Cose che sembrano dimensioni di una subnet ma non lo sono:

  • L’ACL di rete (a quali sorgenti risponde il daemon) è [server].allow_from, non un campo per subnet. Un allow_from vuoto significa “nessuna ACL”: il daemon risponde a ogni sorgente. Il validator rifiuta un allow_from vuoto solo quando [server].listen si lega a tutte le interfacce (0.0.0.0 o ::), perché esporrebbe un resolver aperto.
  • Il controllo del MAC è [server].enforce_device_mac, valido per tutto il daemon. Le subnet non hanno flag di controllo per riga. (Il vecchio alias enforce_client_mac viene ancora letto, con una nota di deprecazione.)
  • Risposta di blocco o TTL per subnet: stanno sul profilo a cui la subnet si lega.
  • Descrizione / note: non sono nello schema. Il deny_unknown_fields chiuso le rifiuta.

Riferimento dei campi

CampoTipoObbligatorioDefaultScopo
idstringa, [a-z0-9-], al massimo 64 caratterisì—Riferimento stabile.
display_namestringa non vuotasì—Etichetta per l’operatore.
cidrsarray di stringhe CIDR, non vuotosì—Blocchi IPv4 e/o IPv6; gli indirizzi semplici valgono come /32 o /128.
profileid di profilosì—Profilo legato; deve esistere in [profiles.*].
priorityi32no0Spareggio a parità di lunghezza del prefisso. Vince il valore più alto.

#[serde(deny_unknown_fields)] è attivo. Il vecchio campo enforce_client_mac su [server] è ancora accettato tramite un alias serde (rinominato in enforce_device_mac); non è un campo per subnet. Fonte: src/config/schema/subnet.rs → Subnet, src/config/schema/mod.rs → ServerGlobals.

Una subnet decide quale profilo riceve una sorgente non mappata, e nient’altro. Cosa fa poi quel profilo con ogni lista dipende dal profilo: vedi profili. warden subnet set accetta solo display_name, profile, priority e cidrs.

Input CIDR: forme rigorose e forme comode

Il TOML su disco contiene sempre CIDR canonici (rete/prefisso). La CLI e la TUI accettano in input un insieme più ampio di forme comode, normalizzate nella forma canonica prima della scrittura:

Forma in inputEsempioSalvata comeNote
CIDR semplice10.14.0.0/24, 2001:db8::/32invariataIPv4 e IPv6.
Indirizzo semplice10.14.0.5, ::110.14.0.5/32, ::1/128Entrambe le famiglie.
Suffisso jolly10.14.0.*, 10.14.*.*, 10.*.*.*/24, /16, /8Solo IPv4.
Intervallo allineato al CIDR10.14.0.0-10.14.0.25510.14.0.0/24Solo IPv4. La dimensione deve essere una potenza di due e l’inizio deve essere allineato al confine del prefisso che ne risulta.

Le forme comode rifiutate, con errori descrittivi: jolly non contigui (10.*.0.*), numero sbagliato di ottetti, tutti jolly, jolly misti a intervalli, intervalli non allineati (10.14.0.5-10.14.0.30), intervalli invertiti, IPv6 con jolly. Il TOML su disco contiene sempre la forma canonica rigorosa. Fonte: src/config/cidr.rs → Cidr::parse(), Cidr::parse_friendly().

Match per famiglia di indirizzi

Un CIDR v4 non corrisponde a un IP sorgente v6, e viceversa. L’unica eccezione è una sorgente IPv6 con IPv4 mappato: il resolver la riporta a IPv4 prima del match, quindi ::ffff:10.0.0.1 corrisponde a 10.0.0.0/8. Se vuoi che la stessa subnet copra entrambe le famiglie, elenca entrambi i CIDR in cidrs:

toml
[[subnets]]
id           = "corp"
display_name = "Azienda"
cidrs        = ["10.0.0.0/8", "fd00::/8"]
profile      = "corp"

Fonte: src/config/cidr.rs → Cidr::contains(), src/profiles/resolver.rs → canonical_ip(), test dello schema multiple_cidrs_ok in src/config/schema/subnet.rs.

Esempi

Una subnet che copre tutta la LAN di casa più un’eccezione IoT: dove si sovrappongono vince il prefisso più lungo.

/etc/purge-warden/subnets.d/home.toml
toml
[[subnets]]
id           = "lan-home"
display_name = "LAN di casa (tutto il resto)"
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     = 100

Un client a 10.10.50.42 corrisponde a entrambe le righe. Vince vlan-iot, perché /24 è più specifico di /16. I valori di priority non decidono questo match: conterebbero solo se due subnet avessero lo stesso prefisso più lungo.

Una VLAN ospiti su due /24 adiacenti:

/etc/purge-warden/subnets.d/guest.toml
toml
[[subnets]]
id           = "vlan-guest"
display_name = "Wi-Fi ospiti"
cidrs        = ["10.10.200.0/24", "10.10.201.0/24"]
profile      = "guest"

Una regola ampia con un’eccezione stretta, utile per domare un blocco upstream rumoroso:

/etc/purge-warden/subnets.d/ranges.toml
toml
[[subnets]]
id           = "range-74"
display_name = "Range 74.x, predefinito"
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 IPv4 e IPv6:

/etc/purge-warden/subnets.d/corp.toml
toml
[[subnets]]
id           = "corp"
display_name = "Azienda"
cidrs        = ["10.0.0.0/8", "fd00::/8"]
profile      = "corp"
priority     = 5
Tip
Con più di una manciata di subnet, dividile in subnets.d/<tema>.toml (home.toml, guest.toml, office.toml). Il config.toml master le carica tramite includes. I comandi della CLI accettano --into <file> per indirizzare la scrittura al file giusto.

CLI

Ogni sottocomando che modifica la config attiva un reload a caldo (sostituzione atomica della config, senza riavviare il daemon). I sottocomandi di sola lettura funzionano senza il daemon.

ComandoCosa fa
warden subnet listUna riga per subnet: <id> "<display_name>" cidrs=[...] profile=<id> priority=<n>. Con l’elenco vuoto stampa un suggerimento con la sintassi di add.
warden subnet show <id>Mostra il dettaglio campo per campo. Se l’id manca, l’errore è subnet not found: <id>.
warden subnet add <id> --cidrs <csv> --profile <id> [--display-name --priority --into <file>]Aggiunge una subnet. I CIDR sono separati da virgole, accettano le forme rigorose e quelle comode, e vengono scritti nella forma canonica. Rifiuta se l’id esiste già, se --cidrs è vuoto o se il profilo indicato non è definito.
warden subnet set <id> <campo> <valore>Modifica un campo. Sono supportati display_name, profile, priority e cidrs (separati da virgole). I controlli dei riferimenti avvengono nel reload dopo la scrittura.
warden subnet remove <id> [--into <file>]Toglie la voce. Un id che non esiste stampa subnet "<id>" not found — nothing to remove ed esce con 0, senza reload.
warden resolve <ip>Sola lettura. Percorre la catena a 5 livelli per un IP sorgente e stampa quale livello ha trovato il match, compreso Via subnet: <id> quando scatta il livello 4. È il modo più veloce di capire perché un client riceve il profilo sbagliato.

Non esiste un comando allow o deny per subnet. I vecchi warden subnet profile-allow e warden subnet profile-deny sono ritirati: non scrivono nulla e rifiutano indicando le Custom List. Per bloccare o permettere un dominio per una subnet, mettilo in una Custom List e monta quella lista sul profilo della subnet con warden profile mount.

Schemi comuni:

bash
# Aggiungi una VLAN IoT, legata a un profilo rigoroso
sudo warden subnet add vlan-iot \
  --cidrs       10.10.50.0/24 \
  --profile     iot-strict \
  --display-name "VLAN IoT" \
  --priority    100

# Input comodo, scritto su disco in forma canonica
sudo warden subnet add lan-guest --cidrs 192.168.1.200-192.168.1.207 --profile guest
# salvato come 192.168.1.200/29

# Sostituisci l'elenco dei CIDR (mantiene id, profilo e priorità)
sudo warden subnet set vlan-iot cidrs 10.10.50.0/24,10.10.51.0/24

# Lega la subnet a un altro profilo
sudo warden subnet set vlan-iot profile iot-strictest

# Guarda 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

Dopo add, set o un remove che ha tolto qualcosa, la CLI chiede al daemon un reload e stampa uno di quattro messaggi:

  • daemon accepted the reload request — activation is not correlated
  • daemon not running — change will take effect on next start
  • note: change landed on disk but no admin token is available to request a daemon reload. Run `warden token generate`, or `systemctl reload purge-warden` to activate now (SIGHUP is unauthenticated, so it works without a token).
  • warning: change landed on disk but the daemon rejected the reload (<msg>). Check `journalctl -u purge-warden`, then try `systemctl reload purge-warden` — it enters the same reload through SIGHUP instead of IPC. Escalate to `restart` only if that fails too: it stops DNS until the lists reload.

Fonte: src/cli/mod.rs → SubnetAction, src/cli/commands/subnets.rs, src/cli/commands/ipc_reload.rs → report_reload_outcome().

TUI

La tab Subnets sta nella sezione Network. Ci arrivi con g s da qualsiasi punto. Il tasto di sezione 3 apre Network sulla foglia Devices, non su Subnets. Il layout è master / detail (la scheda di dettaglio va sotto l’elenco sotto le 110 colonne).

ElementoCosa mostraTasti utili
Elenco principale (a sinistra)Prima le [[subnets]] configurate, poi i gruppi candidati scoperti in automatico, marcati [suggested]. I gruppi raccolgono gli IP non mappati in /24 (v4) o /64 (v6) e mostrano i range con almeno 2 host distinti, i più popolati per primi.↑ / ↓ si spostano; i apre tutti i dettagli della subnet e i suoi client; c apre la vista Clients ordinabile; s lì porta il focus sulle intestazioni di ordinamento dei client
Scheda di dettaglio (a destra)Grafico del traffico orario sulle 24 ore, pannello con 7 metriche (profilo, file di origine, dispositivi online e totali, query di oggi e dell’ultima ora, bloccate in numero e percentuale, produttore più presente), elenco dei client della subnet.—
Finestra AddModulo vuoto per una nuova subnet.a apre; Tab / Shift-Tab passano da un campo all’altro; ← / → scorrono il menu del profilo; Enter su Submit applica.
Finestra EditPrecompilata con la subnet configurata selezionata.e apre; stessa navigazione tra i campi.
Finestra DeleteConferma con un tasto, y / n: le subnet hanno una portata ristretta, non serve digitare una frase.d / Delete apre.
Promozione da un suggerimentoEnter su una riga candidata [suggested] apre Add precompilato con il CIDR canonico e un nome visualizzato generato (lan-10-10-50 per v4, lan6-2001-db8-0-0 per v6). L’id resta vuoto, così lo scegli tu di proposito.Enter su una riga candidata.

Le finestre condividono con la CLI lo stesso nucleo di validazione con ripristino, ricontrollo TOCTOU e scrittura atomica: inviare un modulo della TUI esegue gli stessi percorsi add_inner / set_inner / remove_inner di warden subnet add / set / remove. Fonte: src/tui/tabs/subnets.rs, src/tui/subnet_modal.rs.

La finestra Resolver (raggiungibile da qualsiasi foglia con Shift+S) è il modo più veloce di rispondere a “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 rotta per le subnet. La superficie REST (/api/*) non espone alcun endpoint di lettura o modifica delle subnet: subnet non compare in src/api/routes.rs né in src/api/handlers.rs. Le subnet si scrivono con la CLI (o con la TUI), che scrive il TOML e attiva un Reload generico via IPC.

IPC

Anche il socket Unix non ha un verbo specifico per le subnet. Le modifiche alle subnet fanno la stessa strada di ogni altra modifica della config: scrittura della CLI → validate_or_revert → IpcCommand::Reload { token } → il daemon legge le nuove [[subnets]] dal disco al reload successivo. Fonte: src/ipc/protocol.rs.

Ordine di precedenza

Una subnet contribuisce al filtro solo come livello 4 della catena del resolver. La catena completa (descritta in profili):

  1. Pianificazione attiva. Una pianificazione che punta al dispositivo abbinato o al suo gruppo. Una pianificazione attiva viene controllata prima del profilo del dispositivo, quindi vince dentro la sua finestra.
  2. Profilo diretto del dispositivo ([[devices]].profile).
  3. Il gruppo con la priorità più alta a cui appartiene il dispositivo.
  4. Match di subnet a prefisso più lungo. ← questa pagina.
  5. [server].default_profile. Se non è impostato, la risposta è REFUSED.

Dentro il livello 4: match a prefisso più lungo

Il resolver costruisce un elenco ordinato di tutti i CIDR di tutte le subnet, ordinato per lunghezza del prefisso decrescente, poi priority decrescente, poi id crescente, e lo percorre in ordine. Vince il primo match. Quindi:

  • Un /24 batte sempre un /16, qualunque sia la priority. Il prefisso più lungo decide.
  • Due subnet con la stessa lunghezza di prefisso: vince la priority più alta. A parità di priorità vince l’id più piccolo in ordine lessicografico. Il validator rifiuta un solo caso: lo stesso CIDR in più subnet con la stessa priority e profili diversi. Le altre sovrapposizioni a parità di prefisso non vengono segnalate: l’ordinamento deterministico ne sceglie una.
  • Un CIDR v4 non corrisponde a un IP sorgente v6, e viceversa. Una sorgente IPv6 con IPv4 mappato viene prima riportata a IPv4.
  • L’attribuzione del match viene registrata come Via subnet: <id>, mostrata da warden resolve e dalla finestra Resolver della TUI.

Fonte: src/profiles/resolver.rs → build_resolver_map() (l’ordinamento) e ProfileResolver::resolve() (il percorso del livello 4).

Declassamento per MAC non corrispondente

Quando [server].enforce_device_mac = true (il default) e l’indirizzo sorgente corrisponde a un dispositivo, il resolver consulta l’istantanea ARP prima di rispondere. Il mac del dispositivo o uno dei suoi mac_aliases conserva il dispositivo. Un MAC che appartiene a un altro dispositivo configurato identifica invece quel dispositivo, e la query viene risolta con i livelli di quel dispositivo. Qualsiasi altro MAC declassa il dispositivo: i livelli pianificazione, profilo diretto e gruppo vengono saltati e la risoluzione continua dal livello 4 (subnet). Un dispositivo con ip e senza mac viene escluso allo stesso modo finché enforce_device_mac è attivo, a meno che la tabella ARP non mostri al suo indirizzo uno dei suoi mac_aliases. La regola completa è in il controllo del MAC.

Un dispositivo sotto sospetto per il MAC perde gli override diretto, di gruppo e di pianificazione, ma non viene bloccato in automatico. È l’operatore a decidere cosa lo raccoglie al livello 4 o 5. Il daemon registra ogni caso nel journal come riga tracing::warn!(target = "audit", ...), circa una volta al minuto per indirizzo e MAC:

  • MAC mismatch — dropping device / group / schedule levels, falling through to subnet / default per un declassamento;
  • device pinned by IP only (no MAC) under enforce_device_mac — dropping device / group / schedule levels, falling through to subnet / default per un dispositivo con solo l’IP;
  • observed MAC belongs to another device — resolving as that device, not the device pinned to this IP quando il MAC identifica un altro dispositivo.

Fonte: src/profiles/resolver.rs → ProfileResolver::resolve(), warn_mac_owned_by_other_device().

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 di quella sorgente. Sintomo: un portatile ospite sulla LAN viene rifiutato per ogni nome. warden resolve <ip> esce con codice 3 e stampa:

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

È voluto. block_unmapped_clients è stato ritirato; lasciare default_profile non impostato ora significa “nega i client non mappati”. Fonte: src/profiles/resolver.rs → resolve(), src/cli/commands/resolve.rs.

priority decide i pareggi a parità di prefisso

Il commento dello schema e l’help di --priority lo definiscono “informational only”. Leggilo come una scorciatoia per non può scavalcare il match a prefisso più lungo, non come non viene letto: il resolver ordina per lunghezza del prefisso decrescente, poi priority decrescente, poi id crescente, quindi priority decide tra due subnet che coprono CIDR sovrapposti con la stessa lunghezza di prefisso. Meglio comunque usare prefissi distinti: se vuoi dire “la subnet A vince sulla subnet B per 10.10.50.0/24”, dividi A in 10.10.50.0/25 + 10.10.50.128/25 invece di affidarti a priority. L’intenzione risulta più chiara 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 è un semplice Vec<CIDR> di range sorgente a cui il daemon risponde in assoluto. Una sorgente fuori da allow_from viene rifiutata prima ancora che parta il resolver. Questa è la tua ACL di rete.
  • [[subnets]] decide quale profilo riceve una query a cui si risponde. Entra in gioco solo dopo che allow_from ha accettato la sorgente.

Se un client della VLAN ospiti viene rifiutato senza alcuna traccia di un match di subnet, la causa è quasi sempre allow_from, non [[subnets]]. Il gestore incrementa il contatore total_refused_acl per i rifiuti dell’ACL; le subnet senza match non compaiono affatto in quel contatore, perché avvengono più avanti. Fonte: src/config/schema/mod.rs → ServerGlobals, src/config/cidr.rs → any_contains(), src/tracking/engine.rs → total_refused_acl.

L’identità per IP sorgente si fida del confine L2/L3

Un legame per subnet presuppone che il confine di rete (VLAN, ACL dello switch, 802.1X) sia imposto più a monte. Se il layer 2 (il livello di collegamento della rete) è aperto, chiunque sulla LAN può dichiarare qualsiasi IP, e un’identità basata sulla subnet non è più forte dell’IP che dichiara. Testualmente dal threat model:

MAC address spoofing on the LAN — any device on the same layer-2 segment can present any MAC. MAC-based identity in purge-warden is ergonomic, not security.

IP spoofing on a flat LAN — similar concern. Subnet-based identity assumes the network boundary (VLAN, switch ACL, 802.1X) is enforced upstream. If layer-2 is open, subnet identity is assertable by anyone on the L2.

Il declassamento per MAC non corrispondente descritto sopra fa parte di questo discorso: è difesa in profondità, non autenticazione. Non affidarti al legame di profilo per subnet per isolare davvero livelli di fiducia diversi: usa le VLAN e indirizzi di ascolto per VLAN. Fonte: _catalog/DOCUMENTATION.md, threat model.

Vanno benissimo in [[subnets]].cidrs: fd00::/8, fe80::/10 e ::1/128 vengono letti e abbinati. La protezione SSRF sugli host riservati che rifiuta [[blocklists]].url = "http://10.0.0.5/foo" è una barriera separata per gli URL delle blocklist e non si applica ai CIDR delle subnet. I CIDR delle subnet riguardano chi mappi, non da dove scarichi. Fonte: src/lists/http_client.rs → validate_list_url().

Audit log

Le modifiche alle subnet finiscono nell’audit log insieme a ogni altra modifica della config:

  • warden subnet add / set / remove scrivono ciascuno un record CliMutation subnet.add / subnet.set / subnet.remove con scope = "subnet" (src/cli/commands/subnets.rs → add_inner_locked(), set_fields_inner_locked(), remove_inner_locked()); il reload accettato aggiunge anche una riga Reload con un nuovo post_hash, quindi ogni modifica si può ricostruire dalla traccia di audit.
  • Il declassamento per MAC non corrispondente scrive una riga tracing::warn!(target = "audit", ...) nel journal, non in audit.log.

warden audit tail [-n N] stampa le righe di audit recenti. Il percorso dell’audit log è /var/lib/purge-warden/audit/audit.log. Fonte: src/config/audit.rs → AUDIT_FILE_NAME.

RRL non c’entra

Il runtime conta le query per sorgente in gruppi fissi /24 (v4) e /48 (v6) per mitigare l’amplificazione. Sono lunghezze di prefisso fisse nel codice, non le tue [[subnets]] configurate. Non provare a regolare RRL modificando le righe delle subnet. Fonte: src/security/rrl.rs.

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 config valida precedente. Crea prima il profilo (warden profile add <p> --display-name <nome>) oppure correggi il refuso (warden subnet set <id> profile <corretto>).

Un reload fallisce con subnets[i] "<id>".cidrs[j] "<c>" is not a valid CIDR. Una modifica a mano ha introdotto un errore. La CLI scrive in forma canonica, quindi questo arriva quasi sempre da una modifica manuale. Esegui warden config lint per vedere tutti i messaggi insieme.

Un reload fallisce con subnets[i] "<id>".cidrs must not be empty. Una riga cidrs = [] non serve a nulla. La mossa giusta è warden subnet remove <id>.

warden subnet set <id> cidrs "" viene rifiutato con cidrs cannot be empty — remove the subnet instead. La CLI rifiuta di scrivere un cidrs vuoto. Passa un elenco non vuoto oppure togli la riga.

warden subnet add <id> risponde subnet "<id>" already exists. Modifica quella esistente (warden subnet set ...) oppure scegli un altro id. Un ricontrollo TOCTOU sul percorso di scrittura intercetta il caso raro in cui lo stesso id compare tra quel controllo e la scrittura. Allora il messaggio cambia: nello stesso file è subnet "<id>" appeared in <file> between the duplicate check and the write; nothing was changed; in un altro file è l’errore di id duplicato del validator.

Un dispositivo riceve il profilo sbagliato: ti aspettavi il livello 3 (gruppo), hai ottenuto il livello 4 (subnet). Esegui warden resolve <ip>. L’output indica il livello del match, l’id da cui arriva e il profilo attivo. Le due cause comuni:

  • Il dispositivo non ha un profile proprio e non è in alcun gruppo, quindi i livelli 1–3 non restituiscono nulla e scatta il livello 4. Ogni gruppo ha un profilo, quindi aggiungere il dispositivo a un gruppo, o impostare profile sul dispositivo, risolve il problema.
  • Il dispositivo è stato declassato per il MAC, oppure ha un ip e nessun mac mentre enforce_device_mac è attivo. Il journal riporta la riga di avviso MAC mismatch — dropping device / group / schedule levels, falling through to subnet / default (o la variante per il solo IP). Aggiungi il MAC osservato al dispositivo, come mac o come uno dei mac_aliases, oppure accetta come policy il fallback sulla subnet mentre il dispositivo è sotto sospetto.

warden subnet set <id> ... risponde subnet "<id>" not found in <path>. La CLI cerca l’id in ogni frammento della config, quindi o l’id è scritto male o --into punta al file sbagliato. Cercalo:

bash
grep -RnE 'id\s*=\s*"<id>"' /etc/purge-warden/subnets.d

Un portatile ospite non mappato riceve RCODE=REFUSED per ogni nome. Nessun livello da 1 a 4 ha trovato un match e [server].default_profile non è impostato. Aggiungi una [[subnets]] che copra il range degli ospiti con un profilo sensato, imposta default_profile a un profilo di ripiego, oppure accetta la policy (impedisce al daemon di inoltrare per conto di sconosciuti).

Due subnet si sovrappongono e vince sempre quella sbagliata. Stessa lunghezza di prefisso: controlla priority e l’ordine degli id. Lunghezze diverse: sta vincendo il prefisso più lungo, ed è voluto. Se vuoi davvero che una regola ampia scavalchi una stretta, la regola ampia deve avere un prefisso più lungo: ristruttura i CIDR invece di combattere il resolver.

Per altro, vedi risoluzione problemi (in inglese).

Vedi anche

  • Profili: ciò a cui si lega una subnet; la catena completa a 5 livelli del resolver.
  • Dispositivi: livello 2 della catena; il modo di fissare un singolo host sopra il livello delle subnet.
  • Gruppi: livello 3; insiemi con nome di dispositivi che condividono un profilo.
  • Pianificazioni: livello 1 (pianificazione attiva); cambi di profilo in base all’orario che, dentro la loro finestra, scavalcano il legame del dispositivo o della subnet.
  • Riferimento CLI: l’intera superficie warden subnet … e warden resolve.
↑↓ per navigare · Invio per aprire · Esc per chiudere Vedi tutti i risultati