Ir para o conteúdo
Q
QuoteNode

Wiki

GeoIP e controlo de acesso geográfico

Como o QuoteNode usa uma base de dados GeoIP local para controlo de acesso por país e seguimento de propostas.

GeoIP e controlo de acesso geográfico

O QuoteNode inclui um controlo de acesso geográfico opcional e seguimento por país através de uma base de dados GeoIP local por país (DB-IP Country Lite sem chave por predefinição, ou MaxMind GeoLite2).

Dois usos do GeoIP

1. Controlo de acesso à aplicação

Quando ativado, o filtro GeoIP pode restringir o acesso à aplicação a determinados países. Os pedidos de países não permitidos recebem HTTP 403 (Forbidden).

É útil para organizações que:

  • operam apenas em jurisdições específicas,
  • querem reduzir a exposição a ataques automatizados de certas regiões,
  • têm de cumprir requisitos de residência de dados ou de controlo de acesso.

2. Seguimento de interações com a proposta

Quando um cliente abre um link público de proposta, o sistema regista o código do país do cliente (ISO 3166-1 alpha-2) juntamente com o evento de interação. Isto dá contexto geográfico à análise de propostas:

  • «A sua proposta foi aberta a partir da Alemanha» — confirma alcance internacional,
  • «Várias aberturas de países diferentes» — pode indicar que a proposta foi reencaminhada.

Como funciona

Base de dados

A resolução GeoIP usa uma base de dados local por país no formato MaxMind DB (.mmdb) — não uma API externa. Todas as consultas ocorrem em memória, sem chamadas de rede.

Por predefinição é a edição DB-IP Country Lite sem chave (licença CC-BY-4.0, sem conta). O contentor descarrega-a automaticamente no arranque (e segundo um agendamento diário) se estiver em falta ou desatualizada — independentemente de GEOIP_ENABLED, governado por GEOIP_AUTO_UPDATE (predefinição true). A base pode assim estar pronta enquanto a imposição por país está desligada. Sem descarga manual nem montagem de ficheiro. Para usar antes o MaxMind GeoLite2, define MAXMIND_ACCOUNT_ID / MAXMIND_LICENSE_KEY (uma conta MaxMind gratuita); é o mesmo formato .mmdb. Também podes preencher o ficheiro manualmente com scripts/update-geoip.sh.

Deteção do IP

O IP do cliente é resolvido inteiramente pela aplicação — não é retirado cegamente dos cabeçalhos do pedido. Um X-Forwarded-For, X-Real-IP ou CF-Connecting-IP falsificado a partir de um cliente direto nunca pode falsificar a verificação de país.

  1. A aplicação toma o par de transporte (o endereço que efetivamente abriu a ligação).
  2. Se esse par não for interno, todos os cabeçalhos de reencaminhamento são ignorados e o par é usado diretamente. Um par é interno quando é um proxy de confiança explícito ou qualquer endereço não roteável globalmente (privado/RFC 1918, loopback, link-local, CGNAT, IPv6 ULA) — que, atrás de Docker/Coolify, é sempre interno ao contentor.
  3. Se o par for interno, o cliente é derivado dos seus metadados de reencaminhamento por ordem: CF-Connecting-IP (para que um CDN como a Cloudflare que reescreve X-Forwarded-For continue a dar o cliente real) → X-Forwarded-For (percorrido da direita para a esquerda, ignorando saltos internos) → X-Real-IP. Apenas são aceites IP literais (sem DNS).

Como os pares privados e os CDN são tratados automaticamente, a maioria das implantações não precisa de configuração — o Caddy integrado, uma edge Coolify ou um CDN à frente funcionam de imediato. A variável opcional SECURITY_TRUSTED_PROXIES (IP/CIDR literais separados por vírgulas e/ou nomes de host de serviço) só acrescenta confiança para um proxy invulgar cujo par de transporte seja um endereço público.

O IP do cliente é um filtro grosseiro de melhor esforço, não autenticação. Quem conseguir alcançar a origem diretamente (contornando o CDN/proxy) poderia apresentar um CF-Connecting-IP à escolha; o reforço recomendado é restringir a origem por firewall para que apenas o seu CDN/proxy a alcance.

Os endereços de cliente não roteáveis globalmente (loopback, privados/RFC 1918, link-local, CGNAT, IPv6 ULA) nunca são geo-bloqueados — não podem ser geolocalizados — pelo que os health checks de localhost e os deployments LAN/same-host continuam a funcionar enquanto o GeoIP está ativo. A lista de permissões de IP e a autenticação continuam a aplicar-se-lhes.

Caminhos isentos

Os seguintes caminhos estão sempre isentos das restrições geográficas para se manterem acessíveis em todo o mundo:

  • links públicos de propostas (/offer/public/*) e branding público (/api/v1/public/branding/*),
  • ações de links de e-mail: cancelamento de subscrição (/api/v1/notifications/unsubscribe-token/*) e preferências públicas (/api/v1/notifications/preferences-public/*),
  • endpoints de infraestrutura/saúde (/health*, /actuator/health, /actuator/info).

A autenticação de administrador (/api/v1/auth/login, 2FA) e os recursos autenticados continuam sujeitos ao controlo geográfico.

Configuração

Variável Por omissão Descrição
GEOIP_ENABLED false Apenas interruptor de imposição por país — também o interruptor de emergência. Não afeta o carregamento da base de dados: a BD continua a carregar e a atualizar-se (ver GEOIP_AUTO_UPDATE), por isso pode estar pronta enquanto a imposição está desligada. false desativa de forma fiável toda a imposição por país (ver recuperação abaixo).
GEOIP_DB_PATH /app/data/geoip/GeoLite2-Country.mmdb Caminho para o ficheiro de base de dados .mmdb por país (preenchido automaticamente quando o GeoIP está ativo).
GEOIP_AUTO_UPDATE true Descarregar a base automaticamente no arranque (DB-IP sem chave por predefinição; MaxMind quando MAXMIND_* estão definidos) quando está em falta ou mais antiga que GEOIP_AUTO_UPDATE_MAX_AGE_DAYS (25 por predefinição). Define false para gerir o ficheiro manualmente.
SECURITY_GEOIP_ALLOWED_COUNTRIES (vazio) Códigos de país ISO 3166-1 alpha-2 separados por vírgulas (p. ex. PL,DE,FR). Os códigos são normalizados para maiúsculas e validados; os inválidos são rejeitados. Vazio = sem restrição. Quando definido, este valor do operador prevalece sobre a definição do tenant na aplicação.

Quando nenhuma lista de países está configurada, o filtro GeoIP é passivo — resolve códigos de país para fins de seguimento mas não bloqueia qualquer pedido. Ativar a filtragem por país na interface de administração usa um seletor de países validado (ISO 3166-1 alpha-2) e exige pelo menos um país e uma base de dados carregada.

Atualizar a base de dados: a descarga automática no arranque mantém-na razoavelmente atualizada, mas depois de substituir manualmente o ficheiro .mmdb pode recarregá-lo sem reiniciar em Administração → Segurança → estado efetivo → Recarregar base de dados (um recarregamento protegido — um candidato corrompido ou em falta mantém a base de dados atualmente carregada). Um reinício do backend também adota o novo ficheiro. O painel de estado efetivo mostra se a base de dados está carregada, com as marcas temporais de compilação/carregamento.

Recuperação após um bloqueio de GeoIP

Se uma lista de países permitidos excluir acidentalmente o seu próprio país, recebe HTTP 403 com a sugestão de recuperação GEO_BLOCKED. Para recuperar o acesso:

  1. Defina GEOIP_ENABLED=false no ambiente do backend.
  2. Reinicie o backend (isto desativa a aplicação de GeoIP antes de qualquer política ser avaliada).
  3. Corrija ou limpe a lista de países permitidos, depois defina GEOIP_ENABLED=true e reinicie novamente.

Isto é independente do interruptor de recuperação da lista de permissões de IP — recuperar um nunca desativa o outro de forma silenciosa.

Considerações de privacidade

  • A resolução GeoIP é sem estado — não é armazenada permanentemente qualquer correspondência IP-país.
  • Para o seguimento de propostas é registado apenas o código do país (p. ex. «PT»), não o endereço IP em si.
  • Os endereços IP registados nos eventos web das propostas estão sujeitos ao trabalho configurável de anonimização de IP, que os submete a hash após um número configurável de dias para conformidade com o RGPD.

Last reviewed: Recently