Analiza grafu urządzeń: łączenie punktów między sesjami
Jak bazy grafowe ujawniają ukryte powiązania między urządzeniami, umożliwiając wykrywanie wielu kont i identyfikację siatek oszustów na dużą skalę.
Gdy jeden oszust obsługuje dziesiątki kont, poszczególne konta w izolacji wyglądają legalnie. Każde ma unikalny adres e-mail, prawdopodobny adres IP, realistyczne wzorce przeglądania. Tradycyjne wykrywanie oparte na regułach sprawdza każde konto niezależnie i nie znajduje niczego podejrzanego. Powiązania między kontami — współdzielone urządzenia, nakładające się sesje, wspólne odciski sieciowe — są niewidoczne dla systemów przetwarzających konta pojedynczo.
Dlaczego grafy
Analiza grafu urządzeń zmienia model. Zamiast oceniać konta niezależnie, budujemy graf, w którym węzłami są urządzenia, konta, adresy IP i sesje, a krawędzie reprezentują zaobserwowane powiązania: „tego urządzenia użyto do utworzenia tego konta”, „ten adres IP widziano razem z tym urządzeniem”, „te dwa konta współdzieliły ciasteczko sesji”. Graf ujawnia strukturę, której płaskie tabele nie są w stanie pokazać.
Siatka oszustów wykorzystująca 50 kont na 5 urządzeniach i 3 adresach IP tworzy w grafie charakterystyczny klaster. Gęstość klastra — wiele powiązań w obrębie małej grupy węzłów — jest silnym sygnałem. Legalni użytkownicy rzadko współdzielą urządzenia z obcymi, a ich powiązania konto–urządzenie tworzą rzadkie, drzewiaste struktury, a nie gęste klastry.
Architektura bazy grafowej
Używamy modelu grafu właściwości (property graph) z czterema typami węzłów: Device (identyfikowany przez visitor ID), Account (Twój identyfikator użytkownika), Network (adres IP + ASN) i Session (pojedyncze zdarzenie identyfikacji). Krawędzie niosą metadane: znacznik czasu, wynik pewności (confidence score) oraz typ zdarzenia.
Graf jest przechowywany w specjalnie zaprojektowanym indeksie sąsiedztwa, zoptymalizowanym pod przechodzenie dwuskokowe (2-hop). Gdy pojawia się nowe zdarzenie identyfikacji, wstawiamy je jako węzeł Session, łączymy z węzłami Device i Network oraz sprawdzamy, czy powiązane konto Account ma połączenia z innymi urządzeniami. Ta operacja wstawiania i zapytania kończy się w czasie poniżej 5 ms dla grafów liczących do 10 milionów węzłów.
Na początku faktycznie wypróbowaliśmy Neo4j. Działał świetnie w środowisku deweloperskim przy 100 tys. węzłów. Potem załadowaliśmy dane produkcyjne — 500 mln węzłów — i zapytania Cypher, które trwały 2 ms, zaczęły zajmować 800 ms. David spędził tydzień na testowaniu alternatyw, zanim zbudowaliśmy własny indeks sąsiedztwa oparty na shardowanym RocksDB. Czasem nudne, autorskie rozwiązanie pokonuje eleganckie gotowe.
Algorytmy klasteryzacji
Do grafu urządzeń stosujemy dwa algorytmy klasteryzacji:
Spójne składowe
Najprostsze podejście: znajdź wszystkie węzły osiągalne z danego urządzenia. Jeśli Device A jest połączony z Account 1 i Account 2, a Device B jest również połączony z Account 2, to Device A i Device B należą do tej samej spójnej składowej. Pozwala to zidentyfikować wszystkie konta współdzielące dowolne przechodnie powiązanie przez urządzenie.
Spójne składowe liczy się szybko, ale mogą one tworzyć bardzo duże klastry, gdy legalnie współdzielone urządzenia (komputery rodzinne, terminale w bibliotekach) tworzą mostki między niepowiązanymi kontami. Rozwiązujemy to za pomocą ważenia krawędzi — połączenia przez znane wspólne środowiska otrzymują niższą wagę.
Wykrywanie społeczności
Dla bardziej niuansowej analizy uruchamiamy na ważonym grafie wykrywanie społeczności metodą Louvain. Algorytm ten dzieli graf na społeczności, w których powiązania wewnątrz społeczności są gęste, a między społecznościami rzadkie. Siatki oszustów tworzą zwarte społeczności nawet wtedy, gdy są połączone z szerszym grafem poprzez współdzieloną infrastrukturę.
Algorytm Louvain działa w czasie O(n log n), co czyni go praktycznym dla grafów z milionami węzłów. Uruchamiamy go przyrostowo — gdy dodawane są nowe krawędzie, aktualizujemy przypisania do społeczności lokalnie, zamiast przeliczać cały podział.
Wzorzec z praktyki: wykrywanie siatki oszustów
Pewna platforma gamingowa zintegrowała nasze API grafu urządzeń, aby wykrywać zorganizowane siatki oszustów. Już w pierwszym tygodniu graf ujawnił klaster 127 kont połączonych przez 8 urządzeń i 4 adresy IP. Konta były tworzone przez okres 3 miesięcy, każde z unikalnym adresem e-mail i realistycznym profilem. Wykrywanie oparte na regułach nie oznaczyło żadnego z nich.
Zdradziła je struktura grafu: 127 kont współdzielących 8 urządzeń daje średnio 15,8 konta na urządzenie. Legalni użytkownicy na tej platformie mają średnio 1,2 konta na urządzenie. Gęstość klastra była 47x powyżej poziomu bazowego — jednoznaczny sygnał oszustwa.
Wydajność w skali
Nasz produkcyjny graf urządzeń obsługuje 2,3 miliarda węzłów i 8,1 miliarda krawędzi. Opóźnienie wstawiania wynosi 2,4 ms przy p99. Przechodzenie dwuskokowe (znajdź wszystkie konta połączone z urządzeniem dowolną ścieżką o długości 2) kończy się w 4,1 ms przy p99. Aktualizacje wykrywania społeczności przetwarzają 50 000 nowych krawędzi na sekundę.
Graf jest shardowany według skrótu identyfikatora urządzenia na 12 węzłach, przy czym każdy shard przechowuje około 190 milionów węzłów. Współczynnik replikacji równy 3 zapewnia dostępność. Robimy migawkę grafu co godzinę na potrzeby odtwarzania po awarii oraz codziennie uruchamiamy pełne przeliczenie wykrywania społeczności jako kontrolę spójności względem aktualizacji przyrostowych.
Integracja
Graf urządzeń jest dostępny przez dwa interfejsy: API zapytań w czasie rzeczywistym do pojedynczych wyszukiwań (czy to urządzenie jest połączone z innymi kontami?) oraz API eksportu wsadowego do analityki (podaj wszystkie klastry z więcej niż N kontami). API czasu rzeczywistego jest zaprojektowane do wbudowanych decyzji antyfraudowych — odpytuj podczas tworzenia konta, aby sprawdzić, czy urządzenie widziało już inne konta. API wsadowe zasila procesy dochodzeniowe Twojego zespołu danych.