
معيار مفتوح لتجزئة تدفقات الشبكة إلى معرّفات، يُعرف أيضًا باسم "Community IDs".
عند معالجة بيانات التدفقات الواردة من مجموعة متنوعة من تطبيقات المراقبة (مثل Zeek وSuricata)، غالبًا ما يكون من المرغوب التنقّل بسرعة من مجموعة بيانات إلى أخرى. وفي حين تكون معلومات مُجمَّعة التدفق المطلوبة متوفرة عادةً في مجموعات البيانات، فإن تفاصيل عمليات «الربط» هذه قد تكون مملة، ولا سيما في الحالات الحدّية. تصف هذه المواصفة تجزئة تدفقات «Community ID»، إذ توحّد إنتاج معرّف نصّي يمثّل تدفق شبكة معيّنًا، بحيث يُختزل التنقّل إلى مجرد مقارنة نصوص بسيطة.
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);
}
إنّ Community ID هو معرّف تدفق إضافي ولا يلزم أن يحل محل آليات تعريف التدفق الموجودة التي تدعمها أدوات المراقبة. ومع ذلك، لا بأس في ضبط أداة مراقبة بحيث تسجّل Community ID فقط، إذا كان ذلك مرغوبًا.
يمكن حساب Community ID في الوقت الذي تُنتج فيه أداة المراقبة التدفقات، أو يمكن أيضًا إضافته إلى سجلات التدفق الموجودة في مرحلة لاحقة، بافتراض أن تلك السجلات تتضمّن جميع معلومات نقاط نهاية التدفق المطلوبة.
التصادمات في Community ID، وإن كانت غير مرغوبة، لا تُعتبر قاتلة؛ إذ ينبغي أن تظل بحوزة المستخدم معلومات توقيت التدفق، وربما آلية المعرّف الأصلية لأداة المراقبة (والأمل أن تكون أقوى من Community ID) لإزالة الالتباس.
تعتمد آلية التجزئة على البذر (seeding) لإتاحة تحكّم إضافي في «نطاقات» استخدام Community ID. القيمة الافتراضية للبذرة هي 0، وبالتالي تبقى هذه الآلية بمعزل عن العملية، فلا تؤثر على المشغّلين غير المهتمين بها.
في الإصدار 1 من المعرّف، تكون خوارزمية التجزئة هي SHA1. وقد تغيّرها إصدارات تجزئة مستقبلية أو تتيح إعدادات إضافية.
تُرمَّز النتيجة الثنائية لحجم 20 بايت من SHA1 بترميز base64 لتقليل حجم المخرجات مقارنة بالتمثيل المعتاد لـSHA1 القائم على ASCII. يفترض ذلك أن المساحة هي الشاغل الأساسي، لا زمن الحساب، وقد يصبح هذا الخيار قابلاً للضبط في إصدار لاحق.
يتضمّن معرّف التدفق الناتج رقم إصدار لإبراز تنفيذ Community ID الكامن. يتيح ذلك للمستخدمين التأكد من أنهم يقارنون أشياء متكافئة، مع دعم التغييرات المستقبلية في الخوارزمية. على سبيل المثال، عندما يتضمّن إصدار أحد أدوات المراقبة من المعرّف معرّفات VLAN بينما لا يتضمّنها إصدار آخر، ينبغي أن تفشل مقارنات قيم التجزئة على نحو يمكن الاعتماد عليه. وقد يسمح شكل أكثر تعقيدًا من هذه الميزة بالتقاط إعدادات الضبط إضافةً إلى إصدار التنفيذ.
يقتصر مخطط الإصدارات حاليًا على إضافة البادئة «:» إلى قيمة التجزئة، منتجًا ما يشبه هذا في الإصدار الحالي 1:
1:hO+sN4H+MG5MY/8hIrXPqc4ZQz0=
تتم محاذاة مدخلات التجزئة على حدود 32-بت. تستخدم مكوّنات مُجمَّعة التدفق ترتيب بايتات الشبكة (big-endian) لتوحيد الترتيب بغض النظر عن عتاد المضيف.
تُرتَّب مدخلات التجزئة لإزالة الاتجاهية من مُجمَّعة التدفق: قم بتبديل نقاط النهاية، عند الحاجة، بحيث تأتي مُجمَّعة IP:port الأصغر عدديًا أولاً. إذا تساوت عناوين IP، تحسم المنافذ الأمر. على سبيل المثال، تُنتج مُجمَّعات netflow الخماسية التالية تجزئات Community ID متطابقة، لأن كلتيهما تُرتَّبان في التسلسل 10.0.0.1، 127.0.0.1، 1234، 80.
يتضمّن هذا الإصدار البروتوكولات والحقول التالية:
يتوفر تنفيذ كامل في حزمة pycommunityid. تتضمّن مجموعة من الاختبارات للتحقق من صحة الحساب لمختلف البروتوكولات. ونوصي بها دليلًا للتنفيذات الجديدة.
يتوفر تنفيذ أصغر أيضًا عبر سكربت community-id.py في هذا المستودع، بما في ذلك تخطيط البايتات للقيم المجزَّأة (انظر packet_get_comm_id()). راجع --help وmake.sh للبدء:
$ ./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
للاستكشاف وإصلاح الأخطاء، يدعم التنفيذ إمكانية حذف عملية base64، ويمكنه تقديم تفاصيل إضافية حول التسلسل الدقيق للبايتات التي تدخل في حساب تجزئة SHA1.
يحتوي دليل baseline في هذا المستودع على مجموعات
بيانات تساعدك في التحقق من أن تنفيذك لـCommunity ID يعمل بشكل
صحيح.
لا تتردد في مناقشة جوانب Community ID عبر GitHub هنا: https://github.com/corelight/community-id-spec/issues
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
إنّ المعالجة الدقيقة لنوع ICMP ورمزه (code) مأخوذة من Zeek؛ انظر التنفيذات هنا:
بروتوكولات أخرى محمولة عبر IP:
IP src / IP dst / IP proto
لا يغطي ما سبق حاليًا كيفية التعامل مع التداخل (IP داخل IP، وv6 فوق v4، وما إلى ذلك)، وكذلك التغليفات مثل VLAN وMPLS.
إذا كانت أداة مراقبة الشبكة لا تدعم أيًّا من تركيبات البروتوكولات المذكورة أعلاه، فيمكنها بأمان إرجاع سلسلة فارغة (أو قيمة أخرى لا تسبب تصادمًا) لمعرّف التدفق.
اعتبروا v1 نموذجًا أوليًا. آراء المجتمع، ولا سيما المنفِّذين والمستخدمين التشغيليين للمعرّف، محل تقدير بالغ. يرجى إنشاء issues مباشرةً في مشروع GitHub على https://github.com/corelight/community-id-spec، أو التواصل مع Christian Kreibich ([email protected]).
شكر جزيل على النقاش المفيد والملاحظات لكل من Victor Julien وJohanna Amann وRobin Sommer، وكذلك لجميع المنفِّذين والداعمين.