Quasi nessuna applicazione web moderna risponde direttamente agli utenti. Tra Internet e il codice c'è di solito un reverse proxy: un server che riceve le richieste, decide a quale applicazione inoltrarle, e restituisce la risposta. È un componente semplice da descrivere ma che concentra molte responsabilità importanti, e sceglierlo bene semplifica la vita.
Proxy e reverse proxy
Un proxy tradizionale agisce per conto dei client: i computer di un'azienda escono su Internet attraverso di esso. Un reverse proxy agisce per conto dei server: gli utenti si collegano a lui credendo di parlare con il sito, e lui smista le richieste verso le applicazioni retrostanti, che restano nascoste.
Cosa fa un reverse proxy
Terminazione TLS
Il reverse proxy gestisce i certificati e la cifratura HTTPS. Le applicazioni dietro di lui possono ricevere traffico in chiaro sulla rete interna, senza dover gestire certificati ciascuna per conto proprio. Rinnovi, configurazione dei protocolli e reindirizzamento da HTTP a HTTPS avvengono in un solo punto.
Instradamento
Su un unico indirizzo IP possono convivere molti servizi. Il proxy guarda il nome di dominio o il percorso richiesto e inoltra al servizio giusto: blog.esempio.it a un'applicazione, esempio.it/api a un'altra.
Bilanciamento del carico
Se un'applicazione gira su più istanze, il proxy distribuisce le richieste tra di esse e smette di inviarle a quelle che non rispondono.
Altre funzioni utili
- compressione delle risposte per ridurre il traffico;
- cache dei contenuti statici o delle risposte che cambiano raramente;
- limitazione delle richieste per proteggere da abusi e picchi;
- intestazioni di sicurezza aggiunte in modo uniforme a tutte le risposte;
- registri di accesso centralizzati per tutti i servizi.
Un dettaglio da non dimenticare: l'IP del client
Quando c'è un proxy di mezzo, l'applicazione vede tutte le richieste provenire dall'indirizzo del proxy. Il vero indirizzo del visitatore viene passato in un'intestazione, di solito X-Forwarded-For, insieme a X-Forwarded-Proto per indicare se la richiesta originale era in HTTPS.
L'applicazione deve essere configurata per fidarsi di queste intestazioni solo se arrivano dal proxy. Altrimenti chiunque potrebbe inviare un'intestazione falsa e farsi passare per un altro indirizzo, aggirando limiti o falsando i registri.
I tre strumenti più diffusi
Nginx
Nginx è uno dei server web più usati al mondo, stabile ed efficiente, con una documentazione vastissima. La configurazione è esplicita e molto flessibile:
server {
listen 443 ssl;
server_name app.esempio.it;
ssl_certificate /etc/letsencrypt/live/app.esempio.it/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/app.esempio.it/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
I certificati si ottengono di solito con uno strumento esterno, come Certbot, che li rinnova automaticamente.
Caddy
Caddy si distingue per i certificati HTTPS automatici: basta indicare il nome di dominio e Caddy ottiene e rinnova da solo il certificato da Let's Encrypt. La configurazione equivalente a quella precedente è di tre righe:
app.esempio.it {
reverse_proxy 127.0.0.1:8000
}
Imposta anche le intestazioni di inoltro più comuni senza doverle scrivere. È ideale per piccoli server e progetti personali, ma è adatto anche alla produzione.
Traefik
Traefik è pensato per ambienti con container. Invece di leggere un file di configurazione statico, osserva Docker o Kubernetes e scopre i servizi automaticamente: quando avvii un container con le etichette giuste, Traefik crea la rotta e ottiene il certificato. Quando lo spegni, la rotta sparisce.
È molto comodo dove i servizi cambiano spesso, ma la configurazione tramite etichette può risultare meno intuitiva per chi viene da un approccio tradizionale.
Come scegliere
| Esigenza | Scelta consigliata |
|---|---|
| Massima flessibilità, configurazioni complesse, molta documentazione | Nginx |
| Semplicità e HTTPS automatico con il minimo sforzo | Caddy |
| Molti container che nascono e muoiono, scoperta automatica | Traefik |
Non c'è un vincitore assoluto. Nel mio lavoro uso Caddy quando conta la semplicità, Nginx quando servono regole di cache o riscrittura articolate, e Traefik su server dove convivono molti servizi in container gestiti con Compose.
Buone pratiche
- Fai ascoltare le applicazioni solo su indirizzi interni, così che siano raggiungibili esclusivamente attraverso il proxy.
- Imposta limiti ragionevoli su dimensione delle richieste e tempi di attesa.
- Abilita il rinnovo automatico dei certificati e verifica che funzioni prima della prima scadenza.
- Conserva la configurazione del proxy nel controllo di versione, perché è il punto in cui un errore rende irraggiungibili tutti i servizi insieme.
In sintesi
- Un reverse proxy riceve le richieste degli utenti e le inoltra alle applicazioni, che restano nascoste.
- Centralizza TLS, instradamento, bilanciamento, compressione, cache e limiti alle richieste.
- L'applicazione deve fidarsi delle intestazioni con l'IP del client solo se provengono dal proxy.
- Nginx offre flessibilità, Caddy semplicità con HTTPS automatico, Traefik scoperta automatica dei container.
- Esponi le applicazioni solo internamente e tieni la configurazione del proxy sotto controllo di versione.