Sari la conținut
← Studii de caz
Captură de ecran din Pipeline-ul de amenințări de la edge: de la un dashboard simulat la detecții reale

Securitate4 min read

Pipeline-ul de amenințări de la edge: de la un dashboard simulat la detecții reale

Am înlocuit o hartă falsă a atacurilor cu un pipeline real: detecții IDS de la marginea AS210622, trimise pe o cale autentificată și fail-closed, stocate în SQLite și afișate live — cu o statistică „Blocate: 0” pe care refuzăm să o umflăm.

  • Security
  • IDS
  • Observability
  • AS210622

Context

Acest site are o hartă live a amenințărilor. O vreme, a fost o minciună — un script pe partea de client inventa câte un atac pe secundă peste un fișier JSON static, cu cifre de titlu pe măsură. Acesta este standardul din industrie pentru astfel de pagini și este exact genul de lucru pe care am decis să nu-l mai facem.

Astăzi harta afișează detecții reale de la sistemul de detecție a intruziunilor care rulează la marginea AS210622. Fiecare arc pe care îl vezi corespunde unei potriviri reale de semnătură pe trafic real. Acest studiu de caz descrie cum funcționează pipeline-ul și deciziile de design pe care ți le impune un feed public de securitate.

Constrângeri

  • Pagina este publică. Tot ce e pe ea este disponibil celor care ne sondează, așa că feed-ul nu trebuie să devină niciodată recunoaștere gratuită.
  • Uplink-urile routerelor sunt contorizate și modeste. Agentul de expediere rulează chiar pe routerele de edge; pipeline-ul a trebuit să fie ușor atât în lățime de bandă, cât și în dependențe.
  • Un singur deploy, fără host-uri noi. Colectorul a trebuit să trăiască în containerul existent al site-ului, nu să devină încă un serviciu de operat.

Abordare

Pipeline-ul este deliberat scurt:

edge routers ── detection agent: tail alerts → enrich (ASN/country/city)
                     → batch + gzip → authenticated ship to the site
                                            │
                                      SQLite (node:sqlite)
                                            │
                          GET /api/threats → live map (polls every 5s)

Un agent mic în Go de pe fiecare router urmărește jurnalul de evenimente al IDS-ului, îmbogățește fiecare alertă cu ASN-ul, țara și orașul sursei, apoi trimite loturi comprimate cu gzip — JSON-ul de alerte este repetitiv și se comprimă de aproximativ 10x, ceea ce contează pe un uplink contorizat. Calea de scriere este autentificată și fail-closed: dacă credențialele ei nu sunt configurate, respinge pe toată lumea în loc să accepte scrieri anonime. Evenimentele ajung în SQLite prin driverul încorporat în Node (ales pentru că build-ul Docker rulează npm ci --ignore-scripts și nu poate compila module native), pe un volum cu nume, ca istoricul să supraviețuiască redeploy-urilor. Tipurile de atac sunt rezolvate la scriere și indexate, astfel încât calea de citire servește agregate pe 24 de ore din indecși acoperitori în loc să clasifice la fiecare cerere.

Trei decizii definesc feed-ul public:

  • Destinațiile sunt locații, niciodată IP-uri. Feed-ul spune „Pitești (Port 22 — SSH)”, nu ce host de client a fost sondat. Tipul de eveniment nu are în mod deliberat niciun câmp de IP destinație, așa că greșeala este nereprezentabilă.
  • Motorul rămâne nenumit. Textul public spune „detecții de la marginea AS210622” — a numi IDS-ul îi spune unui atacator exact ce să evite, așa că textul semnăturilor este curățat înainte de afișare, iar pagina nu numără niciodată senzorii.
  • „Blocate” arată zero, pentru că este zero. Textul anterior pretindea o mitigare care nu avea loc. Statistica devine nenulă când detecțiile produc blocări reale în firewall — nu înainte.

Ce s-a stricat

Clasificatorul încadra hit-urile din liste de reputație ca exploit-uri. O semnătură care se termina în „…Block Listed Source” se potrivea ca substring cu un pattern gol rce și dubla numărul de exploit-uri. Remedierea — regulile de reputație se potrivesc primele, acronimele scurte sunt ancorate cu \b — este acum fixată de o suită Vitest de 38 de cazuri care folosesc nume reale de semnături, verificată să eșueze dacă oricare dintre cele două proprietăți este reintrodusă. Regulile de clasificare sunt oglindite în agentul Go, așa că ambele părți se schimbă împreună sau deloc.

Blocarea inline este costisitoare pe tăcute. Un filtru care aruncă o parte din traficul legitim este o cădere pe care ți-o provoci singur, așa că orice blochează la edge trebuie să-și câștige locul mai întâi prin dovezi. A parcurge acele dovezi este aceeași problemă de alert fatigue care ne-a determinat să construim meerkat, consola noastră open source care agregă mii de alerte în decizii per sursă.

Secretele încercau întruna să intre în build. Integrarea de mail își construia inițial clientul la nivel de modul, ceea ce făcea din cheia ei de API o cerință la build time — adică un build arg de Docker, adică un secret citibil în istoricul imaginii. Acum se inițializează la prima cerere; build-ul de producție nu are nevoie de niciun environment.

Unde s-a ajuns

Pipeline-ul este în producție: evenimente reale, ingest fail-closed, clasificare testată, retenție de 24 de ore cu agregate indexate și date care supraviețuiesc recreării containerului. Lipsurile oneste sunt și ele documentate — blocarea nu este încă legată de firewall, iar un deployment cu mai multe replici ar avea nevoie ca cache-ul local procesului să fie regândit.

Dacă dashboard-ul tău de securitate îți arată zgomot — sau ficțiune — te putem ajuta să construiești unul care spune adevărul.