IT

SafeSearch

Work in progress — content may be incomplete.

Un bool sul profilo, otto rewrite Strict iniettati a tempo di resolve. Il tablet dei bambini ora vede Google attraverso forcesafesearch.google.com, non perché il browser l’ha chiesto gentilmente.

Cos’è

SafeSearch è un interruttore per-profilo che forza la modalità Strict di SafeSearch su Google, YouTube, Bing e DuckDuckGo per ogni dispositivo assegnato a quel profilo — al livello DNS, senza alcuna cooperazione del client. Impostare safe_search = true su un profilo fa sì che Warden inietti otto regole di rewrite predefinite nella tabella rewrite risolta di quel profilo, all’avvio, su SIGHUP, e ad ogni tick di ricalcolo delle pianificazioni (60 secondi). Ogni query per www.google.com da un dispositivo sul profilo viene risolta come se il client avesse chiesto forcesafesearch.google.com.

Il meccanismo è lo stesso motore ProfileRewriteRules che alimenta i [[profiles.<id>.rewrite_rules]] scritti dall’operatore. SafeSearch si limita a precaricare otto voci curate che l’operatore non deve mantenere.

Quando ti serve

  • Gestisci un profilo kids e vuoi che i Chromebook e i tablet di casa smettano di restituire risultati espliciti su Google Immagini e Bing, senza installare estensioni lato client.
  • Hai una classe o piccola biblioteca che fa girare Warden su un Raspberry Pi e vuoi SafeSearch attivo anche sui dispositivi ospiti che non rispettano una preferenza browser impostata dall’operatore.
  • Vuoi la modalità ristretta di YouTube attiva per i bambini, sapendo che la protezione è solo Strict (restrict.youtube.com) — oggi non esiste un livello Moderate.

Non ti serve SafeSearch quando:

  • Vuoi bloccare del tutto i motori di ricerca. Aggiungi google.com, bing.com, youtube.com nei deny_rules del profilo o in una blocklist — le blocklist sono valutate prima dei rewrite di SafeSearch, quindi il deny vince.
  • Vuoi un override per-dispositivo di un profilo che ha già SafeSearch attivo. SafeSearch segue il profilo; se un dispositivo è sul profilo kids, SafeSearch è attivo per quel dispositivo. Per esentare un dispositivo, dagli un profilo diverso.

Come funziona

SafeSearch non è uno stage di filtro separato. Si innesta nel motore di rewrite esistente attraverso due punti:

  1. A tempo di resolve del profilo (avvio, warden reload, ogni 60 s quando le pianificazioni ricalcolano), ResolvedProfile::build_v1 guarda Profile.safe_search. Quando è true, invoca safesearch::populate() sulla tabella rewrite del profilo, che aggiunge gli otto preset a meno che una voce scritta dall’operatore non rivendichi già lo stesso host from.
  2. Sull’hot path, ogni query attraversa: filter (allow / deny / blocklist) → rewrite → cache lookup → upstream. SafeSearch sta nello step di rewrite, dopo il filter, prima che venga calcolata la chiave di cache. Quindi:
    • Una voce di blocklist per www.youtube.com vince su SafeSearch — la query è bloccata, mai riscritta.
    • Un hit di cache per forcesafesearch.google.com è riutilizzato fra tutti i client sullo stesso profilo.
    • La risposta DNS rimandata al client mantiene il qname originale; solo la lookup verso l’upstream è cambiata. Il client non vede mai il rewrite.
Il rewrite è silenzioso
L’utente vede www.google.com nel browser e nelle risposte di dig. Warden risolve forcesafesearch.google.com verso l’upstream e stampa la risposta sotto il nome originale. È voluto — niente TLS rotto, niente mismatch di certificati, niente effetti collaterali visibili al client.

Sorgenti: src/profiles/safesearch.rs:1-234, src/profiles/profile.rs:486-489, src/dns/handler.rs:894-903, src/dns/rewrite.rs:1-90.

Provider coperti

Ogni preset è una corrispondenza esatta (match_subdomains = false). Gli host gestiti dal vendor sulla destra eseguono il blocco SafeSearch lato loro.

qname originaleRiscritto inLivello
google.comforcesafesearch.google.comStrict
www.google.comforcesafesearch.google.comStrict
www.youtube.comrestrict.youtube.comStrict
m.youtube.comrestrict.youtube.comStrict
www.youtube-nocookie.comrestrict.youtube.comStrict
www.bing.comstrict.bing.comStrict
edgeservices.bing.comstrict.bing.comStrict
duckduckgo.comsafe.duckduckgo.comStrict

Cosa non è coperto:

  • Apex nudo youtube.com e bing.com. Vengono riscritti solo gli host www. — più m.youtube.com, www.youtube-nocookie.com e edgeservices.bing.com. Gli apex nudi sono lasciati intatti di proposito: Google e Microsoft documentano il lock SafeSearch solo per quei nomi specifici, e puntare un apex non documentato sull’host SafeSearch rischia di rompere il sito. L’apex google.com di Google è l’unica eccezione documentata e resta coperto. In pratica è raramente un buco — browser e app di ricerca risolvono l’host www. — ma un client che chiede l’apex nudo riceve una risposta normale.
  • Livello Moderate di YouTube (restrictmoderate.youtube.com). Differito — Strict (restrict.youtube.com) è l’unica opzione YouTube oggi.
  • Superficie API di YouTube (youtubei.googleapis.com, youtube.googleapis.com). Un bambino che guarda la app ufficiale YouTube Kids usa il filtro dei contenuti interno alla app, non un hostname web, quindi l’enforcement a livello DNS non lo raggiunge.
  • Domini Google regionali (google.co.uk, google.it, ecc.). Se un client interroga esplicitamente google.co.uk, la lista non corrisponde. Il subdomain-walk sui preset è stato volutamente saltato per tenere la tabella prevedibile; aggiungi rewrite per-profilo espliciti se ti serve copertura per Paese.

Sorgente: src/profiles/safesearch.rs:80-113.

Schema

SafeSearch è un singolo campo booleano sul profilo:

CampoTipoObbligatorioDefaultScopo
safe_searchboolnofalseQuando true, gli otto rewrite preimpostati vengono iniettati a tempo di resolve.

Non esiste una tabella [safesearch]. Non ci sono interruttori per-provider. Il senso della feature è che è un singolo interruttore.

Sorgente: src/config/schema/profile.rs:123-124.

Esempi

Il profilo kids più piccolo possibile con SafeSearch attivo:

/etc/purge-warden/profiles.d/kids.toml
toml
[profiles.kids]
display_name = "Bambini"
safe_search  = true

Un profilo kids completo che combina SafeSearch e blocklist di contenuti — i due si sommano:

/etc/purge-warden/profiles.d/kids.toml
toml
[profiles.kids]
display_name     = "Bambini"
safe_search      = true
categories       = ["adult-content"]
blocklists       = ["security-malicious"]
block_response   = "nxdomain"
blocked_ttl_secs = 300

Sovrascrivi il preset per uno specifico host mantenendo gli altri sette — i rewrite scritti dall’operatore hanno precedenza:

/etc/purge-warden/profiles.d/kids.toml
toml
[profiles.kids]
display_name = "Bambini"
safe_search  = true

# Reindirizza www.google.com sulla intranet domestica invece che su forcesafesearch.
# Gli altri sette preset SafeSearch continuano ad applicarsi.
[[profiles.kids.rewrite_rules]]
from             = "www.google.com"
to               = "intranet.local"
match_subdomains = false

Ordine di precedenza

L’ordine conta quando SafeSearch convive con altre feature.

  1. Blocklist e deny admin vincono. SafeSearch si trova dopo lo stage del filtro. Se www.youtube.com è in una deny-list attiva per il profilo, la query è bloccata. SafeSearch non arriva mai a riscriverla.
  2. I rewrite scritti dall’operatore vincono sul preset. Quando la stessa coppia (from, match_subdomains) è presente in entrambi, populate() salta il preset e tiene la voce operatore. È così che l’esempio precedente sostituisce solo una delle otto regole.
  3. Le pianificazioni scambiano l’intero profilo. Un dispositivo che passa da default a kids per uno schedule alle 21:00 prende SafeSearch insieme al resto del profilo; tornando indietro alle 07:00 lo lascia. Il cambio è limitato dal tick di 60 secondi delle pianificazioni.
  4. L’overlay per-dispositivo non vede SafeSearch. [[devices]].allow_rules e deny_rules sono regole dello stage di filtro, non rewrite. La allow rule di un dispositivo non può esentare un singolo host search da SafeSearch — il rewrite avviene dopo il filter, e l’overlay del dispositivo partecipa solo allo step di filter.

Sorgenti: src/dns/handler.rs:894-903 (ordine dell’hot path), src/profiles/safesearch.rs:119-134 (logica di collisione).

CLI

Non esiste un sottocomando warden safesearch dedicato. L’attivazione è un edit TOML più un reload:

# 1. Edita il profilo
sudo $EDITOR /etc/purge-warden/profiles.d/kids.toml
#    aggiungi o ribalta: safe_search = true

# 2. Reload
sudo warden reload

Per ispezionare:

# Flag del profilo (la fonte di verità — mostrato verbatim dalla config)
warden profile show kids | grep -i safe

# Verifica a runtime — dovrebbe rispondere con l'indirizzo di forcesafesearch.google.com
dig @127.0.0.1 -p 53 www.google.com

# Cosa restituisce il motore di rewrite per il profilo risolto.
# Nota: warden rewrite list mostra SOLO le regole scritte dall'operatore;
# gli otto preset SafeSearch sono iniettati a tempo di resolve e sono
# nascosti di proposito dalle liste per non sporcare il modello mentale.
warden rewrite list --profile kids
Perché i preset restano nascosti
warden rewrite list e warden profile show omettono volutamente gli otto rewrite SafeSearch anche con safe_search = true. Il bool è il contratto; i preset sono un dettaglio implementativo. Se vuoi sapere cosa viene applicato, questa pagina è il riferimento — l’insieme delle regole è fisso e viaggia con il daemon.

Sorgente: src/profiles/safesearch.rs:21-24.

TUI

Oggi non c’è un tab SafeSearch dedicato. Il flag non compare ancora nel modale di edit dei Dispositivi né nel drilldown dei Profili — modificalo dal TOML e fai warden reload.

È un gap noto; il campo è un bool primitivo e si infila nel form di edit del profilo senza problemi non appena anche il lato TUI si allinea.

API REST

Leggere il flag:

MetodoPathCosa
GET/api/configConfig completa fusa. Il booleano appare come profiles.<id>.safe_search nel payload JSON.

Non esiste un endpoint dedicato POST /api/profile/<id>/safesearch e non c’è una superficie di scrittura per i campi arbitrari del profilo via REST — le mutazioni del profilo sono solo CLI o edit a mano.

Limiti

Vale la pena conoscerli prima di promettere ai genitori che SafeSearch è attivo:

  • Enforcement solo via DNS. Un dispositivo che usa DNS-over-HTTPS (DoH) verso un resolver pubblico (es. browser-level https://dns.google/dns-query) bypassa Warden completamente. Abbina SafeSearch a un blocco di DoH a livello di rete se la cosa è rilevante. Vedi le ricette di blocco DoH (in arrivo).
  • DNS-over-TLS (DoT) sulla porta 853 verso un resolver pubblico è la stessa storia — un client che interroga Quad9 direttamente non passa mai da Warden.
  • Solo livello Strict. YouTube non ha un’opzione Moderate in Warden oggi. Alcune famiglie vogliono Restricted-Moderate; è un gap di config da segnalare, non un workaround.
  • Niente domini Google regionali. google.co.uk, google.it, ecc. passano senza rewrite. Aggiungi voci esplicite [[profiles.<id>.rewrite_rules]] se la tua famiglia li usa.
  • Le superfici SafeSearch delle app mobile sono fuori scopo. L’app Google Search di Android e l’app YouTube Kids di iOS incorporano il loro filtro dei contenuti; SafeSearch a livello DNS intercetta solo gli hostname web elencati sopra.
  • L’IP restituito dall’upstream non è validato. Se un resolver ostile restituisce un IP non-SafeSearch per forcesafesearch.google.com, Warden lo passa al client. Usa un upstream affidabile (Cloudflare, Quad9, il tuo ISP) e valuta di abilitare DNSSEC sul forwarder.

Risoluzione problemi

Un dispositivo sul profilo kids vede ancora risultati immagine per adulti.

  1. Verifica che il dispositivo sia effettivamente sul profilo: warden device show <id> e controlla il campo profile.
  2. Verifica che il flag sia impostato: grep safe_search /etc/purge-warden/profiles.d/*.toml.
  3. Verifica che il daemon abbia preso la modifica: journalctl -u purge-warden -n 50 | grep -i reload.
  4. Verifica il rewrite: dig @127.0.0.1 -p 53 www.google.com deve rispondere con l’IP a cui risolverebbe forcesafesearch.google.com.
  5. Se lo step 4 mostra l’IP reale di www.google.com, il dispositivo sta interrogando l’upstream direttamente — verifica che il DHCP del router pubblicizzi Warden come server DNS e che il dispositivo non abbia un endpoint DoH proprio.

I rewrite SafeSearch e un rewrite scritto dall’operatore puntano allo stesso host.

Vince la voce operatore; il preset è saltato in silenzio. È voluto. Per confermare: edita il TOML rimuovendo il rewrite operatore, fai warden reload, poi dig di nuovo — la risposta deve tornare a quella SafeSearch.

Modalità ristretta di YouTube mostra la barra di avviso ma fa passare comunque alcuni contenuti.

È il comportamento di YouTube, non di Warden. restrict.youtube.com è l’hostname Strict di YouTube; la piattaforma decide cosa ricade dentro Strict. Il contratto di Warden è “instrada l’utente sul livello più severo di YouTube”, non “garantisce che il livello più severo blocchi tutto”.

warden reload ha accettato la modifica ma dig continua a restituire l’host non riscritto.

Il tick di 60 secondi delle pianificazioni è il limite superiore per i rebuild di profilo, ma warden reload dovrebbe ricostruire immediatamente. Verifica che il daemon stia davvero girando con la nuova config:

warden status | grep -i config
journalctl -u purge-warden -n 20 --no-pager

Se i timestamp non corrispondono al reload, il daemon potrebbe non aver acked il SIGHUP — come ultima risorsa fai systemctl restart purge-warden.

Per diagnostica più profonda, vedi risoluzione problemi.

Vedi anche

  • Profili — l’entità che contiene il campo safe_search.
  • Record DNS locali — l’altro modo per scambiare risposte dell’upstream, ma per-record invece che per-vendor.
  • Liste di blocco — lo stage di deny che gira prima di SafeSearch sull’hot path.
  • Ricetta — famiglia — esempio end-to-end di profilo kids.
  • Schema TOML — ogni campo, ogni vincolo.