
Uno standard aperto per l'hashing dei flussi di rete in identificatori, noto anche come "Community IDs".
Quando si elaborano dati di flusso da una varietà di applicazioni (come Zeek e Suricata), è spesso desiderabile spostarsi rapidamente da un dataset all'altro. Sebbene le informazioni sulla tupla di flusso richieste siano solitamente presenti nei dataset, i dettagli di tali "join" possono essere noiosi, in particolare nei casi limite. Questa specifica descrive l' hashing dei flussi "Community ID", standardizzando la produzione di un identificatore stringa che rappresenta un dato flusso di rete, per ridurre il passaggio a un semplice confronto di stringhe.
function community_id_v1(ipaddr saddr, ipaddr daddr, port sport, port dport, int proto, int seed=0)
{
# Get seed and all tuple parts into network byte order
seed = pack_to_nbo(seed); # 2 bytes
saddr = pack_to_nbo(saddr); # 4 or 16 bytes
daddr = pack_to_nbo(daddr); # 4 or 16 bytes
sport = pack_to_nbo(sport); # 2 bytes
dport = pack_to_nbo(dport); # 2 bytes
# Abstract away directionality: flip the endpoints as needed
# so the smaller IP:port tuple comes first.
saddr, daddr, sport, dport = order_endpoints(saddr, daddr, sport, dport);
# Produce 20-byte SHA1 digest. "." means concatenation. The
# proto value is one byte in length and followed by a 0 byte
# for padding.
sha1_digest = sha1(seed . saddr . daddr . proto . 0 . sport . dport)
# Prepend version string to base64 rendering of the digest.
# v1 is currently the only one available.
return "1:" + base64(sha1_digest)
}
function community_id_icmp(ipaddr saddr, ipaddr daddr, int type, int code, int seed=0)
{
port sport, dport;
# ICMP / ICMPv6 endpoint mapping directly inspired by Zeek
sport, dport = map_icmp_to_ports(type, code);
# ICMP is IP protocol 1, ICMPv6 would be 58
return community_id_v1(saddr, daddr, sport, dport, 1, seed);
}
Il Community ID è un identificatore di flusso aggiuntivo e non deve sostituire i meccanismi di identificazione dei flussi già supportati dai monitor. È comunque accettabile che un monitor venga configurato per registrare solo il Community ID, se desiderabile.
Il Community ID può essere calcolato mentre un monitor produce flussi, oppure può essere aggiunto in seguito ai record di flusso esistenti, supponendo che tali record contengano tutte le informazioni necessarie sugli endpoint del flusso.
Le collisioni nel Community ID, sebbene indesiderabili, non sono considerate fatali, poiché l'utente dovrebbe comunque disporre delle informazioni di temporizzazione del flusso e possibilmente del meccanismo ID nativo del monitor (si spera più forte del Community ID) per la disambiguazione.
Il meccanismo di hashing utilizza il seeding per consentire un controllo aggiuntivo sui "domini" di utilizzo del Community ID. Il seed predefinito è 0, quindi questo meccanismo si fa da parte e non influisce sul funzionamento per gli operatori che non vi sono interessati.
Nella versione 1 dell'ID, l'algoritmo di hash è SHA1. Le future versioni di hash potrebbero cambiarlo o consentire una configurazione aggiuntiva.
Il risultato SHA1 binario di 20 byte viene codificato in base64 per ridurre il volume di output rispetto alla consueta rappresentazione SHA1 basata su ASCII. Questo presuppone che lo spazio, non il tempo di calcolo, sia la preoccupazione principale, e potrebbe diventare configurabile in una versione successiva.
L'ID di flusso risultante include un numero di versione per rendere esplicita l'implementazione sottostante del Community ID. Ciò consente agli utenti di assicurarsi di confrontare mele con mele, supportando al contempo futuri cambiamenti dell'algoritmo. Ad esempio, quando la versione dell'ID di un monitor incorpora gli ID VLAN ma quella di un altro no, i confronti dei valori di hash dovrebbero fallire in modo affidabile. Una forma più complessa di questa funzionalità potrebbe consentire di catturare le impostazioni di configurazione oltre alla versione dell'implementazione.
Lo schema di versionamento attualmente si limita a prefissare il valore di hash con ":", producendo qualcosa del genere nella versione 1 attuale:
1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=
L'input di hash è allineato su confini di 32 bit. I componenti della tupla di flusso utilizzano l'ordine di byte di rete (big-endian) per standardizzare l'ordinamento indipendentemente dall'hardware dell'host.
L'input di hash è ordinato per rimuovere la direzionalità nella tupla di flusso: scambia gli endpoint, se necessario, così che la tupla IP:port numericamente più piccola venga prima. Se gli indirizzi IP sono uguali, decidono le porte. Ad esempio, le seguenti 5-tuple netflow creano hash Community ID identici perché entrambe vengono ordinate nella sequenza 10.0.0.1, 127.0.0.1, 1234, 80.
Un'implementazione completa è disponibile nel pacchetto pycommunityid. Include una serie di test per verificare il calcolo corretto per i vari protocolli. La consigliamo per guidare nuove implementazioni.
Un'implementazione più piccola è disponibile anche tramite lo script community-id.py in questo repository, inclusa la disposizione dei byte dei valori sottoposti a hash (vedi packet_get_comm_id()). Vedi --help e make.sh per iniziare:
$ ./community-id.py --help
usage: community-id.py [-h] [--seed NUM] PCAP [PCAP ...]
Community flow ID reference
positional arguments:
PCAP PCAP packet capture files
optional arguments:
-h, --help show this help message and exit
--seed NUM Seed value for hash operations
--no-base64 Don't base64-encode the SHA1 binary value
--verbose Show verbose output on stderr
Per la risoluzione dei problemi, l'implementazione supporta l'omissione dell'operazione base64, e può fornire ulteriori dettagli sulla sequenza esatta di byte che entrano nel calcolo dell'hash SHA1.
La directory baseline in questo repository contiene dataset per
aiutarti a verificare che la tua implementazione delle funzioni Community ID
funzioni correttamente.
Sentiti libero di discutere aspetti del Community ID su GitHub qui: https://github.com/corelight/community-id-spec/issues
Questa versione include i seguenti protocolli e campi:
TCP / UDP / SCTP:
IP src / IP dst / IP proto / porta sorgente / porta di destinazione
ICMPv4 / ICMPv6:
IP src / IP dst / IP proto / tipo ICMP + "counter-type" o codice
La gestione esatta di tipo e codice ICMP è tratta da Zeek; vedi le implementazioni qui:
Altri protocolli trasportati su IP:
IP src / IP dst / IP proto
Quanto sopra attualmente non copre come gestire l'annidamento (IP in IP, v6 su v4, ecc.) o encapsulazioni come VLAN e MPLS.
Se un monitor di rete non supporta nessuna delle costellazioni di protocollo sopra menzionate, può tranquillamente riportare una stringa vuota (o un altro valore non in collisione) per l'ID di flusso.
Considera v1 un prototipo. Il feedback della comunità, in particolare di implementatori e utenti operativi dell'ID, è enormemente apprezzato. Si prega di creare issue direttamente nel progetto GitHub su https://github.com/corelight/community-id-spec, o contattare Christian Kreibich ([email protected]).
Molte grazie per le utili discussioni e il feedback a Victor Julien, Johanna Amann e Robin Sommer, e a tutti gli implementatori e sostenitori.