سياق الإعادة الهيكلية
كانت حاوية tor القديمة حاويةً مستقلة تتكلم مع بطاقة الشبكة مباشرة ولا تعرف إلا بروتوكول Tor. في ٣٠ يوليو ٢٠٢٦، اتُخذ قرار معماري بدمجها داخل حاوية net الأشمل، والتي تملك الآن بطاقة الشبكة (NIC) وحدها، وتقدم Tor كوضع توجيه قابل للتفعيل عبر رسالة IPC. هذا يسمح مستقبلاً بإضافة اتصال مباشر (Direct) أو بروتوكولات أخرى دون إعادة هيكلة الصلاحيات.
أوضاع الاتصال (ConnMode)
يُحدد الكود وضعَي اتصال ويُخزّن الحالة محلياً داخل حلقة الخدمة. الافتراضي Tor.
ConnMode::Tor- Bus_Vault ترسل IPC
- Net_Vault تستقبل الطلب
- TorState::route_request() يُستدعى
- smoltcp يُحدَّث عبر iface.poll()
- Circuit يفتح TCP → Entry Node :443
- StreamManager يرسل HTTP عبر الدائرة المشفرة
ConnMode::Direct- Bus_Vault ترسل IPC مع mr[0]=0xDE, mr[1]=0
- conn_mode تتغير إلى Direct
- عند الطلب: iface.poll() فقط
- لا يوجد VirtIO حقيقي — TODO في الكود
تهيئة Lazy لـ smoltcp
مكدس الشبكة لا يُهيأ عند بدء الحاوية، بل عند وصول أول رسالة IPC. هذا يُقلل من التعقيد في مرحلة الإقلاع.
// وضع الاتصال الافتراضي: Tor
let mut conn_mode = ConnMode::Tor;
receiver.serve(|msg| {
// ── Lazy Init: تُهيأ smoltcp عند أول رسالة فقط ──
if !net_init {
net_init = true;
let hw_addr = HardwareAddress::Ethernet(
EthernetAddress([0x02, 0x00, 0x00, 0x00, 0x00, 0x01])
);
let mut iface = Interface::new(Config::new(hw_addr), &mut device, Instant::from_millis(0));
iface.update_ip_addrs(|addrs| {
let _ = addrs.push(IpCidr::new(IpAddress::v4(10, 0, 2, 15), 24));
});
// إضافة TCP Socket بمخازن 2048 بايت
let tcp_socket = TcpSocket::new(
SocketBuffer::new(&mut TCP_RX_BUF[..]),
SocketBuffer::new(&mut TCP_TX_BUF[..]),
);
}
// ── تبديل الوضع عبر IPC (tag=Unknown, mr[0]=0xDE) ──
match msg.tag {
MessageTag::Unknown if msg.mr[0] == 0xDE => {
conn_mode = if msg.mr[1] == 0 { ConnMode::Direct } else { ConnMode::Tor };
}
MessageTag::Unknown => {
match conn_mode {
ConnMode::Tor => tor_state.route_request(...),
ConnMode::Direct => iface.poll(...), // TODO: VirtIO
}
}
_ => IpcMessage::error(1)
}
})مخرجات الحاوية الحية
الاعتماديات الحقيقية (Cargo.toml)
أضخم حاوية من حيث الاعتماديات — تمتلك مكدس شبكة كامل ومكتبات Tor مخصصة.
sel4-sysمحليSyscalls للنواة — طباعة وSeL4_Yield في حلقة الذعر.
ipc-syncمحليبنية Receiver لحلقة الخدمة (serve loop).
net-driverمحليمشغل الشبكة الداخلي — قيد التطوير.
tor-cellمحليتمثيل خلايا بروتوكول Tor (OR-Cell).
tor-circuitمحليإدارة دوائر Onion Routing المتعددة القفزات.
tor-streamمحليمدير تدفقات Tor المتزامنة (StreamManager).
tor-handshakeمحليمصافحة التشفير (TAP/ntor Handshake) عند بناء الدائرة.
smoltcp 0.11crates.ioمكدس TCP/IP كامل بـ no_std. يشمل: Ethernet، IPv4، DHCP، TCP sockets.
talc 4crates.ioمخصص ذاكرة ديناميكي بديل لـ bump-alloc. تستهلكه smoltcp لتخصيص بيانات الحزم.
spin 0.9crates.ioMutex لضمان سلامة الوصول للـ Global Allocator من talc.
توثيق الملفات البرمجية
قلب حاوية net. يُهيئ مكدس smoltcp عند أول طلب IPC (lazy init) ثم يدير حلقة خدمة تقبل وضعَي الاتصال: Direct (جاهز للتوسع لـ VirtIO) وTor (عبر دوائر مشفرة). كلاهما يمر عبر نفس الـ DummyDevice حالياً.
NET_HEAP: [u8; 256 * 1024]talc::ClaimOnOom + AssumeUnlockableTCP_RX_BUF / TCP_TX_BUF: [u8; 2048]10.0.2.15/24 (QEMU default)02:00:00:00:00:01 (Fake Static MAC)net_init: bool — يُهيأ عند أول رسالة فقطConnMode::Tor (افتراضياً)يُعرّف DummyDevice — وهو جهاز شبكة وهمي يُلبّي متطلبات smoltcp التجريدية دون إرسال أو استقبال فعلي. receive() تُرجع None دائماً، وtransmit() تُوفّر مخزناً مؤقتاً ثم تتجاهله. هذا هو الجسر المعماري لمشغل VirtIO-NET الحقيقي مستقبلاً.
1500 bytesEthernetدائماً None — لا بيانات واردة حالياًيوفر buf[1500] ثم يتجاهل البياناتمحرك Tor الداخلي. يحتوي على TorState الذي يُغلّف Circuit (دائرة واحدة لـ Circuit::new(1)) وStreamManager. عند استدعاء route_request()، يحاول الاتصال بـ Entry Node (198.51.100.1:443) عبر smoltcp ثم يرسل طلب HTTP عبر القناة المشفرة.
198.51.100.1:443 (محاكاة)10000 (TCP connect)Circuit::new(1) — دائرة واحدةGET / HTTP/1.1 → example.com:80وحدة Tor تُعرّف routing كـ submodule. هي بسيطة وصريحة: "Tor هو خيار اتصال داخل net، وليست حاوية مستقلة بعد الآن."
pub mod routing