
Ein offener Standard zum Hashen von Netzwerkflüssen in Identifikatoren, auch bekannt als „Community IDs“.
Bei der Verarbeitung von Flow-Daten aus einer Vielzahl von Überwachungsanwendungen (wie Zeek und Suricata) ist es oft wünschenswert, schnell von einem Datensatz zu einem anderen zu wechseln. Während die erforderlichen Flow-Tupel-Informationen in den Datensätzen normalerweise vorhanden sind, kann die Durchführung solcher „Joins“ mühsam sein, insbesondere in Randfällen. Diese Spezifikation beschreibt das „Community-ID“-Flow-Hashing, das die Erzeugung eines Zeichenfolgen-Identifikators für einen bestimmten Netzwerk-Flow standardisiert, um den Pivot auf einen einfachen Zeichenfolgenvergleich zu reduzieren.
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);
}
Die Community-ID ist ein zusätzlicher Flow-Identifikator und muss vorhandene Flow-Identifikationsmechanismen, die von den Monitoren bereits unterstützt werden, nicht ersetzen. Es ist jedoch in Ordnung, einen Monitor so zu konfigurieren, dass er nur die Community-ID protokolliert, falls gewünscht.
Die Community-ID kann berechnet werden, während ein Monitor Flows erzeugt, oder kann später zu bestehenden Flow-Datensätzen hinzugefügt werden, sofern diese Datensätze alle erforderlichen Informationen zu den Flow-Endpunkten enthalten.
Kollisionen in der Community-ID sind zwar unerwünscht, werden aber nicht als fatal betrachtet, da der Benutzer weiterhin über Flow-Zeitinformationen und möglicherweise den nativen ID-Mechanismus des Monitors (idealerweise stärker als die Community-ID) zur Disambiguierung verfügen sollte.
Der Hashing-Mechanismus verwendet Seeding, um zusätzliche Kontrolle über „Domänen“ der Community-ID-Nutzung zu ermöglichen. Der Seed ist standardmäßig 0, sodass dieser Mechanismus nicht im Weg steht und den Betrieb für Betreiber, die sich nicht dafür interessieren, nicht beeinträchtigt.
In Version 1 der ID ist der Hash-Algorithmus SHA1. Zukünftige Hash-Versionen können ihn wechseln oder zusätzliche Konfiguration ermöglichen.
Das binäre 20-Byte-SHA1-Ergebnis wird base64-kodiert, um das Ausgabevolumen im Vergleich zur üblichen ASCII-basierten SHA1-Darstellung zu reduzieren. Dies setzt voraus, dass Speicherplatz und nicht Rechenzeit das primäre Anliegen ist, und kann in einer späteren Version konfigurierbar werden.
Die resultierende Flow-ID enthält eine Versionsnummer, um die zugrunde liegende Community-ID-Implementierung explizit zu machen. Dies ermöglicht Benutzern sicherzustellen, dass sie Äpfel mit Äpfeln vergleichen, während zukünftige Änderungen am Algorithmus unterstützt werden. Wenn beispielsweise die Version der ID eines Monitors VLAN-IDs einbezieht, die eines anderen jedoch nicht, sollten Hashwertvergleiche zuverlässig fehlschlagen. Eine komplexere Form dieser Funktion könnte es ermöglichen, zusätzlich zur Implementierungsversion auch Konfigurationseinstellungen zu erfassen.
Das Versionierungsschema stellt dem Hashwert derzeit einfach „:“ voran, was in der aktuellen Version 1 etwa so aussieht:
1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=
Die Hash-Eingabe ist an 32-Bit-Grenzen ausgerichtet. Flow-Tupel-Komponenten verwenden die Netzwerk-Byte-Reihenfolge (Big-Endian), um die Reihenfolge unabhängig von der Host-Hardware zu standardisieren.
Die Hash-Eingabe wird geordnet, um die Richtungsabhängigkeit im Flow-Tupel zu entfernen: Die Endpunkte werden bei Bedarf getauscht, sodass das numerisch kleinere IP:Port-Tupel zuerst kommt. Wenn die IP-Adressen gleich sind, entscheiden die Ports. Beispielsweise erzeugen die folgenden Netflow-5-Tupel identische Community-ID-Hashes, da beide in die Sequenz 10.0.0.1, 127.0.0.1, 1234, 80 geordnet werden.
Eine vollständige Implementierung ist im Paket pycommunityid verfügbar. Es enthält eine Reihe von Tests, um die korrekte Berechnung für die verschiedenen Protokolle zu verifizieren. Wir empfehlen es als Leitfaden für neue Implementierungen.
Eine kleinere Implementierung ist außerdem über das Skript community-id.py in diesem Repository verfügbar, einschließlich des Byte-Layouts der gehashten Werte (siehe packet_get_comm_id()). Siehe --help und make.sh für den Einstieg:
$ ./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
Für die Fehlersuche unterstützt die Implementierung das Weglassen der base64-Operation und kann zusätzliche Details zur genauen Byte-Sequenz liefern, die in die SHA1-Hash-Berechnung eingeht.
Das Verzeichnis baseline in diesem Repository enthält Datensätze, mit denen Sie verifizieren können, dass Ihre Implementierung der Community-ID korrekt funktioniert.
Diskutieren Sie Aspekte der Community-ID gerne hier über GitHub: https://github.com/corelight/community-id-spec/issues
Diese Version enthält die folgenden Protokolle und Felder:
TCP / UDP / SCTP:
IP src / IP dst / IP proto / source port / dest port
ICMPv4 / ICMPv6:
IP src / IP dst / IP proto / ICMP type + "counter-type" or code
Die genaue Behandlung von ICMP-Typ und -Code stammt von Zeek; siehe Implementierungen hier:
Andere IP-basierte Protokolle:
IP src / IP dst / IP proto
Das oben Genannte deckt derzeit nicht ab, wie mit Verschachtelung (IP in IP, v6 über v4 usw.) sowie Kapselungen wie VLAN und MPLS umzugehen ist.
Wenn ein Netzwerk-Monitor keine der oben genannten Protokollkonstellationen unterstützt, kann er für die Flow-ID sicher eine leere Zeichenfolge (oder einen anderen nicht kollidierenden Wert) melden.
Betrachten Sie v1 als Prototyp. Feedback aus der Community, insbesondere von Implementierern und operativen Benutzern der ID, ist sehr willkommen. Bitte erstellen Sie Issues direkt im GitHub-Projekt unter https://github.com/corelight/community-id-spec oder kontaktieren Sie Christian Kreibich ([email protected]).
Vielen Dank für hilfreiche Diskussionen und Feedback an Victor Julien, Johanna Amann und Robin Sommer sowie an alle Implementierer und Unterstützer.