Vai al contenuto
Q
QuoteNode

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.

  1. L’applicazione prende il peer di trasporto (l’indirizzo che ha effettivamente aperto la connessione).
  2. 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.
  3. 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 riscrive X-Forwarded-For dia 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-IP scelto; 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 .mmdb puoi 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:

  1. Imposta GEOIP_ENABLED=false nell’ambiente del backend.
  2. Riavvia il backend (questo disattiva l’applicazione di GeoIP prima che venga valutata qualsiasi politica).
  3. Correggi o svuota la lista dei Paesi consentiti, poi imposta GEOIP_ENABLED=true e 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.

Last reviewed: Recently