تخطَّ إلى المحتوى
netrewind
الصندوق الأسود لشبكتك

البداية

ابنه وشغّله، ثم جرّبه بعطل مقصود

يمكن تنفيذ البناء والفحص والاختبارات على أي نظام؛ إذ تستخدم المجمّعات بدائل صامتة خارج Linux لتسهيل التطوير. أما الرصد الفعلي فيحتاج إلى نواة Linux: يستخدم netlink لحالة الواجهات والجيران والمسارات، ويستخدم eBPF مع BTF لنتائج الاتصالات.

  1. 01

    ابنِ المشروع

    يشغّل هذا الهدف التنسيق والفحص والاختبارات ويبني الملفين التنفيذيين. يظل CGO معطّلًا، لذلك تكون الملفات الناتجة ساكنة ولا تحتاج إلى اعتماديات وقت التشغيل؛ فمشغّل SQLite مكتوب بلغة Go الخالصة.

    make all
     
  2. 02

    ابدأ التسجيل

    الخدمة netrewindd هي المسجّل. تحتاج قراءة إشعارات netlink وإرفاق برامج eBPF إلى CAP_NET_ADMIN، ويعني ذلك تشغيلها بصلاحيات root داخل المختبر.

    وجّه ‎--rules إلى مجلد القواعد لتشغيل الارتباط فور وصول الأحداث. وإذا مررت قيمة فارغة، يقتصر عمل المسجّل على حفظ الأحداث.

    sudo ./build/netrewindd --db ./var/events.db --rules ./rules
     
  3. 03

    راجع السجل

    الأداة netrewind مخصّصة للاستعلام ولا تكتب في المخزن، لذا يمكنك استخدامها بينما يواصل المسجّل عمله.

    ./build/netrewind timeline --last 15m
     

جرّبه من دون تعريض شبكتك للعطل

ينشئ المختبر طوبولوجيا من network namespaces وأزواج veth، ويشغّل المسجّل داخلها، ثم ينفّذ 14 سيناريو: 13 عطلًا وفترة حركة طبيعية ناجحة. بعد ذلك يبحث عن أثر كل سيناريو في السجل.

لا يؤثر المختبر في الشبكة الحقيقية؛ فمساحات الأسماء والمسارات وقواعد nftables معزولة داخله.

يفشل الاختبار إذا لم يترك العطل أثرًا، ويفشل كذلك إذا لم يصل محرّك الارتباط إلى الاستنتاج الصحيح. وجود الدليل واستخلاص النتيجة الصحيحة اختباران منفصلان.

sudo make lab
 

ينشئ lab-up الطوبولوجيا ويحذفها lab-down، بينما ينفّذ inject.sh run <scenario> عطلًا واحدًا داخل مختبر قائم.

ملاحظة مهمة عن tracefs

عند الدخول إلى network namespace تُنشأ مساحة ضم جديدة ويُعاد ضم ‎/sys، فيختفي tracefs ويتعذر إرفاق نقاط تتبّع eBPF. لذلك يجب ضمّه داخل أمر ip netns exec نفسه الذي يشغّل المسجّل، وهذا يفسّر بنية سكربت المختبر.

المسجّل

netrewindd

الخيارالافتراضيالمعنى
--db/var/lib/netrewind/events.dbمسار مخزن الأحداث
--rulesrulesمجلد قواعد الارتباط؛ وتركه فارغًا يعطّل الارتباط بالكامل
--retention168hكم من التاريخ يُحفَظ
--gap-threshold30sأي انقطاع يتجاوز هذه المدة يُسجّل كفجوة في السجل
--observer-idhostnameهوية هذا المسجّل، وتُضاف إلى كل حدث ينتجه
--metrics-addrمطفأاعرض مقاييس Prometheus هنا، مثل 127.0.0.1:9464
--log-levelinfodebug أو info أو warn أو error

قراءة ما سُجّل

تتضمن الأداة ستة أوامر تشترك جميعًا في الخيار ‎--db. استخدم what-happened للتحقيق حول وقت محدد، وincidents لمراجعة الحوادث التي استنتجها المحرّك.

netrewind events

اعرض الأحداث المسجّلة بترتيب زمني

يعرض الأحداث كما سُجّلت من دون تفسير. استخدمه عندما تعرف نوع الحدث الذي تبحث عنه، أو عندما تحتاج إلى مخرجات JSON لمعالجتها بأداة أخرى.

  • $ netrewind events --last 10m
  • $ netrewind events --last 1h --family link
  • $ netrewind events --last 24h --host 192.168.20.10 -o json
الخيارالافتراضيالمعنى
--last1hانظر إلى الوراء بهذا القدر من الآن
--since / --untilالآننافذة زمنية بصيغة RFC3339؛ ويتقدم ‎--since على ‎--last
--kindالكلاعرض هذه الأنواع فقط، مثل link.down
--familyالكلاعرض هذه العائلات فقط، مثل link,l2
--hostالكلاعرض كيانًا واحدًا فقط، باستخدام عنوانه أو اسمه
-o, --outputtabletable أو json
--newest-firstمطفأاعكس الترتيب

netrewind timeline

اقرأ السجل في صورة خط زمني واضح

يعرض السجل في جمل مفهومة بدل الحقول الخام. ويستخدم رمزًا مستقلًا لكل مستوى خطورة كي تظل الدلالة واضحة في الطرفيات أحادية اللون ولقطات الشاشة.

  • $ netrewind timeline --last 15m
  • $ netrewind timeline --last 1h --min-severity warn
الخيارالافتراضيالمعنى
--last30mإلى أيّ مدى تقرأ إلى الوراء
--familyالكلاعرض هذه العائلات فقط
--min-severityinfoinfo أو notice أو warn أو error

netrewind what-happened

أعد بناء ما حدث حول وقت محدد

حدّد جهازًا ووقتًا، فيستخدم الأمر جدول الهويات للعثور على الأحداث المرتبطة بالجهاز حتى إذا كان يستخدم عنوانًا مختلفًا حينها، من دون خلطها بأحداث الجهاز الذي يستخدم العنوان نفسه الآن.

  • $ netrewind what-happened --host 192.168.20.10 --at 15:00
  • $ netrewind what-happened --at 2026-08-23T10:43:00Z --window 5m
  • $ netrewind what-happened --host 192.168.20.10 --at -2h
الخيارالافتراضيالمعنى
--hostكل شيءالجهاز الذي تتبعه، بعنوانه أو بعنوانه العتادي
--atnowالوقت المطلوب: RFC3339 أو HH:MM أو ‎-2h أو now
--window5mمدة البحث قبل الوقت المحدد وبعده

netrewind incidents

اعرض نتائج الارتباط والدليل وراء كل استنتاج

يعرض الحوادث المستنتجة، لا الأحداث الخام. وتتضمن كل حادثة سلسلة الأدلة ونوع العلاقة في كل خطوة وما يُنصح بمراجعته بعد ذلك.

  • $ netrewind incidents --last 24h
  • $ netrewind incidents --last 1h --rule change-broke-a-path
الخيارالافتراضيالمعنى
--last24hإلى أيّ مدى تنظر إلى الوراء
--ruleالكلحوادث هذه القاعدة وحدها
--min-severityالكلinfo أو notice أو warn أو error
-o, --outputtexttext أو json

netrewind serve

اعرض السجل في المتصفح

يعرض الحوادث والخط الزمني وصفحة لكل مضيف باستخدام السجل نفسه الذي تقرؤه أداة سطر الأوامر. الواجهة للقراءة فقط وتُنشأ على الخادم من دون JavaScript. وترتبط افتراضيًا بالعنوان المحلي لأنها لا تتضمن مصادقة ولا ينبغي كشفها على الشبكة المراقَبة.

  • $ netrewind serve
  • $ netrewind serve --db /var/lib/netrewind/events.db
الخيارالافتراضيالمعنى
--addr127.0.0.1:8464عنوان الاستماع؛ ويظل محليًا ما لم تغيّره صراحة
--observer-idhostnameالمسجّل الذي يُنسب إليه هذا العرض

netrewind rules

حمّل قواعد الارتباط وتحقق منها

يفحص مكتبة القواعد بالطريقة نفسها التي يستخدمها المسجّل، حتى تكتشف القاعدة غير الصالحة قبل نشرها بدل بقائها من دون أي تطابق.

  • $ netrewind rules --dir rules
الخيارالافتراضيالمعنى
--dirrulesمجلّد ملفّات القواعد
netrewind rules --dir rules
19 rules loaded from rules
 
address-changed-hands warn 75% 1 clauses (1 required) window 1m0s
An address moved to a different machine
 
change-broke-a-path error 88% 3 clauses (1 required) window 5m0s
A path that was working stopped working
 
collector-not-watching error 100% 1 clauses (1 required) window 1m0s
The recorder is running but one of its senses is not
 
contested-address error 85% 2 clauses (1 required) window 2m0s
Two machines are claiming the same address
 
default-route-lost error 95% 2 clauses (1 required) window 2m0s
The default route disappeared
 
default-route-moved error 85% 2 clauses (1 required) window 2m0s
The default route was re-pointed
 
gateway-hijack error 90% 3 clauses (1 required) window 3m0s
The default gateway is being answered by a different machine
 
gateway-returned-different error 85% 2 clauses (1 required) window 10m0s
The gateway came back, but as a different machine
 
host-moved-ports warn 70% 1 clauses (1 required) window 1m0s
A machine appeared behind a different interface
 
link-degrading error 90% 2 clauses (1 required) window 10m0s
A link is failing rather than having failed
 
link-down-isolated-hosts warn 80% 2 clauses (2 required) window 1m30s
A link went down and took hosts with it
 
path-mtu-blackhole error 90% 2 clauses (1 required) window 10m0s
A path is silently dropping large packets
 
port-flapping warn 88% 2 clauses (1 required) window 5m0s
A port is flapping
 
reachability-lost error 90% 3 clauses (1 required) window 5m0s
A measured path stopped answering
 
recorder-was-blind warn 100% 1 clauses (1 required) window 1m0s
The record has a hole in it
 
resolver-hijacked warn 80% 3 clauses (1 required) window 5m0s
A machine's resolver changed under it
 
rogue-dhcp-server error 92% 3 clauses (1 required) window 5m0s
A second DHCP server is answering on this segment
 
route-flapping error 85% 2 clauses (1 required) window 5m0s
A route is flapping
 
service-unreachable warn 80% 2 clauses (1 required) window 2m0s
A service stopped answering

المقاييس

يقيس المسجّل ما رآه وما فاته

تعرض أدوات الرصد عادة أعداد ما التقطته، لكن انخفاض العدد قد يعني هدوء الشبكة أو توقف الرصد. لذلك يقيس NetRewind فجواته أيضًا.

يعدّ netrewind_recorder_blind_seconds_total مدة فقدان الرؤية، ويعدّ netrewind_dropped_events_total الأحداث التي لم تُحفظ. ويمكن التنبيه إلى زيادة أي منهما قبل الاعتماد على سجل ناقص أثناء التحقيق.

يعلن المسجّل كل سلسلة بقيمة صفر عند الإقلاع، حتى يعمل التنبيه على الزيادة منذ أول قراءة.

sudo ./build/netrewindd --db ./var/events.db --metrics-addr 127.0.0.1:9464
 

تتوفر المقاييس على ‎/metrics بصيغة Prometheus النصية، ويؤدي ترك العنوان فارغًا إلى تعطيلها.

السلسلةالنوعما تَعُدّه
netrewind_recorder_blind_seconds_totalcounterعدد الثواني التي لم يتمكن فيها المسجّل من الرصد. أي زيادة تعني وجود فجوة في السجل.
netrewind_dropped_events_totalcounterأحداث فُقدت لأنها وصلت أسرع من قدرة المسجّل على قراءتها، مصنفة حسب المصدر.
netrewind_clock_steps_totalcounterقفزات مرصودة في الساعة المدنية قد تؤثر في ترتيب الخط الزمني الظاهر.
netrewind_events_totalcounterعدد الأحداث المسجّلة حسب النوع والخطورة. تُحسب جميع التكرارات المجمّعة، لا عدد الصفوف المخزنة فقط.
netrewind_incidents_totalcounterعدد الحوادث المستنتجة حسب القاعدة والخطورة.
netrewind_collector_upgaugeالقيمة 1 عند عمل المجمّع، و0 عند توقفه.
netrewind_stored_eventsgaugeالأحداث المحفوظة في المخزن الآن.
netrewind_build_infogaugeإصدار المسجّل العامل ومعرّف المسجّل.

كتابة قاعدة

تصف كل قاعدة نمطًا معروفًا من الأعطال

القواعد ملفات إعداد وليست شيفرة. ويمكن لمن حقق في عطل شبكة أن يضيف قاعدة جديدة من دون تعديل شيفرة Go، لتتوسع المكتبة مع الخبرة العملية.

نعرض أدناه ملف rules/change-broke-a-path.yaml كاملًا. تبحث هذه القاعدة إلى الخلف عن آخر تغيّر سبق تعطل المسار.

مخرجات مسجّلة
id: change-broke-a-path
title: A path that was working stopped working
severity: error
confidence: 88
window: 300s
root_cause: change
advice: >-
The change named here is the nearest one in time, not a proven cause. Confirm
it against your change record before acting: if it was intended, the breakage
is a side effect nobody planned; if it was not, something changed the network
without going through you.
match:
- as: change
kinds:
- l2.arp_binding_changed
- l2.duplicate_ip
- l3.route_changed
- l3.default_route_changed
- l3.route_removed
- link.down
- policy.rule_changed
- change.config_applied
optional: true
why: >-
This is the last thing that changed on the path before it broke.
- as: breakage
kinds: [flow.first_failure_for_pair]
relation: causes
why: >-
Two machines that had been connecting successfully can no longer complete
a handshake. Whatever else is true, something between them changed.
- as: spread
kinds: [flow.first_failure_for_pair, flow.handshake_fail, l2.neighbor_failed]
optional: true
relation: correlates
why: Other connections started failing in the same window.
rules/change-broke-a-path.yaml
match[0] — as: change, optional: true
يقع هذا البند قبل المرساة، لذلك يبحث عنه المحرّك إلى الخلف بدءًا من الأقرب. وهو ما يسمح للقاعدة بالسؤال عما تغيّر قبل العطل. ولأنه اختياري، تستطيع القاعدة إنشاء حادثة من حلقة واحدة إذا لم تجد تغيّرًا سابقًا، من دون اختلاق سبب.
match[1] — as: breakage, required
هذه هي المرساة والبند الإلزامي الوحيد. وصول flow.first_failure_for_pair يدفع المحرّك إلى تقييم القاعدة لأنه يشير إلى فشل اتصال كان يعمل سابقًا.
relation: causes
تعني وجود علاقة سببية معروفة، وهي أقوى علاقة يمكن أن تصفها القاعدة. يجب استخدامها فقط عندما تدعمها آلية واضحة. ويلزم كل بند بعد الأول بتحديد علاقته، وإلا يرفضه المدقّق.
relation: correlates
لا يدّعي البند spread وجود علاقة سببية؛ بل يسجّل أن اتصالات أخرى فشلت داخل النافذة نفسها. لذلك تعرضه الأداة بصيغة «وفي الوقت نفسه».
root_cause: change
يحدد البند الذي تعتبره القاعدة سببًا جذريًا باستخدام اسم as. ويرفض المدقّق الإشارة إلى بند غير موجود في القاعدة.
window: 300s
تحدد أقصى مدة بين أول بند وآخر بند. يرفض المدقّق أي قاعدة بلا نافذة زمنية، لأن غيابها قد يربط حدثين غير مرتبطين.
advice
توضح ما ينبغي مراجعته بعد ذلك، ولا تأمر بتغيير الشبكة. فالمسجّل يرصد فقط، وقد يؤدي إجراء مثل إعادة تشغيل الواجهة إلى إتلاف دليل مهم. ويضمن اختبار وجود نصيحة في كل قاعدة مشحونة.

حقول البند

as
اسم البند الذي يمكن أن يشير إليه root_cause
kinds
أنواع الأحداث التي يمكن أن تحقق هذا البند
where
يضيف شروطًا باستخدام attrs.<name> أو min_severity أو subject_kind. وتُقارن السمات نصيًا لأن المجمّع قد يكتب قيمة منطقية بينما يعيد المخزن json.Number
min_count
يشترط عددًا أدنى من المطابقات؛ فسقوط منفذ مرة حدث، وتكراره خمس مرات خلال خمس دقائق عطل
optional
يسمح بإنشاء الحادثة من دون هذا البند، وإذا سبق المرساة فيعني البحث عنه إلى الخلف
relation
causes أو correlates أو precedes. لازم على كل بند بعد الأول
why
شرح دور هذه الخطوة في الحادثة، وهو النص الذي يراه المشغّل بدل أسماء الحقول

ما يرفضه المدقّق

لا يحمّل المحرّك قاعدة غير صالحة. ويتوفر الفحص نفسه من سطر الأوامر، حتى يظهر الخطأ أثناء التطوير بدل بقاء القاعدة في الإنتاج من دون أي تطابق.

  • قاعدة بلا نافذة، أو بثقةٍ خارج المدى 1–100.
  • بندٌ لا يُطابق أيّ نوع.
  • بندٌ بعد الأول لا يقول كيف يتّصل بما قبله.
  • قاعدةٌ تُحمّل التبعة بندًا ليس فيها.
  • قاعدة جميع بنودها اختيارية، لأنها ستطابق كل شيء.

اكتشف آخر هذه الفحوص خطأ فعليًا في إحدى القواعد المشحونة كان سيمنعها من مطابقة أي حدث.

  • $ netrewind rules --dir rules
  • $ go test ./internal/correlate/...
  • $ sudo lab/inject.sh all

مفاتيح الربط تمنع خلط الأعطال المنفصلة

يحدد correlate_on الحقول التي يجب أن تتطابق في جميع الأحداث: subject أو subject.id أو attrs.<name> أو observer. من دونه قد يدمج المحرّك عطلين متزامنين على جهازين مختلفين في حادثة واحدة. ومع correlate_on: [subject] لا يمكن ربط تذبذب منفذ على مبدّل بسقوط جار على مبدّل آخر.

كل ما في هذه الصفحة موجود في المستودع.

  • مواصفات المخطّطdocs/schema.md
  • كتابة القواعدdocs/rules.md
  • تشغيلهdocs/runbook.md
المصدر