Un Raspberry Pi può ospitare una piccola applicazione web e renderla raggiungibile attraverso un indirizzo HTTPS, senza aprire una porta in ingresso sul router. Prima di configurare il collegamento serve però una decisione: la pagina deve essere pubblica, oppure deve essere accessibile soltanto a persone autorizzate?
In questa guida realizziamo il secondo caso. Partiamo da una pagina HTML innocua, colleghiamo il Raspberry a Cloudflare Tunnel e usiamo Cloudflare Access per richiedere il login. Poi aggiungiamo un client macchina e l’avvio automatico, come estensioni separate. Ogni passaggio ha un controllo: l’obiettivo è capire dove passa una richiesta e riconoscere quale componente non funziona.
L’esempio può diventare il punto di partenza per un piccolo portale interno, un’anteprima di progetto o un servizio di laboratorio. La pagina dimostrativa serve a verificare il percorso prima di collegare un’applicazione con dati reali.
Che cosa collegano DNS, Tunnel e Access
Il dominio è il nome registrato, per esempio example.com. Il registrar gestisce la registrazione e la delega ai nameserver; il provider DNS autorevole pubblica i record. Possono essere aziende diverse. Usare Cloudflare per il DNS non obbliga a trasferirgli la registrazione del dominio.
Il sottodominio lab.example.com identifica il servizio. Il suo record DNS porta il visitatore a Cloudflare; la route del tunnel associa quel nome all’origine locale, cioè al server HTTP sul Raspberry.
cloudflared è il programma che apre e mantiene le connessioni in uscita dal Raspberry verso Cloudflare. Le richieste arrivano attraverso quel collegamento. Non occorrono un IP pubblico fisso o un servizio di DNS dinamico per questo percorso.
Access decide invece chi può raggiungere l’applicazione. Il browser incontra il controllo di identità prima che la richiesta venga inoltrata all’origine. Nel laboratorio abilitiamo anche la verifica del token Access nel connettore: Cloudflare firma un’attestazione dell’accesso, chiamata JWT, e cloudflared la controlla prima di contattare il server locale.
Il browser usa HTTPS verso Cloudflare; anche il collegamento del tunnel è cifrato. L’ultimo tratto sarà HTTP su 127.0.0.1, all’interno dello stesso Raspberry. Se sposti l’origine su un’altra macchina, devi rivalutare quel tratto e la sua protezione.
Prerequisiti e nomi del laboratorio
Il punto di partenza è un Raspberry già avviato con Raspberry Pi OS o Debian a 64 bit, Bash, systemd, accesso sudo e connessione Internet. L’installazione del sistema operativo e l’accesso SSH iniziale precedono questa guida.
Servono inoltre un account Cloudflare, un dominio che puoi amministrare, accesso al registrar se devi cambiare nameserver e una casella email da autorizzare in Access. La procedura usa una zona DNS in modalità completa, gestita da Cloudflare.
Il laboratorio rientra nel piano DNS Free e in Zero Trust Free, che al momento prevede un limite di 50 utenti. Dominio, hardware e connessione restano costi separati. L’attivazione di Zero Trust richiede di scegliere un piano e inserire i dati di pagamento anche scegliendo Free; Cloudflare specifica che il piano gratuito non comporta un addebito. Controlla le condizioni del piano e i requisiti di attivazione prima di procedere.
Tutti i comandi Linux, compresi i controlli con dig e curl, vanno eseguiti sul Raspberry di laboratorio. Puoi usare tre terminali o sessioni SSH: uno per il server web, uno per il connettore e uno per i controlli. Per le prove da una connessione esterna basta il browser di un altro dispositivo.
example.com è un dominio riservato alla documentazione. Sostituisci lab.example.com con un sottodominio libero del tuo dominio, mantenendo lo stesso nome in DNS, Access, route e comandi.
Controlla l’ambiente:
cat /etc/os-release
dpkg --print-architecture
getconf LONG_BIT
systemctl --versionSul Raspberry previsto qui, l’architettura dei pacchetti è arm64 e la dimensione è 64. Non installare un pacchetto amd64 seguendo istruzioni per un normale PC.
Installa sul laboratorio gli strumenti usati nei passaggi successivi, se mancanti:
sudo apt-get update
sudo apt-get install python3 curl ca-certificates dnsutils iproute2La rete deve consentire DNS e le connessioni in uscita del tunnel sulla porta 7844: UDP per QUIC e TCP per HTTP/2. Il protocollo automatico può ripiegare su HTTP/2 se UDP non è disponibile. Per la verifica Access serve anche HTTPS in uscita verso il dominio della tua organizzazione NOME_TEAM.cloudflareaccess.com. Un firewall restrittivo deve seguire la lista ufficiale delle destinazioni Cloudflare. Non aprire 18080 sul router: è la porta locale dell’esempio.
Scegliere il dominio e decidere dove registrarlo
Per il laboratorio useremo un indirizzo come lab.example.com. Registri il dominio example.com; lab è un sottodominio che crei nella sua zona DNS. Non serve acquistare un dominio per ciascuna applicazione.
Cloudflare comprende servizi diversi: può registrare il dominio, gestirne il DNS, ricevere le richieste web e controllare chi accede all’applicazione. In questa guida useremo DNS, Tunnel e Access. La registrazione presso Cloudflare è facoltativa.
Il percorso dipende da dove parti:
| Situazione | Operazione necessaria |
|---|---|
| Hai già un dominio attivo su Cloudflare | Controlla i record esistenti e passa alla configurazione del laboratorio. |
| Hai un dominio registrato altrove | Mantieni la registrazione dove si trova, aggiungi la zona a Cloudflare e cambia i nameserver presso il registrar. |
| Non hai un dominio | Registrane uno con Cloudflare Registrar oppure con un registrar che consenta di usare nameserver esterni. |
Il registrar continua a occuparsi del rinnovo del nome. Spostare il DNS a Cloudflare non sposta il sito su un altro hosting e non trasferisce le caselle email: i record devono continuare a indicare i rispettivi servizi.
Registrare un dominio nuovo
Puoi acquistarlo direttamente dalla dashboard Cloudflare, in Domains → Registrations → Buy domain. Si apre Register domain: cerca il nome, confronta le disponibilità e seleziona quello che vuoi acquistare. Prima di confermare controlla prezzo iniziale, rinnovo, durata e contatti del registrante. Il dominio è a pagamento anche se userai il piano DNS Free.
Cloudflare non registra tutte le estensioni: consulta l’elenco dei TLD supportati. Il prezzo dipende dal nome e dall’estensione; non va dedotto dal costo di un altro dominio.
Completa le verifiche email richieste e controlla il rinnovo automatico, attivo per impostazione predefinita. I domini acquistati tramite Cloudflare Registrar usano già i nameserver Cloudflare. Finché la registrazione rimane lì, non puoi sostituirli con quelli di un altro provider DNS. La procedura ufficiale di registrazione descrive requisiti e conferma dell’acquisto.
Puoi anche registrare il dominio presso un altro fornitore. Verifica prima che permetta di modificare i nameserver: sarà quel pannello, non quello dell’hosting o del Raspberry, a servirti per la delega del passaggio seguente.
Collegare a Cloudflare un dominio esistente
Nel percorso scelto qui, chiamato full setup, i nameserver autorevoli del dominio devono diventare quelli assegnati da Cloudflare. La registrazione può rimanere presso il fornitore attuale. È il setup ordinario disponibile con il piano DNS Free; la documentazione distingue anche altri tipi di configurazione, che non seguiremo in questo laboratorio. Full setup.
Nella dashboard osservata per questa guida il percorso è Domains → Overview → Add domain → Connect a domain. Alcune versioni della documentazione lo chiamano Onboard a domain. Scegli il collegamento del dominio: Transfer a domain trasferirebbe invece la registrazione.
Inserisci il dominio principale, per esempio example.com, senza https://, percorsi o lab. Nel riquadro Import DNS records puoi scegliere la scansione automatica, l’inserimento manuale oppure un file di zona. Per partire da un dominio già utilizzato, la scansione è un aiuto, ma va confrontata con i record del provider attuale.

Importazione DNS: la scansione automatica trova i record comuni. Le altre opzioni sono inserimento manuale e importazione di un file di zona.
Prosegui con Continue e scegli il piano Free quando richiesto. L’onboarding può mostrare anche opzioni sui crawler e sul file robots.txt: riguardano il comportamento del sito e non realizzano la delega DNS. Valutale per il tuo sito senza confonderle con l’autorizzazione degli utenti in Access.
Prima di cambiare nameserver, salva l’inventario DNS e verifica in Cloudflare:
- i record del sito principale, di
wwwe degli altri sottodomini utilizzati; - i record di posta MX, SPF, DKIM e DMARC;
- le verifiche TXT e gli eventuali record CAA richiesti dai servizi esistenti.
Mantieni i valori indicati dai rispettivi provider. La scansione può omettere nomi personalizzati, compresi alcuni record DKIM: un’importazione incompleta può interrompere sito o posta quando cambia il DNS autorevole. Limiti della scansione automatica.
Controlla anche Proxy status dei record A, AAAA e CNAME importati. Proxied, con la nuvola arancione, fa passare il traffico web attraverso Cloudflare; DNS only, con la nuvola grigia, restituisce il record senza usare il proxy. Gli indirizzi dei server di posta e i CNAME usati per verifiche o DKIM devono restare DNS only secondo le istruzioni del provider. MX e TXT non possono essere proxati. Per il sito esistente verifica la compatibilità indicata dal suo hosting prima di attivare il proxy; il CNAME del laboratorio, creato più avanti dal tunnel, sarà invece Proxied. Limiti del proxy DNS.
Cambiare i nameserver presso il registrar
Cloudflare mostra i nameserver assegnati alla tua zona durante l’attivazione; puoi ritrovarli nella pagina Overview del dominio. Copia quelli indicati per la tua zona, senza riutilizzare valori trovati in un’altra guida.
Prima della sostituzione controlla DNSSEC. Questa protezione firma i dati DNS; il record DS presso il registrar collega la delega alle chiavi della zona. Il TTL indica quanto un dato può restare in cache.
Se DNSSEC è attivo, completa prima questo passaggio con le istruzioni del tuo registrar:
- Prima delle modifiche, recupera e annota il TTL originario del DS e quello della delega NS precedente. Se il pannello non li espone, chiedili al registrar o al provider DNS: il TTL residuo restituito da un resolver non basta per stimare l’intera attesa.
- Rimuovi il vecchio DS e fatti confermare che la rimozione è stata pubblicata nella zona superiore. Conta da quel momento l’intero TTL annotato del DS, non dal clic nel pannello.
- Cambia nameserver solo dopo quell’attesa e la conferma dell’assenza del vecchio DS. Dopo la pubblicazione della nuova delega, attendi anche il TTL dei precedenti NS prima di aggiungere il nuovo DS.
Se non riesci a ottenere tempi e conferme, fai completare la migrazione dal provider prima di proseguire. Un DS ancora legato alle vecchie chiavi può rendere il dominio irraggiungibile.
Apri quindi il pannello del registrar e cerca la gestione Nameserver, spesso nelle impostazioni del dominio. Sostituisci i precedenti con quelli assegnati da Cloudflare e salva. Nel full setup ordinario non mantenere un insieme misto di nameserver vecchi e nuovi. I nomi dei menu dipendono dal registrar; Cloudflare raccoglie le istruzioni per i provider più comuni.
Non devi aggiungere un record A verso il Raspberry per effettuare questo passaggio. Non devi neppure inserire 1.1.1.1: è un resolver pubblico usato dai dispositivi per le ricerche DNS, non il nameserver autorevole assegnato al tuo dominio.
Torna su Cloudflare e attendi lo stato Active. Pending Nameserver Update indica che la delega non è ancora stata verificata. Dopo il cambio e la scadenza del TTL dei precedenti nameserver, abilita DNSSEC in Cloudflare e pubblica il nuovo DS secondo la procedura del registrar. Questo percorso di migrazione comporta un intervallo senza protezione DNSSEC. Sequenza DNSSEC.
Verificare la delega e i servizi esistenti
Dal terminale dei controlli sul Raspberry:
dig +short NS example.com
dig +short MX example.com
dig +short TXT example.com
dig +short DS example.comConfronta i nameserver con quelli assegnati da Cloudflare e i record di posta con l’inventario iniziale. Cache e TTL possono ritardare i risultati. Le query aiutano il confronto, ma non costituiscono da sole una validazione della catena DNSSEC.
Verifica anche che il sito si apra e che la posta continui a funzionare. Solo dopo passa al laboratorio. In seguito, i record del dominio si gestiranno in DNS → Records su Cloudflare: modificare la vecchia zona presso il registrar non aggiornerà più il DNS autorevole.
Non creare ora un record con l’IP di casa. Più avanti, la route del tunnel collegherà lab.example.com al connettore e la dashboard creerà il relativo record DNS.
Avviare un’origine che possiamo riconoscere
Prima del tunnel, facciamo funzionare il servizio locale. Controlla che la porta scelta sia libera:
ss -lnt 'sport = :18080'Non deve comparire un listener. Se la porta è occupata, individua il servizio esistente e scegli un’altra porta, aggiornando tutti i riferimenti della guida.
Nel primo terminale crea una directory nuova. Il blocco si ferma se esiste già, così non sovrascrive una tua applicazione:
(
set -eu
mkdir "$HOME/tunnel-lab"
cat > "$HOME/tunnel-lab/index.html" <<'HTML'
<!doctype html>
<html lang="it">
<head>
<meta charset="utf-8">
<title>Laboratorio Cloudflare Tunnel</title>
</head>
<body>
<h1>Origine del laboratorio raggiunta</h1>
<p>Questa pagina contiene soltanto dati dimostrativi.</p>
</body>
</html>
HTML
)Hai scritto tu index.html; nessun installer lo genera. Avvia il server e lascia aperto il terminale:
python3 -m http.server 18080 \
--bind 127.0.0.1 \
--directory "$HOME/tunnel-lab"Da un altro terminale sullo stesso Raspberry:
curl --fail --show-error http://127.0.0.1:18080/
ss -lnt 'sport = :18080'Devi ricevere l’HTML con Origine del laboratorio raggiunta e vedere l’ascolto su 127.0.0.1:18080. 0.0.0.0 o [::] indicherebbero un’esposizione diversa da quella progettata.
La directory web deve contenere soltanto la pagina dimostrativa: niente token, backup, file .env o collegamenti simbolici a directory private. Il server HTTP di Python è adatto a questa prova, non a un’applicazione di produzione.
Installare cloudflared dal repository ufficiale
La guida usa un tunnel gestito da remoto: route e impostazioni stanno nella dashboard Cloudflare. Il Raspberry conserva il programma e il token necessario a collegarsi. Non dobbiamo creare un file locale config.yml, eseguire tunnel login o generare le credenziali di un tunnel gestito localmente.
Controlla prima se il programma e il repository sono già presenti:
command -v cloudflared || true
grep -R "pkg.cloudflare.com" \
/etc/apt/sources.list /etc/apt/sources.list.d 2>/dev/null || trueSe trovi una configurazione esistente, riusala e verifica che sia il repository stabile corrente. Non aggiungerne un duplicato. Per un’installazione nuova, il blocco seguente crea i due file indicati e si ferma se uno esiste già:
(
set -eu
set -o pipefail
test ! -e /usr/share/keyrings/cloudflare-main.gpg
test ! -e /etc/apt/sources.list.d/cloudflared.sources
LAB_KEY=$(mktemp)
trap 'rm -f -- "$LAB_KEY"' EXIT
curl --fail --show-error --silent \
--output "$LAB_KEY" \
https://pkg.cloudflare.com/cloudflare-main.gpg
sudo install -d -m 0755 /usr/share/keyrings
sudo install -m 0644 "$LAB_KEY" /usr/share/keyrings/cloudflare-main.gpg
sudo tee /etc/apt/sources.list.d/cloudflared.sources >/dev/null <<'APT'
Types: deb
URIs: https://pkg.cloudflare.com/cloudflared
Suites: any
Components: main
Signed-By: /usr/share/keyrings/cloudflare-main.gpg
APT
sudo apt-get update
sudo apt-get install cloudflared
)La chiave e la definizione del repository riguardano APT, non il tunnel. Usa la chiave pubblicata oggi dal repository ufficiale, evitando vecchie istruzioni con apt-key.
Verifica il risultato:
command -v cloudflared
cloudflared --version
cloudflared tunnel run --helpI comandi successivi assumono /usr/bin/cloudflared, il percorso del pacchetto. Se il tuo è diverso, correggi anche le unità systemd. L’opzione --token-file richiede la versione 2025.4.0 o successiva: deve comparire nell’help. Annota la versione effettiva del tuo laboratorio, anziché dedurla dal giorno in cui hai seguito la guida.
Configurare Access prima di pubblicare la route
Apri Zero Trust dall’account Cloudflare. Se non hai ancora un’organizzazione, completa la configurazione iniziale e scegli il nome del team. Quel nome forma il dominio NOME_TEAM.cloudflareaccess.com; non è il tuo sottodominio applicativo.
Per il laboratorio scegliamo il codice monouso via email. Nelle nuove organizzazioni va aggiunto esplicitamente in Integrations → Identity providers → Add new identity provider → One-time PIN. Chi controlla quella casella può ricevere i codici: proteggila con una password unica e l’autenticazione a più fattori del provider email. Configurazione One-time PIN.
Ora crea l’applicazione dalla sezione Zero Trust → Access controls → Applications. Nella dashboard corrente:
- Premi Create new application, scegli Self-hosted and private e prosegui con Continue with Self-hosted and private.
- In Application details → Destinations, configura il public hostname. Con i campi separati inserisci
labin Subdomain e seleziona il dominio attivo. Se usi Switch to custom input, inserisci invece l’hostname completolab.example.com, come nella schermata. - Lascia vuoto Path: la protezione deve coprire l’intero hostname. Il campo del nome non crea da solo un server o un tunnel: dichiara quale destinazione proteggerà Access.

Applicazione Access: l’hostname completo in modalità custom input. Il nome mostrato è dimostrativo. Usa un hostname appartenente al dominio già attivo nel tuo account Cloudflare; il record del tunnel verrà creato più avanti con la route.
Scorri fino a Access policies e premi Create new policy. In Include, scegli il selettore Emails e inserisci l’indirizzo preciso da autorizzare. Dai alla policy un nome riconoscibile, per esempio Tunnel lab browser, e mantieni l’azione Allow.
Una regola Include ammette chi soddisfa quel criterio. Qui l’elenco deve contenere le sole email previste; il placeholder della schermata non è un indirizzo da autorizzare. Le regole Require aggiungono condizioni da soddisfare insieme, mentre Exclude esclude identità o condizioni specifiche. Per questo primo laboratorio basta l’elenco esplicito delle email.

Regola Access: selettore Emails e azione Allow. Il campo email e il nome della policy sono da compilare; qui non compaiono identità reali.
Lascia Policy session duration su Same as application session duration e salva la policy con Save policy. Controlla che risulti associata all’applicazione.
Nella sezione Authentication → Identity, scegli One-time PIN. Se è attivo Accept all available identity providers, disattivalo per selezionare esplicitamente questo metodo nel laboratorio. Il PIN via email è un metodo di login; è la policy Emails a stabilire quali indirizzi sono ammessi. Avere accesso a una casella qualsiasi non deve bastare.
Infine, in Details, imposta Name a Tunnel lab e Session Duration a un’ora per l’esempio. Rileggi destinazione, policy e metodo di autenticazione, poi salva l’applicazione con Create. Le schermate mostrano i campi del modulo, non una configurazione già attiva.
La durata scelta limita la validità del token per l’applicazione. Alla scadenza Access ricontrolla le policy; se la sessione globale di identità è ancora valida, può rinnovare l’accesso senza chiedere un nuovo codice. La gestione delle sessioni distingue questi due tempi.
Per questo risultato non usare una regola Bypass o un’autorizzazione Everyone. Controlla anche che non ci siano altre applicazioni o regole già associate al nome scelto.
L’applicazione Access va preparata prima della route pubblica: salvare la route rende raggiungibile l’endpoint. Access e la route devono riferirsi esattamente allo stesso hostname.
Recupera inoltre due valori per la validazione nel connettore:
- Il team name, visibile nelle impostazioni Zero Trust: il prefisso di
NOME_TEAM.cloudflareaccess.com. - L’Application Audience (AUD) Tag, in Access controls → Applications → Configure → Additional settings per l’app appena creata.
L’AUD identifica l’applicazione per cui il token Access è valido. Non è il token del tunnel.
Creare il tunnel e conservare il suo token
Nella dashboard Cloudflare apri Networking → Tunnels → Create a tunnel e crea un tunnel cloudflared dedicato, per esempio raspberry-lab.
Il pannello mostra le istruzioni di installazione e il token del connettore. Conserva quel token nel tuo gestore dei segreti. In questa procedura non eseguire anche cloudflared service install: prima avviamo il connettore in foreground; più avanti creeremo un servizio dedicato.
Nel secondo terminale Bash sul Raspberry, salva soltanto il token con input nascosto:
(
set -eu
set +x
umask 077
mkdir -m 0700 "$HOME/tunnel-lab-secrets"
read -r -s -p "Token del tunnel di laboratorio: " LAB_TUNNEL_TOKEN
printf '\n'
test -n "$LAB_TUNNEL_TOKEN"
printf '%s' "$LAB_TUNNEL_TOKEN" \
> "$HOME/tunnel-lab-secrets/tunnel.token"
unset LAB_TUNNEL_TOKEN
)Il file contiene il solo token, senza TOKEN=, virgolette o JSON. È fuori dalla directory servita da Python e viene creato con permessi ristretti. Non inserire il segreto direttamente nel comando, in Git o in uno screenshot.
Avvia il connettore:
/usr/bin/cloudflared tunnel --no-autoupdate run \
--token-file "$HOME/tunnel-lab-secrets/tunnel.token"Lascia aperto il terminale e verifica nella dashboard che il tunnel risulti Healthy. Questo conferma la connessione al connettore; il servizio web non è ancora stato verificato attraverso il tunnel. Il parametro token-file evita il segreto negli argomenti del processo.
Associare hostname, origine e validazione Access
Dalla dashboard apri Networking → Tunnels, seleziona il tunnel dedicato al laboratorio e vai in Routes → Add route → Published application. Questo passaggio associa un nome pubblico al servizio locale. Nel modulo Add published application imposta:
| Campo | Valore del laboratorio |
|---|---|
| Subdomain | lab |
| Domain | Il tuo dominio attivo, rappresentato qui da example.com |
| Path | Vuoto |
| Service URL | http://127.0.0.1:18080 |

Route del tunnel: hostname pubblico e Service URL sono due campi distinti. I valori grigi sono placeholder dell’interfaccia; per questa guida il Service URL indica il server HTTP di loopback sulla porta 18080, come riportato nel testo.
Il campo Domain può essere precompilato: verifica che sia la zona che vuoi utilizzare. Il Service URL indica ciò che il connettore deve raggiungere sul Raspberry, non l’indirizzo pubblico che aprirai nel browser.
Nelle Additional application settings, abilita Protect with Access e inserisci team name e AUD dell’applicazione creata prima. Il controllo deve essere richiesto. In questo modo cloudflared verifica firma, emittente e destinatario del JWT Access prima di inoltrare la richiesta. Non occorre aggiungere un file YAML locale per queste impostazioni remote. Parametri Access dell’origine.
Dopo avere verificato hostname, origine e validazione Access, conferma con Add route. Da questo momento l’endpoint può essere raggiunto: per questo l’applicazione Access deve essere già pronta.
Torna al dominio in Domains e apri DNS → Records. Nel setup completo la dashboard configura il record collegato alla route:
| Tipo | Nome | Destinazione | Stato |
|---|---|---|---|
| CNAME | lab | ID_DEL_TUNNEL.cfargotunnel.com | Proxied |
Usa l’identificatore del tuo tunnel, generato da Cloudflare. Non inserire l’IP privato del Raspberry o l’IP pubblico di casa. Se il nome ha già un record incompatibile, risolvi quel conflitto; non aggiungere una seconda definizione alla cieca. Creazione del tunnel e della route.
127.0.0.1 funziona perché il connettore e Python girano sullo stesso host. In un container, localhost indicherebbe il container stesso: per collegare due container servirebbe una rete condivisa e il nome del servizio. Qui evitiamo Docker e un reverse proxy perché non servono a dimostrare questo collegamento.
Verificare il percorso completo
Dal terminale dei controlli sul Raspberry, con il vero hostname del laboratorio:
dig +short lab.example.com A
dig +short lab.example.com AAAA
curl --silent --show-error --max-time 15 \
--dump-header - --output /dev/null \
https://lab.example.com/Con il proxy attivo, DNS può restituire indirizzi Cloudflare invece di mostrare il target CNAME del tunnel. Il target si controlla nella zona DNS.
La richiesta curl non include credenziali e non segue i redirect: deve incontrare Access, non ottenere la pagina del laboratorio. Un 302 verso il login è un risultato previsto per il percorso browser, non una prova di guasto.
Apri poi una finestra privata del browser, visita l’hostname, inserisci l’email autorizzata e usa il codice ricevuto. Il risultato positivo è la frase Origine del laboratorio raggiunta dopo il login. Vedere soltanto la schermata Access dimostra che hai raggiunto il controllo di accesso, non il backend.
Per provare un’identità esclusa, chiudi tutte le finestre private e aprine una nuova, oppure usa un profilo browser separato senza sessioni Access. Una seconda scheda privata può condividere il login già riuscito e falsare il controllo.
Completa queste prove sul laboratorio:
| Prova | Risultato da verificare |
|---|---|
curl locale su 127.0.0.1:18080 | HTML del laboratorio |
| Browser senza sessione | Login o rifiuto, senza contenuto dell’origine |
| Email autorizzata e codice valido | Pagina del laboratorio |
| Email non inclusa nella policy | Nessun accesso alla pagina |
Listener locale con ss | Solo 127.0.0.1:18080 |
| Da un altro dispositivo LAN verso IP del Raspberry e porta 18080 | Nessuna risposta dell’origine su quella porta |
Per l’ultimo controllo usa l’indirizzo LAN del Raspberry di laboratorio. Il bind loopback riguarda questo server: non certifica l’esposizione di ogni altro servizio del Raspberry.
Con One-time PIN, il messaggio che annuncia l’invio del codice può apparire anche per un indirizzo escluso. Non aspettarti quindi sempre un 403 immediato: il criterio è che quell’identità non ottenga il contenuto.
Esegui il controllo pubblico anche attraverso una connessione indipendente, per esempio il browser di un telefono sulla rete mobile. Poi prova due guasti separati: ferma Python con Ctrl+C, controlla l’errore e riavvialo con lo stesso comando; solo dopo ferma cloudflared e ripeti la prova. Questa sequenza permette di distinguere un’origine assente da un tunnel scollegato.
Prima di proseguire, riavvia anche cloudflared con il comando tunnel --no-autoupdate run --token-file già usato. Attendi lo stato Healthy e verifica di nuovo la frase del laboratorio nel browser autenticato.
Estensione: autorizzare uno script
Un browser usa un’identità personale; uno script può usare un Access service token, composto da Client ID e Client Secret. Il token che hai salvato sul Raspberry serve invece ad avviare il tunnel. Sono credenziali diverse.
In Access controls → Service credentials → Service Tokens, crea un token dedicato al laboratorio e scegli una durata. Salva il secret quando viene mostrato. Nell’applicazione Tunnel lab aggiungi una policy separata con azione Service Auth, includendo quello specifico service token. Mantieni la policy personale per il browser.
Puoi eseguire la prova dal terminale dei controlli sul Raspberry. Per usare un altro computer servono Bash e curl già disponibili; il browser da solo non esegue questo blocco.
Il client invia CF-Access-Client-Id e CF-Access-Client-Secret a ogni richiesta. Questo blocco Bash nasconde il Client Secret durante l’inserimento e passa gli header a curl attraverso standard input:
(
set -eu
set +x
read -r -p "Hostname del laboratorio: " LAB_HOST
read -r -p "Access Client ID: " LAB_ACCESS_ID
read -r -s -p "Access Client Secret: " LAB_ACCESS_SECRET
printf '\n'
test -n "$LAB_HOST"
test -n "$LAB_ACCESS_ID"
test -n "$LAB_ACCESS_SECRET"
printf 'header = "CF-Access-Client-Id: %s"\nheader = "CF-Access-Client-Secret: %s"\n' \
"$LAB_ACCESS_ID" "$LAB_ACCESS_SECRET" \
| curl --config - --fail --silent --show-error --max-time 15 \
"https://$LAB_HOST/"
unset LAB_ACCESS_ID LAB_ACCESS_SECRET
)Inserisci nel primo campo solo l’hostname, senza https:// o percorso. Non usare modalità verbose o shell tracing con credenziali reali. Per una CI, affidale al gestore dei segreti della piattaforma.
Con credenziali valide devi ottenere la stessa pagina; con un secret errato non devi ottenerla. La modalità strict service token authentication, obbligatoria per le organizzazioni create dal 5 ottobre 2026, restituisce 401 o 403 sui fallimenti invece di rimandare al login e non rilascia il cookie browser. Nelle organizzazioni precedenti il comportamento dipende dall’impostazione. Service token e modalità strict.
Mantieni Protect with Access anche per questo percorso: il JWT inoltrato al connettore può attestare l’autenticazione tramite service token, senza richiedere un cookie browser. Token applicativi Access.
La pagina statica non ha un secondo login. Se la sostituisci con un’applicazione che richiede un proprio token o una sessione, quel controllo resta separato: superare Access non assegna automaticamente i permessi applicativi.
Estensione: riavviare automaticamente il laboratorio
Finora la chiusura dei terminali ferma i processi. Per mantenere il laboratorio dopo il logout o un riavvio servono due servizi, uno per l’origine e uno per il tunnel.
La configurazione seguente usa due account senza login e directory dedicate. Rimane un laboratorio persistente: rendere persistente http.server non lo trasforma in un server di produzione.
Prima verifica che questi nomi e percorsi siano liberi. Se trovi risorse esistenti, fermati e scegli nomi diversi in tutti i comandi:
getent passwd tunnel-lab-web || true
getent passwd tunnel-lab-connector || true
getent group tunnel-lab-web || true
getent group tunnel-lab-connector || true
sudo ls -ld /srv/tunnel-lab /etc/cloudflared-lab \
/etc/systemd/system/tunnel-lab-web.service \
/etc/systemd/system/tunnel-lab-connector.service 2>/dev/null || trueCrea gli account e copia soltanto i file necessari:
sudo useradd --system --user-group --home-dir /nonexistent \
--shell /usr/sbin/nologin tunnel-lab-web
sudo useradd --system --user-group --home-dir /nonexistent \
--shell /usr/sbin/nologin tunnel-lab-connector
sudo install -d -o root -g root -m 0755 /srv/tunnel-lab
sudo install -o root -g root -m 0644 \
"$HOME/tunnel-lab/index.html" /srv/tunnel-lab/index.html
sudo install -d -o root -g tunnel-lab-connector -m 0750 \
/etc/cloudflared-lab
sudo install -o root -g tunnel-lab-connector -m 0640 \
"$HOME/tunnel-lab-secrets/tunnel.token" \
/etc/cloudflared-lab/tunnel.tokenL’account web può leggere la pagina, ma non il token del connettore. Quest’ultimo è leggibile dal gruppo del connettore e modificabile da root.
Scrivi la prima unità completa:
sudo tee /etc/systemd/system/tunnel-lab-web.service >/dev/null <<'UNIT'
[Unit]
Description=Tunnel lab demonstration website
[Service]
Type=simple
User=tunnel-lab-web
Group=tunnel-lab-web
ExecStart=/usr/bin/python3 -m http.server 18080 --bind 127.0.0.1 --directory /srv/tunnel-lab
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
[Install]
WantedBy=multi-user.target
UNITPoi il connettore:
sudo tee /etc/systemd/system/tunnel-lab-connector.service >/dev/null <<'UNIT'
[Unit]
Description=Cloudflare Tunnel lab connector
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=tunnel-lab-connector
Group=tunnel-lab-connector
ExecStart=/usr/bin/cloudflared tunnel --no-autoupdate run --token-file /etc/cloudflared-lab/tunnel.token
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
[Install]
WantedBy=multi-user.target
UNITSono file scritti da te, non generati da Cloudflare. I percorsi assoluti evitano di dipendere dalla directory della shell; ProtectHome=true spiega perché i servizi usano /srv e /etc invece dei file sotto la tua home. Le restrizioni sul filesystem riducono le scritture disponibili ai processi. Ambiente di esecuzione systemd.
Ferma con Ctrl+C i due processi ancora in foreground. Prima valida le unità:
sudo systemd-analyze verify \
/etc/systemd/system/tunnel-lab-web.service \
/etc/systemd/system/tunnel-lab-connector.serviceSe la verifica segnala errori relativi alle due unità, correggili e ripetila. Solo dopo una verifica riuscita avvia i servizi:
sudo systemctl daemon-reload
sudo systemctl enable --now tunnel-lab-web.service tunnel-lab-connector.service
systemctl is-active tunnel-lab-web.service tunnel-lab-connector.service
systemctl is-enabled tunnel-lab-web.service tunnel-lab-connector.serviceI risultati attesi sono active e enabled per entrambi. Ripeti il controllo locale e quello pubblico con login.
Per leggere lo stato e gli ultimi messaggi:
sudo systemctl status tunnel-lab-web.service tunnel-lab-connector.service --no-pager
sudo journalctl -u tunnel-lab-web.service -u tunnel-lab-connector.service \
-n 80 --no-pagerRestart=on-failure permette a systemd di riavviare un processo terminato con errore; enable lo configura per il boot. Non significa che un comando esplicito di stop debba essere annullato, né garantisce disponibilità se mancano alimentazione o connessione. Comportamento dei servizi systemd.
Su un laboratorio che puoi interrompere, riavvia il Raspberry con sudo reboot. Dopo esserti ricollegato, controlla di nuovo stato, listener, risposta locale e accesso pubblico. Il test dopo reboot è parte del risultato promesso da questa estensione.
Leggere gli errori senza cambiare tutto insieme
| Sintomo | Primo controllo utile |
|---|---|
| Il nome non risolve | Delega attiva, record nella zona autorevole e hostname digitato |
Redirect 302 verso Access | È richiesto il login; non trattarlo come risposta API riuscita |
| Nessun accesso dopo il login | Policy, identità scelta e durata della sessione |
| Rifiuto del connettore dopo Access | Team name, AUD e raggiungibilità delle chiavi di validazione |
502 relativo all’origine Tunnel | Python attivo, porta, protocollo e risposta locale |
Errore Cloudflare 1033 | Connettore disponibile, sua rete in uscita e tunnel selezionato |
| Service token respinto | Client ID/Secret, scadenza, policy Service Auth e modalità strict |
| Funziona fino alla chiusura della shell | Il processo è ancora in foreground o manca uno dei due servizi |
| Funziona sull’host, non nel container | Il localhost del container non è quello dell’host |
Lo stato Healthy del tunnel e un 200 restituito dal servizio locale sono prove di due tratti diversi. Per verificare l’intero percorso serve la risposta corretta all’hostname pubblico dopo l’autenticazione. Anche un singolo codice HTTP va letto insieme alla pagina restituita e ai log del componente. Diagnostica ufficiale Tunnel.
Manutenzione e passaggio a un’applicazione reale
Per aggiornare il pacchetto installato da APT, in una finestra in cui puoi interrompere il laboratorio:
sudo apt-get update
sudo apt-get install --only-upgrade cloudflared
cloudflared --versionSe hai configurato l’estensione systemd, riavvia il connettore con sudo systemctl restart tunnel-lab-connector.service. Se lo esegui ancora nel terminale, fermalo con Ctrl+C e rilancialo con il comando tunnel --no-autoupdate run --token-file già usato. In entrambi i casi attendi Healthy e ripeti i controlli di accesso.
--no-autoupdate rende esplicito che il ciclo di aggiornamento è gestito attraverso il pacchetto e il servizio.
La rotazione del token del tunnel e la scadenza di un service token Access sono operazioni diverse. Dopo aver sostituito il token del connettore nel suo file, riavvia il connettore con la modalità scelta, servizio systemd o processo nel terminale, perché lo rilegga. La rotazione del tunnel token non chiude da sola tutte le connessioni già stabilite: considera tutte le repliche quando pianifichi la sostituzione.
Per un servizio reale, sostituisci Python con un’applicazione mantenuta, definisci aggiornamenti, backup dei suoi dati e una prova di ripristino. Verifica le autorizzazioni dell’applicazione oltre ad Access. Se pubblichi porte Docker, controlla l’esposizione effettiva: una porta pubblicata e le sole regole del firewall host possono dare un quadro diverso da quello che immagini.
Un Raspberry domestico dipende da alimentazione, storage e connessione. Per un servizio con obblighi di disponibilità, confronta questi costi operativi con un hosting gestito prima di scegliere dove farlo vivere.
Quando conviene un accesso privato
Il tutorial crea un hostname pubblico il cui contenuto è protetto. Per amministrare risorse riservate da pochi dispositivi controllati può essere più adatto un percorso di rete privato.
| Scelta | Chi raggiunge il servizio | Cosa richiede al client |
|---|---|---|
| Cloudflare Tunnel con Access | Persone o automazioni ammesse all’hostname pubblico | Browser o credenziali macchina |
| Tailscale Serve | Utenti e dispositivi della tailnet secondo le policy | Accesso autorizzato alla tailnet |
| Twingate | Utenti autorizzati alla specifica Resource | Client e percorso tramite Connector |
| Cloudflare private routing | Client ammessi alle route private configurate | Cloudflare One Client e policy coerenti |
Tailscale Serve e Tailscale Funnel rispondono a esigenze diverse: Funnel pubblica verso Internet, Serve serve la tailnet. Twingate organizza l’accesso attorno a risorse e autorizzazioni; il suo Connector deve poter raggiungere l’origine. Queste alternative richiedono una configurazione propria e non si ottengono cambiando soltanto una policy Access.
Se migri a un accesso privato, controlla che la precedente route pubblica non resti aperta per errore. Per un contenuto deliberatamente pubblico, invece, Tunnel può essere usato senza Access: è una scelta adatta a un sito pensato per visitatori anonimi, non una soluzione a un errore di autenticazione del laboratorio.
Rimuovere il laboratorio senza toccare gli altri servizi
Dal pannello Cloudflare rimuovi la published application route del laboratorio e verifica la rimozione del relativo record DNS. Fallo prima di cancellare l’applicazione Access. Poi elimina l’app Access dedicata, revoca l’eventuale service token e cancella il tunnel quando non ha altri utilizzi. Non rimuovere policy riutilizzate da altre applicazioni o la zona DNS del dominio.
Se hai usato solo i processi in foreground, fermali con Ctrl+C. Se hai completato l’estensione systemd:
sudo systemctl disable --now tunnel-lab-connector.service tunnel-lab-web.service
sudo rm -- \
/etc/systemd/system/tunnel-lab-connector.service \
/etc/systemd/system/tunnel-lab-web.service
sudo systemctl daemon-reload
sudo rm -- /etc/cloudflared-lab/tunnel.token /srv/tunnel-lab/index.html
sudo rmdir /etc/cloudflared-lab /srv/tunnel-lab
sudo userdel tunnel-lab-connector
sudo userdel tunnel-lab-webControlla con getent group se sono rimasti i due gruppi creati per il laboratorio e, soltanto in quel caso, rimuovili con sudo groupdel. Non eseguire questi comandi per account preesistenti.
Elimina infine i due file iniziali e le loro directory:
rm -- "$HOME/tunnel-lab/index.html" "$HOME/tunnel-lab-secrets/tunnel.token"
rmdir "$HOME/tunnel-lab" "$HOME/tunnel-lab-secrets"
ss -lnt 'sport = :18080'rmdir si ferma se trova altro contenuto: esaminalo prima di cancellarlo. Non disinstallare Python, gli strumenti di sistema o cloudflared se servono ad altro. Su una macchina dedicata puoi rimuovere anche il pacchetto e i file APT aggiunti dalla guida, dopo aver verificato che nessun altro tunnel li utilizzi.

