Przejdź do treści
Q
QuoteNode

Wiki

GeoIP i geograficzna kontrola dostępu

Jak QuoteNode używa lokalnej bazy GeoIP do kontroli dostępu na poziomie krajów i do śledzenia otwarć ofert.

GeoIP i geograficzna kontrola dostępu

QuoteNode zawiera opcjonalną geograficzną kontrolę dostępu i śledzenie kraju na poziomie państw z użyciem lokalnej bazy GeoIP (domyślnie keyless DB-IP Country Lite lub MaxMind GeoLite2).

Dwa zastosowania GeoIP

1. Kontrola dostępu do aplikacji

Po włączeniu filtr GeoIP może ograniczyć dostęp do aplikacji do wybranych krajów. Żądania z krajów spoza listy dozwolonych otrzymują HTTP 403 (Forbidden).

Przydaje się to organizacjom, które:

  • działają wyłącznie w określonych jurysdykcjach,
  • chcą ograniczyć ekspozycję na zautomatyzowane ataki z niektórych regionów,
  • muszą spełniać wymagania dotyczące rezydencji danych lub kontroli dostępu.

2. Śledzenie interakcji z ofertą

Gdy klient otwiera publiczny link do oferty, system zapisuje kod kraju klienta (ISO 3166-1 alpha-2) razem ze zdarzeniem interakcji. Daje to geograficzny kontekst dla analityki ofert:

  • „Twoja oferta została otwarta z Niemiec” — potwierdza zasięg międzynarodowy,
  • „Wielokrotne otwarcia z różnych krajów” — może wskazywać, że oferta została przekazana dalej.

Jak to działa

Baza danych

Rozpoznanie GeoIP wykorzystuje lokalną bazę krajów w formacie MaxMind DB (.mmdb) — a nie zewnętrzne API. Wszystkie zapytania odbywają się w pamięci, bez połączeń sieciowych.

Domyślnie jest to keyless DB-IP Country Lite (licencja CC-BY-4.0, bez konta). Kontener pobiera ją automatycznie przy starcie (oraz w codziennym harmonogramie), jeśli jej brakuje lub jest przeterminowana — niezależnie od GEOIP_ENABLED, sterowane przez GEOIP_AUTO_UPDATE (domyślnie true). Baza może więc być gotowa, gdy egzekwowanie krajów jest wyłączone. Nie ma ręcznego pobierania ani montowania pliku. Aby zamiast tego użyć MaxMind GeoLite2, ustaw MAXMIND_ACCOUNT_ID / MAXMIND_LICENSE_KEY (darmowe konto MaxMind); to ten sam format .mmdb. Plik możesz też uzupełnić ręcznie skryptem scripts/update-geoip.sh.

Wykrywanie adresu IP

Adres IP klienta jest ustalany w całości przez aplikację — nie jest pobierany bezkrytycznie z nagłówków żądania. Sfałszowany X-Forwarded-For, X-Real-IP lub CF-Connecting-IP od klienta bezpośredniego nigdy nie podszyje się pod sprawdzanie kraju.

  1. Aplikacja bierze peera transportowego (adres, który faktycznie otworzył połączenie).
  2. Jeśli ten peer nie jest wewnętrzny, wszystkie nagłówki przekazujące są ignorowane, a peer jest używany bezpośrednio. Peer jest wewnętrzny, gdy jest jawnie zaufanym proxy lub dowolnym adresem spoza globalnej puli routowalnej (prywatny/RFC 1918, loopback, link-local, CGNAT, IPv6 ULA) — który za Dockerem/Coolify zawsze jest wewnątrzkontenerowy.
  3. Jeśli peer jest wewnętrzny, klient jest ustalany z jego metadanych przekazujących w kolejności: CF-Connecting-IP (dzięki czemu CDN taki jak Cloudflare, który nadpisuje X-Forwarded-For, nadal daje prawdziwego klienta) → X-Forwarded-For (przeglądany od prawej do lewej, z pominięciem skoków wewnętrznych) → X-Real-IP. Akceptowane są wyłącznie literalne adresy IP (bez DNS).

Ponieważ peery prywatne i CDN-y są obsługiwane automatycznie, większość wdrożeń nie wymaga żadnej konfiguracji — wbudowany Caddy, krawędź Coolify czy CDN z przodu działają od razu. Opcjonalna zmienna SECURITY_TRUSTED_PROXIES (rozdzielone przecinkami literalne IP/CIDR i/lub nazwy hostów usług) dodaje zaufanie tylko dla nietypowego proxy, którego peer transportowy ma adres publiczny.

IP klienta to zgrubny filtr „best-effort”, a nie uwierzytelnianie. Ktoś, kto dosięgnie origin bezpośrednio (z pominięciem CDN/proxy), mógłby podać wybrany CF-Connecting-IP; zalecane utwardzenie to firewall ograniczający origin tak, by docierał do niego tylko Twój CDN/proxy.

Adresy klientów spoza globalnej puli routowalnej (loopback, prywatne/RFC 1918, link-local, CGNAT, IPv6 ULA) nigdy nie są geo-blokowane — nie da się ich zlokalizować — dzięki czemu health-checki z localhost oraz wdrożenia LAN/same-host działają, gdy GeoIP jest aktywne. Lista dozwolonych IP i uwierzytelnianie nadal ich obejmują.

Ścieżki wyłączone

Następujące ścieżki są zawsze wyłączone z restrykcji geograficznych, aby pozostały osiągalne na całym świecie:

  • publiczne linki do ofert (/offer/public/*) i publiczny branding (/api/v1/public/branding/*),
  • akcje z linków e-mail: wypisanie z subskrypcji (/api/v1/notifications/unsubscribe-token/*) i publiczne preferencje (/api/v1/notifications/preferences-public/*),
  • endpointy infrastruktury/health (/health*, /actuator/health, /actuator/info).

Uwierzytelnianie administratora (/api/v1/auth/login, 2FA) oraz uwierzytelnione zasoby pozostają objęte kontrolą geo.

Konfiguracja

ZmiennaDomyślnieOpis
GEOIP_ENABLEDfalsePrzełącznik wyłącznie egzekwowania krajów — zarazem przełącznik awaryjny. Nie wpływa na ładowanie bazy: baza nadal się ładuje i aktualizuje (zob. GEOIP_AUTO_UPDATE), więc może być gotowa, gdy egzekwowanie jest wyłączone. false niezawodnie wyłącza całe egzekwowanie krajów (patrz odzyskiwanie poniżej).
GEOIP_DB_PATH/app/data/geoip/GeoLite2-Country.mmdbŚcieżka do pliku bazy .mmdb (uzupełniana automatycznie, gdy GeoIP jest włączone).
GEOIP_AUTO_UPDATEtrueAutomatyczne pobranie bazy przy starcie (domyślnie keyless DB-IP; MaxMind gdy ustawione MAXMIND_*), gdy brakuje lub jest starsza niż GEOIP_AUTO_UPDATE_MAX_AGE_DAYS (domyślnie 25). Ustaw false, by zarządzać plikiem samodzielnie.
SECURITY_GEOIP_ALLOWED_COUNTRIES(puste)Rozdzielone przecinkami kody krajów ISO 3166-1 alpha-2 (np. PL,DE,FR). Kody są normalizowane do wielkich liter i walidowane; nieprawidłowe są odrzucane. Puste = brak ograniczeń. Gdy ustawione, ta wartość operatora jest nadrzędna wobec ustawienia tenanta w aplikacji.

Gdy żadna lista krajów nie jest skonfigurowana, filtr GeoIP działa pasywnie — rozpoznaje kody krajów do celów śledzenia, ale niczego nie blokuje. Włączenie filtrowania krajów w panelu administratora korzysta z walidowanego selektora krajów (ISO 3166-1 alpha-2) i wymaga co najmniej jednego kraju oraz załadowanej bazy.

Odświeżanie bazy: automatyczne pobranie przy starcie utrzymuje ją w miarę aktualną, ale po ręcznej podmianie pliku .mmdb możesz przeładować go bez restartu w Administracja → Bezpieczeństwo → stan efektywny → Przeładuj bazę (przeładowanie strzeżone — uszkodzony lub brakujący kandydat zachowuje aktualnie załadowaną bazę). Restart backendu również wczytuje nowy plik. Panel stanu efektywnego pokazuje, czy baza jest załadowana, oraz jej znaczniki czasu zbudowania/wczytania.

Odzyskiwanie po blokadzie GeoIP

Jeśli lista dozwolonych krajów przypadkowo wykluczy Twój własny kraj, otrzymasz HTTP 403 ze wskazówką odzyskiwania GEO_BLOCKED. Aby odzyskać dostęp:

  1. Ustaw GEOIP_ENABLED=false w środowisku backendu.
  2. Zrestartuj backend (to wyłącza egzekucję GeoIP, zanim jakakolwiek polityka zostanie oceniona).
  3. Popraw lub wyczyść listę dozwolonych krajów, następnie ustaw GEOIP_ENABLED=true i zrestartuj ponownie.

Jest to niezależne od przełącznika odzyskiwania listy dozwolonych IP — odzyskanie jednego nigdy nie wyłącza po cichu drugiego.

Aspekty prywatności

  • Rozpoznanie GeoIP jest bezstanowe — żadne mapowanie IP→kraj nie jest trwale przechowywane.
  • Dla śledzenia ofert zapisywany jest tylko kod kraju (np. „PL”), a nie sam adres IP.
  • Adresy IP zapisane w zdarzeniach webowych ofert podlegają konfigurowalnemu zadaniu anonimizacji IP, które haszuje je po skonfigurowanej liczbie dni na potrzeby zgodności z RODO.

Last reviewed: Recently