Wiki
GeoIP e controllo accessi geografico
Come QuoteNode usa un database GeoIP locale per il controllo accessi per Paese e il tracciamento delle offerte.
GeoIP e controllo accessi geografico
QuoteNode include un controllo accessi geografico opzionale e il tracciamento per Paese tramite un database GeoIP locale per Paese (DB-IP Country Lite senza chiave per impostazione predefinita, o MaxMind GeoLite2).
Due usi di GeoIP
1. Controllo accessi all’applicazione
Quando è attivo, il filtro GeoIP può limitare l’accesso all’applicazione a Paesi specifici. Le richieste da Paesi non consentiti ricevono HTTP 403 (Forbidden).
È utile alle organizzazioni che:
- operano solo in determinate giurisdizioni,
- vogliono ridurre l’esposizione ad attacchi automatizzati da certe regioni,
- devono rispettare requisiti di residenza dei dati o di controllo accessi.
2. Tracciamento delle interazioni con l’offerta
Quando un cliente apre un link pubblico di un’offerta, il sistema registra il codice Paese del cliente (ISO 3166-1 alpha-2) insieme all’evento di interazione. Questo fornisce contesto geografico all’analisi delle offerte:
- «La tua offerta è stata aperta dalla Germania» — conferma la portata internazionale,
- «Più aperture da Paesi diversi» — può indicare che l’offerta è stata inoltrata.
Come funziona
Database
La risoluzione GeoIP usa un database locale per Paese in formato MaxMind DB (.mmdb) — non un’API esterna. Tutte le ricerche avvengono in memoria, senza chiamate di rete.
Per impostazione predefinita è l’edizione DB-IP Country Lite senza chiave (licenza CC-BY-4.0, nessun account necessario). Il container lo scarica automaticamente all’avvio (e con una pianificazione giornaliera) se manca o è obsoleto — indipendentemente da GEOIP_ENABLED, governato da GEOIP_AUTO_UPDATE (predefinito true). Il database può quindi essere pronto mentre l’applicazione per Paese è disattivata. Nessun download manuale né montaggio del file. Per usare invece MaxMind GeoLite2, imposta MAXMIND_ACCOUNT_ID / MAXMIND_LICENSE_KEY (un account MaxMind gratuito); è lo stesso formato .mmdb. Puoi anche popolare il file manualmente con scripts/update-geoip.sh.
Rilevamento dell’IP
L’IP del client è risolto interamente dall’applicazione — non viene preso ciecamente dalle intestazioni della richiesta. Un X-Forwarded-For, X-Real-IP o CF-Connecting-IP falsificato da un client diretto non può mai falsificare il controllo del Paese.
- L’applicazione prende il peer di trasporto (l’indirizzo che ha effettivamente aperto la connessione).
- Se quel peer non è interno, tutte le intestazioni di inoltro vengono ignorate e il peer è usato direttamente. Un peer è interno quando è un proxy attendibile esplicito oppure un qualsiasi indirizzo non instradabile globalmente (privato/RFC 1918, loopback, link-local, CGNAT, IPv6 ULA) — che dietro Docker/Coolify è sempre interno al container.
- Se il peer è interno, il client viene derivato dai suoi metadati di inoltro nell’ordine:
CF-Connecting-IP(così che un CDN come Cloudflare che riscriveX-Forwarded-Fordia comunque il client reale) →X-Forwarded-For(percorso da destra a sinistra, saltando gli hop interni) →X-Real-IP. Sono accettati solo IP letterali (nessun DNS).
Poiché i peer privati e i CDN sono gestiti automaticamente, la maggior parte dei deployment non richiede alcuna configurazione — il Caddy integrato, un edge Coolify o un CDN davanti funzionano da subito. La variabile opzionale SECURITY_TRUSTED_PROXIES (IP/CIDR letterali separati da virgole e/o nomi host di servizio) aggiunge attendibilità solo per un proxy insolito il cui peer di trasporto è un indirizzo pubblico.
L’IP del client è un filtro approssimativo best-effort, non autenticazione. Chiunque possa raggiungere l’origine direttamente (aggirando CDN/proxy) potrebbe presentare un
CF-Connecting-IPscelto; l’irrobustimento consigliato è limitare l’origine con un firewall così che solo il tuo CDN/proxy possa raggiungerla.
Gli indirizzi client non instradabili a livello globale (loopback, privati/RFC 1918, link-local, CGNAT, IPv6 ULA) non vengono mai geo-bloccati — non possono essere geolocalizzati — così gli health check da localhost e i deployment LAN/same-host continuano a funzionare mentre GeoIP è attivo. La whitelist IP e l’autenticazione continuano comunque ad applicarsi.
Percorsi esenti
I seguenti percorsi sono sempre esenti dalle restrizioni geografiche per restare raggiungibili in tutto il mondo:
- link pubblici delle offerte (
/offer/public/*) e branding pubblico (/api/v1/public/branding/*), - azioni dei link e-mail: disiscrizione (
/api/v1/notifications/unsubscribe-token/*) e preferenze pubbliche (/api/v1/notifications/preferences-public/*), - endpoint di infrastruttura/salute (
/health*,/actuator/health,/actuator/info).
L’autenticazione amministratore (/api/v1/auth/login, 2FA) e gli asset autenticati restano soggetti al controllo geografico.
Configurazione
| Variabile | Predefinito | Descrizione |
|---|---|---|
GEOIP_ENABLED |
false |
Solo interruttore dell’applicazione per Paese — anche interruttore di emergenza. Non influisce sul caricamento del database: il DB continua a caricarsi e aggiornarsi (vedi GEOIP_AUTO_UPDATE), quindi può essere pronto mentre l’applicazione è disattivata. false disattiva in modo affidabile tutta l’applicazione per Paese (vedi ripristino sotto). |
GEOIP_DB_PATH |
/app/data/geoip/GeoLite2-Country.mmdb |
Percorso del file di database .mmdb per Paese (popolato automaticamente quando GeoIP è attivo). |
GEOIP_AUTO_UPDATE |
true |
Scarica automaticamente il database all’avvio (DB-IP senza chiave per impostazione predefinita; MaxMind quando MAXMIND_* sono impostati) quando manca o è più vecchio di GEOIP_AUTO_UPDATE_MAX_AGE_DAYS (25 per impostazione predefinita). Imposta false per gestire il file da solo. |
SECURITY_GEOIP_ALLOWED_COUNTRIES |
(vuoto) | Codici Paese ISO 3166-1 alpha-2 separati da virgole (es. PL,DE,FR). I codici sono normalizzati in maiuscolo e validati; quelli non validi sono rifiutati. Vuoto = nessuna restrizione. Quando impostato, questo valore dell’operatore prevale sull’impostazione del tenant nell’applicazione. |
Quando non è configurata alcuna lista di Paesi, il filtro GeoIP è passivo — risolve i codici Paese a scopo di tracciamento ma non blocca alcuna richiesta. Attivare il filtro per Paese nell’interfaccia di amministrazione usa un selettore di Paesi validato (ISO 3166-1 alpha-2) e richiede almeno un Paese e un database caricato.
Aggiornare il database: il download automatico all’avvio lo mantiene ragionevolmente aggiornato, ma dopo aver sostituito manualmente il file
.mmdbpuoi ricaricarlo senza riavvio da Amministrazione → Sicurezza → stato effettivo → Ricarica database (una ricarica protetta — un candidato corrotto o mancante mantiene il database attualmente caricato). Anche un riavvio del backend acquisisce il nuovo file. Il pannello dello stato effettivo mostra se il database è caricato, con le marche temporali di build/caricamento.
Ripristino dopo un blocco GeoIP
Se una lista di Paesi consentiti esclude accidentalmente il tuo Paese, ricevi HTTP 403 con il suggerimento di ripristino GEO_BLOCKED. Per ripristinare l’accesso:
- Imposta
GEOIP_ENABLED=falsenell’ambiente del backend. - Riavvia il backend (questo disattiva l’applicazione di GeoIP prima che venga valutata qualsiasi politica).
- Correggi o svuota la lista dei Paesi consentiti, poi imposta
GEOIP_ENABLED=truee riavvia di nuovo.
È indipendente dall’interruttore di ripristino della whitelist IP — ripristinare uno non disattiva mai silenziosamente l’altro.
Considerazioni sulla privacy
- La risoluzione GeoIP è stateless — nessuna corrispondenza IP-Paese viene memorizzata in modo permanente.
- Per il tracciamento delle offerte viene registrato solo il codice Paese (es. «IT»), non l’indirizzo IP stesso.
- Gli indirizzi IP registrati negli eventi web delle offerte sono soggetti al job configurabile di anonimizzazione IP, che li sottopone a hash dopo un numero configurabile di giorni per la conformità al GDPR.