در زیرساخت‌های حیاتی شبکه‌های خصوصی مجازی، دسترسی‌پذیری مداوم و پایدار اصلی‌ترین شاخص کارایی محسوب می‌شود. درگاه‌های تجاری، پروکسی‌های پشتیبان پروتکل WireGuard بر بستر TCP و رله‌های خروجی چندکاربره به طور روزمره ده‌ها هزار نشست همزمان TCP را مدیریت می‌کنند. هنگامی که مهندسان وصله‌های امنیتی ضروری یا بهینه‌سازی‌های ساختاری را ارائه می‌دهند، تیم‌های پشتیبانی با یک چالش اساسی روبرو می‌شوند: راه‌اندازی مجدد فرآیند دیمون موجب قطع ناگهانی تونل‌های فعال کاربران می‌گردد.

در چرخه حیات استاندارد سوکت‌ها در سیستم‌عامل لینوکس، فراخوانی دستور close() یا توقف فرآیند موجب ارسال بی‌درنگ بسته‌های FIN یا RST به سمت کلاینت‌ها می‌شود. برای کاربران متصل، این رخداد به معنای لغو انتقال فایل‌ها، قطع تماس‌های تصویری و هجوم تقاضاهای احراز هویت مجدد است. هجوم همزمان هزاران کاربر پدیده توده شتابان (thundering herd) را ایجاد کرده و توان پردازشی سرورهای احراز هویت و پردازنده‌ها را اشباع می‌سازد.

راهکار مرسوم در چنین شرایطی تخلیه اتصالات (connection draining) است، به این ترتیب که ترافیک جدید به فرآیند تازه هدایت شده و فرآیند پیشین تا بسته شدن طبیعی نشست‌ها فعال می‌ماند. با این حال، تونل‌های VPN تجاری بسیار پایدار هستند و به ندرت بسته می‌شوند. در عمل، فرآیند تخلیه ممکن است ساعت‌ها به طول انجامد و مانع استقرار سریع اصلاحات حیاتی گردد. راهکار بنیادین این چالش، جابه‌جایی مستقیم سوکت‌های فعال بین دو فرآیند بدون قطع اتصال است.


چالش ریست اتصال: به‌روزرسانی سرویس‌ها و اختلال در نشست‌های VPN

آسیب‌پذیری اتصالات داده در زمان ارتقای سرویس ناشی از ماهیت وضعیت‌مند پروتکل TCP است. برخلاف ارسال بدون وضعیت بسته‌های UDP، هر سوکت فعال TCP مجموعه‌ای از پارامترهای پویا را در پشته شبکه هسته لینوکس نگهداری می‌کند:

  1. شمارنده‌های پنجره لغزان: مقادیر متوالی دنباله داده‌ها (snd_una و snd_nxt و rcv_nxt) که تحویل منظم و مطمئن جریان بایت‌ها را مدیریت می‌کنند.
  2. تخمین‌زننده‌های پویا: میانگین هموار زمان رفت و برگشت (srtt)، واریانس تاخیر شبکه (rttvar) و پارامترهای کنترل تراکم پنجره (snd_cwnd و snd_ssthresh).
  3. حافظه‌های میانگیر بسته‌ها: ساختارهای sk_buff در هسته که بسته‌های ارسال‌شده در انتظار تایید و داده‌های دریافتی آماده خواندن را ذخیره می‌کنند.
پیامدهای راه‌اندازی مجدد سنتی فرآیند برای کاربران VPN:

[ برنامه کلاینت ] ──► [ تونل فعال VPN ] ──► [ فرآیند قدیمی (شناسه 101) ]
                                                        │
                                                 (دریافت فرمان توقف)
                                                        │
                                                        ▼
[ برنامه کلاینت ] ◄── [ دریافت بسته TCP RST ] ◄── [ حذف سوکت توسط هسته ]
       │
 (قطع ناگهانی ارتباط)
       │
       ▼
 [ هجوم اتصالات مجدد: اشباع منابع پردازشی توسط هزاران نشست همزمان ]

اگر گره شبکه فرآیند قبلی را بدون انتقال وضعیت متوقف سازد، پشته شبکه هسته بی‌درنگ ساختارهای حافظه مرتبط را پاکسازی می‌کند. ارسال بسته‌های Reset به تمام کلاینت‌ها، کانال‌های رمزگذاری‌شده را متلاشی می‌سازد. برای سامانه‌های خودکار و کاربران دورکار، این رویداد موجب اختلال و قطعی ناخواسته سرویس می‌گردد.


معماری Linux TCP_REPAIR: مکانیک انجماد سوکت در هسته

برای پشتیبانی از ذخیره وضعیت و بازیابی فرآیندها در کانتینرها (پروژه CRIU)، هسته لینوکس قابلیت TCP_REPAIR را در سطح SOL_TCP معرفی کرده است. این ویژگی به فرآیندهای مجاز اجازه می‌دهد تا سوکت فعال TCP را در حالت سکون کنترل‌شده قرار دهند.

در وضعیت استاندارد، سیستم‌عامل به برنامه‌های فضای کاربری اجازه تغییر مستقیم شمارنده‌ها یا تایمرها را نمی‌دهد تا از ناهماهنگی در تبادل داده‌ها جلوگیری شود. اما با فعال‌سازی گزینه TCP_REPAIR، هسته به طور موقت نظارت خودکار پروتکل را معلق کرده و به ابزارهای مدیریتی امکان می‌دهد متغیرهای داخلی را بازخوانی و تنظیم کنند.

چرخه حیات سوکت TCP در زمان انتقال با حالت تعمیر:

[ عملکرد عادی ارتباط ] ──► setsockopt(fd, SOL_TCP, TCP_REPAIR, TCP_REPAIR_ON)
                                   │
                                   ▼
                            [ وضعیت تعمیر سوکت ]
                                   │
         ┌─────────────────────────┴─────────────────────────┐
         ▼                                                   ▼
خواندن و نوشتن شماره‌های دنباله                     توقف زمان‌سنج‌ها (RTO و Keepalive)
استخراج بافرهای ورودی و خروجی                       مهار ارسال خودکار بسته‌های RST
         │                                                   │
         └─────────────────────────┬─────────────────────────┘
                                   │
                                   ▼
[ دریافت توصیف‌کننده در دیمون جدید ] ──► setsockopt(fd, SOL_TCP, TCP_REPAIR, TCP_REPAIR_OFF)
                                   │
                                   ▼
                       [ ازسرگیری عادی ارتباط ]

1. توقف تایمرها و ورود به حالت تعمیر سوکت

ورود به حالت تعمیر نیازمند مجوزهای مدیریت شبکه (CAP_NET_ADMIN) است. ناظر سامانه با فراخوانی تابع setsockopt() انجماد سوکت را آغاز می‌کند:

int repair_mode = 1;
if (setsockopt(sock_fd, SOL_TCP, TCP_REPAIR, &repair_mode, sizeof(repair_mode)) < 0) {
    perror("خطا در فعال‌سازی حالت TCP_REPAIR");
    return -1;
}

با اجرای این دستور، هسته تمامی زمان‌سنج‌های داخلی سوکت را معلق می‌سازد. شمارشگر زمان انتظار برای ارسال مجدد (RTO) متوقف می‌شود، بسته‌های پایش اتصال (Keepalive) ارسال نمی‌گردند و تایمرهای پنجره خالی منجمد می‌شوند. بسته‌های ورودی جدید بدون تولید پیام خطای RST در صفوف میانگیر ذخیره می‌گردند.

2. ثبت و بازیابی صفوف داده و شماره‌های دنباله TCP

در وضعیت تعمیر، برنامه مدیریت می‌تواند مقادیر موقعیت دقیق دنباله‌ها را برای داده‌های ورودی و خروجی با بهره‌گیری از TCP_REPAIR_QUEUE و TCP_QUEUE_SEQ استخراج کند:

uint32_t current_seq;
socklen_t seq_len = sizeof(current_seq);
int queue_target = TCP_SEND_QUEUE;

/* انتخاب صف ارسال داده برای خواندن دنباله فعلی */
setsockopt(sock_fd, SOL_TCP, TCP_REPAIR_QUEUE, &queue_target, sizeof(queue_target));
getsockopt(sock_fd, SOL_TCP, TCP_QUEUE_SEQ, &current_seq, &seq_len);

این رابط ساختاریافته دو هدف کلیدی را محقق می‌سازد:

  • ثبت پایدار وضعیت: اندازه‌گیری دقیق حجم داده‌هایی که به تایید طرف مقابل رسیده است.
  • تزریق وضعیت پروتکل: در صورت لزوم بازآفرینی سوکت در یک فضای نام شبکه مستقل، فرآیند مقصد می‌تواند پیش از وصل کردن جریان داده، این مقادیر را تنظیم نماید.

سازوکارهای انتقال سوکت: روش SCM_RIGHTS در برابر CRIU

پیاده‌سازی مهاجرت زنده نیازمند ارسال بدون وقفه نشانگرهای فایل بین فرآیند قبلی و فرآیند جانشین است. دو رویکرد شاخص در معماری‌های نوین وجود دارد.

ساختار تبادل سوکت میان دو فرآیند مستقل:

[ فرآیند قبلی (نسخه v1) ]
       │  1. setsockopt(TCP_REPAIR, TCP_REPAIR_ON)
       │  2. استخراج کلیدهای رمزگذاری و مقادیر دنباله‌ها
       │  3. ارسال توصیف‌کننده با sendmsg() و پیام SCM_RIGHTS
       ▼
 [ گذرگاه ارتباط میان‌فرآیندی UNIX Domain Socket ]
       │
       ▼  4. دریافت توصیف‌کننده فایل فعال با recvmsg()
[ فرآیند جدید (نسخه v2) ]
       │  5. تطبیق شماره‌های دنباله و پیوند با حلقه epoll
       │  6. setsockopt(TCP_REPAIR, TCP_REPAIR_OFF)
       ▼
[ بازگشت پیوسته و پرسرعت جریان تبادل داده ]

1. تبادل توصیف‌کننده فایل از طریق سوکت دامنه یونیکس

در ارتقای نرم‌افزاری بر روی یک سرور واحد، ارسال نشانگر فایل از طریق سوکت دامنه یونیکس با پیام کمکی SCM_RIGHTS بالاترین بازدهی را رقم می‌زند. در این حالت نیازی به بازسازی پرهزینه ساختارهای پیچیده شبکه نیست، زیرا هسته مستقیما ارجاع فایل را بین جداول فرآیندها به اشتراک می‌گذارد.

فرآیند قدیمی پیامی شامل ساختار struct msghdr با پرچم SCM_RIGHTS می‌سازد. فرآیند جدید پیام را از طریق recvmsg() دریافت کرده و توصیف‌کننده معتبری دریافت می‌کند که مستقیما به همان شیء سوکت در حافظه هسته اشاره دارد.

2. بازسازی وضعیت پروتکل و خروج از حالت تعمیر

پس از در اختیار گرفتن نشانگر سوکت، فرآیند جدید حالت نشست رمزگذاری‌شده را بازیابی نموده، سوکت را به حلقه پردازش رویدادها (epoll یا io_uring) متصل کرده و حالت تعمیر را غیرفعال می‌سازد:

int repair_disable = 0;
if (setsockopt(imported_fd, SOL_TCP, TCP_REPAIR, &repair_disable, sizeof(repair_disable)) < 0) {
    perror("خطا در خروج از حالت TCP_REPAIR");
    return -1;
}

با خروج از این حالت، هسته زمان‌بندی تایمرها را متناسب با زمان جاری بازتنظیم کرده و صف بسته‌ها را رها می‌سازد. بسته‌های معلق در مسیر سخت‌افزار شبکه قرار گرفته و جریان داده ورودی بدون افت حتی یک بایت به فرآیند جدید تحویل داده می‌شود.


الگوی عملیاتی: پیاده‌سازی مهاجرت سوکت بدون افت بسته

یک چرخه استاندارد برای ارتقای بدون توقف در سرویس‌های متراکم شامل چهار مرحله منظم است:

  1. استقرار و اعتبارسنجی: راه‌اندازی فرآیند تازه در کنار فرآیند پیشین و تایید پیکربندی و گواهی‌ها پیش از دستکاری اتصالات فعال.
  2. انجماد گروه‌بندی‌شده: فعال‌سازی TCP_REPAIR_ON برای دسته‌های کنترل‌شده از سوکت‌ها جهت حفظ تعادل پاسخ‌دهی سرور.
  3. انتقال از طریق گذرگاه محلی: ارسال نشانگرهای سوکت و وضعیت رمزنگاری از طریق سوکت دامنه یونیکس.
  4. فعال‌سازی مجدد و پایان کار: فراخوانی TCP_REPAIR_OFF در فرآیند جدید، ثبت سوکت‌ها در حلقه تبادل و خاتمه منظم فرآیند قبلی.
گاه‌شمار تبادل نامحسوس اتصالات در سرور:

فرآیند پیشین             وضعیت TCP در هسته             فرآیند تازه
     │                            │                           │
     ├─ TCP_REPAIR_ON ──────────► │ (تایمرها منجمد شدند)      │
     │                            │                           │
     ├─ SCM_RIGHTS fd ──────────────────────────────────────► │ (دریافت نشانگر فایل)
     │                            │                           │
     │                            │ ◄── TCP_REPAIR_OFF ───────┤ (تایمرها بازنشانی شدند)
     │                            │                           │
     ├─ (پایان منظم کار)          │ (تبادل پرسرعت ترافیک)     ├─ (مدیریت بسته داده)

موازنه‌های فنی در دسترسی‌پذیری بالا و مهار خطاها

بهره‌گیری از این قابلیت نیازمند در نظر گرفتن ملاحظات فنی زیر است:

  • مجوزهای امنیتی: استفاده از این ویژگی نیازمند دسترسی CAP_NET_ADMIN است. برنامه‌ها باید پس از اتمام فاز انتقال این دسترسی را حذف نمایند.
  • مهلت ارسال مجدد در کلاینت: هرچند تایمرهای سرور متوقف هستند، زمان‌سنج‌های دستگاه کلاینت فعال می‌مانند. کل فرآیند جابه‌جایی باید بین 200 تا 500 میلی‌ثانیه به پایان برسد تا از فعال شدن خطای انقضای زمان RTO در کلاینت جلوگیری شود.
  • همگام‌سازی زمینه رمزنگاری: حفظ جریان بایت‌های خام TCP به تنهایی کارآمد نخواهد بود اگر وضعیت امنیتی لایه بالاتر مفقود شود. نشست‌های WireGuard و کلیدهای TLS باید همراه با توصیف‌کننده سوکت منتقل گردند.

معماری RiceGuard: تداوم نشست‌های کاربری در گره‌های مرزی

سامانه VPNRice با ادغام هوشمندانه این سازوکارها در هسته شبکه RiceGuard، اختلالات ناشی از به‌روزرسانی در گره‌های مرزی را به طور بنیادین برطرف ساخته است. به جای تحمیل قطعی‌های مکرر به کاربران هنگام استقرار نرم‌افزار، RiceGuard انتقال سوکت‌ها را به صورت خودکار در سطح هسته لینوکس مدیریت می‌کند.

با ترکیب توزیع سوکت مبتنی بر eBPF و قابلیت‌های TCP_REPAIR، سرورهای RiceGuard نشست‌های فعال را بدون افت داده یا ارسال پیام‌های ریست، میان ریسه‌های پردازشی مستقل جابه‌جا می‌نمایند. تونل‌های ارتباطی پیوستگی کامل خود را حفظ کرده و ثبات فوق‌العاده‌ای در حفاظت از حریم خصوصی دیجیتال به کاربران هدیه می‌دهند.