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.
- Aplikacja bierze peera transportowego (adres, który faktycznie otworzył połączenie).
- 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.
- 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 nadpisujeX-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
| Zmienna | Domyślnie | Opis |
|---|---|---|
GEOIP_ENABLED | false | Przełą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_UPDATE | true | Automatyczne 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
.mmdbmoż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:
- Ustaw
GEOIP_ENABLED=falsew środowisku backendu. - Zrestartuj backend (to wyłącza egzekucję GeoIP, zanim jakakolwiek polityka zostanie oceniona).
- Popraw lub wyczyść listę dozwolonych krajów, następnie ustaw
GEOIP_ENABLED=truei 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.