🖥️ Apache / Nginx reverse proxy¶
HIX può girare in due topologie: - Standalone — HIX ascolta direttamente sulla porta 80/443 e gestisce il traffico internet senza intermediari. - Dietro un reverse proxy (Apache, Nginx, Cloudflare Tunnel, Traefik...) — il proxy termina SSL, fa load balancing, comprime, e inoltra la richiesta a HIX su HTTP puro su una porta interna.
Quando lavori dietro un proxy, HIX deve saperlo per ricostruire correttamente
l'IP reale del client, lo scheme (http vs https), e l'host originale. Questa configurazione è la modalità proxied.
Quando ti serve?¶
- Per servire HTTPS con Let's Encrypt senza gestire certificati in HIX.
- Per mettere HIX dietro Apache/Nginx esistenti che già servono altri siti.
- Per usare Cloudflare come CDN/WAF davanti a HIX.
- Per fare load balancing di più istanze HIX dietro un singolo frontend.
- Per scaricare TLS e compressione da HIX e dedicarlo alla logica applicativa.
Setup in hix.json¶
Sezione server¶
host = 127.0.0.1 → ascolta solo localmente, il proxy è l'unico client.
port = 8080 → porta interna.
mode = "proxied" → HIX sa di essere dietro un proxy e legge X-Forwarded-* / Forwarded.
Sezione server — lista proxy fidati¶
trusted_proxies è una lista separata da spazi di IP o range CIDR i cui
header X-Forwarded-* HIX accetterà. Senza questa lista, HIX ignora gli
header e usa l'IP della connessione TCP (quello del proxy, non del client).
⚠️ Non usare mai
0.0.0.0/0come trusted_proxy. Questo permetterebbe a qualsiasi client esterno di falsificare il proprio IP inviando unX-Forwarded-Forcontraffatto. Elenca solo gli IP che controlli.
Header supportati¶
HIX rileva l'IP reale del client guardando, in ordine:
1. CF-Connecting-IP (Cloudflare)
2. X-Forwarded-For (primo valore pubblico nella catena)
3. X-Real-IP (Nginx classico)
4. Client-IP (legacy)
5. L'IP della connessione TCP (fallback)
Capisce anche il Forwarded: RFC 7239 (standard moderno):
HIX_ParseForwarded() estrae for, proto, host, by, port dal
primo hop (più vicino al client).
Configurazione Apache¶
Reverse proxy base¶
<VirtualHost *:443>
ServerName myapp.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/myapp.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/myapp.com/privkey.pem
ProxyPreserveHost On
ProxyRequests Off
# HTTP - tutte le richieste a HIX
ProxyPass / http://127.0.0.1:8080/
ProxyPassReverse / http://127.0.0.1:8080/
# Header per HIX
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Host "%{HTTP_HOST}s"
# X-Forwarded-For aggiunto da Apache automaticamente
# Per WebSocket (pool_ws)
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:8080/$1 [P,L]
</VirtualHost>
Moduli richiesti: proxy, proxy_http, proxy_wstunnel, rewrite, headers,
ssl.
Healthcheck¶
Apache può testare HIX con l'endpoint pubblico /hix-ping:
<Proxy "balancer://hix">
BalancerMember "http://127.0.0.1:8080" route=hix1
ProxySet hcmethod=GET hcuri=/hix-ping hcinterval=10
</Proxy>
Configurazione Nginx¶
upstream hix {
server 127.0.0.1:8080;
}
server {
listen 443 ssl http2;
server_name myapp.com;
ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem;
location / {
proxy_pass http://hix;
proxy_http_version 1.1;
# Header forwarded (HIX li legge se l'IP è in trusted_proxies)
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
# WebSocket - HIX pool_ws
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# SSE - HIX pool_rest
proxy_buffering off;
proxy_read_timeout 3600s;
}
}
💡 Per SSE (
/events),proxy_buffering offè obbligatorio. Senza, Nginx bufferizza lo stream e nulla raggiunge il client.
Lettura dal codice¶
Con server.mode = "proxied", gli helper di HIX ritornano valori "visti" dal client
reale, non dal proxy:
UIP() // -> "203.0.113.5" (IP reale del client, non del proxy)
UScheme() // -> "https" (legge X-Forwarded-Proto)
UIsHttps() // -> .T.
UHost() // -> "myapp.com" (legge X-Forwarded-Host)
Senza server.mode = "proxied":
🔍 La funzione
HIX_GetClientIP(oReq)applica inoltre un filtroHIX_IsPublicIP()sulla catena diX-Forwarded-Forper scartare gli IP privati iniettati. Prende il primo IP pubblico nella catena.
Cloudflare¶
Se HIX è dietro Cloudflare (Tunnel, orange proxy, R2):
1. Aggiungi i range di Cloudflare a trusted_proxies:
Lista aggiornata: https://www.cloudflare.com/ips/
-
Attiva
server.mode = "proxied". -
HIX rileverà automaticamente l'header
CF-Connecting-IPche Cloudflare aggiunge con l'IP reale del client, anche se non inviiX-Forwarded-For.
Errori comuni¶
| Sintomo | Causa | Fix |
|---|---|---|
UIP() ritorna l'IP del proxy |
server.mode != "proxied" |
Configura correttamente |
UIP() falsificabile dall'esterno |
trusted_proxies vuoto o 0.0.0.0/0 |
Limita agli IP reali dei proxy |
| WebSocket non si connette dopo Apache | Manca proxy_wstunnel o regola Upgrade |
Aggiungi RewriteRule [P] con ws:// |
| SSE non raggiunge il client | Nginx sta bufferizzando | proxy_buffering off; proxy_read_timeout 3600s; |
I redirect vanno a http:// non https |
HIX non vede X-Forwarded-Proto |
proxy_set_header X-Forwarded-Proto $scheme; |
I cookie perdono Secure |
HIX pensa di essere in HTTP puro | Attiva server.mode = "proxied" così UIsHttps() è .T. |
Best practice¶
host = 127.0.0.1quando HIX è dietro un proxy locale: nessun utente esterno può bypassare il proxy parlando direttamente con HIX.trusted_proxiesil più restrittivo possibile: solo gli IP reali dei proxy, mai range pubblici interi.- Termina TLS al proxy, non in HIX. Sfrutti l'ecosistema certbot/Let's Encrypt senza spostare nulla lato HIX.
- Per i WebSocket, mantieni
proxy_read_timeout≥ping_interval_sdi HIX più un margine, o le connessioni inattive verranno tagliate. - Usa l'endpoint pubblico
/hix-pingcome healthcheck per il tuo bilanciatore. - In topologie multi-HIX, usa le sticky session se ti basi su sessioni in memoria
(
session.storage = "memory"). Se passi a"file", tutte le istanze HIX devono condividere la cartellapaths.session.