استخدم السكربت المساعد في تبويب 11 الذي يقوم بتطبيق معلمات النواة على dom0 وجميع VMs تلقائياً (الخيار رقم 1).
chmod +x auto-script.sh && ./auto-script.sh
يفضل استخدام هارد خارجي مع دعم USB 3.2 لتحقيق سرعة 450-900 MB/s لتشغيل النظام عليه وجعله محمولاً.
مدعوم رسميًا في Qubes 4.3 - يمكن تركه مفعلاً، لكن قد تحتاج أحيانًا لتوقيع وحدات النواة (kernel modules) إذا واجهت مشاكل مع أجهزة معينة.
BIOS/UEFI Setup
النظام الأساسي (معزول عن الشبكة، يتم التحديث عبر القنوات الرسمية)
sudo qubes-dom0-update
تُطبّق معلمات dom0 في GRUB، ومعلمات VMs عبر qvm-prefs
🔴 معلمات Xen: أضفها إلى GRUB_CMDLINE_XEN_DEFAULT
bootscrub=1 xen_scrub_pages=1
🔴 معلمات Linux: أضفها إلى GRUB_CMDLINE_LINUX
init_on_free=1 init_on_alloc=1 page_poison=1 lockdown=confidentiality module.sig_enforce=1 slab_nomerge slub_debug=FZ vsyscall=none kernel.kptr_restrict=2 oops=panic debugfs=off quiet loglevel=0 spectre_v2=on page_alloc.shuffle=1 preempt=voluntary pti=on mds=full
smt=off - تم نقله إلى قسم "إعدادات الخبراء" (يؤثر بشدة على الأداء بنسبة 30-50%).ipv6.disable=1 - غير مجدٍ في dom0 (dom0 لا يتعامل مع بطاقة الشبكة مباشرة). طبقه على VMs عبر kernelopts.noswap - قد يسبب تجمد النظام. استخدم vm.swappiness=1 بدلاً منه.أمر qvm-prefs VM kernelopts محدود بـ 512 حرف فقط. هذا يعني أنك لا تستطيع إضافة جميع المعلمات أدناه دفعة واحدة.
الحلول: استخدم القائمة المختصرة (أقل من 300 حرف) أو فعّل النواة الداخلية (in-vm kernel) للقوالب التي تحتاج حماية إضافية.
هذه المعلمات تحمي برامجك من هجمات المعالج. في Qubes، VMs تستخدم نواة dom0 لكن معاملاتها تُضبط بشكل منفصل ولا ترث معاملات GRUB.
xen_scrub_pages=1 init_on_free=1 init_on_alloc=1 page_poison=1 mitigations=auto random.trust_cpu=off random.trust_bootloader=off spec_store_bypass_disable=on tsx_async_abort=full mds=full,nosmt page_alloc.shuffle=1 randomize_kstack_offset=on l1tf=full,force ipv6.disable=1 slab_nomerge vsyscall=none retbleed=stuff spectre_v2_user=on kvm.nx_huge_pages=force
init_on_free=1 init_on_alloc=1 page_poison=1 slab_nomerge vsyscall=none mitigations=auto random.trust_cpu=off random.trust_bootloader=off spec_store_bypass_disable=on ipv6.disable=1
| # | المعلمة | الشرح | الفائدة | يطبق على |
|---|---|---|---|---|
| 1 | bootscrub=1 |
يمسح الذاكرة عند إقلاع Xen | يمنع تسرب بيانات من جلسة سابقة | 🔄 Xen |
| 2 | xen_scrub_pages=1 |
يمسح الذاكرة قبل إعادة استخدامها بين VMs | يمنع تسرب البيانات من VM إلى آخر | 🔄 Xen |
| 3 | init_on_free=1 |
يمسح الذاكرة فور تحريرها | يمنع تسرب كلمات المرور والمفاتيح | 🔄 الكل |
| 4 | init_on_alloc=1 |
يمسح الذاكرة قبل تخصيصها | يمنع تطبيقاً خبيثاً من قراءة بقايا بيانات تطبيق آخر | 🔄 الكل |
| 5 | page_poison=1 |
يسمم صفحات الذاكرة المحررة | يصعّب استغلال ثغرات Use-After-Free | 🔄 الكل |
| 6 | lockdown=confidentiality |
يمنع حتى الجذر من تعديل النواة أو قراءة ذاكرتها | يمنع العبث بنظام dom0 | 🖥️ dom0 |
| 7 | module.sig_enforce=1 |
يمنع تحميل وحدات نواة غير موقعة | يمنع حقن rootkits | 🖥️ dom0 |
| 8 | ipv6.disable=1 |
يعطل IPv6 بالكامل | يمنع تسرب البيانات عبر IPv6 | 🔄 الكل |
| 9 | noswap |
يعطل الـ swap تماماً | يمنع تسرب البيانات إلى القرص (⚠️ قد يسبب تجمد النظام) | 🖥️ dom0 |
| 10 | slab_nomerge |
يمنع دمج الكائنات المتشابهة في النواة | يصعّب استغلال ثغرات الكومة | 🔄 الكل |
| 11 | slub_debug=FZ |
يفعل فحوصات سلامة الذاكرة ويضيف مناطق عازلة | يكتشف تجاوزات السعة | 🔄 الكل |
| 12 | vsyscall=none |
يعطل واجهة vsyscall القديمة | يغلق سطح هجوم ROP | 🔄 الكل |
| 13 | kernel.kptr_restrict=2 |
يمنع عرض عناوين النواة | يصعّب بناء هجمات ROP | 🖥️ dom0 |
| 14 | oops=panic |
يجعل النواة تنهار عند أي خطأ | يمنع استغلال الأخطاء لمواصلة الهجوم | 🖥️ dom0 |
| 15 | debugfs=off |
يعطل debugfs بالكامل | يمنع تسرب معلومات بنية النواة | 🖥️ dom0 |
| 16 | spectre_v2=on |
يفعل حماية إضافية من Spectre v2 | يمنع هجمات القنوات الجانبية على المعالج | 🖥️ dom0 |
| 17 | preempt=voluntary |
جدولة استباقية طوعية للنواة | أكثر استقراراً من full مع أمان جيد | 🖥️ dom0 |
| 18 | pti=on |
يفعّل عزل جداول الصفحات | يوقف ثغرة Meltdown | 🖥️ dom0 |
| 19 | mds=full |
يفعل الحماية الكاملة من Microarchitectural Data Sampling | يمنع تسرب البيانات بين الخيوط | 🖥️ dom0 |
| 20 | quiet loglevel=0 |
يمنع عرض رسائل النواة أثناء الإقلاع | يمنع تسرب معلومات للمهاجم | 🔄 الكل |
| 21 | page_alloc.shuffle=1 |
عشوائية تخصيص صفحات الذاكرة | يصعّب استغلال ثغرات heap | 🔄 الكل |
| 22 | mitigations=auto |
يفعّل تصحيحات الثغرات تلقائياً | يمنع Spectre, Meltdown داخل VMs | 📱 AppVMs |
| 23 | random.trust_cpu=off |
لا تثق بمولد الأرقام العشوائية في المعالج | يمنع تخمين المفاتيح عبر RNG مخترق | 📱 AppVMs |
| 24 | random.trust_bootloader=off |
لا تثق بمولد الأرقام العشوائية في محمل الإقلاع | يمنع تخمين المفاتيح عبر RNG مخترق | 📱 AppVMs |
| 25 | spec_store_bypass_disable=on |
يعطل ثغرة Spectre v4 | يمنع تسرب البيانات عبر المخازن المؤقتة | 📱 AppVMs |
| 26 | tsx_async_abort=full |
يفعل الحماية الكاملة من TSX Async Abort | يمنع تسرب بيانات المعالج | 📱 AppVMs |
| 27 | mds=full,nosmt |
يفعل الحماية الكاملة من MDS مع تعطيل SMT | يمنع تسرب البيانات بين الخيوط | 📱 AppVMs |
| 28 | l1tf=full,force |
يفعل الحماية الكاملة من L1 Terminal Fault | يمنع تسرب بيانات ذاكرة L1 | 📱 AppVMs |
| 29 | randomize_kstack_offset=on |
عشوائية إزاحة مكدس النواة | يصعّب استغلال ثغرات stack | 📱 AppVMs |
| 30 | retbleed=stuff |
الحماية من هجوم Retbleed | يمنع تسرب البيانات عبر التنبؤ غير المباشر | 📱 AppVMs |
| 31 | spectre_v2_user=on |
حماية Spectre v2 لمساحة المستخدم | يمنع هجمات Spectre v2 من التطبيقات | 📱 AppVMs |
| 32 | kvm.nx_huge_pages=force |
يفعل الحماية من Nested Page Tables | يمنع هجمات VM Escape | 📱 AppVMs |
| 33 | smt=off |
يعطل Hyper-Threading (⚠️ للخبراء فقط) | يمنع هجمات Spectre/Meltdown بين VMs لكن يؤثر بشدة على الأداء (30-50%) | 🔴 خبير |
🖥️ لـ dom0: أضف المعلمات إلى /etc/default/grub ثم:
sudo grub2-mkconfig -o /boot/grub2/grub.cfg && sudo reboot
📱 لـ VMs: طبق لكل VM على حدة (انتبه لحد 512 حرف):
qvm-prefs VMNAME kernelopts "المعلمات هنا"
من قائمة GRUB، اضغط e على خيار الإقلاع، ابحث عن السطر الذي يبدأ بـ linux، احذف المعلمات التي أضفتها، ثم اضغط Ctrl+X أو F10 للإقلاع.
بعد الإقلاع، استعد ملف GRUB الأصلي من النسخة الاحتياطية: sudo cp /etc/default/grub.backup.* /etc/default/grub && sudo grub2-mkconfig -o /boot/grub2/grub.cfg
💡 أو استخدم السكربت المساعد في تبويب 11 للتطبيق التلقائي على الجميع.
💡 للحصول على تشفير عابر للبيانات داخل VMs، راجع تبويب 5 (Amnesic Tmpfs) و تبويب 6 (RAM Pool).
sys-net، العزل الفيزيائي، وما يراه كل طرف). أما إعدادات Tor والبوابات ففي تبويب 2.
راوتر صغير (مثل GL.iNet) في وضع WISP، متصلاً بجهاز Qubes عبر كابل Ethernet فقط، مع تعطيل البث اللاسلكي للشبكة الداخلية.
eth0في Qubes، لا أحد يتصل بالإنترنت مباشرة إلا sys-net. ثم يأتي sys-firewall كوسيط إجباري لجميع الأجهزة الأخرى.
sys-net. الإعداد الصحيح: التطبيق ← sys-firewall ← sys-net → الإنترنت.
| الطرف | الإعداد العادي (WiFi مباشر) | إعداد WISP + Ethernet |
|---|---|---|
| الموزع الوسيط | 🔴 يرى جهاز Qubes مباشرة (MAC، بصمة TCP/IP، أوقات الاتصال) | 🟡 يرى راوتراً واحداً فقط (لا يعرف عدد أو نوع الأجهزة خلفه) |
| الجيران على نفس الشبكة | 🔴 يرون جهاز Qubes (يمكنهم مسحه ومحاولة اختراقه) | 🟢 لا يرون إلا راوتراً واحداً (لا يستطيعون رؤية ما خلفه) |
| المزود الرسمي | 🟢 يرى الموزع الوسيط فقط (لا يراك) | 🟢 يرى الموزع الوسيط فقط (لا يراك) |
| الموقع النهائي (بدون Tor) | 🔴 يرى IP المزود الرسمي | 🔴 يرى IP المزود الرسمي |
| الموقع النهائي (مع Tor) | 🟢 يرى IP عقدة خروج Tor | 🟢 يرى IP عقدة خروج Tor |
| المعيار | 🔴 موزع + WiFi مباشر | 🟡 شركة رسمية | 🟢 موزع + WISP + Ethernet |
|---|---|---|---|
| جهاز Qubes ظاهر للغير؟ | 🔴 الموزع + الجيران | 🟢 لا أحد | 🟢 لا أحد |
| خطر ثغرات سائق الواي فاي | 🔴 كبير | 🟢 لا يوجد | 🟢 لا يوجد |
| ما يراه المزود الرسمي | 🟢 الموزع فقط | 🔴 أنت مباشرة | 🟢 الموزع فقط |
| اختراق الراوتر = خطر داخل جهازك؟ | — | — | 🟢 لا (خارجي) |
| التكلفة | لا شيء | لا شيء | 🟡 ~30-50$ |
| مستوى الحماية | 🔴 ضعيف | 🟡 متوسط | 🟢 ممتاز |
| # | الخطة | الأمان | متى تستخدم؟ |
|---|---|---|---|
| 🟢 A | WISP + Ethernet | ⭐⭐⭐⭐⭐ | الإعداد اليومي الدائم |
| 🟢 B | WISP + VPN على الراوتر + Ethernet | ⭐⭐⭐⭐⭐ | حماية إضافية من الموزع (VPN قبل وصول البيانات لـ Qubes) |
| 🟡 C | WISP + WiFi داخلي مشفر (WPA3) | ⭐⭐⭐ | إذا تعذر الكابل مؤقتاً |
| 🟡 D | USB Tethering من هاتف أندرويد | ⭐⭐⭐ | السفر، لا يتوفر راوتر WISP |
| 🟠 E | WiFi مباشر + MAC عشوائي + جدار ناري | ⭐⭐ | طوارئ فقط، آخر خيار |
| 🔴 F | WiFi مباشر عادي | ⭐ | لا تستخدمه أبداً |
usb0. أفضل من WiFi مباشر لكن الهاتف نفسه قد يكون مخترقاً.# /usr/lib/NetworkManager/conf.d/31-randomize-mac.conf [connection] ethernet.cloned-mac-address=random wifi.cloned-mac-address=random wifi.scan-rand-mac-address=yes
في إعداد WISP + Ethernet، هذا احتياطي إضافي فقط — الراوتر هو من يتعامل مع الشبكة الخارجية.
qvm-prefs sys-net kernelopts "ipv6.disable=1"
qvm-prefs sys-firewall kernelopts "ipv6.disable=1"
about:config → media.peerconnection.enabled = false
sys-whonix هو netvm الوحيد لجهاز التصفح.
🔗 للمرحلة التالية: توجه إلى تبويب 2 لإعداد Tor والبوابات وأنواع الاتصال.
anon-work يشفر البيانات بطبقة TLS/HTTPS.📖 نتيجة: حتى لو كانت عقدة الخروج خبيثة، فهي لا ترى سوى بيانات مشفرة بـ TLS (كلمات المرور، الرسائل، إلخ).
جهازك ← شبكة Tor ← الإنترنت
ISP يرى اتصال Tor | الموقع يرى IP خروج Tor
جهازك ← جسر سري ← Tor ← الإنترنت
ISP يرى اتصال مشفر عادي | لتجاوز الحجب
جهازك ← VPN ← Tor ← الإنترنت
ISP يرى VPN فقط | الأكثر خصوصية
جهازك ← Tor ← VPN ← الإنترنت
VPN يرى وجهتك | للراحة فقط
جهازك ← VPN ← الإنترنت
VPN يعرف هويتك ووجهاتك
جهازك ← الإنترنت
كل شيء مكشوف
| نوع الاتصال | ISP يرى | الموقع يرى | الخصوصية | السرعة | التوصية |
|---|---|---|---|---|---|
| بدون حماية | كل شيء | IP حقيقي | 🔴 معدومة | 🟢 سريع | ❌ لا تستخدم |
| VPN فقط | اتصال VPN | IP VPN | 🟡 متوسطة | 🟢 سريع | استخدام عادي |
| Tor فقط | اتصال Tor | IP خروج Tor | 🟢 عالية | 🟡 متوسط | ✅ أساسي |
| Tor + Bridges | اتصال مشفر عادي | IP خروج Tor | 🟢 عالية جداً | 🟡 متوسط | 🌉 لتجاوز الحجب |
| VPN → Tor | اتصال VPN | IP خروج Tor | 🟢 ممتازة | 🟡 متوسط | 🔐 موصى به |
| Tor → VPN | اتصال Tor | IP VPN | 🟡 جيدة | 🟡 متوسط | ⚠️ للراحة |
| المعيار | VPN | Tor (Whonix) | Tor + Bridges | I2P |
|---|---|---|---|---|
| السرعة | 🟢 سريع | 🟡 متوسط | 🟡 متوسط | 🟡 متوسط إلى بطيء |
| إخفاء الهوية | 🟡 متوسط | 🟢 عالي جداً | 🟢 عالي جداً | 🟢 عالي |
| مقاومة الحجب | 🟢 عالية | 🔴 ضعيفة | 🟢 عالية جداً | 🟡 متوسطة |
| إخفاء استخدام Tor | ❌ لا | ❌ لا | ✅ نعم | 🟡 غير معروف |
| سهولة الإعداد | 🟢 سهلة | 🟢 سهلة | 🟢 سهلة | 🔴 صعبة |
| التكلفة | ~50€/سنة | مجاني | مجاني | مجاني |
| Gateway (GW) | Workstation (WS) | |
|---|---|---|
| الوظيفة | تشغيل عمليات Tor والعمل كجسر اتصال لـ WS | تشغيل تطبيقات المستخدم وإجراء الأنشطة بأمان |
| نوع الـ VM في Qubes | AppVM + provides_network true | AppVM (عادي) |
| يحتوي على Tor | ✅ نعم | ❌ لا |
| يأخذ عقد دخول (Entry Guards) | ✅ نعم | ❌ لا |
| netvm الخاص به | sys-firewall-X | sys-whonix-X |
| provides_network | ✅ true | ❌ false |
sys-net ← sys-firewall-A ← sys-whonix-A ← anon-work-A
Whonix-Workstation تعتمد على توزيعة Kicksecure الأمنية، وهو نظام تشغيل مُصلب (Hardened OS) يوفر طبقات حماية تتجاوز مجرد تمرير البيانات عبر Tor.
حارس الدخول (Entry Guard) هو أول عقدة Tor تتصل بها البوابة. دورة تغييره تستمر لأسابيع أو أشهر. إذا وقعت على عقدة خبيثة، فستظل عالقاً معها. استخدام Gateway واحد لجميع الأنشطة يعني أن جميع هوياتك مرتبطة بنفس الحارس.
# 1. جدار ناري مؤقت (DispVM) qvm-create --class DispVM --label orange --template default-dvm sys-firewall-A qvm-prefs sys-firewall-A provides_network true qvm-prefs sys-firewall-A netvm sys-net # 2. بوابة Whonix qvm-create --class AppVM --label red --template whonix-gateway-18 sys-whonix-A qvm-prefs sys-whonix-A provides_network true qvm-prefs sys-whonix-A netvm sys-firewall-A # 3. محطة العمل qvm-create --class AppVM --label green --template whonix-workstation-18 anon-work-A qvm-prefs anon-work-A netvm sys-whonix-A
# انسخ الأوامر أعلاه وغير A → B qvm-create --class DispVM --label cyan --template default-dvm sys-firewall-B qvm-prefs sys-firewall-B provides_network true qvm-prefs sys-firewall-B netvm sys-net # ... تابع بنفس الطريقة
sys-firewall-A | Type: DisposableVM | Template: default-dvm | Networking: sys-net | فعّل Provides networksys-whonix-A | Type: AppVM | Template: whonix-gateway-18 | Networking: sys-firewall-A | فعّل Provides networkanon-work-A | Type: AppVM | Template: whonix-workstation-18 | Networking: sys-whonix-AA إلى Bqvm-clone ينسخ حالة Tor مع حارس الدخول. أنشئ Gateway جديداً من القالب مباشرة.default-dvm - أي تغيير فيه سيؤثر على كل الأجهزة المؤقتة في النظام.الجسور هي نقاط دخول بديلة إلى شبكة Tor، تخفي حقيقة أنك تتصل بـ Tor عن مزود الخدمة (ISP).
🕵️ ماذا يرى المراقب؟
معظم مستخدمي Whonix لا يحتاجون جسوراً. لكن ثلاثة فئات قد تحتاجها:
| الفئة | الهدف | نوع الجسر المناسب |
|---|---|---|
| 1️⃣ المحجوبون | Tor محجوب ويحتاج أي طريقة للوصول | obfs4 أو Snowflake |
| 2️⃣ المخفيون | إخفاء حقيقة استخدام Tor عن خصم خطير | جسور خاصة (Private) |
| 3️⃣ المختبرون | اختبار اتصال الجسور فقط | أي نوع |
| النوع | السرعة | مقاومة الحجب | آلية العمل | ماذا يظهر لمزود الإنترنت؟ | الأفضل لـ |
|---|---|---|---|---|---|
| obfs4 | 🟡 متوسطة | 🟢 عالية | تشويش الحزم لجعلها بلا نمط ثابت | حركة بيانات مشفرة عشوائية غير مألوفة | الاستخدام العام، الحجب المتوسط |
| Snowflake | 🟡 متوسطة إلى جيدة | 🟢 عالية جداً | التمرير عبر متصفحات متطوعين باستخدام WebRTC | مكالمة فيديو أو تصفح عبر WebRTC (مثل Google Meet) | البيئات شديدة الحجب |
| meek_azure | 🔴 بطيئة | 🟢 عالية جداً | الإخفاء داخل سيرفر CDN ضخم ليظهر كتصفح HTTPS عادي | زيارة عادية لموقع خادم سحابي معروف (مثل microsoft.com) | الصين، الشرق الأوسط، كحل طوارئ |
| WebTunnel | 🟢 جيدة | 🟢 عالية جداً | إخفاء الاتصال داخل نفق WebSocket عبر HTTPS | اتصال ويب آمن عادي بدون بصمات غريبة | شبكات تمنع البروتوكولات غير المألوفة |
🖥️ الطريقة الرسومية (الأسهل):
sys-whonix، انقر على أيقونة Tor Control Panel في شريط المهام.⌨️ الطريقة الطرفية:
anon-connection-wizard
bridges@torproject.org من Gmail أو RiseupSnowflake هو نقل قابل للتوصيل يمرر حركة المرور عبر متصفحات متطوعين باستخدام WebRTC، مما يجعله الأصعب في الاكتشاف والحجب.
✅ مميزات Snowflake:
🔧 للإعداد اليدوي (متقدم): أضف إلى /usr/local/etc/torrc.d/50_user.conf:
UseBridges 1 ClientTransportPlugin snowflake exec /usr/bin/snowflake-client Bridge snowflake 192.0.2.3:80 2B280B23E1107BB62ABFC40DDCC8824814F80A72 fingerprint=2B280B23E1107BB62ABFC40DDCC8824814F80A72 url=https://1098762253.rsc.cdn77.org/ fronts=www.cdn77.com,www.phpmyadmin.net ice=stun:stun.l.google.com:19302,stun:stun.antisip.com:3478,stun:stun.bluesip.net:3478,stun:stun.dus.net:3478,stun:stun.epygi.com:3478,stun:stun.sonetel.com:3478,stun:stun.uls.co.za:3478,stun:stun.voipgate.com:3478,stun:stun.voys.nl:3478 utls-imitate=hellorandomizedalpn
#nameserver 10.0.2.3 في /etc/resolv.conf.whonix.
sys-whonix، افتح Nyx من قائمة التطبيقات أو اكتب nyx في الطرفية.192.168.0.1 UNKNOWN 1 / Guard
123.45.67.89 RelayName 1 / Guard
للخروج من Nyx: اضغط q مرتين.
هناك شيئان مختلفان تماماً رغم تشابه الاسم:
| المصطلح | المعنى |
|---|---|
| Bridges (الجسور) | نقاط دخول بديلة لشبكة Tor لتجاوز الحجب |
| Bridged Networking | إعداد في برامج المحاكاة (VirtualBox) لا يجب تغييره |
--class AppVM --template whonix-gateway-18 + provides_network true--class AppVM --template whonix-workstation-18 + netvm sys-whonix-Xقبل الغوص في الأدوات والسيناريوهات العملية، من المهم فهم التقنيات الأساسية التي يعتمد عليها هذا الدليل لتشفير البيانات، وأيضاً سيناريو التشفير المزدوج المتقدم.
Linux Unified Key Setup — معيار تشفير الأقراص المدمج في نواة Linux.
cryptsetup وأدوات مثل GNOME Disks.🎯 متى تستخدمه؟ عندما تحتاج تشفيراً مدمجاً في Linux وتريد أفضل حماية ضد هجمات GPU بفضل Argon2id. وهو التشفير الأفضل للاستخدام اليومي على لينكس إذا لم ترد الإخفاء.
VeraCrypt — خليفة TrueCrypt، برنامج مفتوح المصدر لتشفير الملفات والأقراص.
🎯 متى تستخدمه؟ عندما تحتاج إنكاراً معقولاً أو التوافق عبر أنظمة متعددة.
ما هو Argon2id؟
خوارزمية اشتقاق مفاتيح حديثة مصممة خصيصاً لاستهلاك كميات كبيرة من الذاكرة، مما يجعل هجمات كروت الشاشة (GPU) ومنصات التعدين (ASIC) غير عملية. قوتها الحقيقية تكمن في إجبار المهاجم على تخصيص ذاكرة ضخمة لكل تخمين فردي، مما يقتل تماماً خاصية التوازي الجماعي التي تعتمد عليها كروت الشاشة.
| الخوارزمية / الإعداد | الذاكرة | سرعة التخمين على GPU متطور | مستوى الأمان |
|---|---|---|---|
| SHA-256 (غير مملح) | أقل من 1 ميغابايت | ~10,000,000,000/ثانية (10 مليار) | 🔴 هش جداً |
| PBKDF2 (افتراضي VeraCrypt) | أقل من 1 ميغابايت | ملايين/ثانية | 🔴 ضعيف |
| Argon2id (إعدادات OWASP الدنيا) | 46 ميغابايت | ~1,000/ثانية | 🟡 جيد |
| Argon2id (أعلى توصيات RFC 9106) | 2 جيجابايت | ~20-50/ثانية | 🟢 ممتاز |
| Argon2id (إعداد هذا الدليل – حماية قصوى) | 4 جيجابايت | أقل من 25/ثانية | 🟢🔒 قصوى |
الأرقام من دراسات أكاديمية حديثة (2025–2026) ومن توصيات OWASP وRFC 9106. بالنسبة لإعداد 4GB، السرعة تتضاءل لأن البطاقة الرسومية القادرة على 24GB VRAM لا يمكنها تشغيل أكثر من 6 تخمينات متوازية، مما ينهار معه معدل التخمين إلى أقل من 25/ثانية.
المهاجم يستطيع تجربة مليارات الكلمات في الثانية باستخدام بطاقة رسوميات واحدة. إذا كانت كلمة مرورك مكونة من 8 أحرف عشوائية، يمكن كسرها في ساعات أو أيام.
نفس البطاقة الرسومية تصبح قادرة على تجربة أقل من 25 كلمة في الثانية. حتى مع وجود 1000 بطاقة، فإن كسر كلمة مرور مكونة من 6 كلمات عشوائية سيستغرق آلاف السنين.
sudo cryptsetup luksDump /dev/sdX | grep Argon2 للتأكد من تفعيله.
طريقتان لإنشاء حاوية LUKS2 مشفرة بأعلى معايير الحماية ضد هجمات كروت الشاشة (GPU). اختر الأنسب لك: أمر مباشر أو سكريبت تفاعلي.
qvm-prefs storage-vault maxmem 6000
sudo cryptsetup luksFormat --type luks2 --pbkdf argon2id --pbkdf-memory 4194304 --iter-time 8000 /home/user/data.img
--type luks2 — استخدام الإصدار الحديث من LUKS.--pbkdf argon2id — خوارزمية مقاومة لهجمات GPU.--pbkdf-memory 4194304 — تخصيص 4 جيجابايت من RAM لاشتقاق المفتاح.--iter-time 8000 — وقت اشتقاق ~8 ثوانٍ.سكريبت يسألك عن المسار، الحجم، الرام، والوقت، ثم ينشئ الحاوية تلقائياً. يدعم إنشاء حاوية جديدة أو تشفير ملف موجود مسبقاً.
يمكنك استخدام أداة GNOME Disks المدمجة للتهيئة السريعة. لكن انتبه: الأداة لا تسمح باختيار Argon2id (تستخدم الإعدادات الافتراضية فقط)، لذا يفضل استخدام الطريقتين أعلاه للحماية القصوى.
| المعيار | 🔵 LUKS فقط | 🟢 VeraCrypt فقط | 🔴 VC + LUKS |
|---|---|---|---|
| ⚡ سرعة القراءة/الكتابة | 🟢 1-5 GB/s | 🟡 100-400 MB/s | 🟡 مثل VC |
| 🛡️ سلامة البيانات (Integrity) | ✅ AEAD | ❌ XTS | ✅ من LUKS |
| 🔐 مقاومة هجمات GPU | 🟢 Argon2id | 🟡 PBKDF2 | 🟢✅ كليهما |
| 🕵️ قابلية اكتشاف التشفير | 🔴 رأس LUKS | 🟢 عشوائي | 🟢 VC يخفي |
| 🎭 الإنكار المعقول | ❌ لا يدعم | ✅ Hidden | ✅✅ ممتاز |
| 🪟 توافق Windows | ❌ | ✅ | ❌ (LUKS داخلي) |
| 🐧 توافق Qubes OS | ✅ مدمج | 🟡 تثبيت | 🟡 تثبيت |
الفكرة: طبقتا تشفير مستقلتان: VeraCrypt خارجي (للإنكار المعقول) و LUKS داخلي (للحماية وسلامة البيانات).
كلمة مرور "الفخ" (Decoy) ← ملفات عادية. لا أثر للبيانات الحساسة.
✅ إنكار معقول كامل.
كلمة المرور الحقيقية ← LUKS داخلي يحوي بيانات حساسة (مفاتيح، محادثات، سكربتات).
⚠️ تجنب SSD إذا كان الإنكار المعقول ضرورياً (TRIM).
الفكرة: تشفير قسم/حاوية بـ VeraCrypt، ثم تهيئته مباشرةً كـ LUKS. يُستخدم داخل Whonix RAM مع أتمتة كاملة عبر السكربت.
المرحلة الأولى: VeraCrypt الخارجي
المرحلة الثانية: فتح VC بدون تثبيت
/dev/mapper/veracrypt1 بدون نظام ملفات.المرحلة الثالثة: تهيئة LUKS مباشرة
cryptsetup على البلوك ديفايس.| 1 | في كيوب التخزين: افتح VeraCrypt بدون تثبيت (Do not mount) ← يظهر /dev/mapper/veracrypt1. |
| 2 | في نفس كيوب التخزين: افتح LUKS على /dev/mapper/veracrypt1 بدون تثبيت (Unlock only) ← يظهر /dev/mapper/luks-.... |
| 3 | من dom0: مرّر البلوك ديفايس LUKS المفتوح (أيقونة Qubes Devices) إلى whonix-work-ram أو أي Whonix workstation. |
| 4 |
تلقائياً: خلال 10 ثوانٍ، تكتشف خدمة mount-usb.service (التي تم تفعيلها مسبقاً عبر الخيار 10 في السكربت المساعد) القرص /dev/xvdi وتُثبّته فوراً على /home/user/usb.لا حاجة لأي أمر يدوي – القرص جاهز للاستخدام. |
🔑 تدفق التشفير:
💾 فلاشة → 🔐 VeraCrypt (كلمة ١) → 🧅 LUKS مباشر (كلمة ٢) → 📁 ext4 → ✅ بياناتmount-to-whonix.sh
يمكنك أيضاً التحكم اليدوي بالقرص عبر هذا السكربت (يعمل من dom0):
~/Desktop/ram-pool-scripts/mount-to-whonix.sh/home/user/usb.umount داخل VM ثم يفصل الجهاز من dom0.lsblk داخل VM ويُبيّن حالة نقطة التثبيت.كلاهما طبقتان. الفرق يظهر بعد فتح VeraCrypt.
noexec في Whonix Whonix يطبق noexec على الأجهزة الخارجية، مما يمنع تشغيل السكربتات حتى بعد تمرير البلوك ديفايس.
السكربت create-ram-vm.sh يعالج هذا كالتالي:
/home/user/usb داخل whonix-work-ram (مسار داخلي لا يخضع لـ noexec)./home/user/usb مباشرة دون عوائق، مع بقاء البيانات في RAM.💡 الخلاصة: السكربت لا يلغي سياسة noexec، لكنه يتجاوزها بذكاء عن طريق التركيب على مسار داخلي، محققاً العزل والأمان مع صلاحية التنفيذ.
قسم مرئي عادي (FAT/exFAT) يشغل معظم المساحة، وقسم صغير مشفر (VC+LUKS) في المؤخرة يبدو كمساحة غير مهيأة.
مثال 32GB: 30GB مرئي + 2GB مشفر
القسم المشفر لا يحمل توقيع نظام ملفات، يُفتح فقط عبر VeraCrypt ثم تطبق LUKS مباشرة.
| الميزة | HDD | SSD |
|---|---|---|
| المسح الآمن | ✅ سهل (كتابة فوقية) | ❌ صعب (Wear Leveling) |
| TRIM | ❌ غير موجود | ✅ قد يكشف مساحات |
| استعادة البيانات | 🟡 ممكنة | 🟢 شبه مستحيلة (بعد TRIM) |
| الطريقة الموصى بها | wipe / shred | ATA Secure Erase / Crypto Erase |
shred على SSD! استخدم ATA Secure Erase أو Crypto Erase.
الفكرة: كيوب التخزين (زائل) يفتح التشفير بالكامل (VC + LUKS) دون أي تثبيت، ثم يمرر البلوك ديفايس النهائي إلى كيوب RAM (whonix-work-ram) الذي يثبته ويعمل على البيانات. البيانات في RAM فقط وتختفي عند الإغلاق.
📊 التدفق الآمن (مصحح):
📦 storage-vault (زائل) → 🔓 فتح VC ← 🧅 فتح LUKS (Unlock only، لا mount) → 🖱️ تمرير البلوك ديفايس عبر dom0 → 🧠 whonix-work-ram (RAM Pool) → ✅ السكربت يثبّت تلقائياً على مسار داخليكلمة مرور VC + كلمة مرور LUKS تدخلان في كيوب التخزين فقط. البيانات تُكتب في RAM وتختفي عند الإغلاق 🧹
create-ram-vm.sh وأجب y — يثبّت تلقائياً على /home/user/usb.create-ram-vm.shالسكربت الموجود على سطح المكتب يقوم بكل شيء تلقائياً:
~/Desktop/ram-pool-scripts/create-ram-vm.sh/home/user/usb ويجعله جاهزاً للتنفيذ (حل مشكلة noexec)⚠️ مرّر البلوك ديفايس من dom0 أولاً، ثم شغّل السكربت.
/dev/sdb1) وليس القرص كاملاً (/dev/sdb). البلوك ديفايس الصحيح هو الذي يظهر بعد فتح LUKS في كيوب التخزين.
storage-vault ← GNOME Disks ← Unlock LUKS (لا mount).whonix-work-ram./home/user/usb.كلمة مرور LUKS لا تغادر storage-vault. البيانات في RAM. 🛡️
cryptsetup luksHeaderBackup …المشكلة: أنشأت قرص النظام المشفر بإعدادات PBKDF الافتراضية وتريد رفع استهلاك الذاكرة ووقت الاشتقاق لحماية الإقلاع. لا يوجد أمر مباشر لتعديل فتحة موجودة على قرص النظام.
تنبيه هام: هذا هو قرص النظام — الذي يُقلع منه Qubes. أي خطأ يمنع الإقلاع. تأكد من وجود USB حي للطوارئ قبل البدء.
الطريقة الوحيدة: استبدال كلمة المرور الضعيفة بأخرى قوية، ثم حذف القديمة. الخطوتان إجباريتان في كل مرة — حتى عند تغيير كلمة المرور لاحقًا.
luksAddKey (بذاكرة ووقت عاليين) → luksRemoveKey (للقديمة) → كلمة مرور واحدة فقط → المهاجم يختار الأضعف
| 0 | قبل البدء: يُفضّل رفع رام dom0 لتحقيق أقصى استفادة |
|
⬆️ عبر تعديل |
|
| 1 | شغّل السكربت من القائمة الرئيسية |
|
⬆️ الخيار رقم 9 في القائمة. يكتشف القرص تلقائيًا ويسألك عن الذاكرة (بالجيجابايت) والوقت (بالثواني) المطلوبين ⬆️ |
|
| 2 | سيُنشئ السكربت على سطح المكتب ويُشغّله |
|
⬆️ يُنفذ |
|
⛔ لا تستخدم luksChangeKey أبدًا لهذا الغرض.
حتى مع --pbkdf-force-iterations، لا يقبل --pbkdf-memory أبدًا — سيعيد الذاكرة للقيمة الافتراضية (1GB).
dom0_mem في GRUB لتحقيق أقصى استفادة.luksAddKey + luksRemoveKey تلقائيًا باستخدام الوقت الذي تحدده.sudo dracut -f.
استخدم السكربت المساعد في تبويب 11.
luksAddKey مباشرةً نفّذ luksRemoveKey. المهاجم يختار الأسهل دائمًا.
كل بطاقة تمثل تهديداً حقيقياً – مع شرح مبسط وطريقة الحماية
مزود الخدمة (ISP) يرى كل المواقع التي تزورها حتى مع HTTPS. يمكنه بيع هذه البيانات أو تسليمها للسلطات.
ما هي؟ الخصم يراقب توقيت حزم البيانات الداخلة والخارجة من شبكة Tor، ويطابق الأنماط الزمنية ليكتشف أن المصدر والوجهة هما نفس الشخص.
🎯 كيف يعمل؟
📖 مثال حقيقي: في 2013، ألقت FBI القبض على طالب في هارفارد هدد بتفجير. قاموا بمراقبة شبكة الجامعة ورأوا أن توقيت اتصاله بشبكة Tor يطابق تماماً توقيت إرسال رسالة التهديد.
🛡️ كيف تحمي نفسك؟
جهاز صغير (Wi-Fi Pineapple) ينتحل شخصية شبكة شرعية ويجبر جهازك على الاتصال به للتنصت على حركة المرور.
طبقات الحماية:
هاتفك يمسح الشبكات والأجهزة حولك باستمرار. Google وApple تحتفظان بقاعدة بيانات لتحديد موقعك.
إذا كنت تستخدم VPN يدعم IPv4 فقط، فقد تتسرب اتصالات IPv6 مباشرة إلى مزود الخدمة.
إذا وقعت على عقدة دخول خبيثة، تبقى عالقاً معها لأشهر، ويمكن ربط جميع أنشطتك.
المواقع تجمع معلومات عن جهازك: الخطوط، دقة الشاشة، اللغة. هذه البصمة فريدة بنسبة 99%.
حتى مع Tor، يمكن للمواقع استخدام WebRTC لمعرفة عنوان IP الحقيقي لجهازك.
ثغرات مثل "Leaky Page" تسمح للمواقع بسرقة تاريخ التصفح من تبويبات أخرى.
شخص يصل لجهازك في غيابك ويزرع Keylogger فيزيائي أو ينسخ القرص الصلب.
الخصم يبرد ذاكرة RAM لاستخراج مفاتيح التشفير بعد إطفاء الجهاز بدقائق. هذا الهجوم غير عملي خارج المختبر.
فلاشة USB تنتحل شخصية لوحة مفاتيح وتنفذ أوامر خبيثة بصلاحيات root.
ثغرات في تصميم المعالجات تسمح بسرقة البيانات من الذاكرة عبر الحدود الافتراضية.
شريحة إدارة مخفية داخل المعالج تعمل حتى عند إطفاء الجهاز بصلاحيات كاملة.
إعادة بناء ما يظهر على الشاشة أو استخراج مفاتيح من خلال الموجات الكهرومغناطيسية.
الصور تحمل إحداثيات GPS، نوع الكاميرا، تاريخ الالتقاط، واسم المؤلف.
Zoom وAdobe تضيفان علامات مائية غير مرئية. الطابعات الملونة تطبع نقاطاً صفراء خفية.
WhatsApp وiCloud يحتفظون بنسخ غير مشفرة من محادثاتك يمكن تسليمها للسلطات.
حذف الملفات لا يمسحها فعلياً. على HDD يمكن استعادتها بسهولة. على SSD، TRIM و Garbage Collection تجعل الاستعادة أصعب لكنها ليست مستحيلة.
طريقة كتابتك فريدة ويمكن استخدامها لربط هوياتك المجهولة بهويتك الحقيقية.
طريقة تحريكك للفأرة وسرعة كتابتك وكيفية حلك لـ CAPTCHA تستخدم للتعرف عليك.
أسهل طريقة لاختراقك هي خداعك عبر رسائل بريد مزيفة أو روابط خبيثة.
أي صورة تظهر فيها يمكن فهرستها وربطها بك. Clearview AI لديها مليارات الصور.
حتى لو كان وجهك مغطى، يمكن التعرف عليك من طريقة مشيتك.
بطاقاتك البنكية وجواز سفرك يحملان شرائح يمكن قراءتها عن بعد وتتبع تحركاتك.
Windows وmacOS وUbuntu ترسل بيانات تشخيصية تكشف عن وجود برامج "مشبوهة".
بعض التطبيقات تستخدم بروتوكولات تشفير محلية الصنع ثبت ضعفها.
خدمات VPN تدعي عدم الاحتفاظ بالسجلات لكنها تضطر للتسجيل بصمت بأمر قضائي.
Bitcoin وEthereum ليستا مجهولتين. كل معاملة مسجلة في سلسلة الكتل العامة.
أكبر عدو لك هو فمك. لا تخبر أحداً – حتى أقرب الناس إليك – عن أنشطتك الحساسة أو عن استخدامك لهذا الدليل.
إذا اختفيت تماماً من العالم الرقمي، أو قضيت كل وقتك على Tor، أو لم يكن لديك أي حسابات اجتماعية – فأنت تلفت الانتباه.
أكبر أخطاء OPSEC تحدث عندما يستخدم الشخص نفس البريد الإلكتروني، أو نفس طريقة الكتابة، أو يفتح رابطاً حساساً من جهازه الشخصي.
في معظم البلدان (خاصة الولايات المتحدة)، أي شيء تقوله للشرطة يمكن استخدامه ضدك. حتى لو كنت بريئاً، قد تقول شيئاً يورطك.
في حالة الطوارئ، آخر شيء تريد القلق بشأنه هو البحث عن رقم محامٍ. احفظ رقم محامٍ موثوق في ذاكرتك أو في مكان آمن.
قضايا مثل AN0M وEncroChat وSky ECC أثبتت أن الأجهزة "فائقة الأمان" التي تباع للمجرمين غالباً ما تكون فخاخاً تديرها وكالات الاستخبارات.
من توثيق Qubes الرسمي: هناك 3 أنواع من تسريب البيانات:
أخطر تهديد على Qubes. برمجيات خبيثة في VM معزول وأخرى في VM متصل بالشبكة تتواصل عبر CPU cache. جدار الحماية لا يمنع هذا. توثيق Qubes يؤكد عدم وجود حلول عملية كاملة لهذا الهجوم.
تنبيه: هذه هي الدفاعات العملية الوحيدة المتاحة حالياً في Qubes OS ضد التهديدات التي تستهدف القرص الصلب (التحليل الجنائي) والنظام المضيف (dom0). انتبه للفرق بين Ephemeral VM و RAM-VM - فالأولى تشفير زائل على القرص (يُورّث من قالب DVM)، والثانية VM بالكامل في RAM عبر tmpfs.
الآلية: تعيين root rw False على قالب DVM ← الأجهزة المشتقة ترث تلقائياً خاصية التشفير الزائل على القرص.
أمر التفعيل:
qvm-volume config DVM_TEMPLATE:root rw False
يحل:
الآلية: VM بالكامل في RAM عبر RAM pool + tmpfs.
أمر التفعيل:
qvm-create -P ram_pool -t TEMPLATE VMNAME
🔑 ملاحظة: جميع الأجهزة المستهلكة (Disposable VMs) المشتقة من VM في RAM pool تعمل أيضاً في RAM تلقائياً.
يحل:
luksSuspend) أو Shutdown كامل + RAM-Wipe.
الآلية: dom0 يُركب للقراءة فقط. كل التغييرات على dom0 تُكتب في RAM وتختفي عند الإغلاق.
أمر التفعيل: إضافة rootovl إلى GRUB_CMDLINE_LINUX في /etc/default/grub.
يحل:
root rw False من قالب DVM) يحمي من التحليل الجنائي للقرص (Forensic Analysis) - الأسرع للجلسات اليومية. RAM-VM (عبر RAM pool) يوفر حماية قصوى للبيانات - لا أثر على القرص، وجميع الأجهزة المستهلكة المشتقة منه تعمل في RAM تلقائياً. للحماية من Cold Boot: استخدم BusKill (luksSuspend) أو Shutdown كامل + RAM-Wipe - فالهجوم يستهدف RAM نفسها. Live Mode (عبر rootovl في GRUB) يحمي النظام المضيف نفسه من العبث وهجمات الاستمرارية. معاً، يشكلان درعاً كاملاً ضد هجمات الاستمرارية (Persistence Attacks) والكشف الجنائي (Forensics). لكنهما لا يحميان من القنوات الخفية التعاونية (Cooperative Covert Channels) التي تمثل حدود العزل في Qubes.
| 🛡️ تقني | 🟡 شبكة → sys-whonix (تبويب 2) 🔴 تتبع → Kicksecure (تبويب 2) 🔴 فيزيائي → Live Mode + تشفير 🔵 بيانات → ExifTool (تبويب 3) 🔴 Tor → بوابات متعددة (تبويب 2) 🔴 معالج → معلمات النواة (تبويب 0) 🟡 مالي → Monero حصراً 🧅 IP → Whonix Gateway (تبويب 2) 📶 WiFi → WISP+Ethernet (تبويب 1) |
| 🧠 سلوكي | 🔴 كلام → الصمت التام 🟡 نمط حياة → كن طبيعياً 🔴 خلط → عزل تام للهويات 🔴 قانوني → لا تتحدث مع الشرطة 🔵 طوارئ → احفظ رقم محامٍ 🔴 فخاخ → لا حلول جاهزة ✍️ كتابة → تغيير الأسلوب |
| 🚨 طوارئ | 🔥 احترقت → خطة الحذف والهروب 🔍 تلاعب → خطة المغادرة الفورية 💀 تدمير → BusKill 🧹 Forensic → Ephemeral VM (وراثة DVM) ❄️ Cold Boot → BusKill / Shutdown + RAM-Wipe ⚡ مضيف → Live Mode (rootovl) |
| 💰 تمويل | 💵 نقداً → iVPN 🪙 Monero → Mullvad / Njalla 🔄 تبديل → sideshift.ai / bisq ❌ تجنب → Bitcoin/Ethereum |
تقنية tmpfs تجعل المجلدات الحساسة (السجلات، الكاش، ملفات المستخدم) موجودة في RAM فقط، وتختفي تماماً عند إعادة التشغيل. هذا يوفر طبقة إضافية من الخصوصية والأمان.
/var/log - سجلات النظام (512MB)/var/cache - ذاكرة التخزين المؤقت (512MB)/var/tmp - الملفات المؤقتة (256MB)/tmp - الملفات المؤقتة (512MB)/home/user - مجلد المستخدم الرئيسي (2GB)default-dvm يجعله يتورث إلى جميع الأجهزة الزائلة (DVMs).whonix-workstation-18) يؤثر فقط على القالب نفسه ولا يتورث للأجهزة المشتقة.
لتطبيق أو إلغاء Amnesic Tmpfs، انتقل إلى
تبويب 11 (السكريبت المساعد)
وقم بتشغيل auto-script.sh.
chmod +x auto-script.sh && ./auto-script.sh
ثم اختر: 6) Amnesic Tmpfs
ستظهر لك قائمة:
فكرة من Hitchhiker's Guide: مثل Tails، لكن داخل Qubes. الأجهزة التي تعمل في RAM تختفي تماماً عند الإغلاق.
تعمل على مستند حساس جداً. فجأة، تسمع طرقاً على الباب. تضغط على إيقاف التشغيل. بعد 60 ثانية، حتى لو صودر الجهاز، لا توجد أي طريقة لاستعادة ما كنت تعمل عليه. "لا بيانات = لا جريمة".
هذه التقنية تسمح بإنشاء pool من نوع file على نظام ملفات tmpfs، ثم إنشاء AppVMs على هذا pool بحيث تكون ملفات الكيوب في الذاكرة.
| النوع | الأمر | ملاحظات |
|---|---|---|
| تغيير دائم (تعديل GRUB) | sudo nano /etc/default/grubsudo grub2-mkconfig -o /boot/grub2/grub.cfg | ابحث عن السطر GRUB_CMDLINE_XEN_DEFAULT وغيّر قيمة dom0_mem، مثال: dom0_mem=max:8192M |
لتجنب التكرار، جميع السكريبتات الكاملة متوفرة في تبويب 11 (السكريبت المساعد)
chmod +x auto-script.sh && ./auto-script.sh
ثم اختر: 5) إنشاء سكريبتات RAM Pool
setup-ram-pool.sh – ينشئ RAM pool في الذاكرةcreate-ram-vm.sh – ينشئ جهازاً واحداً (مع معلمات النواة الكاملة + DVM Template)create-multi-ram-vm.sh – ينشئ عدة أجهزة مع اختيار البوابات (مع معلمات النواة الكاملة + إمكانية الحفظ)cleanup-ram-pool.sh – يحذف جميع الأجهزة ويفرغ RAM poolram-pool-status.sh – يعرض حالة RAM pool/home/user/Desktop/ram-pool-scripts/
لحذف جميع الأجهزة وتفريغ RAM pool يدوياً:
#!/bin/bash
RAM_POOL_PATH="$HOME/ram_pool"
POOL_NAME="ram_pool"
echo "🧹 تنظيف RAM Pool..."
# حذف الأجهزة
for vm in $(qvm-ls --raw-list 2>/dev/null | grep -E "whonix-work-ram|ram-"); do
echo " حذف: $vm"
qvm-kill "$vm" 2>/dev/null
qvm-remove --force "$vm" 2>/dev/null
done
# حذف pool
qvm-pool remove "$POOL_NAME" 2>/dev/null
# إلغاء التثبيت
mount | grep -q "$RAM_POOL_PATH" && sudo umount "$RAM_POOL_PATH" 2>/dev/null
# حذف المجلد
[ -d "$RAM_POOL_PATH" ] && sudo rm -rf "$RAM_POOL_PATH"
echo "✅ تم التنظيف"
free -h
| المشكلة | السبب | الحل |
|---|---|---|
qvm-create يفشل مع "No space left" | RAM pool ممتلئ أو حجمه صغير | df -h /home/$USER/ram_pool ثم sudo mount -o remount,size=8G /home/$USER/ram_pool |
| البيانات لا تختفي بعد إعادة التشغيل (لـ AppVM) | الـ pool غير مثبت على tmpfs | تأكد من أن mount | grep ram_pool يظهر tmpfs |
| معلمات النواة لم تُطبق | لم يتم استخدام السكريبت المعدل | تأكد من استخدام الإصدار المحدث من السكريبت المساعد (يحتوي على KERNEL_OPTS) |
ephemeral_volatile لا يعمل | الخاصية تحتاج إلى إعادة تشغيل الـ pool أو إعادة إنشاء VM | بعد تفعيل الخاصية، أنشئ VM جديد؛ VM القديمة لا تتأثر |
راجع هذه الإجراءات بانتظام - الأمان عملية مستمرة وليس إعداد لمرة واحدة
لا تثق بأي USB غير معروف. يمكن برمجة أي USB ليصبح لوحة مفاتيح وتنفيذ أوامر بصلاحيات root.
الحماية الأساسية: Qubes يعزل USB تلقائياً في sys-usb (VM منفصل عن dom0). هذا يمنع أي جهاز USB ضار من الوصول المباشر لـ dom0.
للإقلاع من USB: إذا كنت تقلع من هارد خارجي، ثبّت usbguard في dom0:
sudo qubes-dom0-update usbguard
sudo systemctl enable usbguard
sudo usbguard generate-policy > /etc/usbguard/rules.conf
تحذير "USB in dom0 is not restricted" طبيعي عند الإقلاع من USB.
التهديد: مزود الخدمة (ISP) يستطيع معرفة أنك تستخدم Tor، حتى لو كان لا يستطيع رؤية محتوى اتصالك.
الحل (مدفوع): استخدم VPN موثوق قبل Tor. المسار: sys-net → sys-vpn → sys-whonix → anon-whonix. أنشئ كيوب VPN واجعله netvm لـ sys-whonix.
البديل (مجاني): استخدم Tor + Bridges بدلاً من VPN. Bridges تخفي حقيقة استخدام Tor عن ISP بدون تكلفة. راجع تبويب 2 (Whonix) لقسم الجسور.
التهديد: إهمال التحديثات يترك ثغرات معروفة مفتوحة للاستغلال. طبّق التحديثات فور ظهورها.
التحديث الأساسي:
sudo qubes-dom0-updatesudo apt update && sudo apt upgrade (داخل كل قالب)التحديث عبر Tor: Qubes يستخدم UpdatesProxy الذي يوجّه تحديثات القوالب عبر sys-whonix تلقائياً.
sudo apt install debsums && sudo debsums -c للتحقق من سلامة الحزم.
التهديد: قرصك قد يتعطل أو يُسرق. بدون نسخ احتياطي خارج الجهاز، قد تفقد كل بياناتك.
الحل الأساسي (Qubes Backup):
qubes-backup --encrypt --passphrase-file /path/to/key /mnt/backup
بدائل خارجية:
التهديد: أي نظام آخر (مثل Windows) يمكنه تعديل /boot غير المشفر وتثبيت Bootkit أو استبدال النواة بملف ضار.
المصادر الرسمية: وثائق Qubes و Kicksecure تحذران من التشغيل المزدوج لأن /boot غير مشفر ويمكن التلاعب به.
من منتدى Qubes: "Bootkit يمكنه تثبيت نفسه دون أن يفعل المستخدم أي شيء خاطئ."
التهديد: حتى لو "مررت" USB إلى VM آخر، dom0 يضطر لتشغيل سوائق USB وقراءة Vendor/Product IDs وجدول الأقسام.
ماذا يمكن أن يفعل USB ضار؟
وضعك (الإقلاع من USB): الهارد الخارجي موثوق، لكن أي USB آخر يشكل خطراً. لا يمكن تحقيق عزل USB كامل مع الإقلاع من USB.
lspci | grep USB.
① Evil Maid (الخادمة الشريرة):
شخص يصل لجهازك في غيابك ويقوم بـ: تثبيت Keylogger، تعديل Bootloader، تثبيت برمجيات على مستوى Firmware.
الحماية: كلمة مرور BIOS + Secure Boot + Anti Evil Maid (AEM) - يتطلب TPM 1.2 و Intel TXT + Live Mode (OverlayFS) - dom0 في RAM، كل التغييرات تختفي بعد الإطفاء.
⚠️ ملاحظة: Live Mode لا يحمي من تلاعب UEFI/BIOS نفسه، و USB للأمان فيه مقايضة أمنية.
② Cold Boot (الإقلاع البارد):
المهاجم يبرد RAM لاستخراج مفاتيح التشفير بعد إطفاء الجهاز. يمكن استرجاع البيانات لـ 90 دقيقة مع التبريد.
ما يحمي:
luksSuspend يمسح مفاتيح LUKS من RAMما لا يحمي:
③ مقارنة الأوضاع:
| الوضع | RAM | السرعة | Cold Boot | Evil Maid |
|---|---|---|---|---|
| Sleep | 🔴 نشطة | 🟢 ثواني | ❌ ضعيف | ❌ |
| Hibernate | 🟢 تفرغ | 🟡 ١٠-٣٠ث | ✅ | 🟡 جزئي (الصورة قابلة للاستعادة) |
| Shutdown | 🟢 تفريغ | 🔴 ٣٠-٦٠+ث | 🟡 يقلل المخاطر | ✅ |
السكريبتات المتوفرة في تبويب 11 (اختر 8) أدوات التدمير):
النوع: 💀 تدمير شامل بمؤقت زمني
آلية التدمير: ينفذ تلقائياً بعد انتهاء مؤقت زمني (تحدده أنت بالدقائق).
مثالي لسيناريو: الاعتقال أو الإكراه - إذا لم تلغِ العملية خلال المهلة، يُدمر كل شيء تلقائياً.
للإلغاء: sudo /usr/local/bin/cancel قبل انتهاء المهلة.
المسار: ~/Desktop/emergency/deadman-switch.sh
النوع: 💀 تدمير شامل فوري
آلية التدمير: ينفذ فوراً عند التشغيل (اختصار لوحة مفاتيح).
مثالي لسيناريو: مداهمة مفاجئة أو خطر فوري يتطلب تدميراً سريعاً.
ملاحظة: لا يمكن إلغاؤه بعد التشغيل.
المسار: ~/Desktop/buskill/buskill-selfdestruct.sh
qvm-kill --allEFI/qubes من قسم EFIddluksSuspend لجميع الأجهزة⚠️ النتيجة: تدمير شامل لا رجعة فيه. حتى النسخة الاحتياطية لرأس LUKS لن تنفع وحدها - يجب إعادة بناء /boot وEFI/qubes أيضاً. إعادة التثبيت الكامل قد يكون الحل الأسهل.
النوع: 🗑️ حذف الخدمة فقط
لا علاقة له بالتدمير. وظيفته الوحيدة هي حذف خدمة systemd الخاصة بـ Dead Man's Switch.
deadman.serviceملاحظة: لا يحذف BusKill نفسه (/etc/qubes-rpc/buskill.selfDestruct)، فقط يلغي المؤقت.
المسار: ~/Desktop/emergency/uninstall-deadman.sh
📊 مقارنة سريعة:
| المعيار | ① Dead Man's | ② BusKill | ③ Uninstall |
|---|---|---|---|
| النوع | 💀 تدمير مؤجل | 💀 تدمير فوري | 🗑️ حذف خدمة |
| التوقيت | بعد مؤقت | فوري | — |
| آلية التدمير | شاملة | شاملة | لا يوجد |
| حذف EFI/qubes | ✅ | ✅ | ❌ |
| تدمير /boot | ✅ | ✅ | ❌ |
| قتل VMs | ✅ | ✅ | ❌ |
| مسح رأس LUKS | ✅ كل الأقراص | ✅ كل الأقراص | ❌ |
| luksSuspend | ✅ كل الأجهزة | ✅ كل الأجهزة | ❌ |
| يمسح qubes | ✅ | ✅ | ❌ |
| الإلغاء | ✅ قبل المهلة | ❌ | — |
| قابلية الاستعادة | ⚠️ تحتاج /boot + EFI | ⚠️ تحتاج /boot + EFI | — |
| الأفضل لـ | اعتقال / إكراه | مداهمة / خطر فوري | تنظيف النظام |
① إذا احترقت (هويتك انكشفت):
لديك وقت: احذف الهوية من الإنترنت، تخلص من SIM والهاتف (دمره وألقه)، امسح القرص أو دمره فيزيائياً، احتفظ برقم محامٍ، تظاهر بأن شيئاً لم يكن.
لا وقت (طارئ): أغلق/افصل التيار فوراً. RAM ستتلاشى والبيانات تصبح غير قابلة للقراءة. التزم الصمت - لا تتحدث بدون محامٍ.
② إذا اكتشفت تلاعباً:
باللابتوب: لا تلمس الزرع - لا تستخدم الجهاز. أخرج القرص (إذا كان مشفراً) وغادر فوراً.
بالغرفة: افترض أن كل شيء مزروع (كاميرات، مسجلات). لا تلمس شيئاً - غادر فوراً بهدوء. لا تعد أبداً.
③ حيلة لكشف التفتيش: التقط صورة لمكتبك قبل المغادرة وقارن عند العودة. خيط رفيع أو قطعة شمع على الدرج.
④ استعادة البيانات: qubes-backup --restore على جهاز جديد نظيف.
① أساسيات: كلمات مرور قوية وفريدة لكل خدمة. حدّث النظام أسبوعياً. استخدم Disposable VMs لفتح الملفات المشبوهة.
② شبكة وتصفح: عزل USB في sys-usb (افتراضي في Qubes). تعطيل JavaScript أو استخدام NoScript. استخدم متصفح Tor داخل Whonix للأنشطة الحساسة.
③ تخزين وتشفير: LUKS2 مع integrity للبيانات الحساسة. RAM pool للتشغيل المؤقت (لا أثر ع القرص). معلمات النواة: init_on_free=1, init_on_alloc=1.
① حماية الإقلاع: كلمة مرور BIOS/UEFI قوية - تمنع تغيير إعدادات الإقلاع. فعّل Secure Boot. استخدم TPM لتخزين مفاتيح التشفير بأمان.
② أدوات متقدمة: Anti Evil Maid (AEM) - متوفر في Qubes (Intel CPUs). Heads firmware - بديل BIOS مفتوح مع TPM verification كامل - أقوى من Secure Boot.
③ أجهزة متخصصة: NitroPad (Nitrokey) - لابتوب مع Heads مدمج. Purism Librem - لابتوب مع kill switches فيزيائية.
④ أثناء التنقل: لا تترك جهازك دون مراقبة. استخدم Faraday Cage لمنع الاتصالات اللاسلكية. تحقق من الأجهزة الغريبة عند العودة.
استخدم السكربت المساعد في تبويب 11 لتطبيق إعدادات Kicksecure تلقائياً على جميع القوالب.
chmod +x auto-script.sh && ./auto-script.sh
ثم اختر: 3) تطبيق إعدادات Kicksecure
Kicksecure هو نظام تشغيل كامل مبني على Debian، صُمم من الألف إلى الياء ليكون شديد التحصين (Hardened).
إنه ليس مجرد "Debian مع بعض الإعدادات الإضافية"، بل هو حزمة شاملة من الحماية تطبق نموذج أمان متعدد الطبقات، بدءًا من النواة (kernel) المحصنة، مرورًا بصلاحيات المستخدمين، ووصولاً إلى التطبيقات والشبكة.
النتيجة: نظام جاهز للاستخدام اليومي، مقاوم للفيروسات والهجمات، ويوفر حماية استباقية بدلاً من رد الفعل.
في Qubes OS، يعمل Kicksecure كـ Template (قالب) ليمنح جميع أجهزتك الافتراضية (AppVMs) تحصيناته تلقائيًا.
sys-whonix للحصول على Whonix + Kicksecure معاً.qvm-create --template=kicksecure anon-work && qvm-prefs anon-work netvm sys-whonixفي Qubes OS، جميع القوالب (Templates) تشترك في نواة dom0 ولا يمكنها استخدام نواتها الخاصة. لذلك، لا يمكن تثبيت hardened-kernel داخل القالب.
بدلاً من ذلك، يتم تطبيق تحصينات النواة عبر:
Kicksecure لا يعتمد على طبقة حماية واحدة، بل يطبق نموذج "خطة الدفاع متعدد الطبقات" (Multi-Layer Defense Model) ليشمل:
إعدادات KSPP، تعطيل ميزات خطيرة، عشوائية تخطيط الهياكل.
فصل صارم للحسابات، حماية من هجمات التخمين.
جدار ناري محكم، مزامنة وقت آمنة.
توحيد معلومات النظام والمتصفح لتبدو متطابقًا إحصائيًا مع بقية المستخدمين.
تشفير كامل للقرص، مسح الذاكرة عند الإغلاق.
تحقق صارم من التوقيعات الرقمية في كل مراحل التطوير.
Tor يخفي عنوان IP فقط. لكن المواقع يمكنها التعرف عليك عبر بصمة المتصفح: الخطوط، دقة الشاشة، الإعدادات... Kicksecure يوحد هذه المعلومات بين جميع مستخدميه، مما يجعل بصمتك غير مميزة.
الخطوة 1: تثبيت القالب من مستودعات المجتمع:
qvm-template --enablerepo qubes-templates-community install kicksecure-18
الخطوة 2: تثبيت الإضافة الرسمية لإدارة الوقت:
sudo qubes-dom0-update --action=install qubes-core-admin-addon-kicksecure
الخطوة 3: تحديث القالب دورياً:
sudo qubes-dom0-update --action=update kicksecure
ما هي tirdad؟ أداة قديمة كانت تهدف لعشوائية أرقام تسلسل TCP (TCP ISN Randomization).
معلمات النواة الحديثة في هذا الدليل (مثل init_on_free=1، init_on_alloc=1، page_alloc.shuffle=1) توفر حماية شاملة وأعمق ضد نفس الهجمات التي كانت tirdad تحاول سدها.
| الميزة | 🛡️ Kicksecure | 🧅 Whonix Workstation |
|---|---|---|
| الهدف الأساسي | تحصين الأمان (Security Hardening) | إخفاء الهوية (Anonymity) |
| العلاقة بينهما | Whonix مبني على Kicksecure ← يرث جميع تحسيناته الأمنية | |
| توجيه الشبكة | ❌ لا يوجد توجيه إجباري | ✅ توجيه إجباري عبر Tor |
| بنية النظام | نظام تشغيل واحد (Monolithic) | جهازان: Gateway + Workstation |
sudo systemctl mask bluetooth.service cups.service avahi-daemon.service ModemManager.service
echo "blacklist pcspkr" | sudo tee -a /etc/modprobe.d/blacklist.conf
echo "blacklist thunderbolt" | sudo tee -a /etc/modprobe.d/blacklist.conf
echo "* hard core 0" | sudo tee -a /etc/security/limits.conf
echo "kernel.core_pattern=|/bin/false" | sudo tee -a /etc/sysctl.d/99-core.conf
echo "vm.swappiness=10" | sudo tee -a /etc/sysctl.d/99-swappiness.conf
حزمة أمان متقدمة من Kicksecure - تتطلب تثبيتاً منفصلاً
sudo apt update && sudo apt install security-misc
تخفي هذه الميزة معلومات حساسة من /sys و /proc، تفاصيل الهاردوير (lspci، /proc/cpuinfo)، ومعرفات الأجهزة الفريدة.
sudo systemctl enable hide-hardware-info.service && sudo reboot
ميزة hidepid تقيد رؤية معلومات العمليات للمستخدمين غير الجذر.
sudo systemctl enable proc-hidepid.service && sudo systemctl start proc-hidepid.service
النتيجة المتوقعة: بصمتك غير مميزة ضمن أكبر مجموعة من المستخدمين.
sys-usb و sys-net و sys-firewall وجميع الأجهزة المستهلكة (Disposable VMs) مشتقة من default-dvm. تغيير قالبها إلى Kicksecure سيحصن جميع مكونات النظام الأساسية دفعة واحدة.
كل هذه الخطوات مؤتمتة في السكربت المساعد في تبويب 11.
default-dvm ينعكس تلقائياً على كل ما هو مشتق منه.
passwordless-sudo الضروري لعمل هذا الجهاز. أبقِه على القالب الرسمي.sys-usb و sys-net و sys-firewall.default-dvm.سكريبت شامل لتهيئة بيئة Live Mode مع تنظيف الذاكرة وإنشاء DVMs زائلة
استخدم السكربت المساعد في تبويب 11 الذي يقوم بتشغيل Live Mode تلقائياً (الخيار رقم 7). السكريبت الكامل موجود هناك.
chmod +x auto-script.sh && ./auto-script.sh
💡 ملاحظة: كود live.sh الكامل موجود داخل السكريبت المساعد في تبويب 11، وليس هنا. هذا لتجنب التكرار وتسهيل الصيانة.
هذا هو الدرع الكامل. dom0 يعمل في RAM، والبيانات الحساسة في RAM أيضاً. لا يوجد أي دليل رقمي بعد الإغلاق.
| السيناريو | dom0 | بيانات VMs | مستوى الحماية | المتطلبات |
|---|---|---|---|---|
| وضع Live فقط | ✅ في RAM | ⚠️ على القرص | 🟢 جيدة | 16GB RAM |
| RAM-VM فقط | ⚠️ على القرص | ✅ في RAM | 🟢 جيدة | حسب حجم VM |
| Live + RAM-VM | ✅ في RAM | ✅ في RAM | 🔴 قصوى | 32GB+ RAM |
عند الدمج: لا أثر لـ dom0 ولا لبيانات VMs الحساسة على القرص. بمجرد إطفاء الجهاز، لا يوجد أي دليل رقمي على أي نشاط. هذا هو ما يجعل النظام "فاقداً للذاكرة" (Amnesic) بشكل كامل.
للاستخدام اليومي: Live Mode وحده + Ephemeral VMs كافٍ لمعظم المستخدمين. للجلسات شديدة الحساسية: الدمج مع RAM-VM هو الخيار الأقوى.
هذا هو المرجع الوحيد للمقارنة بين جميع الأنواع. راجع التبويبات المذكورة للتفاصيل الكاملة.
| الميزة / النوع | DVM عادي | Ephemeral DVM | Amnesic Tmpfs | VM في RAM Pool | Dom0 Live Boot | Live + RAM-VM |
|---|---|---|---|---|---|---|
| مكان التخزين الأساسي | القرص الصلب | القرص الصلب (مع تشفير عابر) |
RAM (tmpfs) | RAM (ram_pool) جميع volumes في RAM |
RAM (نسخة كاملة) | RAM (dom0 + VMs) |
مكان /home/user |
القرص الصلب (يُحذف) | القرص الصلب (ليس RAM) | RAM (tmpfs) | RAM | RAM | RAM |
الكتابة إلى / (root) |
N/A | تُحوَّل إلى volatile volume (على القرص) |
تُكتب في RAM | تُكتب في RAM | تُكتب في RAM | تُكتب في RAM |
خاصية ephemeral |
❌ | ✅ مفعّلة تشفير عابر بمفتاح عشوائي |
❌ | ❌ (غير ضرورية) | N/A | ✅ كامل |
| مسح الذاكرة (RAM Wipe) | ❌ | ❌ (بيانات على القرص) | ❌ | ❌ (تُحرر فقط) | ✅ نعم | ✅ نعم |
| سرعة الإقلاع | 🟢 سريع | 🟢 سريع | 🟡 متوسط | 🔴 أبطأ | 🔴 أبطأ | 🔴 الأبطأ |
| الاستخدام المثالي | فتح ملف لمرة واحدة | جلسة عمل + تشفير عابر | جعل مجلدات محددة تختفي | أقصى عزل - جهاز كامل في RAM | جلسة طوارئ - dom0 في RAM | حماية قصوى - لا أثر نهائياً |
| التبويب المرجعي | - | تبويب 9 | تبويب 5 | تبويب 6 | تبويب 9 | 9 + 6 |
/home/user) لا تزال على القرص الصلب.| المعيار | 🧠 Amnesic Tmpfs (تبويب 5) | 💾 RAM Pool (تبويب 6) |
|---|---|---|
| ماذا يجعل زائلاً؟ | مجلدات محددة داخل VM موجود | الـ VM بالكامل (ملفات النظام والتخزين) |
| أين يُطبّق؟ | داخل أي AppVM موجودة | على مستوى dom0 (عند إنشاء VM جديدة) |
| مستوى العزل | 🟡 جزئي - مجلدات محددة في RAM | 🟢 كامل - VM بالكامل في RAM |
| الأفضل لـ | تنظيف السجلات والكاش بعد كل جلسة | جلسات عمل حساسة جدًا، بيئة Tails داخل Qubes |
/home/user). هذا يوفر طبقة إضافية من العزل والخصوصية، ويمكن نقلها بسهولة على فلاشة USB.
torsocks: sudo apt install torsocks -yمقارنة دقيقة ومحدثة لأهم تطبيقات المراسلة والمشاركة من حيث الأمان والخصوصية، متوافقة مع تقييمات صفحة Whonix الرسمية (2025):
| المعيار | 🔷 SimpleX | 🔴 Cwtch | 🟢 OnionShare | 💬 Gajim | 📘 Element | 💬 XMPP | 🟣 Session | 🟠 Signal | 🟢 Briar | ✈️ Telegram |
|---|---|---|---|---|---|---|---|---|---|---|
| 🔹 الخصائص الأساسية | ||||||||||
| الغرض الأساسي | مراسلة | مراسلة | مشاركة ملفات + محادثة | مراسلة | مراسلة | مراسلة | مراسلة | مراسلة | مراسلة | مراسلة |
| نموذج الشبكة | لامركزي (خوادم SMP) | ند للند (P2P) عبر Tor v3 | ند للند (P2P) عبر Tor | فيدرالي (خوادم XMPP) | فيدرالي (خوادم Matrix) | فيدرالي (خوادم XMPP) | لامركزي (شبكة Oxen) | مركزي (خوادم Signal) | ند للند (P2P) عبر Tor/Bluetooth | مركزي (خوادم Telegram) |
| بروتوكول التشفير | Simplex Messaging Protocol (SMP) | Tapir Protocol | Tor onion protocol | OMEMO | Olm/Megolm | OMEMO | Oxen Protocol | Signal Protocol | Briar Protocol | MTProto |
| تشفير E2EE | ✅ كامل (افتراضي) | ✅ كامل (افتراضي) | ✅ كامل (افتراضي) | 🟡 OMEMO (تفعيل يدوي) | 🟡 اختياري | 🟡 OMEMO (اختياري) | ✅ كامل | ✅ كامل | ✅ كامل | 🟡 جزئي (المحادثات السرية فقط) |
| 🔹 خصائص الأمان (حسب صفحة Whonix الرسمية) | ||||||||||
| Serverless / ند للند | ✅ توجيه أحادي (الخادم لا يخزن) | ✅ عميل ← onion | ✅ عميل ← onion (الجهاز هو الخادم) | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ✅ عميل ← onion | ❌ لا |
| لا مخاطر من استضافة Onion | ✅ نعم | ✅ نعم | ❌ لا (الجهاز هو الخادم) | ✅ نعم | ✅ نعم | ✅ نعم | ✅ نعم | ✅ نعم | ❌ لا | ✅ نعم |
| تشفير E2EE افتراضي | ✅ نعم | ✅ نعم | ✅ نعم | ❌ لا | ❌ لا | ❌ لا | ✅ نعم | ✅ نعم | ✅ نعم | ❌ لا |
| مقاومة الكم (Quantum Resistance) | ✅ نعم | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ❌ لا |
| قابلية التحقق (Verifiability) | ✅ (SMP) | ✅ (Tapir) | ✅ (Onion E2EE) | ✅ (OMEMO) | ⚠️ ضعيف | ✅ (OMEMO) | ⚠️ غير مدقق | ✅ | ✅ | ❌ ضعيف |
| الإنكار المعقول(Deniability) | ✅ (SMP) | ✅ (Tapir) | ❌ لا | ✅ (OMEMO) | ❌ لا | ✅ (OMEMO) | ❌ لا | ❌ لا | ❌ لا | ❌ لا |
| حشو الرسائل (Message Padding) | ✅ نعم | ✅ نعم | ❓ غير معروف | ✅ (OMEMO) | ❓ غير معروف | ✅ (OMEMO) | ❓ غير معروف | ❓ غير معروف | ❓ غير معروف | ❌ لا |
| 🔹 خصائص أمان إضافية | ||||||||||
| Perfect Forward Secrecy | ✅ (SMP) | ✅ (Tor) | ✅ (Tor) | ✅ (OMEMO) | ❌ ضعيف | ✅ (OMEMO) | ⚠️ (V2 ديسمبر 2025) | ✅ | ✅ | 🟡 جزئي |
| مقاومة البيانات الوصفية | 🟢 ممتاز (معرفات مؤقتة) | 🟢 ممتاز | 🟢 ممتاز | 🔴 ضعيف | 🔴 ضعيف | 🔴 ضعيف | 🟡 جيد | 🔴 ضعيف (رقم هاتف) | 🟢 ممتاز | 🔴 ضعيف جداً |
| 🔹 خصائص تقنية | ||||||||||
| مفتوح المصدر | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | 🟡 العميل فقط |
| لغة برمجة آمنة ذاكرياً | ✅ (Haskell, Kotlin) | ✅ (Go, Rust) | ✅ (Python) | ✅ (Python) | 🟡 جزئي | 🟡 جزئي | 🟡 جزئي | 🟡 جزئي | 🟡 جزئي | 🟡 جزئي |
| تدقيق أمني مستقل | ✅ (Trail of Bits: 2022, 2024) | ❌ لم يتم بعد | ✅ (Radically Open Security: 2021) | 🟡 البروتوكول فقط (2016) | 🟡 البروتوكول فقط | 🟡 البروتوكول فقط (2016) | ❌ لم يتم | ✅ | ❌ غير معروف | ❌ غير معروف |
| توقيع الإصدارات | ✅ | ❓ غير معروف | ✅ | ❓ غير معروف | ❓ غير معروف | ❓ غير معروف | ❓ غير معروف | ✅ | ❓ غير معروف | ❓ غير معروف |
| البناء القابل للتكرار | ✅ | ✅ | ❌ لا | ✅ | ❓ غير معروف | ✅ | ❓ غير معروف | ❓ غير معروف | ❓ غير معروف | ❌ لا |
| 🔹 خصائص الاستخدام | ||||||||||
| يتطلب رقم هاتف | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ❌ لا | ✅ مطلوب | ❌ لا | ✅ مطلوب |
| يتطلب اتصالاً متزامناً | ❌ | ✅ (للمحادثات الخاصة) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ (صندوق بريد) | ❌ |
| حدود حجم الملفات | غير محدد | غير محدد | ✅ غير محدود | حسب الخادم | حسب الخادم | حسب الخادم | غير محدد | 100MB | غير محدد | 2GB |
| يعمل بدون إنترنت (شبكة محلية) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ (Bluetooth/Wi-Fi) | ❌ |
| يدعم iOS | ✅ | ❌ (Android/Linux فقط) | ❌ (Desktop فقط) | ❌ (Linux فقط) | ✅ | ✅ | ✅ | ✅ | ❌ (Android فقط) | ✅ |
| 🔹 التوصية النهائية | ||||||||||
| التوصية الأمنية في Whonix | ⭐ الخيار الأمثل للمراسلة المجهولة | ⭐ ممتاز للخصوصية القصوى (بدون تدقيق) | ⭐ للمشاركة الآمنة والمحادثة المؤقتة | ⚠️ للمحترفين (يعتمد على خادم) | ⚠️ بحذر (مشاكل forward secrecy) | ⚠️ بحذر (يعتمد على خادم) | ❌ غير موصى به (مشاكل أمنية) | ❌ غير موصى به (رقم هاتف إلزامي) | ❌ غير موصى به (Tor-over-Tor) | ❌ غير موصى به لأي غرض خاص |
❌ تطبيقات غير موصى بها في Whonix: Signal (رقم هاتف إلزامي)، Session (مشاكل أمنية وغياب PFS)، Briar (تعارض Tor-over-Tor)، Telegram (تشفير جزئي وخوادم مركزية)، Matrix/Element (مشاكل forward secrecy وتسريب بيانات وصفية).
أنت ← → [خادم مركزي] ← → صديقك⚠️ الخادم يرى من تتواصل معه ومتى
أنت ← [خادمك] ← → [خادم صديقك] → صديقك⚠️ الخادمان يعرفان من تتواصل معه
أنت ← ← [شبكة Tor] → → صديقك✅ لا يوجد خادم وسيط يراقب
أنت → [قناة ١] → [خادم] → [قناة ٢] → صديقك✅ الخادم لا يعرف الطرفين معاً، معرفات مؤقتة
لا يوجد تطبيق واحد يفعل كل شيء. الإستراتيجية المثلى هي استخدام التطبيق المناسب لكل مهمة:
SimpleX Chat هو تطبيق مراسلة لامركزي وآمن، لا يعتمد على معرفات المستخدمين، ويوفر أعلى مستويات الخصوصية. تم اختباره ويعمل بشكل ممتاز في Whonix و Qubes OS دون الحاجة لإعدادات معقدة.
هذه هي الطريقة الوحيدة التي تمكّن عزل الدوائر (Isolate Circuits) وإظهار خيار عناوين .onion داخل SimpleX. بدونها، يبقى اتصالك يمر عبر Tor ولكن دون مزايا الخصوصية المتقدمة هذه. يوفر Whonix وكيل SOCKS تلقائياً على المنفذ 9050.
127.0.0.1 أوlocalhost 9050 للوصول لهذه الإعدادات: فعّل Developer tools من الإعدادات ← About، ثم ارجع إلى Network & Servers ← Advanced network settings.
App session: لا يوجد عزل. جميع ملفاتك الشخصية تتشارك نفس جلسة التطبيق ودائرة Tor (أداء أعلى، خصوصية أقل).Chat profile (موصى به): يمنح كل ملف شخصي دائرة Tor مستقلة، مما يمنع الخوادم ومراقبي الشبكة من رؤية أن حركة المرور قادمة من نفس الجهاز .Servers (تجريبي BETA): يمنح كل خادم (جهة اتصال/مجموعة) دائرة Tor مستقلة. ⚠️ لا يُنصح به للمجموعات الكبيرة أو عدد جهات الاتصال الكبير لأنه قد يخلق حركة مرور كثيفة ويتجاوز حصة TCP sockets، كما أن إنشاء عدد كبير من دوائر Tor المنفصلة قد يكون بطيئاً جداً .Unprotected لمستخدمي Whonix (لأن Tor يخفي IP بالفعل).When IP hidden لمستخدمي Whonix (يضمن إخفاء IP دائماً مع السماح بالاتصال بالخوادم القديمة).هذا السكربت يجعل بيانات SimpleX محمولة في مجلد بجانب التطبيق. ملاحظة: بعد التشغيل، فعّل SOCKS Proxy يدوياً من داخل التطبيق حسب الخطوات أعلاه للاستفادة من عزل الدوائر وعناوين .onion.
cat > run-simplex.sh << 'EOF'
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PORTABLE_DIR="${SCRIPT_DIR}/simplex-chat-data"
APP_DIR="${SCRIPT_DIR}/simplex" # مجلد فرعي للثنائيات
mkdir -p "${APP_DIR}"
# 1️⃣ أولاً: البحث عن AppImage في المجلد الفرعي أو المستوى الأعلى
APPIMAGE_PATH=$(ls "${APP_DIR}"/simplex*.AppImage 2>/dev/null | head -1)
if [[ -z "${APPIMAGE_PATH}" ]]; then
APPIMAGE_PATH=$(ls "${SCRIPT_DIR}"/simplex*.AppImage 2>/dev/null | head -1)
fi
# 2️⃣ إذا لم يكن موجوداً، نتحقق من wget ثم نحمّله
if [[ -z "${APPIMAGE_PATH}" ]]; then
echo "📥 SimpleX غير موجود. سنحتاج إلى تحميله."
if ! command -v wget &> /dev/null; then
echo "⚠️ wget غير موجود. تثبيته الآن..."
sudo apt update && sudo apt install -y wget
echo "✅ تم تثبيت wget"
fi
echo "📥 جاري تحميل SimpleX..."
wget -c "https://github.com/simplex-chat/simplex-chat/releases/latest/download/simplex-desktop-x86_64.AppImage" \
-O "${APP_DIR}/simplex-desktop-x86_64.AppImage"
APPIMAGE_PATH="${APP_DIR}/simplex-desktop-x86_64.AppImage"
echo "✅ تم التحميل"
fi
# 3️⃣ التحقق النهائي من وجود الملف
if [[ ! -f "${APPIMAGE_PATH}" ]]; then
echo "❌ خطأ: لم يتم العثور على ملف AppImage بعد التحميل."
exit 1
fi
mkdir -p "${PORTABLE_DIR}"
chmod +x "${APPIMAGE_PATH}"
export XDG_CONFIG_HOME="${PORTABLE_DIR}/.config"
export XDG_DATA_HOME="${PORTABLE_DIR}/.local/share"
export XDG_CACHE_HOME="${PORTABLE_DIR}/.cache"
export HOME="${PORTABLE_DIR}"
echo "🚀 جاري تشغيل SimpleX Chat..."
echo "💡 تذكير: فعّل SOCKS Proxy من الإعدادات ← Network & Servers ← 127.0.0.1:9050"
exec "${APPIMAGE_PATH}" "$@"
EOF
chmod +x run-simplex.sh
Use .onion hosts يظهر ويعمل بكفاءة، مما يسمح بحصر الاتصالات داخل شبكة Tor فقط (عبر اختيار Required)، متجنباً بذلك هجمات عقد الخروج الضارة.لا تستخدم sudo مباشرة. استبدله بـ:
qvm-run -u root anon-whonix '<command>'
مثال: qvm-run -u root anon-whonix 'whonix_firewall'
Cwtch (يُنطق /kʊtʃ/) هو بروتوكول مراسلة لامركزي ومقاوم للبيانات الوصفية (Metadata)، مبني على شبكة Tor v3 Onion Services. تم تطويره بواسطة منظمة Open Privacy Research Society (كندا).
cwtch/ ├── cwtch # سكريبت التشغيل ├── lib/ │ ├── cwtch # الملف التنفيذي │ └── libcwtch.so ├── Tor/ ├── install.sh ├── install-home.sh ├── install-sys.sh ├── install-whonix.sh └── cwtch-whonix.yml
cat > run-cwtch-portable.sh << 'EOF'
#!/bin/sh
SCRIPT=$(realpath "$0")
SCRIPTPATH=$(dirname "$SCRIPT")
cd "$SCRIPTPATH"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$SCRIPTPATH/lib"
export CWTCH_HOME="${SCRIPTPATH}/cwtch-data"
export CWTCH_RESTRICT_PORTS=true
export CWTCH_BIND_EXTERNAL_WHONIX=true
exec ./lib/cwtch
EOF
chmod +x run-cwtch-portable.sh
1. على Whonix-Gateway (البوابة):
sudo onion-grater-add 40_cwtch
2. على Whonix-Workstation (محطة العمل):
sudo mkdir -p /etc/whonix_firewall.d/ echo 'EXTERNAL_OPEN_PORTS+=" $(seq 15000 15378) "' | sudo tee -a /etc/whonix_firewall.d/50_user.conf
ثم أعد تحميل جدار الحماية:
sudo whonix_firewall
3. داخل تطبيق Cwtch (بعد التشغيل لأول مرة):
90509051📌 لماذا؟ بدون إدخال هذه المنافذ، يحاول Cwtch تشغيل نسخته المدمجة من Tor داخل Workstation (وهو ما لا يعمل). بإدخالها، تخبره باستخدام Tor الخاص بـ Gateway مباشرة.
⚠️ بدون هذه الإعدادات الثلاثة، لن يتمكن Cwtch من الاتصال بشبكة Tor.
OnionShare أداة مفتوحة المصدر من Freedom of the Press Foundation تسمح بمشاركة الملفات أو استقبالها بشكل آمن ومجهول عبر شبكة Tor. الملفات تنتقل مباشرة من جهازك إلى جهاز المستلم دون المرور عبر أي خادم وسيط. يدعم أيضاً استضافة المواقع والمحادثة المجهولة.
.onion مؤقتة.onion# افتح الطرفية كـ root ونفّذ sudo onion-grater-add 40_onionshare # ⚠️ خطوة حرجة: تأكد من فك ضغط الملف إذا كان مضغوطاً sudo gunzip /usr/local/etc/onion-grater-merger.d/40_onionshare.yml.gz # للتحقق من نجاح العملية ls /usr/local/etc/onion-grater-merger.d/ # يجب أن ترى 40_onionshare.yml بدون .gz
# افتح المنافذ المطلوبة في جدار الحماية sudo mkdir -p /usr/local/etc/whonix_firewall.d echo 'EXTERNAL_OPEN_PORTS+=" $(seq 17600 17659) "' | sudo tee -a /usr/local/etc/whonix_firewall.d/50_user.conf sudo whonix_firewall # شغّل OnionShare onionshare
| المعيار | 🧅 OnionShare | 📱 Signal | ☁️ Google Drive |
|---|---|---|---|
| مكان تخزين الملف | ✅ جهازك فقط | 🟡 خوادم Signal (مؤقتاً) | ❌ خوادم جوجل |
| حجم الملفات | ✅ غير محدود | 🟡 100MB | ✅ كبير جداً |
| تسجيل البيانات | ✅ لا يوجد | 🟡 الحد الأدنى | ❌ يسجل كل شيء |
| المحادثة المجهولة | ✅ مدعومة | 🟡 مراسلة فقط | ❌ غير مدعومة |
| التوصية للصحافة | ⭐ مثالي للملفات الكبيرة | 🟡 جيد للمراسلة السريعة | ❌ غير آمن |
XMPP هو بروتوكول مفتوح ولامركزي للمراسلة الفورية. يدعم تشفيراً قوياً من طرف إلى طرف عبر OMEMO، ولا يتطلب رقم هاتف للتسجيل. اختر خادماً موثوقاً مثل conversations.im.
🔒 الخصوصية: محتوى الرسائل مشفر بالكامل. لكن حماية البيانات الوصفية ضعيفة، حيث يمكن مراقبة من يتواصل مع من (social graph).
لا يتطلب Gajim إعدادات إضافية في البوابة - يعمل مباشرة عبر Tor النظام. يجب ضبط إعدادات الوكيل (Proxy) يدوياً.
sudo apt update sudo apt install gajim gajim-httpupload -y
cat > run-gajim-portable.sh << 'EOF'
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PORTABLE_DIR="${SCRIPT_DIR}/gajim-data"
mkdir -p "$PORTABLE_DIR"
CONFIG_FILE="${PORTABLE_DIR}/config"
if [ ! -f "$CONFIG_FILE" ]; then
echo "[global]" > "$CONFIG_FILE"
echo "use_keyring = False" >> "$CONFIG_FILE"
fi
if ! command -v gajim &> /dev/null; then
echo "❌ Gajim غير مثبت"
exit 1
fi
gajim -c "$PORTABLE_DIR" &
EOF
chmod +x run-gajim-portable.sh
Matrix هو بروتوكول مفتوح ولامركزي للتواصل الفوري يعتمد على نموذج "الخادم-الخادم" (Federation). حسب صفحة Whonix الرسمية، عليه تحفظات أمنية خطيرة:
حسب توصية Whonix الرسمية، استخدم extrepo لإضافة مستودع Element بأمان:
# الطريقة الموصى بها من Whonix sudo extrepo enable element.io sudo apt update && sudo apt full-upgrade sudo apt install --no-install-recommends element-desktop
هذا السكريبت يجعل Element محمولاً بحيث يحفظ جميع الإعدادات والمحادثات ومفاتيح التشفير داخل مجلد Element-Data على الفلاشة.
cat > run-element-portable.sh << 'EOF'
#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PORTABLE_DATA_DIR="${SCRIPT_DIR}/Element-Data"
mkdir -p "${PORTABLE_DATA_DIR}"
if ! command -v element-desktop &> /dev/null; then
echo "❌ Element غير مثبت"
exit 1
fi
element-desktop --profile-dir="${PORTABLE_DATA_DIR}" &
EOF
chmod +x run-element-portable.sh
هذه الطريقة تُثبّت Signal في قالب Whonix نفسه، مما يجعله متاحاً لجميع الـ AppVMs المشتقة منه.
# 0. تثبيت المتطلبات الأساسية sudo apt update > /dev/null 2>&1 sudo apt install wget gnupg -y > /dev/null 2>&1 # 1. تثبيت مفتاح التوقيع الرسمي wget -O- https://updates.signal.org/desktop/apt/keys.asc 2> /dev/null | gpg --dearmor > signal-desktop-keyring.gpg cat signal-desktop-keyring.gpg | sudo tee /usr/share/keyrings/signal-desktop-keyring.gpg > /dev/null # 2. إضافة المستودع الرسمي إلى قائمة المصادر wget -O signal-desktop.sources https://updates.signal.org/static/desktop/apt/signal-desktop.sources 2> /dev/null cat signal-desktop.sources | sudo tee /etc/apt/sources.list.d/signal-desktop.sources > /dev/null # 3. تحديث قاعدة البيانات وتثبيت Signal sudo apt update > /dev/null 2>&1 sudo apt install signal-desktop -y
✅ بعد التثبيت، أعد إغلاق الشبكة عن القالب. لتشغيله في الـ AppVM: signal-desktop.
هذه الطريقة لا تمس القالب نهائياً ولا تحتاج لفتح أي شبكة (شبكة الكيوب مفتوحة أصلاً عبر Tor). يتم تحميل ملف AppImage وتشغيله مباشرة داخل الـ AppVM المعزول.
cat > run-signal.sh << 'EOF'
#!/bin/bash
set -e
cd "$(dirname "$0")"
SCRIPT_DIR="$(pwd)"
# البحث عن AppImage
APPIMAGE=$(find "$SCRIPT_DIR" -maxdepth 1 -iname "signal*.AppImage" -type f 2>/dev/null | head -1)
# إذا لم يوجد: تثبيت wget (إن لزم) ثم تحميل النسخة المستقرة الرسمية
if [ -z "$APPIMAGE" ]; then
command -v wget &>/dev/null || { echo "⚠️ تثبيت wget..."; sudo apt update && sudo apt install -y wget; }
echo "📥 تحميل Signal AppImage (الإصدار المستقر)..."
wget -qc --show-progress -O "$SCRIPT_DIR/signal-desktop.AppImage" "https://updates.signal.org/desktop/signal-desktop.AppImage"
APPIMAGE="$SCRIPT_DIR/signal-desktop.AppImage"
else
APPIMAGE="$(basename "$APPIMAGE")"
fi
# تأكيد الوجود + صلاحيات التنفيذ
[ -f "$SCRIPT_DIR/$APPIMAGE" ] || { echo "❌ لم يعثر على AppImage"; exit 1; }
chmod +x "$SCRIPT_DIR/$APPIMAGE"
# البيئة المحمولة (جميع الإعدادات تُحفظ داخل مجلد السكربت)
[ -d "$SCRIPT_DIR/Signal.AppImage.home" ] || "$SCRIPT_DIR/$APPIMAGE" --appimage-portable-home
[ -d "$SCRIPT_DIR/Signal.AppImage.config" ] || "$SCRIPT_DIR/$APPIMAGE" --appimage-portable-config
echo "🚀 تشغيل Signal داخل الكيوب..."
exec "$SCRIPT_DIR/$APPIMAGE" "$@"
EOF
chmod +x run-signal.sh
sudo (عدا تثبيت wget داخل الكيوب مرة واحدة).إذا فضّلت طريقة APT في القالب، يمكنك استخدام هذا السكربت داخل الـ AppVM لحفظ البيانات محلياً في مجلد منفصل.
cat > run-signal-portable.sh << 'EOF'
#!/bin/bash
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PORTABLE_DIR="${SCRIPT_DIR}/signal-data"
mkdir -p "$PORTABLE_DIR"
if ! command -v signal-desktop &> /dev/null; then
echo "❌ Signal غير مثبت في القالب. نفّذ أوامر APT أولاً."
exit 1
fi
echo "🚀 تشغيل Signal ببيئة محمولة داخل الكيوب..."
echo "📁 البيانات تُحفظ في: $PORTABLE_DIR"
signal-desktop --user-data-dir="$PORTABLE_DIR" --password-store="basic" &
SIGNAL_PID=$!
while kill -0 $SIGNAL_PID 2>/dev/null; do
sleep 1
done
echo "✅ تم إغلاق Signal."
exit 0
EOF
chmod +x run-signal-portable.sh
لا يتطلب إعدادات إضافية - يعمل مباشرة عبر شبكة Oxen.
cat > run-session.sh << 'EOF'
#!/bin/bash
set -e
cd "$(dirname "$0")"
SCRIPT_DIR="$(pwd)"
# البحث عن AppImage
APPIMAGE=$(find "$SCRIPT_DIR" -maxdepth 1 -iname "session*.AppImage" -type f 2>/dev/null | head -1)
# إذا لم يوجد: تثبيت wget (إن لزم) ثم تحميل
if [ -z "$APPIMAGE" ]; then
command -v wget &>/dev/null || { echo "⚠️ تثبيت wget..."; sudo apt update && sudo apt install -y wget; }
echo "📥 تحميل Session..."
wget -qc --show-progress -O "$SCRIPT_DIR/Session.AppImage" "https://getsession.org/linux"
APPIMAGE="$SCRIPT_DIR/Session.AppImage"
else
APPIMAGE="$(basename "$APPIMAGE")"
fi
# تأكيد الوجود + صلاحيات التنفيذ
[ -f "$SCRIPT_DIR/$APPIMAGE" ] || { echo "❌ لم يعثر على AppImage"; exit 1; }
chmod +x "$SCRIPT_DIR/$APPIMAGE"
# البيئة المحمولة (إن لزم)
[ -d "$SCRIPT_DIR/Session.AppImage.home" ] || "$SCRIPT_DIR/$APPIMAGE" --appimage-portable-home
[ -d "$SCRIPT_DIR/Session.AppImage.config" ] || "$SCRIPT_DIR/$APPIMAGE" --appimage-portable-config
echo "🚀 تشغيل Session..."
exec "$SCRIPT_DIR/$APPIMAGE" "$@"
EOF
chmod +x run-session.sh
cat > run-telegram.sh << 'EOF'
#!/bin/bash
set -e
cd "$(dirname "$0")"
TELEGRAM_DIR="./Telegram"
TELEGRAM_BIN="$TELEGRAM_DIR/Telegram"
PORTABLE_FLAG_DIR="$TELEGRAM_DIR/TelegramForcePortable"
# 1. هل تيليجرام موجود أصلاً؟
if [[ ! -f "$TELEGRAM_BIN" ]]; then
echo "ℹ️ تيليجرام غير موجود، سنحتاج إلى تحميله."
# 2. هل أداة التحميل wget موجودة؟
if ! command -v wget &> /dev/null; then
echo "⚠️ wget غير موجودة. تثبيتها الآن..."
sudo apt update
sudo apt install -y wget
echo "✅ تم تثبيت wget."
else
echo "✅ wget موجودة مسبقاً."
fi
# 3. تحميل تيليجرام
echo "📥 جاري تحميل Telegram..."
wget -c --show-progress -O telegram.tar.xz "https://telegram.org/dl/desktop/linux"
mkdir -p "$TELEGRAM_DIR"
tar -xf telegram.tar.xz -C "$TELEGRAM_DIR" --strip-components=1
rm telegram.tar.xz
echo "✅ تم تثبيت تيليجرام."
else
echo "✅ تيليجرام موجود مسبقاً، لا داعي للتحميل."
fi
# 4. إنشاء مجلد ForcePortable (ضروري للتشغيل المحمول)
mkdir -p "$PORTABLE_FLAG_DIR"
echo "🚀 تشغيل Telegram (وضع محمول)..."
exec "$TELEGRAM_BIN" "$@"
EOF
chmod +x run-telegram.sh
حتى مع أقوى تطبيقات المراسلة، الصور والمستندات تحمل بيانات خفية تكشف عنك (GPS، نوع الكاميرا، اسم المؤلف، تاريخ الإنشاء).
mat2 document.pdf
مدمج في Whonix/Tails - ينشئ نسخة نظيفة
exiftool -all= -overwrite_original image.jpg
الأقوى - يدعم جميع الصيغ
dangerzone-cli file.pdf
للملفات المشبوهة - يحولها لصور آمنة
sudo apt install mat2 exiftool| فشل اتصال التطبيق عبر Tor | تأكد من تنفيذ sudo onion-grater-add في البوابة وفك ضغط ملفات .gz. جرب torsocks -i بدلاً من التشغيل المباشر. تأكد من أن Whonix-Gateway يعمل ومتصل بالإنترنت. |
| بطء شديد في المراسلة | طبيعي مع Tor. استخدم torsocks -i لعزل الدائرة قد يساعد. تجنب إرسال ملفات كبيرة جداً دفعة واحدة. |
| اختفاء المفاتيح بعد إعادة التشغيل | تأكد من توجيه بيانات التطبيق إلى المجلد المحمول الصحيح (cwtch-data/، simplex-chat-data/ إلخ). تأكد من صلاحيات المجلد باستخدام ls -la. |
| تطبيق AppImage لا يعمل | تأكد من تنفيذ chmod +x application.AppImage. جرب تشغيله من الطرفية لرؤية الأخطاء. تأكد من تثبيت fuse: sudo apt install fuse -y. |
| اختراق مشتبه به | أغلق التطبيق فوراً. احذف المجلد المحمول بالكامل. ابدأ من جديد مع تغيير جميع المعرفات. استخدم torsocks -i لدائرة جديدة تماماً. |
| خطأ "Permission denied" | تأكد من أن الفلاشة مهيأة بنظام ملفات يدعم الصلاحيات (ext4). أنظمة FAT32/NTFS لا تدعم chmod وقد تسبب مشاكل. |
USB/ ├── PortableApps/ │ ├── SimpleXChat/ │ │ ├── run-simplex-chat.sh │ │ ├── simplex-desktop-x86_64.AppImage │ │ └── simplex-chat-data/ │ ├── Cwtch/ │ │ ├── run-cwtch-portable.sh │ │ ├── lib/ │ │ │ └── cwtch │ │ ├── Tor/ │ │ └── cwtch-data/ │ ├── Signal/ ⚠️ غير آمن للمجهولية │ │ ├── run-signal-portable.sh │ │ └── signal-data/ │ ├── Session/ ⚠️ غير آمن │ │ ├── run-session.sh │ │ ├── Session.AppImage │ │ ├── Session.AppImage.home/ │ │ └── Session.AppImage.config/ │ ├── Element/ │ │ ├── run-element-portable.sh │ │ └── Element-Data/ │ ├── Gajim/ ⚠️ محمول جزئياً │ │ ├── run-gajim-portable.sh │ │ └── gajim-data/ │ └── Telegram/ ⚠️ غير آمن │ ├── run-telegram.sh │ └── Telegram/ │ ├── Telegram │ └── TelegramForcePortable/ ├── backups/ 📦 نسخ احتياطية │ └── backup-YYYYMMDD.tar.gz └── README.md
لحماية بياناتك المحمولة، قم بعمل نسخ احتياطية دورية:
# من مجلد USB الرئيسي tar -czf backups/backup-$(date +%Y%m%d).tar.gz PortableApps/*/simplex-chat-data PortableApps/*/cwtch-data PortableApps/*/Element-Data
# استخراج النسخة الاحتياطية tar -xzf backups/backup-YYYYMMDD.tar.gz
torsocks يفرض على أي تطبيق استخدام شبكة Tor، حتى لو كان لا يدعم الـ Proxy. لا يتطلب أي إعدادات في البوابة.
torsocks ./application.AppImage
torsocks -i ./application.AppImage
# تأكد من تثبيت curl أولاً which curl || sudo apt install curl -y torsocks curl https://check.torproject.org/api/ip
torsocks: يشارك الدائرة مع تطبيقات أخرى - قد يُربط نشاطكtorsocks -i: يفتح دائرة جديدة لكل أمر - يمنع الربط تماماً-i.gz في البوابة.
chmod +x auto-script.sh && ./auto-script.sh
#!/bin/bash
# ============================================================
# auto-script.sh - سكريبت تعزيز أمان Qubes OS (نسخة 2026)
# بعد المراجعة والتحقق من المصادر الرسمية
# ============================================================
# الحصول على المستخدم الحقيقي والمسارات
REAL_USER=$(logname 2>/dev/null || echo "$SUDO_USER" 2>/dev/null || echo "$USER")
REAL_HOME="/home/$REAL_USER"
DESKTOP_PATH="$REAL_HOME/Desktop"
R='\033[0;31m'; G='\033[0;32m'; Y='\033[1;33m'; B='\033[0;34m'; N='\033[0m'
ok() { echo -e "${G}✓ $1${N}"; }
info() { echo -e "${B}ℹ $1${N}"; }
warn() { echo -e "${Y}⚠ $1${N}"; }
err() { echo -e "${R}✗ $1${N}"; }
pause() { echo; read -p "اضغط Enter للمتابعة..."; }
BASE_TEMPLATE=$(qubes-prefs default_template)
menu() {
clear
echo "======"
echo " 🔒 تعزيز أمان Qubes OS + Kicksecure"
echo "======"
echo ""
echo "1) إعداد معلمات النواة (dom0 + VMs)"
echo "2) إعداد MAC Randomization + تعطيل IPv6"
echo "3) إنشاء بوابات Whonix"
echo "4) تثبيت Kicksecure + جعله الأساس"
echo "5) إنشاء سكريبتات RAM Pool"
echo "6) إنشاء سكريبت Amnesic Tmpfs"
echo "7) تشغيل Live Mode"
echo "8) 💀 أدوات التدمير (BusKill + الطوارئ)"
echo "9) 🛡️ تقوية تشفير قرص النظام (LUKS PBKDF)"
echo "10) إعداد توصيل تلقائي للأقراص في Whonix"
echo "11) تنفيذ الأقسام التلقائية (1 إلى 8)"
echo "0) خروج"
echo ""
read -p "اختر: " c
case $c in
1) kernel_opts_menu ;;
2) mac_random ;;
3) whonix_gws ;;
4) kicksecure ;;
5) ram_pool_scripts ;;
6) amnesic_script ;;
7) live_mode ;;
8) emergency_script ;;
9) luks_hardening ;;
10) whonix_auto_mount ;;
11) run_auto ;;
0) exit 0 ;;
*) menu ;;
esac
}
# ===================================================================
# القسم 1: إعداد معلمات النواة (النسخة المصححة والموثقة)
# ===================================================================
# ========
# 1. قائمة إعداد معلمات النواة (3 خيارات فقط)
# ========
kernel_opts_menu() {
clear
echo "======"
echo " ⚙️ إعداد معلمات النواة"
echo "======"
echo ""
echo "1) إعداد dom0 (GRUB + Secureblue sysctl)"
echo "2) إعداد جميع VMs (kernelopts)"
echo "3) استعادة GRUB من النسخة الاحتياطية"
echo "0) رجوع للقائمة الرئيسية"
echo ""
read -p "اختر: " c
case $c in
1) setup_kernel_opts_dom0 ;;
2) setup_kernel_opts_vms ;;
3) rollback_grub ;;
0) menu ;;
*) kernel_opts_menu ;;
esac
}
# ========
# 1أ. إعداد dom0 (GRUB + Secureblue sysctl)
# ========
setup_kernel_opts_dom0() {
clear
echo "=========================================="
echo " 🔧 إعداد dom0 (GRUB + Secureblue sysctl)"
echo "=========================================="
# ------------- الجزء 1: GRUB -------------
echo ""
echo "📌 الجزء الأول: إعداد معلمات GRUB"
echo ""
if [ ! -f /etc/default/grub ]; then
err "الملف /etc/default/grub غير موجود!"
pause
return 1
fi
# استخراج UUID بطرق متعددة
CURRENT_UUID=$(grep -oP 'rd\.luks\.uuid=luks-\K[a-f0-9-]+' /etc/default/grub 2>/dev/null)
if [ -z "$CURRENT_UUID" ]; then
CURRENT_UUID=$(sudo cryptsetup luksUUID $(findmnt -n -o SOURCE /) 2>/dev/null)
fi
if [ -z "$CURRENT_UUID" ]; then
err "لا يمكن استخراج UUID من GRUB الحالي"
echo ""
read -p "أدخل UUID يدوياً (بدون luks-): " CURRENT_UUID
[ -z "$CURRENT_UUID" ] && { err "لم يتم إدخال UUID"; pause; return 1; }
fi
ok "UUID: $CURRENT_UUID"
# إنشاء نسخة احتياطية
BACKUP_FILE="/etc/default/grub.backup.$(date +%Y%m%d_%H%M%S)"
sudo cp /etc/default/grub "$BACKUP_FILE"
ok "نسخة احتياطية: $BACKUP_FILE"
echo ""
echo "📋 معلمات dom0:"
echo ""
echo "┌─────────────────────────────────────────────────────────────┐"
echo "│ Xen معلمات: │"
echo "│ bootscrub=1 xen_scrub_pages=1 │"
echo "│ │"
echo "│ Linux معلمات: │"
echo "│ init_on_free=1 init_on_alloc=1 page_poison=1 │"
echo "│ lockdown=confidentiality module.sig_enforce=1 │"
echo "│ slab_nomerge vsyscall=none kernel.kptr_restrict=2 │"
echo "│ oops=panic debugfs=off quiet loglevel=0 spectre_v2=on │"
echo "│ page_alloc.shuffle=1 preempt=voluntary pti=on mds=full │"
echo "└─────────────────────────────────────────────────────────────┘"
echo ""
read -p "متابعة تطبيق معلمات GRUB؟ (y/n): " confirm
[[ "$confirm" != "y" && "$confirm" != "Y" ]] && { err "تم الإلغاء"; pause; return 0; }
# إنشاء ملف GRUB الجديد
cat > /tmp/grub_new << 'INNER_EOF'
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=false
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="rd.luks.uuid=UUID_PLACEHOLDER rd.lvm.lv=qubes_dom0/root rd.lvm.lv=qubes_dom0/swap plymouth.ignore-serial-consoles rhgb quiet init_on_free=1 init_on_alloc=1 page_poison=1 lockdown=confidentiality module.sig_enforce=1 slab_nomerge vsyscall=none kernel.kptr_restrict=2 oops=panic debugfs=off loglevel=0 spectre_v2=on page_alloc.shuffle=1 preempt=voluntary pti=on mds=full"
GRUB_DISABLE_RECOVERY="true"
GRUB_THEME="/boot/grub2/themes/qubes/theme.txt"
GRUB_CMDLINE_XEN_DEFAULT="console=none dom0_mem=min:1024M dom0_mem=max:8192M ucode=scan bootscrub=1 xen_scrub_pages=1 gnttab_max_frames=2048 gnttab_max_maptrack_frames=4096"
GRUB_DISABLE_OS_PROBER="true"
GRUB_CMDLINE_LINUX="$GRUB_CMDLINE_LINUX rd.qubes.hide_all_usb"
INNER_EOF
sed -i "s/UUID_PLACEHOLDER/luks-$CURRENT_UUID/" /tmp/grub_new
sudo cp /tmp/grub_new /etc/default/grub
rm /tmp/grub_new
info "جاري تحديث GRUB..."
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
if [ $? -eq 0 ]; then
ok "تم تحديث GRUB بنجاح"
else
err "فشل تحديث GRUB! استعادة النسخة الاحتياطية..."
sudo cp "$BACKUP_FILE" /etc/default/grub
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
pause
return 1
fi
# ------------- الجزء 2: Secureblue sysctl -------------
echo ""
echo "📌 الجزء الثاني: إعداد Secureblue sysctl (طبقة حماية إضافية)"
echo ""
read -p "هل تريد تطبيق إعدادات Secureblue sysctl؟ (y/n): " confirm_sysctl
if [[ "$confirm_sysctl" == "y" || "$confirm_sysctl" == "Y" ]]; then
if [ -f /etc/sysctl.d/99-qubes-hardening.conf ]; then
sudo cp /etc/sysctl.d/99-qubes-hardening.conf /etc/sysctl.d/99-qubes-hardening.conf.backup.$(date +%Y%m%d_%H%M%S)
ok "نسخة احتياطية لـ sysctl"
fi
sudo tee /etc/sysctl.d/99-qubes-hardening.conf << 'EOF'
# Secureblue Hardening for Qubes dom0
# المصدر: https://github.com/secureblue/secureblue
# منع تفريغ الذاكرة عند الوصول الفيزيائي (SysRq)
kernel.sysrq=0
# تقييد الوصول إلى أدوات المراقبة (يمنع القنوات الجانبية)
kernel.perf_event_paranoid=3
# إخفاء عناوين النواة (يصعّب استغلال KASLR)
kernel.kptr_restrict=2
# إعادة تشغيل تلقائي بعد 5 ثوانٍ من الانهيار
kernel.panic=5
# تقييد تسجيل console (يقلل تسرب البيانات)
kernel.printk=3 3 3 3
# منع تحميل نواة بديلة (يمنع الاستمرارية)
kernel.kexec_load_disabled=1
# تعطيل io_uring تماماً (يمنع rootkits)
kernel.io_uring_disabled=2
# حماية الملفات العادية من هجمات Symlink
fs.protected_regular=2
# حماية الـ FIFOs من تصعيد الصلاحيات
fs.protected_fifos=2
# منع المستخدمين العاديين من قراءة dmesg
kernel.dmesg_restrict=1
# تعطيل eBPF لغير المتميزين
kernel.unprivileged_bpf_disabled=1
# تحديد الحد الأقصى لتعيينات الذاكرة
vm.max_map_count=1048576
# تعطيل core dumps
fs.suid_dumpable=0
EOF
sudo sysctl --system
ok "تم تطبيق Secureblue sysctl"
else
info "تم تخطي Secureblue sysctl"
fi
echo ""
warn "⚠️ التغييرات لن تفعّل إلا بعد إعادة التشغيل"
echo ""
echo "📋 للتحقق من التطبيق بعد إعادة التشغيل، استخدم:"
echo " cat /proc/cmdline | grep -E 'init_on_free|pti'"
echo " sysctl kernel.sysrq kernel.perf_event_paranoid"
echo ""
read -p "إعادة التشغيل الآن؟ (y/n): " reboot_choice
[[ "$reboot_choice" == "y" || "$reboot_choice" == "Y" ]] && sudo reboot
pause
}
# ========
# 1ب. إضافة معلمات النواة لجميع الـ VMs (النسخة النهائية)
# ========
setup_kernel_opts_vms() {
clear
echo "=========================================="
echo " 🔧 إعداد معلمات النواة لجميع الـ VMs"
echo "=========================================="
echo ""
# القائمة الكاملة
NEW_OPTS="xen_scrub_pages=1 init_on_free=1 init_on_alloc=1 page_poison=1 mitigations=auto random.trust_cpu=off random.trust_bootloader=off spec_store_bypass_disable=on tsx_async_abort=full mds=full,nosmt page_alloc.shuffle=1 randomize_kstack_offset=on l1tf=full,force ipv6.disable=1 slab_nomerge vsyscall=none retbleed=stuff spectre_v2_user=on kvm.nx_huge_pages=force"
read -p "تطبيق المعلمات على جميع VMs؟ (y/n): " confirm
[[ "$confirm" != "y" && "$confirm" != "Y" ]] && { info "تم الإلغاء"; return; }
info "إغلاق VMs..."
sudo qvm-shutdown --all 2>/dev/null
sleep 3
local APPLIED_COUNT=0
# تطبيق المعلمات على الكل ما عدا dom0
for vm in $(qvm-ls --raw-list 2>/dev/null); do
vm_clean=$(echo "$vm" | tr -d '[:space:]')
[ "$vm_clean" = "dom0" ] && continue
if qvm-prefs "$vm_clean" kernelopts "$NEW_OPTS" 2>/dev/null; then
echo " ✅ $vm_clean: تم التطبيق"
((APPLIED_COUNT++))
else
warn " ❌ $vm_clean: فشل"
fi
done
echo ""
ok "✅ تم تطبيق المعلمات على $APPLIED_COUNT VM"
# تصفير البوابات الخاصة
echo ""
info "🧹 تصفير kernelopts لبوابات Whonix..."
for gw in $(qvm-ls --raw-list 2>/dev/null | grep -E 'sys-whonix|whonix-gateway'); do
gw_clean=$(echo "$gw" | tr -d '[:space:]')
if qvm-prefs "$gw_clean" kernelopts "" 2>/dev/null; then
echo " 🧹 $gw_clean: تم التصفير (kernelopts=\"\")"
else
warn " ❌ $gw_clean: فشل التصفير"
fi
done
echo ""
info "إعادة تشغيل الخدمات الأساسية..."
for vm in sys-net sys-firewall sys-usb; do
qvm-start "$vm" 2>/dev/null && echo " 🔄 $vm: تم التشغيل"
done
# تفعيل ephemeral_volatile
echo ""
echo "╔═══════════════════════════════════════════════════════════════╗"
echo "║ 💧 تفعيل ephemeral_volatile ║"
echo "╠═══════════════════════════════════════════════════════════════╣"
echo "║ يتم تفعيل التشفير العابر للـ volatile volume ║"
echo "╚═══════════════════════════════════════════════════════════════╝"
echo ""
info "تفعيل ephemeral_volatile على الـ pools..."
for pool in vm-pool varlibqubes; do
if qvm-pool ls 2>/dev/null | grep -q "$pool"; then
qvm-pool set "$pool" -o ephemeral_volatile=True 2>/dev/null && \
ok "تم تفعيل ephemeral_volatile على $pool" || \
warn "فشل تفعيل ephemeral_volatile على $pool"
else
warn "الـ pool $pool غير موجود، تخطي"
fi
done
ok "تم تفعيل ephemeral_volatile على $EPHEMERAL_COUNT VM"
echo ""
ok "✅ اكتمل إعداد معلمات VMs بنجاح!"
pause
}
# ========
# 1ج. استعادة GRUB من النسخة الاحتياطية
# ========
rollback_grub() {
clear
echo "======"
echo " 🔄 استعادة GRUB من النسخة الاحتياطية"
echo "======"
echo ""
echo "📁 النسخ الاحتياطية المتوفرة:"
ls -la /etc/default/grub.backup.* 2>/dev/null | head -5 || { err "لا توجد نسخ احتياطية"; pause; return 1; }
echo ""
read -p "أدخل اسم ملف النسخة الاحتياطية (أو Enter لأحدث نسخة): " backup_name
if [ -z "$backup_name" ]; then
backup_name=$(ls -t /etc/default/grub.backup.* 2>/dev/null | head -1)
else
backup_name="/etc/default/$backup_name"
fi
[ ! -f "$backup_name" ] && { err "الملف غير موجود"; pause; return 1; }
sudo cp "$backup_name" /etc/default/grub
ok "تم استعادة الملف"
sudo grub2-mkconfig -o /boot/grub2/grub.cfg
ok "تم تحديث GRUB"
read -p "إعادة التشغيل الآن؟ (y/n): " reboot_choice
[[ "$reboot_choice" == "y" || "$reboot_choice" == "Y" ]] && sudo reboot
pause
}
# ========
# 2. MAC Randomization + تعطيل IPv6 + إغلاق القالب
# ========
mac_random() {
info "إعداد MAC Randomization: $BASE_TEMPLATE"
info "التحقق من إعدادات IPv6 لـ sys-net و sys-firewall..."
for vm in sys-net sys-firewall; do
if qvm-ls "$vm" >/dev/null 2>&1; then
CURRENT_OPTS=$(qvm-prefs "$vm" kernelopts 2>/dev/null | xargs)
if [[ "$CURRENT_OPTS" == *"ipv6.disable=1"* ]]; then
warn "⚠️ $vm: IPv6 معطل بالفعل"
else
info "🔧 $vm: جاري تعطيل IPv6..."
qvm-prefs "$vm" kernelopts "$CURRENT_OPTS ipv6.disable=1"
ok "✅ تم تعطيل IPv6 لـ $vm"
fi
else
warn "$vm غير موجود، تخطي"
fi
done
if qvm-ls "$BASE_TEMPLATE" >/dev/null 2>&1; then
info "🔧 إعداد MAC Randomization في $BASE_TEMPLATE..."
qvm-run "$BASE_TEMPLATE" "sudo bash -c 'mkdir -p /usr/lib/NetworkManager/conf.d/ && cat > /usr/lib/NetworkManager/conf.d/31-randomize-mac.conf << EOF
[connection]
ethernet.cloned-mac-address=random
wifi.cloned-mac-address=random
wifi.scan-rand-mac-address=yes
EOF'"
ok "✅ تم إعداد MAC Randomization في $BASE_TEMPLATE"
info "إغلاق القالب $BASE_TEMPLATE..."
qvm-shutdown "$BASE_TEMPLATE" 2>/dev/null || true
ok "تم إغلاق $BASE_TEMPLATE"
else
warn "القالب $BASE_TEMPLATE غير موجود، تخطي إعداد MAC"
fi
info "ملاحظة: قد تحتاج إلى إعادة تشغيل الأجهزة المبنية على هذا القالب"
pause
}
# ========
# 3. إنشاء بوابات Whonix
# ========
whonix_gws() {
for g in "sys-whonix-A:red" "sys-whonix-B:blue"; do
n=${g%:*}; l=${g#*:}
if ! qvm-ls | grep -q "$n"; then
qvm-create --class AppVM --label "$l" --template whonix-gateway-18 "$n"
qvm-prefs "$n" provides_network true
ok "تم إنشاء $n"
else
info "$n موجود بالفعل، تخطي"
fi
done
pause
}
# ========
# 4. تثبيت Kicksecure + جعله الأساس + إعدادات متقدمة (مصحح لـ Qubes)
# ========
kicksecure() {
clear
echo "=========================================="
echo " 🔒 تثبيت وتكوين Kicksecure 18 لـ Qubes OS"
echo "=========================================="
echo ""
echo "📌 ملاحظة: في Qubes OS، القوالب تشارك نواة dom0."
echo " سيتم تطبيق تقوية المستخدم (userspace) فقط داخل القالب."
echo " يجب ضبط معاملات النواة عبر kernelopts أو GRUB."
echo ""
info "التحقق من وجود قالب Kicksecure 18..."
if qvm-ls | grep -q kicksecure-18; then
ok "قالب Kicksecure 18 موجود مسبقاً"
info "تخطي مرحلة التثبيت..."
else
info "قالب Kicksecure 18 غير موجود، جاري التثبيت..."
qvm-template --enablerepo qubes-templates-community install kicksecure-18
if ! qvm-ls | grep -q kicksecure-18; then
err "فشل تثبيت kicksecure-18"
pause
return
fi
ok "تم تثبيت Kicksecure-18 بنجاح"
fi
info "تثبيت الإضافات..."
sudo qubes-dom0-update --action=install -y qubes-core-admin-addon-kicksecure
info "إعادة تشغيل خدمة qubesd..."
sudo systemctl restart qubesd.service
ok "تم إعادة تشغيل qubesd.service"
info "تشغيل قالب Kicksecure 18..."
qvm-start kicksecure-18
local MAX_WAIT=30
local WAIT_COUNT=0
while ! qvm-check --running kicksecure-18 2>/dev/null; do
sleep 2
WAIT_COUNT=$((WAIT_COUNT + 1))
if [ $WAIT_COUNT -ge $MAX_WAIT ]; then
warn "القالب لم ينته من التشغيل، نكمل بحذر..."
break
fi
done
sleep 5
# 1. ضبط المنطقة الزمنية
info "ضبط المنطقة الزمنية إلى UTC..."
qvm-run kicksecure-18 "sudo timedatectl set-timezone Etc/UTC" 2>/dev/null || true
ok "تم ضبط المنطقة الزمنية"
# 2. تفعيل MAC Randomization
info "إعداد MAC Randomization..."
qvm-run kicksecure-18 "sudo bash -c 'mkdir -p /usr/lib/NetworkManager/conf.d/ && cat > /usr/lib/NetworkManager/conf.d/31-randomize-mac.conf << \"EOF\"
[connection]
ethernet.cloned-mac-address=random
wifi.cloned-mac-address=random
wifi.scan-rand-mac-address=yes
EOF'" 2>/dev/null || true
ok "تم تكوين MAC Randomization"
# 3. تعطيل الخدمات غير الضرورية
info "تعطيل الخدمات غير الضرورية..."
qvm-run kicksecure-18 "sudo systemctl mask bluetooth.service cups.service avahi-daemon.service ModemManager.service 2>/dev/null || true" 2>/dev/null || true
qvm-run kicksecure-18 "sudo systemctl disable --now NetworkManager-wait-online.service 2>/dev/null || true" 2>/dev/null || true
ok "تم تعطيل الخدمات غير الضرورية"
# 4. إزالة الحزم غير الضرورية
info "إزالة الحزم غير الضرورية..."
qvm-run kicksecure-18 "sudo apt remove -y --purge thunderbird hexchat transmission-common 2>/dev/null || true" 2>/dev/null || true
qvm-run kicksecure-18 "sudo apt autoremove -y 2>/dev/null || true" 2>/dev/null || true
ok "تمت إزالة الحزم غير الضرورية"
# 5. إغلاق القالب
info "إغلاق قالب Kicksecure 18..."
qvm-shutdown --wait kicksecure-18 2>/dev/null || true
ok "تم إغلاق Kicksecure-18"
# 6. إنشاء قالب DVM مقوّى (بدون rw False)
echo ""
echo "╔═══════════════════════════════════════════════════════════════╗"
echo "║ 🧬 إنشاء قالب DVM مقوّى (قالب عابر) ║"
echo "╚═══════════════════════════════════════════════════════════════╝"
echo ""
read -p "هل تريد إنشاء قالب DVM مقوّى من Kicksecure؟ (y/n): " create_dvm
if [[ "$create_dvm" == "y" || "$create_dvm" == "Y" ]]; then
info "إنشاء قالب DVM مقوّى..."
if ! qvm-ls kicksecure-18-dvm >/dev/null 2>&1; then
qvm-create --template kicksecure-18 --label red kicksecure-18-dvm
ok "✓ تم إنشاء kicksecure-18-dvm"
else
info "kicksecure-18-dvm موجود مسبقاً"
fi
qvm-prefs kicksecure-18-dvm template_for_dispvms true
# تم حذف: qvm-volume config kicksecure-18-dvm:root rw False
qvm-prefs kicksecure-18-dvm kernelopts "init_on_free=1 init_on_alloc=1 page_poison=1 slab_nomerge"
ok "✓ تم تعيين kicksecure-18-dvm كـ DVM مقوّى"
read -p "هل تريد جعله الـ default-dvm؟ (y/n): " make_default
if [[ "$make_default" == "y" || "$make_default" == "Y" ]]; then
qvm-prefs default-dvm template kicksecure-18-dvm
ok "✓ default-dvm يستخدم الآن kicksecure-18-dvm"
fi
fi
# 7. السؤال عن جعل Kicksecure القالب الافتراضي (يتضمن تعديل sys-usb)
echo ""
echo "╔═══════════════════════════════════════════════════════════════╗"
echo "║ 🎯 جعل Kicksecure 18 القالب الافتراضي لـ default-dvm ║"
echo "╚═══════════════════════════════════════════════════════════════╝"
echo ""
read -p "هل تريد جعل Kicksecure 18 الافتراضي لـ default-dvm؟ (y/n): " yn
if [[ "$yn" == "y" || "$yn" == "Y" ]]; then
BASE_TEMPLATE="kicksecure-18"
if ! qvm-ls --raw-list | grep -q "^$BASE_TEMPLATE$"; then
err "القالب $BASE_TEMPLATE غير موجود"
pause
return
fi
info "إيقاف الآلات المتأثرة..."
qvm-kill sys-* 2>/dev/null
qvm-kill default-dvm 2>/dev/null
info "تغيير قالب default-dvm..."
qvm-prefs default-dvm template "$BASE_TEMPLATE"
ok "✓ default-dvm يعمل الآن من Kicksecure 18"
echo ""
info "مسح kernelopts لـ sys-firewall و sys-net..."
qvm-prefs sys-firewall kernelopts "" 2>/dev/null
qvm-prefs sys-net kernelopts "" 2>/dev/null
ok "✓ تم مسح kernelopts للآلات المعنية"
echo ""
info "رفع إعدادات الذاكرة لـ sys-net و sys-firewall..."
qvm-prefs sys-net memory 800 2>/dev/null
qvm-prefs sys-net maxmem 800 2>/dev/null
qvm-prefs sys-firewall memory 800 2>/dev/null
qvm-prefs sys-firewall maxmem 800 2>/dev/null
ok "✓ تم رفع إعدادات الذاكرة"
# تعديل sys-usb فقط إذا وافق المستخدم على جعل Kicksecure افتراضياً
if qvm-ls sys-usb >/dev/null 2>&1; then
info "تعديل إعدادات sys-usb..."
qvm-prefs sys-usb memory 800 2>/dev/null
qvm-prefs sys-usb maxmem 800 2>/dev/null
qvm-start sys-usb 2>/dev/null || true
ok "✓ تم رفع ذاكرة sys-usb إلى 800MB"
fi
echo ""
info "تشغيل الآلات..."
qvm-start sys-net 2>/dev/null
qvm-start sys-firewall 2>/dev/null
sleep 5
sudo systemctl restart qubesd.service
ok "✓ اكتمل بنجاح"
fi
echo ""
echo "╔═══════════════════════════════════════════════════════════════╗"
echo "║ ✅ اكتمل إعداد Kicksecure! ║"
echo "╠═══════════════════════════════════════════════════════════════╣"
echo "║ 📋 تم تطبيق: ║"
echo "║ • المنطقة الزمنية UTC ║"
echo "║ • تفعيل MAC Randomization ║"
echo "║ • تعطيل الخدمات غير الضرورية ║"
echo "║ • إزالة الحزم غير الضرورية ║"
echo "║ ║"
echo "║ ⚠️ ملاحظة: يتم تطبيق معاملات النواة عبر: ║"
echo "║ • dom0: GRUB (التبويب 0 أو الخيار 1 من السكربت) ║"
echo "║ • الآلات: kernelopts (الخيار 2 من السكربت) ║"
echo "╚═══════════════════════════════════════════════════════════════╝"
echo ""
pause
}
# ========
# 5. سكريبتات RAM Pool
# ========
ram_pool_scripts() {
mkdir -p "$DESKTOP_PATH/ram-pool-scripts"
echo 'org.gnome.DiskUtility.desktop
janondisttorbrowser.desktop
pcmanfm-qt.desktop
qterminal.desktop
anondist-torbrowser_update.desktop' | qvm-appmenus --set-default-whitelist - whonix-workstation-18
qvm-appmenus --update whonix-workstation-18
echo "✅ تم تعيين Disks (org.gnome.DiskUtility.desktop) افتراضياً - تأكد من تثبيتها"
# ========== setup-ram-pool.sh ==========
cat > "$DESKTOP_PATH/ram-pool-scripts/setup-ram-pool.sh" << 'EOF'
#!/bin/bash
RAM_POOL_PATH="$HOME/ram_pool"
RAM_POOL_SIZE="4G"
sudo mkdir -p "$RAM_POOL_PATH"
sudo mount -t tmpfs -o size=$RAM_POOL_SIZE tmpfs "$RAM_POOL_PATH"
if ! qvm-pool ls | grep -q ram_pool; then
qvm-pool add ram_pool file -o dir_path="$RAM_POOL_PATH"
fi
qvm-pool set ram_pool -o ephemeral_volatile=True
echo "✅ RAM pool جاهز مع ephemeral_volatile مفعل"
EOF
# ========== setup-ram-pool.sh ==========
cat > "$DESKTOP_PATH/ram-pool-scripts/setup-ram-pool.sh" << 'EOF'
#!/bin/bash
RAM_POOL_PATH="$HOME/ram_pool"
RAM_POOL_SIZE="4G"
sudo mkdir -p "$RAM_POOL_PATH"
sudo mount -t tmpfs -o size=$RAM_POOL_SIZE tmpfs "$RAM_POOL_PATH"
if ! qvm-pool ls | grep -q ram_pool; then
qvm-pool add ram_pool file -o dir_path="$RAM_POOL_PATH"
fi
qvm-pool set ram_pool -o ephemeral_volatile=True
echo "✅ RAM pool جاهز مع ephemeral_volatile مفعل"
EOF
# ========== create-ram-vm.sh (فردي - بدون توصيل تلقائي) ==========
cat > "$DESKTOP_PATH/ram-pool-scripts/create-ram-vm.sh" << 'SCRIPT_EOF'
#!/bin/bash
# create-ram-vm.sh - إنشاء whonix-work-ram
set -e
GATEWAY="sys-whonix"
WORKSTATION="whonix-work-ram"
TEMPLATE="whonix-workstation-18"
RAM_PATH="$HOME/ram_pool"
KERNEL_OPTS="xen_scrub_pages=1 init_on_free=1 init_on_alloc=1 page_poison=1 mitigations=auto random.trust_cpu=off random.trust_bootloader=off spec_store_bypass_disable=on tsx_async_abort=full mds=full,nosmt page_alloc.shuffle=1 randomize_kstack_offset=on l1tf=full,force ipv6.disable=1 slab_nomerge vsyscall=none retbleed=stuff spectre_v2_user=on kvm.nx_huge_pages=force"
# 1. RAM pool
if ! mount | grep -q "$RAM_PATH"; then
sudo mkdir -p "$RAM_PATH"
sudo mount -t tmpfs -o size=4G tmpfs "$RAM_PATH"
qvm-pool add ram_pool file -o dir_path="$RAM_PATH" 2>/dev/null || true
qvm-pool set ram_pool -o ephemeral_volatile=True 2>/dev/null || true
fi
# 2. إنشاء VM
qvm-kill "$WORKSTATION" 2>/dev/null || true
qvm-remove --force "$WORKSTATION" 2>/dev/null || true
qvm-create -P ram_pool -t "$TEMPLATE" -l red "$WORKSTATION"
qvm-prefs "$WORKSTATION" kernelopts "$KERNEL_OPTS"
echo "✅ تم إنشاء $WORKSTATION"
# 3. توصيل البوابة (اختياري - تأكد من وجودها)
qvm-prefs "$WORKSTATION" netvm "$GATEWAY" 2>/dev/null || echo "⚠️ تعذّر توصيل البوابة"
SCRIPT_EOF
chmod +x "$DESKTOP_PATH/ram-pool-scripts/create-ram-vm.sh"
# ========== mount-to-whonix.sh (توصيل + فصل آمن) ==========
cat > "$DESKTOP_PATH/ram-pool-scripts/mount-to-whonix.sh" << 'EOF'
#!/bin/bash
# mount-to-whonix.sh - توصيل/فصل الأقراص في Whonix VMs
set -e
MOUNT_POINT="/home/user/usb"
DEFAULT_DISK="xvdi"
G='\033[0;32m'; Y='\033[1;33m'; R='\033[0;31m'; N='\033[0m'
find_vm() {
mapfile -t VMS < <(qvm-ls --raw-list --running --template-source whonix-workstation-18 whonix-workstation-18-dvm | grep -v "^sys-whonix")
[ ${#VMS[@]} -eq 0 ] && { echo -e "${R}❌ لا توجد كيوبات Whonix عاملة${N}"; exit 1; }
echo -e "${G}الكيوبات المتاحة:${N}"
for i in "${!VMS[@]}"; do echo -e " ${Y}[$((i+1))]${N} ${VMS[$i]}"; done
while true; do
read -p "اختر الرقم: " C
[[ "$C" =~ ^[0-9]+$ && $C -ge 1 && $C -le ${#VMS[@]} ]] && { TARGET="${VMS[$((C-1))]}"; break; }
echo -e "${R}خطأ${N}"
done
}
echo -e "\n${G}🔌 إدارة الأقراص${N}"
echo -e " [1] توصيل وتركيب\n [2] فصل آمن (umount + detach)\n [3] عرض الحالة\n [4] خروج"
read -p "اختر: " OP
case $OP in
1) # توصيل
find_vm
qvm-run --pass-io -u root "$TARGET" "lsblk -o NAME,SIZE,TYPE,MOUNTPOINT | head -20"
read -p "اسم القرص [$DEFAULT_DISK]: " DISK; DISK=${DISK:-$DEFAULT_DISK}
qvm-run --pass-io -u root "$TARGET" "test -b /dev/$DISK" || { echo -e "${R}❌ غير موجود${N}"; exit 1; }
qvm-run --pass-io -u root "$TARGET" "mkdir -p $MOUNT_POINT && mount /dev/$DISK $MOUNT_POINT && echo '✅ تم'" || echo -e "${R}❌ فشل${N}"
;;
2) # فصل آمن
find_vm
echo -e "${Y}الأجهزة المثبتة على $MOUNT_POINT:${N}"
qvm-run --pass-io -u root "$TARGET" "mount | grep $MOUNT_POINT" 2>/dev/null || echo -e "${Y}لا شيء مثبت${N}"
read -p "متابعة الفصل الكامل؟ (y/n): " CONFIRM
[[ "$CONFIRM" =~ ^[Yy] ]] || exit 0
# إلغاء التثبيت داخل VM
echo -e "${Y}جاري إلغاء التثبيت من VM...${N}"
qvm-run --pass-io -u root "$TARGET" "sync && umount $MOUNT_POINT 2>/dev/null" && echo -e "${G}✅ تم إلغاء التثبيت${N}" || echo -e "${Y}⚠️ غير مثبت أو فشل الإلغاء${N}"
# فصل جميع الأجهزة من dom0
echo -e "${Y}جاري فصل الأجهزة من dom0...${N}"
qvm-block list | grep "$TARGET" | while read -r line; do
DEVICE=$(echo "$line" | awk '{print $1}')
echo -e "فصل $DEVICE..."
qvm-block detach "$TARGET" "$DEVICE" 2>/dev/null && echo -e "${G}✅ $DEVICE مفصول${N}" || echo -e "${R}❌ فشل فصل $DEVICE${N}"
done
echo -e "${G}🎉 تم الفصل الكامل. يمكنك إعادة توصيل الجهاز لاحقاً وسيتولى المراقب تركيبه تلقائياً.${N}"
;;
3) # عرض الحالة
find_vm
echo -e "${Y}=== حالة الأجهزة ===${N}"
qvm-run --pass-io -u root "$TARGET" "lsblk -o NAME,SIZE,TYPE,MOUNTPOINT"
echo -e "\n${Y}=== حالة التثبيت ===${N}"
qvm-run --pass-io -u root "$TARGET" "mountpoint -q $MOUNT_POINT 2>/dev/null && echo '✅ مثبت' || echo '⚠️ غير مثبت'"
echo -e "\n${Y}=== الأجهزة المتصلة ===${N}"
qvm-block list | grep "$TARGET" || echo "لا توجد أجهزة متصلة"
;;
4) echo -e "${G}👋${N}"; exit 0 ;;
*) echo -e "${R}❌ خطأ${N}"; exit 1 ;;
esac
EOF
chmod +x "$DESKTOP_PATH/ram-pool-scripts/mount-to-whonix.sh"
# ========== apply-cwtch-onionshare.sh ==========
cat > "$DESKTOP_PATH/ram-pool-scripts/apply-cwtch-onionshare.sh" << 'EOF'
#!/bin/bash
# apply-cwtch-onionshare.sh - إعداد Cwtch و OnionShare على كيوب Whonix عامل
set -e
G='\033[0;32m'; Y='\033[1;33m'; R='\033[0;31m'; N='\033[0m'
echo -e "${G}🔧 تطبيق إعدادات Cwtch و OnionShare${N}"
# 1. البحث عن كيوبات Whonix العاملة (باستثناء sys-whonix)
mapfile -t VMS < <(qvm-ls --running --raw-list | grep -i whonix | grep -v sys-whonix)
if [ ${#VMS[@]} -eq 0 ]; then
echo -e "${R}❌ لا توجد كيوبات Whonix عاملة. شغّل whonix-work-ram أولًا.${N}"
exit 1
fi
echo -e "${G}الكيوبات المتاحة:${N}"
for i in "${!VMS[@]}"; do
echo -e " ${Y}[$((i+1))]${N} ${VMS[$i]}"
done
# 2. اختيار الكيوب
while true; do
read -p "👉 اختر رقم الكيوب لتطبيق الإعدادات عليه (1-${#VMS[@]}): " CHOICE
if [[ "$CHOICE" =~ ^[0-9]+$ ]] && [ "$CHOICE" -ge 1 ] && [ "$CHOICE" -le "${#VMS[@]}" ]; then
WORKSTATION="${VMS[$((CHOICE-1))]}"
break
else
echo -e "${R}❌ اختيار غير صحيح.${N}"
fi
done
GATEWAY=$(qvm-prefs "$WORKSTATION" netvm 2>/dev/null | cut -d'|' -f1 | tr -d '[:space:]')
if [ -z "$GATEWAY" ] || [ "$GATEWAY" = "None" ]; then
echo -e "${R}❌ $WORKSTATION لا يملك بوابة محددة.${N}"
exit 1
fi
echo -e "\n${Y}⚙️ سيتم تطبيق الإعدادات على:${N}"
echo -e " المحطة: ${G}$WORKSTATION${N}"
echo -e " البوابة: ${G}$GATEWAY${N}"
read -p "❓ متابعة؟ (y/n): " CONFIRM
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
echo -e "${R}تم الإلغاء.${N}"
exit 0
fi
# 3. إعداد البوابة (onion-grater)
echo -e "\n${Y}🔐 إضافة قواعد onion-grater على $GATEWAY ...${N}"
qvm-run --pass-io -u root "$GATEWAY" "onion-grater-add 40_cwtch && onion-grater-add 40_onionshare && systemctl restart onion-grater" && \
echo -e "${G}✅ تم إعداد onion-grater${N}" || echo -e "${R}❌ فشل إعداد onion-grater${N}"
# 4. إعداد محطة العمل (فتح المنافذ)
echo -e "\n${Y}📡 فتح المنافذ على $WORKSTATION ...${N}"
qvm-run --pass-io -u root "$WORKSTATION" "mkdir -p /usr/local/etc/whonix_firewall.d && echo 'EXTERNAL_OPEN_PORTS+=\" \$(seq 15000 15378) \$(seq 17600 17659) \"' >> /usr/local/etc/whonix_firewall.d/50_user.conf && whonix_firewall" && \
echo -e "${G}✅ تم فتح المنافذ وإعادة تحميل الجدار الناري${N}" || echo -e "${R}❌ فشل إعداد الجدار الناري${N}"
echo -e "\n${G}🎉 اكتملت إعدادات Cwtch و OnionShare${N}"
EOF
chmod +x "$DESKTOP_PATH/ram-pool-scripts/apply-cwtch-onionshare.sh"
# ========== create-multi-ram-vm.sh (متعدد - بدون توصيل تلقائي) ==========
cat > "$DESKTOP_PATH/ram-pool-scripts/create-multi-ram-vm.sh" << 'EOF'
#!/bin/bash
BASE_TEMPLATE="whonix-workstation-18"
VM_BASE="whonix-work-ram"
RAM_POOL_PATH="$HOME/ram_pool"
RAM_POOL_SIZE="4G"
SAVE_SCRIPT_PATH="$HOME/Desktop/qubes-auto-create.sh"
G='\033[0;32m'; Y='\033[1;33m'; R='\033[0;31m'; B='\033[0;34m'; N='\033[0m'
KERNEL_OPTS="xen_scrub_pages=1 init_on_free=1 init_on_alloc=1 page_poison=1 mitigations=auto random.trust_cpu=off random.trust_bootloader=off spec_store_bypass_disable=on tsx_async_abort=full mds=full,nosmt page_alloc.shuffle=1 randomize_kstack_offset=on l1tf=full,force ipv6.disable=1 slab_nomerge vsyscall=none retbleed=stuff spectre_v2_user=on kvm.nx_huge_pages=force"
echo -e "${G}🔧 إنشاء أجهزة VM في RAM pool...${N}"
# 1. عدد الأجهزة
echo -e "${Y}كم عدد أجهزة VM التي تريد إنشاؤها؟${N}"
read -p "العدد: " VM_COUNT
if ! [[ "$VM_COUNT" =~ ^[0-9]+$ ]] || [ "$VM_COUNT" -lt 1 ]; then
echo -e "${R}❌ خطأ: الرجاء إدخال رقم صحيح أكبر من 0${N}"
exit 1
fi
# 2. البحث عن بوابات sys-whonix
echo -e "${Y}🔍 البحث عن بوابات sys-whonix المتاحة...${N}"
mapfile -t GATEWAYS < <(qvm-ls --raw-data --fields NAME,CLASS 2>/dev/null | grep -E '^sys-whonix(-[0-9]+)?' | awk '{print $1}' | cut -d'|' -f1)
if [ ${#GATEWAYS[@]} -eq 0 ]; then
mapfile -t GATEWAYS < <(qvm-ls 2>/dev/null | grep -E '^sys-whonix(-[0-9]+)?' | awk '{print $1}')
fi
if [ ${#GATEWAYS[@]} -eq 0 ]; then
echo -e "${R}❌ خطأ: لم يتم العثور على أي بوابة sys-whonix${N}"
exit 1
fi
echo -e "${G}✅ تم العثور على البوابات التالية:${N}"
for i in "${!GATEWAYS[@]}"; do
CLEAN_GATEWAY=$(echo "${GATEWAYS[$i]}" | cut -d'|' -f1 | tr -d '[:space:]')
GATEWAYS[$i]="$CLEAN_GATEWAY"
echo -e " ${Y}[$((i+1))]${N} ${GATEWAYS[$i]}"
done
# 3. اختيار البوابات
echo -e "\n${Y}هل تريد استخدام بوابات مختلفة لكل VM؟ (y/n)${N}"
read -p "اختيار: " USE_DIFFERENT_GATEWAYS
declare -a VM_GATEWAYS
if [[ "$USE_DIFFERENT_GATEWAYS" =~ ^[Yy]$ ]]; then
echo -e "\n${Y}حدد رقم البوابة لكل VM:${N}"
for (( i=1; i<=VM_COUNT; i++ )); do
while true; do
read -p "VM رقم $i - اختر رقم البوابة (1-${#GATEWAYS[@]}): " GATEWAY_NUM
if [[ "$GATEWAY_NUM" =~ ^[0-9]+$ ]] && [ "$GATEWAY_NUM" -ge 1 ] && [ "$GATEWAY_NUM" -le ${#GATEWAYS[@]} ]; then
VM_GATEWAYS[$i]=${GATEWAYS[$((GATEWAY_NUM-1))]}
echo -e " ${G}✅ تم اختيار: ${VM_GATEWAYS[$i]}${N}"
break
else
echo -e "${R}❌ رقم غير صحيح${N}"
fi
done
done
else
echo -e "\n${Y}اختر رقم البوابة لجميع الأجهزة:${N}"
while true; do
read -p "رقم البوابة (1-${#GATEWAYS[@]}): " GATEWAY_NUM
if [[ "$GATEWAY_NUM" =~ ^[0-9]+$ ]] && [ "$GATEWAY_NUM" -ge 1 ] && [ "$GATEWAY_NUM" -le ${#GATEWAYS[@]} ]; then
SELECTED_GATEWAY=${GATEWAYS[$((GATEWAY_NUM-1))]}
for (( i=1; i<=VM_COUNT; i++ )); do
VM_GATEWAYS[$i]=$SELECTED_GATEWAY
done
echo -e "${G}✅ تم اختيار: $SELECTED_GATEWAY${N}"
break
else
echo -e "${R}❌ رقم غير صحيح${N}"
fi
done
fi
# 4. تأكيد
echo -e "\n${B}📋 ملخص الأجهزة:${N}"
for (( i=1; i<=VM_COUNT; i++ )); do
echo -e " ${VM_BASE}${i} → ${VM_GATEWAYS[$i]}"
done
echo -e "\n${Y}هل تريد المتابعة؟ (y/n)${N}"
read -p "اختيار: " CONFIRM
if [[ ! "$CONFIRM" =~ ^[Yy]$ ]]; then
echo -e "${R}تم الإلغاء${N}"
exit 0
fi
# 5. تحقق القالب
if ! qvm-check --quiet "$BASE_TEMPLATE" 2>/dev/null; then
echo -e "${R}❌ القالب $BASE_TEMPLATE غير موجود${N}"
exit 1
fi
# 6. حذف الأجهزة القديمة
echo -e "${Y}🗑️ حذف الأجهزة القديمة...${N}"
for vm in $(qvm-ls --raw-data --fields NAME 2>/dev/null | grep "^${VM_BASE}[0-9]" | cut -d'|' -f1); do
qvm-kill "$vm" 2>/dev/null
qvm-remove --force "$vm" 2>/dev/null
done
echo -e "${G}✅ تم الحذف${N}"
# 7. RAM pool
if ! mount | grep -q "$RAM_POOL_PATH"; then
echo -e "${Y}📁 إنشاء RAM pool...${N}"
sudo mkdir -p "$RAM_POOL_PATH"
sudo mount -t tmpfs -o size=$RAM_POOL_SIZE tmpfs "$RAM_POOL_PATH"
if ! qvm-pool ls | grep -q ram_pool; then
qvm-pool add ram_pool file -o dir_path="$RAM_POOL_PATH"
qvm-pool set ram_pool -o ephemeral_volatile=True 2>/dev/null
fi
echo -e "${G}✅ RAM pool جاهز${N}"
fi
# 8. إنشاء الأجهزة
declare -a CREATED_VMS
for (( i=1; i<=VM_COUNT; i++ )); do
VM_NAME="${VM_BASE}${i}"
GATEWAY="${VM_GATEWAYS[$i]}"
CLEAN_GATEWAY=$(echo "$GATEWAY" | cut -d'|' -f1 | tr -d '[:space:]')
echo ""
echo -e "${Y}📦 إنشاء: $VM_NAME (بوابة: $CLEAN_GATEWAY)${N}"
if qvm-create -P ram_pool -t "$BASE_TEMPLATE" -l red "$VM_NAME" 2>/dev/null; then
echo -e " ${G}✅ تم الإنشاء${N}"
CREATED_VMS+=("$VM_NAME")
echo -e " ${Y}⚙️ معلمات النواة...${N}"
qvm-prefs "$VM_NAME" kernelopts "$KERNEL_OPTS" 2>/dev/null && echo -e " ${G}✅ تم${N}" || echo -e " ${Y}⚠️ فشل${N}"
echo -e " ${Y}🔌 توصيل البوابة...${N}"
if qvm-prefs "$VM_NAME" netvm "$CLEAN_GATEWAY" 2>/dev/null; then
echo -e " ${G}✅ تم توصيل $CLEAN_GATEWAY${N}"
else
echo -e " ${R}❌ فشل التوصيل${N}"
fi
qvm-features "$VM_NAME" no-monitor-layout 1 2>/dev/null || true
else
echo -e " ${R}❌ فشل إنشاء $VM_NAME${N}"
fi
done
echo -e "\n${G}🎉 تم إنشاء ${#CREATED_VMS[@]} جهاز${N}"
# 9. حفظ الإعدادات بدون أي توصيل تلقائي
echo -e "\n${B}💾 حفظ الإعدادات كسكريبت؟${N}"
read -p "اختيار (y/n): " SAVE_SCRIPT
if [[ "$SAVE_SCRIPT" =~ ^[Yy]$ ]]; then
cat > "$SAVE_SCRIPT_PATH" << EOT
#!/bin/bash
# سكريبت محفوظ - إنشاء أجهزة Whonix في RAM
BASE_TEMPLATE="$BASE_TEMPLATE"
VM_BASE="$VM_BASE"
RAM_POOL_PATH="$RAM_POOL_PATH"
RAM_POOL_SIZE="$RAM_POOL_SIZE"
KERNEL_OPTS="$KERNEL_OPTS"
G='\\033[0;32m'
Y='\\033[1;33m'
R='\\033[0;31m'
N='\\033[0m'
echo -e "\${G}🚀 بدء الإنشاء المحفوظ...\${N}"
if ! qvm-check --quiet "\$BASE_TEMPLATE" 2>/dev/null; then
echo -e "\${R}❌ القالب غير موجود\${N}"
exit 1
fi
for vm in \$(qvm-ls --raw-data --fields NAME 2>/dev/null | grep "^\${VM_BASE}[0-9]" | cut -d'|' -f1); do
qvm-kill "\$vm" 2>/dev/null
qvm-remove --force "\$vm" 2>/dev/null
done
if ! mount | grep -q "\$RAM_POOL_PATH"; then
sudo mkdir -p "\$RAM_POOL_PATH"
sudo mount -t tmpfs -o size=\$RAM_POOL_SIZE tmpfs "\$RAM_POOL_PATH"
qvm-pool add ram_pool file -o dir_path="\$RAM_POOL_PATH" 2>/dev/null || true
qvm-pool set ram_pool -o ephemeral_volatile=True 2>/dev/null || true
fi
echo -e "\${Y}📦 إنشاء الأجهزة...\${N}"
EOT
for (( i=1; i<=VM_COUNT; i++ )); do
cat >> "$SAVE_SCRIPT_PATH" << EOT
VM_NAME="${VM_BASE}${i}"
GATEWAY="${VM_GATEWAYS[$i]}"
echo " إنشاء: \$VM_NAME (بوابة: \$GATEWAY)"
if qvm-create -P ram_pool -t "\$BASE_TEMPLATE" -l red "\$VM_NAME" 2>/dev/null; then
echo -e " \${G}✅ تم الإنشاء\${N}"
qvm-prefs "\$VM_NAME" kernelopts "\$KERNEL_OPTS" 2>/dev/null
qvm-prefs "\$VM_NAME" netvm "\$GATEWAY" 2>/dev/null
qvm-features "\$VM_NAME" no-monitor-layout 1 2>/dev/null
else
echo -e " \${R}❌ فشل الإنشاء\${N}"
fi
EOT
done
cat >> "$SAVE_SCRIPT_PATH" << EOT
echo -e "\n\${G}✅ تم إنشاء الأجهزة بدون توصيل تلقائي\${N}"
EOT
chmod +x "$SAVE_SCRIPT_PATH"
echo -e "${G}✅ تم الحفظ في: $SAVE_SCRIPT_PATH${N}"
fi
EOF
chmod +x "$DESKTOP_PATH/ram-pool-scripts/create-multi-ram-vm.sh"
# ========== cleanup-ram-pool.sh ==========
cat > "$DESKTOP_PATH/ram-pool-scripts/cleanup-ram-pool.sh" << 'EOF'
#!/bin/bash
RAM_POOL_PATH="$HOME/ram_pool"
echo "🧹 تنظيف RAM Pool..."
for vm in $(qvm-ls --raw-list 2>/dev/null | grep -E "whonix-work-ram|ram-"); do
qvm-kill "$vm" 2>/dev/null
qvm-remove --force "$vm" 2>/dev/null
done
qvm-pool remove ram_pool 2>/dev/null
mount | grep -q "$RAM_POOL_PATH" && sudo umount "$RAM_POOL_PATH"
[ -d "$RAM_POOL_PATH" ] && sudo rm -rf "$RAM_POOL_PATH"
echo "✅ تم التنظيف"
free -h
EOF
# ========== ram-pool-status.sh ==========
cat > "$DESKTOP_PATH/ram-pool-scripts/ram-pool-status.sh" << 'EOF'
#!/bin/bash
echo "=== حالة RAM Pool ==="
mount | grep ram_pool && df -h "$HOME/ram_pool"
echo "VMs في RAM Pool:"
qvm-pool volumes ram_pool 2>/dev/null | grep -oE '^[^:]+' | sort -u
echo "استخدام الذاكرة:"
free -h
EOF
chmod +x "$DESKTOP_PATH/ram-pool-scripts"/*.sh
ok "تم إنشاء 7 سكريبتات في $DESKTOP_PATH/ram-pool-scripts/"
pause
}
# ========
# 6. سكريبت Amnesic Tmpfs
# ========
amnesic_script() {
clear
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ 🧠 Amnesic Tmpfs - مجلدات في RAM تختفي بعد الإغلاق ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
echo "1) تطبيق Amnesic Tmpfs على جهاز"
echo "2) إلغاء Amnesic Tmpfs من جهاز"
echo "0) رجوع"
echo ""
read -p "اختر: " CHOICE
case $CHOICE in
1) apply_amnesic ;;
2) remove_amnesic ;;
0) return ;;
*) amnesic_script ;;
esac
}
apply_amnesic() {
clear
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ 📌 تطبيق Amnesic Tmpfs ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
SCRIPT_PATH="$DESKTOP_PATH/apply-amnesic.sh"
cat > "$SCRIPT_PATH" << 'SCRIPTEOF'
#!/bin/bash
clear
echo "تطبيق Amnesic Tmpfs"
echo ""
echo "📋 الأجهزة المتاحة:"
echo "----------------------------------------"
qvm-ls --raw-list 2>/dev/null | grep -v dom0
echo "----------------------------------------"
echo ""
read -p "🔧 اسم الجهاز: " TARGET_VM
[ -z "$TARGET_VM" ] && { echo "❌ لا يوجد اسم"; read -p "Enter..."; exit 1; }
! qvm-ls "$TARGET_VM" >/dev/null 2>&1 && { echo "❌ غير موجود"; read -p "Enter..."; exit 1; }
echo ""
echo "🔧 تجهيز: $TARGET_VM"
qvm-start "$TARGET_VM" 2>/dev/null
sleep 3
cat > /tmp/rc_local_content.txt << 'RCEOF'
#!/bin/bash
mkdir -p /var/log /var/cache /var/tmp /tmp /home/user/QubesIncoming
mount -t tmpfs tmpfs /var/log -o size=512M,mode=0755,nosuid,nodev
mount -t tmpfs tmpfs /var/cache -o size=512M,mode=0755,nosuid,nodev
mount -t tmpfs tmpfs /var/tmp -o size=256M,mode=1777,nosuid,nodev,noexec
mount -t tmpfs tmpfs /tmp -o size=512M,mode=1777,nosuid,nodev,noexec
mount -t tmpfs tmpfs /home/user -o size=2G,mode=0700,nosuid,nodev
cp -r /etc/skel/. /home/user/ 2>/dev/null
mkdir -p /home/user/QubesIncoming
chown -R user:user /home/user 2>/dev/null
exit 0
RCEOF
qvm-run --pass-io "$TARGET_VM" 'sudo tee /rw/config/rc.local' < /tmp/rc_local_content.txt 2>/dev/null
qvm-run "$TARGET_VM" "sudo chmod +x /rw/config/rc.local" 2>/dev/null
qvm-shutdown "$TARGET_VM" 2>/dev/null
rm -f /tmp/rc_local_content.txt
echo ""
echo "✅ تم تطبيق Amnesic Tmpfs على: $TARGET_VM"
read -p "Enter..."
SCRIPTEOF
chmod +x "$SCRIPT_PATH"
bash "$SCRIPT_PATH"
rm -f "$SCRIPT_PATH"
}
remove_amnesic() {
clear
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ 🗑️ إلغاء Amnesic Tmpfs ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
SCRIPT_PATH="$DESKTOP_PATH/remove-amnesic.sh"
cat > "$SCRIPT_PATH" << 'SCRIPTEOF'
#!/bin/bash
clear
echo "إلغاء Amnesic Tmpfs"
echo ""
echo "📋 الأجهزة المتاحة:"
echo "----------------------------------------"
qvm-ls --raw-list 2>/dev/null | grep -v dom0
echo "----------------------------------------"
echo ""
read -p "🔧 اسم الجهاز: " TARGET_VM
[ -z "$TARGET_VM" ] && { echo "❌ لا يوجد اسم"; read -p "Enter..."; exit 1; }
! qvm-ls "$TARGET_VM" >/dev/null 2>&1 && { echo "❌ غير موجود"; read -p "Enter..."; exit 1; }
echo ""
echo "🔧 تجهيز: $TARGET_VM"
qvm-start "$TARGET_VM" 2>/dev/null
sleep 3
# كتابة #!/bin/bash فقط في rc.local
qvm-run "$TARGET_VM" "sudo bash -c 'echo \"#!/bin/bash\" > /rw/config/rc.local'" 2>/dev/null
qvm-run "$TARGET_VM" "sudo chmod +x /rw/config/rc.local" 2>/dev/null
qvm-shutdown "$TARGET_VM" 2>/dev/null
echo ""
echo "✅ تم إلغاء Amnesic Tmpfs من: $TARGET_VM"
echo "📌 تم استعادة rc.local إلى الوضع الافتراضي"
read -p "Enter..."
SCRIPTEOF
chmod +x "$SCRIPT_PATH"
bash "$SCRIPT_PATH"
rm -f "$SCRIPT_PATH"
}
# ========
# 7. Live Mode
# ========
live_mode() {
clear
REAL_USER=$(logname 2>/dev/null || echo "$SUDO_USER" 2>/dev/null || echo "$USER")
info "المستخدم الحقيقي: $REAL_USER"
warn "هذا السكريبت سيقوم بإنشاء ملف live.sh وتنفيذه بصلاحيات sudo"
warn "قد يستغرق التنفيذ عدة دقائق"
warn "🟢 سيتم تثبيت Overlay-Live Mode مع zram"
read -p "متابعة؟ (y/n): " confirm
[[ "$confirm" != "y" && "$confirm" != "Y" ]] && return
LIVE_SCRIPT="/home/$REAL_USER/Desktop/live.sh"
info "جاري إنشاء $LIVE_SCRIPT ..."
cat > "$LIVE_SCRIPT" << 'EOOFF'
#!/bin/bash
# Qubes Dom0 Amnesic modes
# ⚠️ Make backup before running! Run as root: sudo ./amnesic.sh
echo "=== Qubes Dom0 Live Boot Setup ==="
#BOOT_UUID
BOOT_UUID=$(findmnt -n -o UUID /boot 2>/dev/null || echo "AUTO_BOOT_NOT_FOUND")
if [ "$BOOT_UUID" = "AUTO_BOOT_NOT_FOUND" ]; then
BOOT_UUID=$(blkid -s UUID -o value -d $(findmnt -n -o SOURCE /boot 2>/dev/null))
fi
# LUKS_UUID
LUKS_DEVICE=$(blkid -t TYPE="crypto_LUKS" -o device 2>/dev/null | head -n1 || echo "")
if [ -n "$LUKS_DEVICE" ]; then
LUKS_UUID=$(sudo cryptsetup luksUUID "$LUKS_DEVICE" 2>/dev/null)
else
LUKS_UUID="AUTO_LUKS_NOT_FOUND"
fi
# Latest XEN_PATH
XEN_PATH=$(ls /boot/xen*.gz 2>/dev/null | sort -V | tail -1 | xargs basename 2>/dev/null || echo "/xen-4.19.4.gz")
# Latest kernel/initramfs
LATEST_KERNEL=$(ls /boot/vmlinuz-*qubes*.x86_64 2>/dev/null | grep -E 'qubes\.fc[0-9]+' | sort -V | tail -1 | xargs basename)
LATEST_INITRAMFS=$(echo "/initramfs-${LATEST_KERNEL#vmlinuz-}.img")
# Max memory dom0
system_total_mb=$(xl info | grep total_memory | awk '{print $3}')
if [ -n "$system_total_mb" ] && [ "$system_total_mb" -gt 0 ] 2>/dev/null; then
# 80% total_memory
DOM0_MAX_MB=$((system_total_mb * 80 / 100))
DOM0_MAX_GB=$((DOM0_MAX_MB / 1024))
DOM0_MAX_RAM="dom0_mem=max:${DOM0_MAX_MB}M"
DOM0_MAX_GBG="${DOM0_MAX_GB}G"
else
DOM0_MAX_RAM="dom0_mem=max:10240M"
DOM0_MAX_GB="10"
DOM0_MAX_GBG="10G"
fi
# qubes_dom0-root
Qubes_Root=$(findmnt -n -o SOURCE /)
# /home/user
if [ -n "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
USER_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6)
else
USER_HOME="$HOME"
fi
if [ ! -d "$USER_HOME" ]; then
echo "home dir '$USER_HOME' not found!" >&2
exit 1
fi
# === dom0 resize ===
REQUIRED_FREE_GB=100
MIN_DOM0_SIZE_GB=40
get_dom0_size_gb() {
local size_bytes
size_bytes=$(df -B1 /dev/mapper/qubes_dom0-root 2>/dev/null | awk 'NR==2 {print $2}')
if [[ -z "$size_bytes" ]]; then
echo "Warning: failed to determine dom0 size" >&2
return 1
fi
echo "$((size_bytes / 1024 / 1024 / 1024))"
return 0
}
get_vg_free_gb() {
local lv_size data_pct
lv_size=$(lvs --noheadings --nosuffix --units b -o lv_size qubes_dom0/vm-pool 2>/dev/null | tr -dc '0-9')
data_pct=$(lvs --noheadings -o data_percent qubes_dom0/vm-pool 2>/dev/null | tr ',' '.' | tr -dc '0-9.')
if [[ -z "$lv_size" || -z "$data_pct" ]]; then
echo "Warning: failed to determine free space in vm-pool" >&2
return 1
fi
local free_gb
free_gb=$(awk "BEGIN { printf \"%.0f\", ($lv_size * (100 - $data_pct) / 100) / 1024 / 1024 / 1024 }")
echo "$free_gb"
return 0
}
main() {
if [[ "$EUID" -ne 0 ]]; then
echo "Warning: This script should be run as root (sudo)" >&2
# Changed from exit 1 to just warning
fi
local dom0_size_gb vg_free_gb
dom0_size_gb=$(get_dom0_size_gb) || dom0_size_gb="unknown"
vg_free_gb=$(get_vg_free_gb) || vg_free_gb="unknown"
echo "Current dom0 size: ${dom0_size_gb} GB"
echo "Free space in VM pool: ${vg_free_gb} GB"
if [[ "$vg_free_gb" != "unknown" ]] && ((vg_free_gb < REQUIRED_FREE_GB)); then
echo "Info: free space is less than ${REQUIRED_FREE_GB} GB (available: ${vg_free_gb} GB) - skipping resize"
# Changed from exit 0 to continue
elif [[ "$dom0_size_gb" != "unknown" ]] && ((dom0_size_gb >= MIN_DOM0_SIZE_GB)); then
echo "Info: dom0 size is already ${dom0_size_gb} GB (>= ${MIN_DOM0_SIZE_GB} GB) - skipping resize"
# Changed from exit 0 to continue
else
echo "Conditions met. Starting dom0 resize..."
if lvresize --size 40G /dev/mapper/qubes_dom0-root; then
resize2fs /dev/mapper/qubes_dom0-root
lvresize -L +20G qubes_dom0/root-pool
echo "Done. New dom0 size: $(get_dom0_size_gb) GB"
else
echo "Warning: dom0 resize failed - continuing with other commands"
fi
fi
echo "--- dom0 resize completed ---"
}
main "$@"
# === swapoff ===
sudo sed -i '/\/dev\/mapper\/swap/!{/^[[:space:]]*#/!{/\/s/^/# /}}' /etc/fstab
sudo sed -i '/\/dev\/mapper\/swap/b; /[[:space:]]\+swap[[:space:]]\+/s/^/# /' /etc/fstab
# === harden autostart ===
mkdir -p "$USER_HOME/.config"
if [ ! -f "$USER_HOME/.config/harden.sh" ]; then
cat > "$USER_HOME/.config/harden.sh" << 'EOF'
#!/bin/bash
sleep 1
if findmnt -n -o SOURCE / | grep -qE "(overlay|/dev/zram0)"; then
notify-send --expire-time=20000 "Amnesic session is running" "dom0 mode: $(findmnt -n -o SOURCE /)" --icon=dialog-information
sudo sysctl -w kernel.sysrq=0
sudo sysctl -w kernel.perf_event_paranoid=3
sudo sysctl -w kernel.kptr_restrict=2
sudo sysctl -w kernel.panic=5
sudo sysctl -w fs.protected_regular=2
sudo sysctl -w fs.protected_fifos=2
sudo sysctl -w kernel.printk="3 3 3 3"
sudo sysctl -w kernel.kexec_load_disabled=1
sudo sysctl -w kernel.io_uring_disabled=2
sudo chattr +i /boot/grub2/grub.cfg
sudo chattr +i /boot
else
sudo chattr -i /boot/grub2/grub.cfg
sudo chattr -i /boot
fi
EOF
chmod 755 "$USER_HOME/.config/harden.sh"
echo "Created harden.sh"
else
echo "harden.sh already exists, skipping"
fi
# === autostart desktop entry ===
mkdir -p "$USER_HOME/.config/autostart"
if [ ! -f "$USER_HOME/.config/autostart/harden.desktop" ]; then
cat > "$USER_HOME/.config/autostart/harden.desktop" << EOF
[Desktop Entry]
Encoding=UTF-8
Version=0.9.4
Type=Application
Name=harden
Comment=
Exec=$USER_HOME/.config/harden.sh
OnlyShowIn=XFCE;
RunHook=0
StartupNotify=false
Terminal=false
Hidden=false
EOF
echo "Created harden.desktop"
else
echo "harden.desktop already exists, skipping"
fi
# === Dracut module directories ===
DIR_OVERLAY_CRYPT=/usr/lib/dracut/modules.d/90overlay-crypt
DIR_RAMBOOT=/usr/lib/dracut/modules.d/90ramboot
DIR_OVERLAY=/usr/lib/dracut/modules.d/90overlayfs-root
DIR_RAMWIPE=/usr/lib/dracut/modules.d/40ram-wipe
for d in "$DIR_RAMBOOT" "$DIR_OVERLAY" "$DIR_RAMWIPE" "$DIR_OVERLAY_CRYPT"; do
if [ ! -d "$d" ]; then
mkdir -p "$d"
echo "Created $(basename "$d")"
else
echo "$(basename "$d") already exists, skipping"
fi
done
# === 90overlay-crypt/module-setup.sh ===
if [ ! -f "$DIR_OVERLAY_CRYPT/module-setup.sh" ]; then
cat > "$DIR_OVERLAY_CRYPT/module-setup.sh" << 'EOF'
#!#!/bin/bash
check() {
require_binaries cryptsetup || return 1
require_binaries losetup || return 1
require_binaries mkfs.ext4 || return 1
return 0
}
depends() {
return 0
}
installkernel() {
hostonly='' instmods overlay 2>/dev/null || true
hostonly='' instmods dm-crypt 2>/dev/null || true
}
install() {
inst_multiple cryptsetup losetup mkfs.ext4 dd modprobe mount umount shred
inst_hook pre-pivot 10 "$moddir/overlay-crypt.sh"
}
EOF
chmod 755 "$DIR_OVERLAY_CRYPT/module-setup.sh"
echo "Created 90overlay-crypt/module-setup.sh"
else
echo "90overlay-crypt/module-setup.sh already exists, skipping"
fi
# === 90overlay-crypt/overlay-crypt.sh ===
if [ ! -f "$DIR_OVERLAY_CRYPT/overlay-crypt.sh" ]; then
cat > "$DIR_OVERLAY_CRYPT/overlay-crypt.sh" << 'EOF'
#!/bin/bash
. /lib/dracut-lib.sh
if ! getargbool 0 cryptovl ; then
return
fi
modprobe overlay 2>/dev/null || true
modprobe dm-crypt 2>/dev/null || true
#
mount -o remount,ro /sysroot 2>/dev/null || true
#
mkdir -p /live/image
mount --bind /sysroot /live/image
umount /sysroot
#
dd if=/dev/urandom bs=64 count=1 of=/dev/shm/overlay-key status=none
chmod 600 /dev/shm/overlay-key
# create 20 GB size (seek)
mkdir -p /var/lib
dd if=/dev/zero of=/var/lib/overlay-crypt.img bs=1M count=0 seek=20480 status=none
#
losetup -f
LOOP_DEV=$(losetup -f --show /var/lib/overlay-crypt.img)
#
cryptsetup luksFormat --type luks2 \
--cipher aes-xts-plain64 --key-size 512 \
--hash sha256 --pbkdf pbkdf2 --pbkdf-force-iterations 1000 \
--batch-mode --key-file /dev/shm/overlay-key "$LOOP_DEV"
#
cryptsetup open --type luks2 --key-file /dev/shm/overlay-key "$LOOP_DEV" overlaycrypt
#
mkfs.ext4 -F -L "overlaycrypt" /dev/mapper/overlaycrypt
#
mkdir -p /cow
mount -o noatime,nodiratime,nobarrier /dev/mapper/overlaycrypt /cow
mkdir -p /cow/work /cow/rw
#
mount -t overlay -o noatime,nodiratime,volatile,lowerdir=/live/image,upperdir=/cow/rw,workdir=/cow/work,default_permissions,relatime overlay /sysroot
#
mkdir -p /sysroot/live/cow /sysroot/live/image
mount --bind /cow/rw /sysroot/live/cow
mount --bind /live/image /sysroot/live/image
#
umount /cow 2>/dev/null || true
umount /live/image 2>/dev/null || true
#
shred -u /dev/shm/overlay-key 2>/dev/null || rm -f /dev/shm/overlay-key
EOF
chmod 755 "$DIR_OVERLAY_CRYPT/overlay-crypt.sh"
echo "Created 90overlay-crypt/overlay-crypt.sh"
else
echo "90overlay-crypt/overlay-crypt.sh already exists, skipping"
fi
# === 90ramboot/module-setup.sh ===
if [ ! -f "$DIR_RAMBOOT/module-setup.sh" ]; then
cat > "$DIR_RAMBOOT/module-setup.sh" << 'EOF'
#!/usr/bin/bash
check() {
return 0
}
depends() {
return 0
}
install() {
inst_simple "$moddir/zram-mount.sh"
inst_hook cleanup 00 "$moddir/zram-mount.sh"
}
EOF
chmod 755 "$DIR_RAMBOOT/module-setup.sh"
echo "Created 90ramboot/module-setup.sh"
else
echo "90ramboot/module-setup.sh already exists, skipping"
fi
# === 90ramboot/zram-mount.sh ===
if [ ! -f "$DIR_RAMBOOT/zram-mount.sh" ]; then
cat > "$DIR_RAMBOOT/zram-mount.sh" << EOF
#!/bin/sh
. /lib/dracut-lib.sh
if ! getargbool 0 rootzram ; then
return
fi
mkdir -p /mnt
umount /sysroot
mount -o ro $Qubes_Root /mnt
modprobe zram
echo $DOM0_MAX_GBG > /sys/block/zram0/disksize
#/mnt/usr/sbin/mkfs.xfs -f -m reflink=0 /dev/zram0
/mnt/usr/sbin/mkfs.ext2 /dev/zram0
mount -o nodev,nosuid,noatime,nodiratime /dev/zram0 /sysroot
EXCLUDES=("dev" "proc" "sys" "tmp" "run" "mnt" "media" "lost+found" "var/log")
FIND_EXPR=()
for dir in "${EXCLUDES[@]}"; do
FIND_EXPR+=(-name "$dir" -o)
done
unset 'FIND_EXPR[${#FIND_EXPR[@]}-1]'
find /mnt -mindepth 1 -maxdepth 1 ! \( "${FIND_EXPR[@]}" \) -exec cp -a {} /sysroot \;
for dir in "${EXCLUDES[@]}"; do
mkdir -p "/sysroot/$dir"
done
# Disable swap
if [ -f /sysroot/etc/fstab ]; then
sed -i '/[ \t]swap[ \t]/d' /sysroot/etc/fstab
fi
if [ -d /sysroot/etc/systemd/system ]; then
ln -sf /dev/null /sysroot/etc/systemd/system/dev-mapper-swap.device
fi
umount /mnt
exit 0
EOF
chmod 755 "$DIR_RAMBOOT/zram-mount.sh"
echo "Created 90ramboot/zram-mount.sh"
else
echo "90ramboot/zram-mount.sh already exists, skipping"
fi
# === 90overlayfs-root/module-setup.sh ===
if [ ! -f "$DIR_OVERLAY/module-setup.sh" ]; then
cat > "$DIR_OVERLAY/module-setup.sh" << 'EOF'
#!/bin/bash
check() {
[ -d /lib/modules/$kernel/kernel/fs/overlayfs ] || return 1
}
depends() {
return 0
}
installkernel() {
hostonly='' instmods overlay
}
install() {
inst_hook pre-pivot 10 "$moddir/overlay-mount.sh"
}
EOF
chmod 755 "$DIR_OVERLAY/module-setup.sh"
echo "Created 90overlayfs-root/module-setup.sh"
else
echo "90overlayfs-root/module-setup.sh already exists, skipping"
fi
# === 90overlayfs-root/overlay-mount.sh ===
if [ ! -f "$DIR_OVERLAY/overlay-mount.sh" ]; then
cat > "$DIR_OVERLAY/overlay-mount.sh" << 'EOF'
#!/bin/sh
. /lib/dracut-lib.sh
if ! getargbool 0 rootovl ; then
return
fi
modprobe overlay
mount -o remount,nolock,noatime $NEWROOT
mkdir -p /live/image
mount --bind $NEWROOT /live/image
umount $NEWROOT
mkdir /cow
mount -n -t tmpfs -o mode=0755,size=100%,nr_inodes=500k,noexec,nodev,nosuid,noatime,nodiratime tmpfs /cow
mkdir /cow/work /cow/rw
mount -t overlay -o noatime,nodiratime,volatile,lowerdir=/live/image,upperdir=/cow/rw,workdir=/cow/work,default_permissions,relatime overlay $NEWROOT
mkdir -p $NEWROOT/live/cow
mkdir -p $NEWROOT/live/image
mount --bind /cow/rw $NEWROOT/live/cow
umount /cow
mount --bind /live/image $NEWROOT/live/image
umount /live/image
umount $NEWROOT/live/cow
EOF
chmod 755 "$DIR_OVERLAY/overlay-mount.sh"
echo "Created 90overlayfs-root/overlay-mount.sh"
else
echo "90overlayfs-root/overlay-mount.sh already exists, skipping"
fi
# === ramboot dracut.conf ===
if [ ! -f /etc/dracut.conf.d/ramboot.conf ]; then
cat > /etc/dracut.conf.d/ramboot.conf << 'EOF'
add_drivers+=" zram "
add_dracutmodules+=" ramboot "
EOF
echo "Created ramboot.conf"
else
echo "ramboot.conf already exists, skipping"
fi
# === 40ram-wipe/module-setup.sh ===
if [ ! -f "$DIR_RAMWIPE/module-setup.sh" ]; then
cat > "$DIR_RAMWIPE/module-setup.sh" << 'EOF'
#!/bin/bash
# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*-
# ex: ts=8 sw=4 sts=4 et filetype=sh
## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC
## See the file COPYING for copying conditions.
check() {
require_binaries sync || return 1
require_binaries sleep || return 1
require_binaries dmsetup || return 1
return 0
}
depends() {
return 0
}
install() {
inst_simple "/usr/libexec/ram-wipe/ram-wipe-lib.sh" "/lib/ram-wipe-lib.sh"
inst_multiple sync
inst_multiple sleep
inst_multiple dmsetup
inst_hook shutdown 40 "$moddir/wipe-ram.sh"
inst_hook cleanup 80 "$moddir/wipe-ram-needshutdown.sh"
}
installkernel() {
return 0
}
EOF
chmod +x "$DIR_RAMWIPE/module-setup.sh"
echo "Created 40ram-wipe/module-setup.sh"
else
echo "40ram-wipe/module-setup.sh already exists, skipping"
fi
# === 40ram-wipe/wipe-ram-needshutdown.sh ===
if [ ! -f "$DIR_RAMWIPE/wipe-ram-needshutdown.sh" ]; then
cat > "$DIR_RAMWIPE/wipe-ram-needshutdown.sh" << 'EOF'
#!/bin/sh
## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC
## See the file COPYING for copying conditions.
type getarg >/dev/null 2>&1 || . /lib/dracut-lib.sh
. /lib/ram-wipe-lib.sh
ram_wipe_check_needshutdown() {
#local kernel_wiperam_setting
kernel_wiperam_setting="$(getarg wiperam)"
if [ "$kernel_wiperam_setting" = "skip" ]; then
force_echo "wipe-ram-needshutdown.sh: Skip, because wiperam=skip kernel parameter detected, OK."
return 0
fi
true "wipe-ram-needshutdown.sh: Calling dracut function need_shutdown to drop back into initramfs at shutdown, OK."
need_shutdown
return 0
}
ram_wipe_check_needshutdown
EOF
chmod +x "$DIR_RAMWIPE/wipe-ram-needshutdown.sh"
echo "Created 40ram-wipe/wipe-ram-needshutdown.sh"
else
echo "40ram-wipe/wipe-ram-needshutdown.sh already exists, skipping"
fi
# === 40ram-wipe/wipe-ram.sh ===
if [ ! -f "$DIR_RAMWIPE/wipe-ram.sh" ]; then
cat > "$DIR_RAMWIPE/wipe-ram.sh" << 'EOF'
#!/bin/sh
## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC
## See the file COPYING for copying conditions.
## Credits:
## First version by @friedy10.
## https://github.com/friedy10/dracut/blob/master/modules.d/40sdmem/wipe.sh
. /lib/ram-wipe-lib.sh
drop_caches() {
sync
echo 3 > /proc/sys/vm/drop_caches
sync
}
ram_wipe() {
#local kernel_wiperam_setting
kernel_wiperam_setting="$(getarg wiperam)"
if [ "$kernel_wiperam_setting" = "skip" ]; then
force_echo "wipe-ram.sh: Skip, because wiperam=skip kernel parameter detected, OK."
return 0
fi
force_echo "wipe-ram.sh: RAM extraction attack defense... Starting RAM wipe pass during shutdown..."
drop_caches
force_echo "wipe-ram.sh: RAM wipe pass completed, OK."
}
ram_wipe
EOF
chmod +x "$DIR_RAMWIPE/wipe-ram.sh"
echo "Created 40ram-wipe/wipe-ram.sh"
else
echo "40ram-wipe/wipe-ram.sh already exists, skipping"
fi
# === ram-wipe dracut.conf ===
if [ ! -f /etc/dracut.conf.d/30-ram-wipe.conf ]; then
cat > /etc/dracut.conf.d/30-ram-wipe.conf << 'EOF'
add_dracutmodules+=" ram-wipe "
EOF
echo "Created 30-ram-wipe.conf"
else
echo "30-ram-wipe.conf already exists, skipping"
fi
# === ram-wipe-lib.sh ===
DIR_RAMWIPE_LIB=/usr/libexec/ram-wipe
if [ ! -d "$DIR_RAMWIPE_LIB" ]; then
mkdir -p "$DIR_RAMWIPE_LIB"
fi
if [ ! -f "$DIR_RAMWIPE_LIB/ram-wipe-lib.sh" ]; then
cat > "$DIR_RAMWIPE_LIB/ram-wipe-lib.sh" << 'EOF'
#!/bin/sh
## Copyright (C) 2023 - 2025 ENCRYPTED SUPPORT LLC
## See the file COPYING for copying conditions.
if [ -z "$DRACUT_SYSTEMD" ]; then
force_echo() {
echo "<28>dracut INFO: $*" > /dev/kmsg
echo "dracut INFO: $*" >&2
}
else
force_echo() {
echo "INFO: $*" >&2
}
fi
EOF
chmod +x "$DIR_RAMWIPE_LIB/ram-wipe-lib.sh"
echo "Created ram-wipe-lib.sh"
else
echo "ram-wipe-lib.sh already exists, skipping"
fi
# Update INITRAMFS
dracut --verbose --force
# Create GRUB custom
echo "Creating GRUB custom ..."
cat > /etc/grub.d/40_custom << EOF
#!/usr/bin/sh
exec tail -n +3 \$0
menuentry 'Qubes Encrypted-Overlay Amnesic Mode' --class qubes --class gnu-linux --class gnu --class os --class xen \$menuentry_id_option 'xen-gnulinux-simple-/dev/mapper/qubes_dom0-root' {
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root $BOOT_UUID
echo 'Loading Xen ...'
if [ "\$grub_platform" = "pc" -o "\$grub_platform" = "" ]; then
xen_rm_opts=
else
xen_rm_opts="no-real-mode edd=off"
fi
insmod multiboot2
multiboot2 /$XEN_PATH placeholder console=none dom0_mem=min:1024M $DOM0_MAX_RAM ucode=scan smt=off gnttab_max_frames=2048 gnttab_max_maptrack_frames=4096 \${xen_rm_opts}
echo 'Loading Linux $LATEST_KERNEL ...'
module2 /$LATEST_KERNEL placeholder root=/dev/mapper/qubes_dom0-root ro rd.luks.uuid=$LUKS_UUID rd.lvm.lv=qubes_dom0/root rd.lvm.lv=qubes_dom0/swap plymouth.ignore-serial-consoles rhgb cryptovl quiet module.sig_enforce=1 bootscrub=on
echo 'Loading initial ramdisk ...'
insmod multiboot2
module2 --nounzip $LATEST_INITRAMFS
}
menuentry 'Qubes Zram-Live Amnesic Mode' --class qubes --class gnu-linux --class gnu --class os --class xen \$menuentry_id_option 'xen-gnulinux-simple-/dev/mapper/qubes_dom0-root' {
insmod part_gpt
insmod ext2
search --no-floppy --fs-uuid --set=root $BOOT_UUID
echo 'Loading Xen ...'
if [ "\$grub_platform" = "pc" -o "\$grub_platform" = "" ]; then
xen_rm_opts=
else
xen_rm_opts="no-real-mode edd=off"
fi
insmod multiboot2
multiboot2 /$XEN_PATH placeholder console=none dom0_mem=min:1024M $DOM0_MAX_RAM ucode=scan smt=off gnttab_max_frames=2048 gnttab_max_maptrack_frames=4096 \${xen_rm_opts}
echo 'Loading Linux $LATEST_KERNEL ...'
module2 /$LATEST_KERNEL placeholder root=/dev/mapper/qubes_dom0-root ro rd.luks.uuid=$LUKS_UUID rd.lvm.lv=qubes_dom0/root rd.lvm.lv=qubes_dom0/swap plymouth.ignore-serial-consoles rhgb rootzram quiet module.sig_enforce=1 bootscrub=on
echo 'Loading initial ramdisk ...'
insmod multiboot2
module2 --nounzip $LATEST_INITRAMFS
}
EOF
chmod 755 /etc/grub.d/40_custom
# Update GRUB
grub2-mkconfig -o /boot/grub2/grub.cfg
# Cleanup
dnf clean all
journalctl --vacuum-time=1d
rm -rf /var/cache/dnf/* 2>/dev/null || true
echo
echo "Done!"
echo "✓ ALL STEPS COMPLETED SUCCESSFULLY! Reboot Qubes OS, select one of the new GRUB options (Encrypted-Overlay or Zram-Live), and clone your appVMs to the varlibqubes pool to run in full amnesia mode."
EOOFF
chmod +x "$LIVE_SCRIPT"
ok "تم إنشاء $LIVE_SCRIPT"
info "جاري تنفيذ live.sh بصلاحيات sudo..."
sudo bash "$LIVE_SCRIPT"
info "جاري حذف $LIVE_SCRIPT..."
rm -f "$LIVE_SCRIPT"
ok "تم حذف الملف"
pause
}
# ========
# 8. سكريبتات الطوارئ (BusKill)
# ========
emergency_script() {
mkdir -p "$DESKTOP_PATH/emergency"
# ========== سكريبت Dead Man's Switch ==========
cat > "$DESKTOP_PATH/emergency/deadman-switch.sh" << 'EOF'
#!/bin/bash
# ⚠️ Dead Man's Switch - تدمير مؤجل باستخدام BusKill
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ 💀 Dead Man's Switch - التدمير المؤجل (BusKill) 💀 ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
read -p "المهلة بالدقائق قبل التدمير: " T
[ -z "$T" ] && T=5
read -p "اكتب YES للتأكيد النهائي: " C
[ "$C" != "YES" ] && { echo "تم الإلغاء"; exit 1; }
# طباعة أمر الإلغاء أولاً
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ 📌 أمر الإلغاء (احفظه الآن قبل متابعة التثبيت): ║"
echo "║ sudo /usr/local/bin/cancel ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
# التحقق من وجود BusKill وتثبيته إذا لم يكن موجوداً
if [ ! -f "/etc/qubes-rpc/buskill.selfDestruct" ]; then
echo "⚠️ BusKill غير مثبت. جاري تثبيته تلقائياً..."
sudo tee /etc/qubes-rpc/buskill.selfDestruct > /dev/null << 'BUSKILL'
#!/bin/bash
# 1. حذف مجلد Qubes من EFI
EFI_PART=$(findmnt -n -o SOURCE /boot/efi 2>/dev/null)
if [ -n "$EFI_PART" ]; then
sudo mount $EFI_PART /mnt
sudo rm -rf /mnt/EFI/qubes
sudo umount /mnt
echo "✅ تم حذف مجلد Qubes من $EFI_PART"
else
echo "⚠️ لم يتم العثور على قسم EFI"
fi
# حذف مدخل الإقلاع من NVRAM
if [ -d "/sys/firmware/efi" ]; then
# البحث عن مدخل Qubes وحذفه
sudo efibootmgr | grep -i qubes | while read -r line; do
bootnum=
sudo efibootmgr -b "" -B
echo "✅ تم حذف مدخل الإقلاع: Boot"
done
fi
# 2. تدمير قسم /boot
BOOT_PART=$(findmnt -n -o SOURCE /boot)
echo "💀 بدء تدمير $BOOT_PART"
sudo dd if=/dev/urandom of=$BOOT_PART bs=1M status=progress &
WHICH="/usr/bin/which"
sudo qvm-kill --all &
CRYPTSETUP=$($WHICH --skip-alias cryptsetup) || echo "ERROR: Unable to find cryptsetup"
LS=$($WHICH --skip-alias ls) || echo "ERROR: Unable to find ls"
CP=$($WHICH --skip-alias cp) || echo "ERROR: Unable to find cp"
MV=$($WHICH --skip-alias mv) || echo "ERROR: Unable to find mv"
LN=$($WHICH --skip-alias ln) || echo "ERROR: Unable to find ln"
MKDIR=$($WHICH --skip-alias mkdir) || echo "ERROR: Unable to find mkdir"
MOUNT=$($WHICH --skip-alias mount) || echo "ERROR: Unable to find mount"
CAT=$($WHICH --skip-alias cat) || echo "ERROR: Unable to find cat"
GREP=$($WHICH --skip-alias grep) || echo "ERROR: Unable to find grep"
ECHO=$($WHICH --skip-alias echo) || echo "ERROR: Unable to find echo"
AWK=$($WHICH --skip-alias awk) || echo "ERROR: Unable to find awk"
HEAD=$($WHICH --skip-alias head) || echo "ERROR: Unable to find head"
LSBLK=$($WHICH --skip-alias lsblk) || echo "ERROR: Unable to find lsblk"
OD=$($WHICH --skip-alias od) || echo "ERROR: Unable to find od"
SUDO=$($WHICH --skip-alias sudo) || echo "ERROR: Unable to find sudo"
CHMOD=$($WHICH --skip-alias chmod) || echo "ERROR: Unable to find chmod"
BASH=$($WHICH --skip-alias bash) || echo "ERROR: Unable to find bash"
NOHUP=$($WHICH --skip-alias nohup) || echo "ERROR: Unable to find nohup"
SLEEP=$($WHICH --skip-alias sleep) || echo "ERROR: Unable to find sleep"
QVM_KILL=$($WHICH --skip-alias qvm-kill) || echo "ERROR: Unable to find qvm-kill"
CHROOT=$($WHICH --skip-alias chroot) || echo "ERROR: Unable to find chroot"
SYNC=$($WHICH --skip-alias sync) || echo "ERROR: Unable to find sync"
LDD=$($WHICH --skip-alias ldd) || echo "ERROR: Unable to find ldd"
XARGS=$($WHICH --skip-alias xargs) || echo "ERROR: Unable to find xargs"
CHROOT_PATH='/dev/shm/buskill/chroot'
DIE_SCRIPT='/usr/bin/die.sh'
if [[ $EUID -ne 0 ]]; then
exec $SUDO $BASH "$0" "$@"
fi
$NOHUP $SLEEP 60 && echo o > /proc/sysrq-trigger &
$NOHUP $SLEEP 61 && echo b > /proc/sysrq-trigger &
$NOHUP $SLEEP 62 && echo b > /proc/sysrq-trigger &
$QVM_KILL --all &
echo "INFO: shredding LUKS header"
writes=''
oldIFS="$IFS"
IFS=$'\n'
for line in $( $LSBLK --list --output 'UUID,FSTYPE' | $GREP 'crypt' ); do
device="/dev/disk/by-uuid/$(echo "$line" | $AWK '{print $1}')"
echo -e "\t$device"
$CRYPTSETUP luksErase --batch-mode "$device" || $HEAD --bytes 20M /dev/urandom > $device &
writes="$writes $!"
luksVersion=$($OD --skip-bytes 6 --read-bytes 2 --format d2 --endian=big --address-radix "n" "$device")
if [[ $luksVersion -eq 1 ]]; then
payloadOffset=$($OD --skip-bytes 104 --read-bytes 4 --format d4 --endian=big --address-radix "n" "$device")
luksEndByte=$(( 512 * $payloadOffset ))
elif [[ $luksVersion -eq 2 ]]; then
hdr_size=$($OD --skip-bytes 8 --read-bytes 8 --format d8 --endian=big --address-radix "n" "$device")
luksEndByte=$(( 2 * $hdr_size ))
else
luksEndByte=20971520
fi
exec 5<> "$device"
$HEAD --bytes "$luksEndByte" /dev/urandom >&5 &
writes="$writes $!"
exec 5>&-
done
IFS="$oldIFS"
writes=$(echo "$writes" | $XARGS)
if [[ $writes ]]; then wait $writes; fi
sync; echo 3 > /proc/sys/vm/drop_caches
$MKDIR -p "$CHROOT_PATH/proc"
$MKDIR -p "$CHROOT_PATH/sys"
$MKDIR -p "$CHROOT_PATH/dev"
$MKDIR -p "$CHROOT_PATH/pts"
$MKDIR -p "$CHROOT_PATH/bin"
$MKDIR -p "$CHROOT_PATH/lib64"
$MKDIR -p "$CHROOT_PATH/lib/systemd"
$MKDIR -p "$CHROOT_PATH/usr/sbin"
$MKDIR -p "$CHROOT_PATH/usr/bin"
$MOUNT -t proc none "$CHROOT_PATH/proc"
$MOUNT -t sysfs none "$CHROOT_PATH/sys"
$MOUNT -o bind /dev "$CHROOT_PATH/dev"
$MOUNT -o bind /dev/pts "$CHROOT_PATH/dev/pts"
binaries="$BASH $CRYPTSETUP $ECHO $LS $NOHUP $SLEEP $XARGS $SYNC"
for binary in $binaries; do
$CP -vf "$binary" "$CHROOT_PATH/$binary"
libs="$( $LDD "$binary" | $GREP -Eo '/lib.*\.so(\.[0-9]*)*' )"
for lib in $libs; do
$CP -vf "$lib" "$CHROOT_PATH/$lib"
done
done
$MV "$CHROOT_PATH/lib" "$CHROOT_PATH/usr/lib"
$LN -s "usr/lib" "$CHROOT_PATH/lib"
$CAT << EOFF > "$CHROOT_PATH/$DIE_SCRIPT"
#!$BASH
$NOHUP $SLEEP 10 && echo o > /proc/sysrq-trigger &
$NOHUP $SLEEP 11 && echo o > /proc/sysrq-trigger &
echo "INFO: removing decryption keys from memory"
waits=''
for device in \$( $LS -1 "/dev/mapper" ); do
echo -e "\t\$device";
$CRYPTSETUP luksSuspend "\$device" &
waits="\$waits \$!"
done
echo "INFO: finished luksSuspend calls"
waits=\$(echo "\$waits" | $XARGS)
if [[ \$waits ]]; then wait \$waits; fi
echo "INFO: finished waiting"
sync; echo 3 > /proc/sys/vm/drop_caches
echo "INFO: finished syncing"
echo "INFO: Rebooting"
echo o > /proc/sysrq-trigger
EOFF
$CHMOD +x "$CHROOT_PATH/$DIE_SCRIPT"
$CHROOT "$CHROOT_PATH" "$DIE_SCRIPT"
BUSKILL
sudo chmod +x /etc/qubes-rpc/buskill.selfDestruct
sudo tee /etc/qubes-rpc/policy/buskill.selfDestruct > /dev/null << 'POLICY'
sys-usb dom0 allow
@anyvm @anyvm deny
POLICY
echo "✅ تم تثبيت BusKill تلقائياً"
else
echo "✅ BusKill موجود مسبقاً"
fi
# سكربت nuke
sudo tee /usr/local/bin/nuke > /dev/null << 'NUKE'
#!/bin/bash
/etc/qubes-rpc/buskill.selfDestruct
NUKE
sudo chmod 755 /usr/local/bin/nuke
# سكربت الإلغاء
sudo tee /usr/local/bin/cancel > /dev/null << 'CANCEL'
#!/bin/bash
sudo systemctl stop deadman.service
echo "✓ تم إلغاء التدمير"
CANCEL
sudo chmod 755 /usr/local/bin/cancel
echo "ALL ALL=(root) NOPASSWD: /bin/systemctl stop deadman.service" | sudo tee /etc/sudoers.d/cancel > /dev/null
sudo chmod 440 /etc/sudoers.d/cancel
# خدمة systemd
sudo tee /etc/systemd/system/deadman.service > /dev/null << SERVICE
[Unit]
Description=Dead Man's Switch (BusKill)
After=multi-user.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c "sleep ${T}m && /usr/local/bin/nuke"
[Install]
WantedBy=multi-user.target
SERVICE
# تفعيل الخدمة
echo "📦 جاري تفعيل الخدمة..."
sudo systemctl daemon-reload
sudo systemctl enable deadman.service
sudo systemctl start deadman.service --no-block 2>/dev/null &
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ ✅ تم تفعيل Dead Man's Switch بنجاح ║"
echo "╠═══════════════════════════════════════════════════════════╣"
echo "║ المهلة: ${T} دقائق ║"
echo "║ للإلغاء: sudo /usr/local/bin/cancel ║"
echo "║ للتحقق: systemctl status deadman.service ║"
echo "╚═══════════════════════════════════════════════════════════╝"
EOF
# ========== سكريبت إلغاء التثبيت الكامل ==========
cat > "$DESKTOP_PATH/emergency/uninstall-deadman.sh" << 'UNINSTALL'
#!/bin/bash
# إلغاء تثبيت Dead Man's Switch بالكامل
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ 🗑️ إلغاء تثبيت Dead Man's Switch بالكامل ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
echo "⚠️ تحذير: هذا سيحذف Dead Man's Switch بالكامل"
echo " (لن يحذف BusKill نفسه، فقط المؤقت)"
echo ""
read -p "اكتب YES للتأكيد: " CONFIRM
if [ "$CONFIRM" != "YES" ]; then
echo "تم الإلغاء."
exit 1
fi
echo ""
echo "🗑️ جاري إلغاء التثبيت..."
sudo systemctl stop deadman.service 2>/dev/null && echo "✓ تم إيقاف الخدمة"
sudo systemctl disable deadman.service 2>/dev/null && echo "✓ تم تعطيل الخدمة"
sudo rm -f /etc/systemd/system/deadman.service && echo "✓ تم حذف ملف الخدمة"
sudo rm -f /usr/local/bin/nuke && echo "✓ تم حذف nuke"
sudo rm -f /usr/local/bin/cancel && echo "✓ تم حذف cancel"
sudo rm -f /etc/sudoers.d/cancel && echo "✓ تم حذف صلاحيات sudoers"
sudo systemctl daemon-reload && echo "✓ تم تحديث systemd"
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ ✅ تم إلغاء تثبيت Dead Man's Switch بنجاح ║"
echo "╠═══════════════════════════════════════════════════════════╣"
echo "║ 📌 BusKill (/etc/qubes-rpc/buskill.selfDestruct) بقي ║"
echo "║ لحذفه: sudo rm -f /etc/qubes-rpc/buskill.selfDestruct ║"
echo "╚═══════════════════════════════════════════════════════════╝"
UNINSTALL
# ========== سكريبت BusKill المنفرد ==========
mkdir -p "$DESKTOP_PATH/buskill"
cat > "$DESKTOP_PATH/buskill/buskill-selfdestruct.sh" << 'EOF'
#!/bin/bash
# 1. حذف مجلد Qubes من EFI
EFI_PART=$(findmnt -n -o SOURCE /boot/efi 2>/dev/null)
if [ -n "$EFI_PART" ]; then
sudo mount $EFI_PART /mnt
sudo rm -rf /mnt/EFI/qubes
sudo umount /mnt
echo "✅ تم حذف مجلد Qubes من $EFI_PART"
else
echo "⚠️ لم يتم العثور على قسم EFI"
fi
# حذف مدخل الإقلاع من NVRAM
if [ -d "/sys/firmware/efi" ]; then
# البحث عن مدخل Qubes وحذفه
sudo efibootmgr | grep -i qubes | while read -r line; do
bootnum=
sudo efibootmgr -b "" -B
echo "✅ تم حذف مدخل الإقلاع: Boot"
done
fi
# 2. تدمير قسم /boot
BOOT_PART=$(findmnt -n -o SOURCE /boot)
echo "💀 بدء تدمير $BOOT_PART"
sudo dd if=/dev/urandom of=$BOOT_PART bs=1M status=progress &
WHICH="/usr/bin/which"
sudo qvm-kill --all &
CRYPTSETUP=$($WHICH --skip-alias cryptsetup) || echo "ERROR: Unable to find cryptsetup"
LS=$($WHICH --skip-alias ls) || echo "ERROR: Unable to find ls"
CP=$($WHICH --skip-alias cp) || echo "ERROR: Unable to find cp"
MV=$($WHICH --skip-alias mv) || echo "ERROR: Unable to find mv"
LN=$($WHICH --skip-alias ln) || echo "ERROR: Unable to find ln"
MKDIR=$($WHICH --skip-alias mkdir) || echo "ERROR: Unable to find mkdir"
MOUNT=$($WHICH --skip-alias mount) || echo "ERROR: Unable to find mount"
CAT=$($WHICH --skip-alias cat) || echo "ERROR: Unable to find cat"
GREP=$($WHICH --skip-alias grep) || echo "ERROR: Unable to find grep"
ECHO=$($WHICH --skip-alias echo) || echo "ERROR: Unable to find echo"
AWK=$($WHICH --skip-alias awk) || echo "ERROR: Unable to find awk"
HEAD=$($WHICH --skip-alias head) || echo "ERROR: Unable to find head"
LSBLK=$($WHICH --skip-alias lsblk) || echo "ERROR: Unable to find lsblk"
OD=$($WHICH --skip-alias od) || echo "ERROR: Unable to find od"
SUDO=$($WHICH --skip-alias sudo) || echo "ERROR: Unable to find sudo"
CHMOD=$($WHICH --skip-alias chmod) || echo "ERROR: Unable to find chmod"
BASH=$($WHICH --skip-alias bash) || echo "ERROR: Unable to find bash"
NOHUP=$($WHICH --skip-alias nohup) || echo "ERROR: Unable to find nohup"
SLEEP=$($WHICH --skip-alias sleep) || echo "ERROR: Unable to find sleep"
QVM_KILL=$($WHICH --skip-alias qvm-kill) || echo "ERROR: Unable to find qvm-kill"
CHROOT=$($WHICH --skip-alias chroot) || echo "ERROR: Unable to find chroot"
SYNC=$($WHICH --skip-alias sync) || echo "ERROR: Unable to find sync"
LDD=$($WHICH --skip-alias ldd) || echo "ERROR: Unable to find ldd"
XARGS=$($WHICH --skip-alias xargs) || echo "ERROR: Unable to find xargs"
CHROOT_PATH='/dev/shm/buskill/chroot'
DIE_SCRIPT='/usr/bin/die.sh'
if [[ $EUID -ne 0 ]]; then
exec $SUDO $BASH "$0" "$@"
fi
$NOHUP $SLEEP 60 && echo o > /proc/sysrq-trigger &
$NOHUP $SLEEP 61 && echo b > /proc/sysrq-trigger &
$NOHUP $SLEEP 62 && echo b > /proc/sysrq-trigger &
$QVM_KILL --all &
echo "INFO: shredding LUKS header"
writes=''
oldIFS="$IFS"
IFS=$'\n'
for line in $( $LSBLK --list --output 'UUID,FSTYPE' | $GREP 'crypt' ); do
device="/dev/disk/by-uuid/$(echo "$line" | $AWK '{print $1}')"
echo -e "\t$device"
$CRYPTSETUP luksErase --batch-mode "$device" || $HEAD --bytes 20M /dev/urandom > $device &
writes="$writes $!"
luksVersion=$($OD --skip-bytes 6 --read-bytes 2 --format d2 --endian=big --address-radix "n" "$device")
if [[ $luksVersion -eq 1 ]]; then
payloadOffset=$($OD --skip-bytes 104 --read-bytes 4 --format d4 --endian=big --address-radix "n" "$device")
luksEndByte=$(( 512 * $payloadOffset ))
elif [[ $luksVersion -eq 2 ]]; then
hdr_size=$($OD --skip-bytes 8 --read-bytes 8 --format d8 --endian=big --address-radix "n" "$device")
luksEndByte=$(( 2 * $hdr_size ))
else
luksEndByte=20971520
fi
exec 5<> "$device"
$HEAD --bytes "$luksEndByte" /dev/urandom >&5 &
writes="$writes $!"
exec 5>&-
done
IFS="$oldIFS"
writes=$(echo "$writes" | $XARGS)
if [[ $writes ]]; then wait $writes; fi
sync; echo 3 > /proc/sys/vm/drop_caches
$MKDIR -p "$CHROOT_PATH/proc"
$MKDIR -p "$CHROOT_PATH/sys"
$MKDIR -p "$CHROOT_PATH/dev"
$MKDIR -p "$CHROOT_PATH/pts"
$MKDIR -p "$CHROOT_PATH/bin"
$MKDIR -p "$CHROOT_PATH/lib64"
$MKDIR -p "$CHROOT_PATH/lib/systemd"
$MKDIR -p "$CHROOT_PATH/usr/sbin"
$MKDIR -p "$CHROOT_PATH/usr/bin"
$MOUNT -t proc none "$CHROOT_PATH/proc"
$MOUNT -t sysfs none "$CHROOT_PATH/sys"
$MOUNT -o bind /dev "$CHROOT_PATH/dev"
$MOUNT -o bind /dev/pts "$CHROOT_PATH/dev/pts"
binaries="$BASH $CRYPTSETUP $ECHO $LS $NOHUP $SLEEP $XARGS $SYNC"
for binary in $binaries; do
$CP -vf "$binary" "$CHROOT_PATH/$binary"
libs="$( $LDD "$binary" | $GREP -Eo '/lib.*\.so(\.[0-9]*)*' )"
for lib in $libs; do
$CP -vf "$lib" "$CHROOT_PATH/$lib"
done
done
$MV "$CHROOT_PATH/lib" "$CHROOT_PATH/usr/lib"
$LN -s "usr/lib" "$CHROOT_PATH/lib"
$CAT << EOFF > "$CHROOT_PATH/$DIE_SCRIPT"
#!$BASH
$NOHUP $SLEEP 10 && echo o > /proc/sysrq-trigger &
$NOHUP $SLEEP 11 && echo o > /proc/sysrq-trigger &
echo "INFO: removing decryption keys from memory"
waits=''
for device in \$( $LS -1 "/dev/mapper" ); do
echo -e "\t\$device";
$CRYPTSETUP luksSuspend "\$device" &
waits="\$waits \$!"
done
echo "INFO: finished luksSuspend calls"
waits=\$(echo "\$waits" | $XARGS)
if [[ \$waits ]]; then wait \$waits; fi
echo "INFO: finished waiting"
sync; echo 3 > /proc/sys/vm/drop_caches
echo "INFO: finished syncing"
echo "INFO: Rebooting"
echo o > /proc/sysrq-trigger
EOFF
$CHMOD +x "$CHROOT_PATH/$DIE_SCRIPT"
$CHROOT "$CHROOT_PATH" "$DIE_SCRIPT"
EOF
chmod +x "$DESKTOP_PATH/buskill/buskill-selfdestruct.sh"
chmod +x "$DESKTOP_PATH/emergency"/*.sh
ok "تم إنشاء سكريبتات الطوارئ في $DESKTOP_PATH/emergency/"
ok "تم إنشاء سكريبت BusKill في $DESKTOP_PATH/buskill/"
echo ""
echo "╔═══════════════════════════════════════════════════════════╗"
echo "║ 📁 الملفات المنشأة: ║"
echo "╠═══════════════════════════════════════════════════════════╣"
echo "║ ⏰ deadman-switch.sh - تدمير مؤجل (Dead Man's Switch)║"
echo "║ 🔧 uninstall-deadman.sh - إلغاء تثبيت الخدمة ║"
echo "║ 🛡️ buskill-selfdestruct.sh - تدمير ذاتي (مسح رأس LUKS + حذف qubes os من boot/efi + حذف boot ملفات اقلاع qubes os) ║"
echo "╚═══════════════════════════════════════════════════════════╝"
echo ""
warn "⚠️ استخدم بحذر شديد - هذه السكريبتات تدمر البيانات نهائياً"
pause
}
#=====≈=
9. تقوية قرص النظام
#=======
luks_hardening() {
clear
echo "======"
echo " 🛡️ تقوية تشفير قرص النظام (LUKS PBKDF)"
echo "======"
echo ""
# تحديد المستخدم الحقيقي وسطح المكتب
REAL_USER=$(logname 2>/dev/null || echo "$SUDO_USER" 2>/dev/null || echo "$USER")
DESKTOP_DIR="/home/${REAL_USER}/Desktop"
SCRIPT_PATH="${DESKTOP_DIR}/luks-harden.sh"
# تحديد قرص النظام
ROOT_DISK=$(sudo blkid | grep crypto_LUKS | head -1 | cut -d: -f1)
if [ -z "$ROOT_DISK" ]; then
echo "❌ لم يتم العثور على قرص نظام مشفر بـ LUKS"
read -p "اضغط Enter للعودة..."
return
fi
echo "✅ قرص النظام: $ROOT_DISK"
# عرض الإعدادات الحالية
echo ""
echo "📊 الإعدادات الحالية:"
sudo cryptsetup luksDump "$ROOT_DISK" | grep -E "Memory|Time cost|PBKDF" | head -5
# إدخال المستخدم
echo ""
read -p "كم جيجابايت رام تريد تخصيصها؟ (مثلاً 3 أو 4): " RAM_GB
read -p "كم ثانية تريد أن يستغرق فتح القرص؟ (مثلاً 8 أو 10): " TARGET_SEC
RAM_KB=$((RAM_GB * 1024 * 1024))
# تأكيد
echo ""
echo "⚠️ القرص: $ROOT_DISK"
echo " الذاكرة: ${RAM_GB}GB"
echo " الزمن المستهدف: ~${TARGET_SEC} ثوانٍ"
echo ""
read -p "هل تريد المتابعة؟ (y/n): " CONFIRM
if [ "$CONFIRM" != "y" ] && [ "$CONFIRM" != "Y" ]; then
echo "❌ أُلغي"
read -p "اضغط Enter للعودة..."
return
fi
# إنشاء السكربت
cat > "$SCRIPT_PATH" << SCRIPTEOF
#!/bin/bash
set -e
echo "🔐 إضافة كلمة مرور جديدة..."
echo ""
echo "📋 سَيُطلب منك:"
echo " 1️⃣ كلمة المرور القديمة (لأي فتحة موجودة)"
echo " 2️⃣ كلمة المرور الجديدة (مرتين للتأكيد)"
echo ""
echo "⚠️ لن يقبل النظام كلمة مرور ضعيفة."
echo " استخدم عبارة طويلة (6+ كلمات عشوائية) أو استخدم --force-password لاحقًا."
echo ""
sudo cryptsetup luksAddKey \\
--pbkdf argon2id \\
--pbkdf-memory ${RAM_KB} \\
--iter-time $((TARGET_SEC * 1000)) \\
${ROOT_DISK}
echo ""
echo "✅ أُضيفت كلمة المرور الجديدة"
echo ""
echo "📊 القيم الفعلية:"
sudo cryptsetup luksDump ${ROOT_DISK} | grep -E "Memory|Time cost" | tail -2
echo ""
echo "💡 احتفظ بعدد الدورات أعلاه. إذا غيّرت كلمة المرور مستقبلًا،"
echo " استخدم --pbkdf-force-iterations بهذا الرقم لتضمن نفس القوة."
echo ""
read -p "🗑️ هل تريد حذف كلمة المرور القديمة؟ (y/n): " DELETE_OLD
if [ "\$DELETE_OLD" = "y" ] || [ "\$DELETE_OLD" = "Y" ]; then
sudo cryptsetup luksRemoveKey ${ROOT_DISK}
echo "✅ حُذفت كلمة المرور القديمة"
else
echo "⚠️ نصيحة: وجود كلمتي مرور يجعل الأضعف هو المستهدف."
fi
echo ""
read -p "🔄 هل تريد تحديث صورة الإقلاع؟ (y/n): " UPDATE_INIT
if [ "\$UPDATE_INIT" = "y" ] || [ "\$UPDATE_INIT" = "Y" ]; then
sudo dracut -f
echo "✅ تم تحديث صورة الإقلاع. أعد التشغيل للتأكد."
fi
echo ""
read -p "🗑️ هل تريد حذف ملف السكربت هذا من سطح المكتب؟ (y/n): " DELETE_SELF
if [ "\$DELETE_SELF" = "y" ] || [ "\$DELETE_SELF" = "Y" ]; then
rm -f "\$0"
echo "✅ حُذف ملف السكربت."
fi
echo ""
echo "🎉 تم!"
SCRIPTEOF
chmod +x "$SCRIPT_PATH"
chown "$REAL_USER:$REAL_USER" "$SCRIPT_PATH"
echo ""
echo "📄 أُنشئ السكربت في: $SCRIPT_PATH"
echo ""
# تشغيل السكربت
bash "$SCRIPT_PATH"
echo ""
read -p "اضغط Enter للعودة..."
}
#==========
10. whonix_auto_mount
#==========
whonix_auto_mount() {
echo -e "${G}🔧 إعداد التوصيل التلقائي في قالب Whonix workstation...${N}"
qvm-run -u root whonix-workstation-18 "
cat > /etc/systemd/system/mount-usb.service << 'EOF'
[Unit]
Description=USB mount watcher (like rc.local)
After=multi-user.target
[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do if [ -b /dev/xvdi ] && ! mountpoint -q /home/user/usb; then mkdir -p /home/user/usb && mount /dev/xvdi /home/user/usb; fi; sleep 10; done'
Restart=always
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable mount-usb.service
"
echo -e "${Y}إيقاف القالب لحفظ التغييرات...${N}"
qvm-shutdown whonix-workstation-18
echo -e "${G}✅ تم. يعمل تلقائياً كـ rc.local على كل VM جديد.${N}"
pause
}
# ========
# 11. تنفيذ التلقائي فقط (يشغل من 1 إلى 8)
# ========
run_auto() {
info "بدء التنفيذ التلقائي لجميع الأقسام..."
echo ""
kernel_opts_menu
mac_random
whonix_gws
kicksecure
ram_pool_scripts
amnesic_script
live_mode
emergency_script
echo ""
ok "تم تنفيذ جميع الأقسام بنجاح"
pause
}
menu