Enhetsgrafanalys: att koppla ihop punkterna över sessioner
Hur grafdatabaser avslöjar dolda kopplingar mellan enheter och möjliggör upptäckt av flerkontoanvändning och identifiering av bedrägerinätverk i stor skala.
När en enda bedragare driver dussintals konton ser de enskilda kontona legitima ut när de betraktas isolerat. Vart och ett har en unik e-postadress, en trovärdig IP-adress, realistiska surfmönster. Traditionell regelbaserad detektion granskar varje konto oberoende och hittar inget misstänkt. Kopplingarna mellan kontona — de delade enheterna, överlappande sessioner, gemensamma nätverksfingeravtryck — är osynliga för system som behandlar konton ett i taget.
Varför grafer
Enhetsgrafanalys förändrar modellen. Istället för att bedöma konton oberoende bygger vi en graf där noderna är enheter, konton, IP-adresser och sessioner, och kanterna representerar observerade kopplingar: "den här enheten användes för att skapa det här kontot", "den här IP:n sågs tillsammans med den här enheten", "de här två kontona delade en sessionscookie". Grafen avslöjar struktur som platta tabeller inte kan.
Ett bedrägerinätverk som använder 50 konton över 5 enheter och 3 IP-adresser bildar ett distinkt kluster i grafen. Klusterdensiteten — många kopplingar inom en liten grupp noder — är en stark signal. Legitima användare delar sällan enheter med främlingar, och deras konto-enhetskopplingar bildar glesa, trädlika strukturer snarare än täta kluster.
Grafdatabasarkitektur
Vi använder en property graph-modell med fyra nodtyper: Device (identifierad via visitor ID), Account (ditt user ID), Network (IP-adress + ASN) och Session (enskild identifieringshändelse). Kanterna bär metadata: tidsstämpel, konfidenspoäng och händelsetyp.
Grafen lagras i ett specialbyggt adjacensindex optimerat för tvåstegstraverseringar. När en ny identifieringshändelse anländer infogar vi händelsen som en Session-nod, kopplar den till Device- och Network-noderna och kontrollerar om något länkat Account har kopplingar till andra enheter. Denna infoga-och-fråga-operation slutförs på under 5ms för grafer med upp till 10 miljoner noder.
Vi provade faktiskt Neo4j först. Det fungerade utmärkt i utvecklingsmiljö med 100K noder. Sedan laddade vi produktionsdata — 500M noder — och Cypher-frågor som tog 2ms började ta 800ms. David ägnade en vecka åt att benchmarka alternativ innan vi byggde vårt eget adjacensindex uppbackat av shardad RocksDB. Ibland slår den tråkiga, egenbyggda lösningen den eleganta hyllvaran.
Klustringsalgoritmer
Vi tillämpar två klustringsalgoritmer på enhetsgrafen:
Connected components
Den enklaste ansatsen: hitta alla noder som är nåbara från en given enhet. Om Device A är kopplad till Account 1 och Account 2, och Device B också är kopplad till Account 2, då ligger Device A och B i samma connected component. Detta identifierar alla konton som delar någon transitiv enhetskoppling.
Connected components är snabba att beräkna men kan producera väldigt stora kluster när legitima delade enheter (familjedatorer, biblioteksterminaler) skapar bryggor mellan orelaterade konton. Vi hanterar detta med kantviktning — kopplingar genom kända delade miljöer får lägre vikt.
Community detection
För mer nyanserad analys kör vi Louvain community detection på den viktade grafen. Denna algoritm partitionerar grafen i communities där kopplingar inom en community är täta och kopplingar mellan communities är glesa. Bedrägerinätverk bildar täta communities även när de är kopplade till den bredare grafen genom delad infrastruktur.
Louvain-algoritmen körs i O(n log n)-tid, vilket gör den praktisk för grafer med miljontals noder. Vi kör den inkrementellt — när nya kanter läggs till uppdaterar vi community-tilldelningarna lokalt istället för att räkna om hela partitionen.
Mönster från verkligheten: upptäckt av bedrägerinätverk
En spelplattform integrerade vårt enhetsgraf-API för att upptäcka organiserade bedrägerinätverk. Redan under första veckan avslöjade grafen ett kluster av 127 konton kopplade genom 8 enheter och 4 IP-adresser. Kontona hade skapats under en period på 3 månader, vart och ett med en unik e-postadress och en realistisk profil. Regelbaserad detektion hade flaggat noll av dem.
Grafstrukturen var det som avslöjade det: 127 konton som delar 8 enheter ger i genomsnitt 15,8 konton per enhet. Legitima användare har i genomsnitt 1,2 konton per enhet på den här plattformen. Klusterdensiteten var 47x över baslinjen — en otvetydig bedrägerisignal.
Prestanda i stor skala
Vår enhetsgraf i produktion hanterar 2,3 miljarder noder och 8,1 miljarder kanter. Insättningslatensen är 2,4ms vid p99. Tvåstegstraversering (hitta alla konton kopplade till en enhet via valfri väg av längd 2) slutförs på 4,1ms vid p99. Uppdateringar av community detection behandlar 50 000 nya kanter per sekund.
Grafen är shardad efter hash av device ID över 12 noder, där varje shard rymmer cirka 190 miljoner noder. En replikeringsfaktor på 3 säkerställer tillgänglighet. Vi tar en ögonblicksbild av grafen varje timme för katastrofåterställning och kör en fullständig omräkning av community detection dagligen som en konsistenskontroll mot de inkrementella uppdateringarna.
Integration
Enhetsgrafen är tillgänglig genom två gränssnitt: ett realtids-frågeAPI för enskilda uppslag (är den här enheten kopplad till andra konton?) och ett batch-export-API för analys (ge mig alla kluster med fler än N konton). Realtids-API:et är utformat för inline-beslut om bedrägeri — fråga under kontoskapande för att kontrollera om enheten har setts med andra konton. Batch-API:et matar ditt datateams utredningsflöden.