🔒 SSL / TLS¶
SSL/TLS cifra il canale tra il browser e il server. Senza, tutto viaggia in chiaro - e questo include:
- Cookie di sessione (
HIXSID=abc123) - un intermediario può catturarli e impersonare l'utente. - Credenziali di login (
username=demo&password=1234). - Token JWT (
Authorization: Bearer eyJ...). - Il body di ogni risposta (dati sensibili dell'utente).
Con HTTPS, tutto viaggia cifrato e firmato. Un attaccante nel mezzo della rete vede solo byte opachi.
http://app.com ─────▶ plaintext ─────▶ server (chiunque legge)
https://app.com ─────▶ TLS encrypt ─────▶ server (solo il server decifra)
In produzione, HTTPS non è opzionale. Qualsiasi cosa con login, sessione, JWT o pagamenti deve andare attraverso HTTPS. I browser moderni segnalano i siti HTTP come "Non sicuro" e bloccano nuove API (geolocation, service workers, fetch con credenziali, ...) senza TLS.
Attivazione in HIX¶
Da hix.json¶
{
"paths": {
"certs": "certs"
},
"server": {
"host": "0.0.0.0",
"port": 443,
"ssl": true,
"cert_private": "hix.key",
"cert_public": "hix.crt"
}
}
| Chiave | Valore |
|---|---|
paths.certs |
Directory dove risiedono i file dei certificati (default: certs) |
ssl |
true abilita TLS, false (default) lo disabilita |
cert_private |
Nome del file .key dentro paths.certs |
cert_public |
Nome del file .crt dentro paths.certs |
port |
Convenzione: 443 per HTTPS, 80 per HTTP |
Da codice¶
LOCAL oCfg := THixConfig():New()
oCfg:lSSL := .T.
oCfg:cCertPrivate := "certs/hix.key"
oCfg:cCertPublic := "certs/hix.crt"
oCfg:nPort := 443
oSrv := THixServer():New( oCfg )
All'avvio,
oCfg:Validate()controlla che entrambi i file esistano. Se mancano, il server scrive un errore nel log e non parte.
Ottenere un certificato¶
Produzione - Let's Encrypt (gratuito e automatico)¶
Let's Encrypt è una CA gratuita che emette certificati con lo strumento certbot:
Questo genera due file in /etc/letsencrypt/live/app.example.com/:
privkey.pem→cert_privatefullchain.pem→cert_public
I certificati scadono dopo 90 giorni - certbot è programmato per rinnovarli automaticamente.
Sviluppo - certificato self-signed¶
Per localhost:
openssl req -x509 -newkey rsa:2048 -nodes -days 365 ;
-keyout certs/hix.key -out certs/hix.crt ;
-subj "/CN=localhost"
Il browser mostrerà un avviso "certificato non attendibile" - è normale. Ok per test locali; mai per la produzione.
Helper di rilevamento¶
Da un controller puoi sapere se la richiesta è arrivata via HTTPS:
Utile per forzare il cookie come Secure, o per reindirizzare il traffico HTTP→HTTPS:
FUNCTION HixMwForceHttps( oCtx )
IF ! UIsHttps()
oCtx:lHandled := .T.
URedirect( "https://" + UHost() + UPath(), 301 )
RETURN .F.
ENDIF
RETURN .T.
HIX direttamente vs dietro un proxy¶
HIX direttamente (self-contained)¶
{
"paths": {
"certs": "certs"
},
"server": {
"host": "0.0.0.0",
"port": 443,
"ssl": true,
"cert_private": "hix.key",
"cert_public": "hix.crt"
}
}
HIX termina TLS e serve HTTPS direttamente. Ideale per piccole app o self-hosted.
Dietro un proxy (Apache / Nginx / Cloudflare)¶
Il solito in produzione: il proxy termina TLS e inoltra HTTP puro a HIX sulla rete interna:
server.ssl = false → HIX parla HTTP puro con il proxy. server.mode = "proxied" abilita la lettura di X-Forwarded-*.
# Apache reverse proxy
<VirtualHost *:443>
ServerName app.example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/app.example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/app.example.com/privkey.pem
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-For "%{REMOTE_ADDR}s"
</VirtualHost>
| HIX direttamente | Dietro proxy | |
|---|---|---|
| Termina TLS | HIX | Proxy |
| Certificato | In HIX | Nel proxy |
| Rinnovo | Manuale o cron | Gestito dal proxy |
| Backend multipli | ❌ | ✅ Load balancing |
| Adatto per | Piccole app, dev | Produzione seria |
Cookie sicuri con HTTPS¶
Quando tutto va attraverso TLS, i cookie di sessione dovrebbero essere marcati come Secure così il browser non li invia mai su HTTP:
// Cookie marcato come Secure (solo HTTPS)
USetCookie( "session_id", cSid, 3600 )
// HIX aggiunge automaticamente HttpOnly + SameSite=Lax
// In sospeso: flag Secure nelle versioni più nuove - verificare se esposto
I cookie HIX portano già
HttpOnly; SameSite=Laxdi default, che filtra alcuni attacchi. Il flagSecureviene aggiunto dal proxy se termina TLS lì, o va abilitato esplicitamente con TLS locale.
Errori comuni¶
| Sintomo | Causa |
|---|---|
SSL: cert_private non trovato all'avvio |
Path al .key scritto male o file mancante |
SSL: cert_public non trovato |
Stessa cosa con il .crt |
Browser: NET::ERR_CERT_AUTHORITY_INVALID |
Certificato self-signed o CA non riconosciuta |
ERR_CERT_DATE_INVALID |
Certificato scaduto - rinnovare con certbot renew |
ERR_SSL_PROTOCOL_ERROR |
Il server non parla TLS ma il client ha richiesto https:// |
| Warning di mixed content | Il tuo HTML https:// carica <img src="http://..."> - usa URL relativi o https:// |
Best practice¶
- HTTPS in produzione sempre. Nessuna eccezione. Let's Encrypt è gratuito.
- HTTP → HTTPS redirect. La porta 80 serve solo a reindirizzare con 301 verso
https://(o per la challenge di certbot). - Rinnovo automatico.
certbot renewin cron + reload del server. Se non lo fai, il certificato scade dopo 90 giorni e l'app va giù. - Dietro un proxy in prod. Termina TLS in Apache/Nginx o in una CDN. HIX resta sulla rete interna a servire HTTP puro.
- HSTS. Una volta che tutto è HTTPS, invia l'header
Strict-Transport-Security: max-age=31536000; includeSubDomainscosì il browser rifiuta l'HTTP nelle visite future. - Niente chiavi committate.
certs/*.keymai nel repo. Aggiungili a.gitignore.