
tailsnitch v1.7
مدقق أمان لتكوينات Tailscale. يمسح شبكة tailnet الخاصة بك بحثًا عن التكوينات الخاطئة، وضوابط الوصول المفرطة في السماح، وانتهاكات أفضل الممارسات الأمنية.
Tailsnitch
أداة تدقيق أمني لإعدادات Tailscale. يقوم Tailsnitch بفحص شبكة tailnet الخاصة بك بحثًا عن 57 حالة إعداد خاطئ، وضوابط وصول متساهلة بشكل مفرط، وانتهاكات أفضل الممارسات الأمنية.
بدء سريع
# 1. قم بتعيين بيانات اعتماد Tailscale API الخاصة بك
export TS_API_KEY="tskey-api-..."
# 2. تشغيل التدقيق
tailsnitch
# 3. عرض النتائج عالية الخطورة فقط
tailsnitch --severity high
# 4. إصلاح بعض المشكلات ~بشكل تفاعلي~ وضع yolo
tailsnitch --fix
التثبيت
تنزيل الملف الثنائي المُجمّع مسبقًا
قم بتنزيل أحدث إصدار من GitHub Releases.
مستخدمو macOS: قم بإزالة سمة quarantine بعد التنزيل:
sudo xattr -rd com.apple.quarantine tailsnitch
التثبيت عبر Go
go install github.com/Adversis/tailsnitch@latest
البناء من المصدر
git clone https://github.com/Adversis/tailsnitch.git
cd tailsnitch
go build -o tailsnitch .
المصادقة
يدعم Tailsnitch طريقتين للمصادقة. يُفضَّل استخدام OAuth عند تكوين كلتيهما.
الخيار 1: عميل OAuth (موصى به)
توفر عملاء OAuth وصولًا محدد النطاق وقابلًا للتدقيق ولا تنتهي صلاحيته عند مغادرة الموظفين.
export TS_OAUTH_CLIENT_ID="..."
export TS_OAUTH_CLIENT_SECRET="tskey-client-..."
أنشئ عميل OAuth على: https://login.tailscale.com/admin/settings/oauth
النطاقات المطلوبة للتدقيق للقراءة فقط:
يغطي all:read كل شيء. منح النطاقات بشكل فردي:
| النطاق | الاستخدام |
|---|---|
policy_file:read | ملف سياسة tailnet — ACL-، NET-، SSH-* |
devices:core:read | قائمة الأجهزة — DEV-، NET-، ACL-011 |
dns:read | إعدادات DNS — DNS-001، DEV-007 |
auth_keys:read | مفاتيح مصادقة الأجهزة — AUTH-*، ACL-011 |
feature_settings:read | إعدادات tailnet — DEV-008، DEV-009، DEV-014 |
logs:network:read | إعداد تسجيل تدفق الشبكة — LOG-001 |
networking_settings:read | إعداد شهادة HTTPS — NET-004 |
log_streaming:read | وجهات بث السجلات — LOG-002 |
webhooks:read | نقاط نهاية webhook — LOG-005، LOG-012 |
oauth_keys:read | عملاء OAuth — LOG-006 |
users:read | أدوار المستخدمين وحالتهم — USER-001، LOG-006 |
account_settings:read | جهة الاتصال الأمنية — LOG-011 |
devices:posture_attributes:read | تكاملات الوضعية — DEV-014 |
أي نطاق تستبعده يؤثر فقط على الفحوصات التي تحتاجه: تلك الفحوصات تُبلغ بأنها لم تستطع قراءة الإعداد بدلاً من اعتبارها ناجحة.
تقرأ AUTH-005 و AUTH-006 الهويات الموحدة لشبكة tailnet، والتي تسميها وحدة التحكم الإدارية trust credentials. تصل من نفس قائمة المفاتيح مثل مفاتيح المصادقة، لذا يُتوقع أن يغطيها auth_keys:read. لم يتم تأكيد ذلك مقابل شبكة tailnet حية. إذا تعذرت قراءة قائمة المفاتيح، يُبلغ كلا الفحصين بأنهما لم يُقيَّما بدلاً من اعتبارهما ناجحين. ما إذا كان النطاق المفقود يُرجع خطأً أو يُرجع القائمة مع تصفية الهويات غير مؤكد؛ إذا قام بالتصفية بصمت، فسيُبلغ AUTH-005 بعدم وجود trust credentials وسيجد AUTH-006 شيئًا لفحصه.
نطاقات إضافية لوضع الإصلاح:
devices:core- حذف الأجهزة، تعديل العلامات (يتطلب اختيار العلامة)auth_keys- حذف مفاتيح المصادقة
Tailnet Lock
يُبلغ DEV-010 و DEV-012 عن Tailnet Lock، والذي لا يعرضه Tailscale API كإعداد لشبكة tailnet. الأجهزة المقفلة بواسطته مرئية عبر API، لكن تحديد ما إذا كان القفل مفعلًا يتطلب واجهة tailscale المحلية، والتي تقرأ الخفي على الجهاز الذي يشغل tailsnitch. عند تدقيق شبكة tailnet أخرى باستخدام --tailnet، تعامل مع ذلك الجزء من النتيجة وفقًا لذلك. استخدم --tailscale-path إذا كان الملف الثنائي في موقع غير قياسي.
الخيار 2: مفتاح API
تعمل مفاتيح API كمستخدم قام بإنشائها وترث صلاحيات ذلك المستخدم.
export TS_API_KEY="tskey-api-..."
أنشئ مفتاح API على: https://login.tailscale.com/admin/settings/keys
أمثلة الاستخدام
تدقيق أساسي
# تشغيل تدقيق كامل
tailsnitch
# عرض الفحوصات الناجحة أيضًا (مفصّل)
tailsnitch --verbose
# الإخراج بصيغة JSON للمعالجة
tailsnitch --json
# تدقيق شبكة tailnet محددة (عندما يكون لعميل OAuth وصول إلى عدة شبكات)
tailsnitch --tailnet mycompany.com
تصفية النتائج
# عرض المشكلات الحرجة وعالية الخطورة فقط
tailsnitch --severity high
# التصفية حسب الفئة
tailsnitch --category access # مشكلات ACL
tailsnitch --category auth # المصادقة والمفاتيح
tailsnitch --category device # أمان الأجهزة
tailsnitch --category network # التعرض الشبكي
tailsnitch --category ssh # قواعد SSH
tailsnitch --category log # التسجيل والإدارة
# تشغيل فحوصات محددة فقط
tailsnitch --checks ACL-001,AUTH-001,DEV-010
tailsnitch --checks stale-devices,tailnet-lock-not-enabled
# قائمة جميع الفحوصات المتاحة
tailsnitch --list-checks
وضع الإصلاح التفاعلي
يتيح لك وضع الإصلاح معالجة المشكلات مباشرة عبر Tailscale API:
# وضع الإصلاح التفاعلي
tailsnitch --fix
# معاينة ما سيتم إصلاحه (تشغيل تجريبي)
tailsnitch --fix --dry-run
# التحديد التلقائي للإصلاحات الآمنة (لا يزال يتطلب تأكيدًا)
tailsnitch --fix --auto
# تعطيل تسجيل تدقيق إجراءات الإصلاح
tailsnitch --fix --no-audit-log
العناصر القابلة للإصلاح عبر API:
| الفحص | الإجراء |
|---|---|
| AUTH-001، AUTH-002، AUTH-003 | حذف مفاتيح المصادقة |
| DEV-002 | إزالة العلامات من أجهزة المستخدمين |
| DEV-004 | حذف الأجهزة القديمة |
| DEV-005 | تفويض الأجهزة المعلقة |
يوفر وضع الإصلاح أيضًا روابط مباشرة لوحدة التحكم الإدارية للمشكلات التي تتطلب تدخلًا يدويًا.
تصدير أدلة SOC 2
إنشاء تقارير أدلة لعمليات تدقيق SOC 2 مع تعيينات معايير Common Criteria (CC):
# التصدير بصيغة JSON
tailsnitch --soc2 json > soc2-evidence.json
# التصدير بصيغة CSV (لجداول البيانات)
tailsnitch --soc2 csv > soc2-evidence.csv
يتضمن تقرير SOC 2:
- نتائج الاختبار لكل مورد (كل جهاز، مفتاح، قاعدة ACL تُختبر بشكل فردي)
- تعيينات رموز CC (CC6.1، CC6.2، CC6.3، CC6.6، CC7.1، CC7.2، إلخ)
- حالة نجاح/فشل/غير قابل للتطبيق لكل اختبار تحكم
- طابع زمني لمسار التدقيق
مثال على إخراج CSV:
resource_type,resource_id,resource_name,check_id,check_title,cc_codes,status,details,tested_at
device,node123,prod-server,DEV-001,Tagged devices with key expiry disabled,CC6.1;CC6.3,PASS,Tags: [tag:server] key expiry enabled,2025-01-05T10:30:00Z
key,tskey-auth-xxx,tskey-auth-xxx,AUTH-001,Reusable auth keys exist,CC6.1;CC6.2;CC6.3,FAIL,Reusable key expires in 45 days,2025-01-05T10:30:00Z
تجاهل المخاطر المعروفة
أنشئ ملف .tailsnitch-ignore لكتم النتائج المتعلقة بالمخاطر المقبولة المعروفة:
# .tailsnitch-ignore
# تجاهل الفحوصات المعلوماتية
ACL-008 # لا نستخدم المجموعات عمدًا
ACL-009 # قواعد ACL القديمة مناسبة لحالة استخدامنا
# تجاهل فحوصات محددة متوسطة الخطورة مع مبرر
DEV-006 # الأجهزة الخارجية مقاولون معتمدون
LOG-001 # سجلات التدفق تتطلب خطة Enterprise
# تجاهل عنصر واحد ضمن فحص، بدلاً من كتم الفحص بأكمله
ACL-011:tag:monitoring # واسع التصميم؛ كل علامة أخرى لا تزال تُفحص
AUTH-001:tskey-auth-xxxx # يُدار تلقائيًا عبر CI، متتبع في TICKET-123
يسمي السطر إما فحصًا كاملاً (ACL-011) أو عنصرًا واحدًا ضمنه
(CHECK-ID:item، مقسومًا على أول نقطتين - قد يحتوي العنصر نفسه على
نقطتين). قاعدة لكل عنصر تكتم ذلك العنصر فقط: لا يزال الفحص يعمل
ويُبلغ عن كل شيء آخر يجده. كتم كل عنصر مُشار إليه لا يحول أبدًا
فحصًا فاشلاً إلى فحص ناجح - تبقى النتيجة، مخفضة إلى
معلوماتية، لذا لا تُقرأ النتيجة المكتومة أبدًا كتحكم مُرضى.
مواقع ملفات التجاهل (تُفحص بالترتيب):
.tailsnitch-ignoreفي الدليل الحالي~/.tailsnitch-ignoreفي الدليل الرئيسي
نظرًا لأن الموقع الأول هو دليل العمل، يمكن أن يأتي ملف التجاهل
من مستودع بدلاً منك. يُبلغ كل تشغيل عن الملف الذي استخدمه
وعن عدد النتائج والعناصر التي كتمها، ويسجل --json ذلك في
حقول ignore_file و ignored (CHECK-ID لفحص كامل،
CHECK-ID:item لعنصر واحد مكتوم). استخدم --no-ignore لتخطي الملف.
# استخدام ملف تجاهل محدد
tailsnitch --ignore-file /path/to/ignore
# تعطيل معالجة ملف التجاهل تمامًا
tailsnitch --no-ignore
تصدير JSON ومعالجته
# تصدير تقرير كامل
tailsnitch --json > audit.json
# استخراج الفحوصات الفاشلة بصيغة TSV
tailsnitch --json | jq -r '
.suggestions
| map(select(.pass == false))
| .[]
| [.id, .title, .severity, .remediation]
| @tsv
' > findings.tsv
# ملخص حسب الخطورة
tailsnitch --json | jq '
.suggestions
| map(select(.pass == false))
| group_by(.severity)
| map({severity: .[0].severity, count: length})
'
# قائمة المشكلات الحرجة/عالية الخطورة مع روابط الإدارة
tailsnitch --json | jq -r '
.suggestions
| map(select(.pass == false and (.severity == "CRITICAL" or .severity == "HIGH")))
| .[]
| "\(.id): \(.title)\n Fix: \(.fix.admin_url // "manual")\n"
'
مرجع الأوامر
| العلم | الوصف |
|---|---|
--json | الإخراج بصيغة JSON |
--severity | التصفية حسب الحد الأدنى للخطورة: critical، high، medium، low، info |
--category | التصفية حسب الفئة: access، auth، network، ssh، log، device، dns |
--checks | تشغيل فحوصات محددة (معرّفات أو أسماء مفصولة بفواصل) |
--list-checks | قائمة جميع الفحوصات المتاحة والخروج |
--tailnet | تحديد شبكة tailnet للتدقيق (الافتراضي: من مفتاح API) |
--verbose | عرض الفحوصات الناجحة أيضًا |
--fix | تفعيل وضع الإصلاح التفاعلي |
--auto | التحديد التلقائي للإصلاحات الآمنة (يتطلب --fix) |
--dry-run | معاينة إجراءات الإصلاح دون تنفيذها (يتطلب --fix) |
--no-audit-log | تعطيل تسجيل تدقيق إجراءات الإصلاح |
--soc2 | تصدير أدلة SOC 2: json أو csv |
--tailscale-path | مسار واجهة tailscale CLI (لفحوصات Tailnet Lock) |
--timeout | الميزانية الزمنية الإجمالية للتدقيق (الافتراضي 2m) |
--ignore-file | مسار ملف التجاهل |
--no-ignore | تعطيل معالجة ملف التجاهل |
--version | عرض معلومات الإصدار |
الفحوصات الأمنية
ينفذ Tailsnitch 57 فحصًا أمنيًا عبر 7 فئات. راجع docs/CHECKS.md للتوثيق التفصيلي لكل فحص.
خطورة حرجة
| المعرف | الفحص | المخاطر |
|---|---|---|
| ACL-001 | سياسة 'السماح للجميع' الافتراضية | جميع الأجهزة لديها وصول غير مقيد |
| ACL-002 | إعداد خاطئ لـ SSH autogroup:nonroot | SSH كأي مستخدم غير جذر |
| ACL-006 | tagOwners واسع جدًا | تصعيد الامتيازات عبر العلامات |
| ACL-007 | استخدام autogroup:danger-all | وصول ممنوح للمستخدمين الخارجيين |
خطورة عالية
| المعرف | الفحص | المخاطر |
|---|---|---|
| ACL-011 | وصول العلامة يعبر حدود الثقة | مفتاح قابل لإعادة الاستخدام مسروق يصنع علامة تصل إلى كل شيء |
| AUTH-001 | مفاتيح مصادقة قابلة لإعادة الاستخدام | إضافات غير محدودة للأجهزة إذا سُرقت |
| AUTH-002 | مفاتيح مصادقة بصلاحية طويلة | نافذة تعرض ممتدة |
| AUTH-003 | مفاتيح مفوضة مسبقًا | تجاوز موافقة الجهاز |
| AUTH-006 | موضوع الهوية الموحدة واسع جدًا | أي مبدأ يضمنه المُصدر يمكنه صنع العلامة |
| DEV-001 | أجهزة موسومة بدون انتهاء صلاحية المفتاح | وصول غير محدد |
| DEV-002 | أجهزة مستخدمين موسومة | تستمر بعد إزالة المستخدم |
| DEV-010 | Tailnet Lock معطل | لا حماية ضد المفاتيح المسروقة |
| DEV-012 | توقيعات Tailnet Lock معلقة | العقد غير الموقعة تحتاج مراجعة |
| NET-001 | تعرض Funnel | وصول إنترنت عام |
| NET-003 | حدود ثقة موجه الشبكة الفرعية | حركة مرور غير مشفرة على الشبكة المحلية |
| SSH-002 | SSH الجذر بدون وضع check | لا إعادة مصادقة مطلوبة |
خطورة متوسطة
| المعرف | الفحص | المخاطر |
|---|---|---|
| ACL-004 | استخدام autogroup:member | المستخدمون الخارجيون مشمولون |
| ACL-005 | تم تكوين AutoApprovers | تجاوز موافقة المسار |
| AUTH-004 | مفاتيح CI/CD غير مؤقتة | الأجهزة القديمة تتراكم |
| AUTH-005 | اتحاد هوية عبء العمل غير مستخدم | المفاتيح طويلة العمر تبقى قابلة للسرقة |
| DEV-003 | عملاء قديمون | ثغرات محتملة |
| DEV-004 | أجهزة قديمة | سطح هجوم غير مستخدم |
| DEV-005 | أجهزة غير مفوضة | قائمة انتظار الموافقة المعلقة |
| DEV-007 | أسماء أجهزة حساسة | تعرض سجل CT |
| DEV-009 | إعداد موافقة الجهاز | قد لا يكون مفعلًا |
| NET-004 | تعرض سجل HTTPS CT | أسماء الأجهزة عامة |
| NET-005 | رؤية حركة مرور عقدة الخروج | المشغل يرى كل حركة المرور |
| NET-006 | تعرض Serve | خدمات محلية على tailnet |
| SSH-003 | تعرض واجهة المسجل | الجلسات مرئية للشبكة |
معلوماتي
فحوصات لإعدادات التسجيل، وإعدادات DNS، وأدوار المستخدمين، وعناصر التحقق اليدوي.
خطورة تعتمد على النتيجة
تصنف عدة فحوصات ما تجده بدلاً من حمل خطورة ثابتة واحدة. ثلاثة منها تستحق الذكر هنا:
- ACL-011 يُبلغ عن وصول كل علامة بمستوى معلوماتي. يفشل فقط عندما تصل علامة يمكن لمفتاح مصادقة تعيينها إلى وجهة wildcard، أو شبكة فرعية موجهة أو خروج عقدة الخروج: خطورة عالية إذا كان مفتاح قابل لإعادة الاستخدام يعين تلك العلامة، ومتوسطة إذا كان مفتاح لمرة واحدة فقط يفعل ذلك. عدد الأجهزة لا يحدد الخطورة أبدًا.
- AUTH-005 يُبلغ بمستوى متوسط عندما لا تحتوي شبكة tailnet على trust credentials على الإطلاق، ومستوى منخفض عندما توجد trust credentials لكن مفتاحًا قابلًا لإعادة الاستخدام لا يزال يصنع علامات لا يغطيها أي منها.
- AUTH-006 يُبلغ بمستوى عالٍ لموضوع ليس سوى wildcard، ومستوى منخفض لـ wildcard أضيق أو جمهور مفقود.
مثال على الإخراج
+=====================================================================+
| TAILSNITCH SECURITY AUDIT |
| Tailnet: example.com |
| Version: 1.0.0 (build: abc123) |
+=====================================================================+
Using ignore file: .tailsnitch-ignore (3 rules)
=== ACCESS CONTROLS ===================================================
[CRITICAL] ACL-001: Default 'allow all' policy active
Your ACL policy omits the 'acls' field. Tailscale applies a
default 'allow all' policy, granting all devices full access.
Remediation:
Define explicit ACL rules following least privilege principle.
Source: https://tailscale.com/docs/reference/examples/acls
----------------------------------------------------------------------
=== AUTHENTICATION & KEYS =============================================
[HIGH] AUTH-001: Reusable auth keys exist
Found 2 reusable auth key(s). These can be reused to add
multiple devices if compromised.
Details:
- Key tskey-auth-xxx (expires in 45 days)
- Key tskey-auth-yyy (expires in 89 days)
Remediation:
Store reusable keys in a secrets manager. Prefer one-off keys.
Source: https://tailscale.com/docs/features/access-control/auth-keys
----------------------------------------------------------------------
SUMMARY
======================================================================
Critical: 1 High: 3 Medium: 5 Low: 2 Info: 8
Total findings: 19 | Passed: 33
فحوصات Tailnet Lock
تتطلب فحوصات Tailnet Lock (DEV-010، DEV-012) واجهة tailscale المحلية وتعمل ضد خفي الجهاز المحلي. عند تدقيق شبكة tailnet بعيدة عبر --tailnet، تعكس هذه الفحوصات الحالة المحلية، وليس شبكة tailnet المُدقَّقة.
# تحديد مسار ثنائي tailscale مخصص إذا لزم الأمر
tailsnitch --tailscale-path /opt/tailscale/bin/tailscale
تكامل CI/CD
شغّل Tailsnitch في خطوط CI/CD لاكتشاف الانحدارات الأمنية:
# GitHub Actions example
- name: Audit Tailscale Security
env:
TS_OAUTH_CLIENT_ID: ${{ secrets.TS_OAUTH_CLIENT_ID }}
TS_OAUTH_CLIENT_SECRET: ${{ secrets.TS_OAUTH_CLIENT_SECRET }}
run: |
tailsnitch --json > audit.json
# Fail if critical or high severity issues exist
if tailsnitch --severity high --json | jq -e '.summary.critical + .summary.high > 0' > /dev/null; then
echo "Critical or high severity issues found!"
tailsnitch --severity high
exit 1
fi
المراجع
الترخيص
MIT
المساهمة
راجع CONTRIBUTING.md للإرشادات.