در معماری‌های توزیع‌شده با ترافیک فشرده و تونل‌های رمزگذاری‌شده، مکانیسم کنترل جریان مانع از اشباع دریافت‌کننده کند توسط فرستنده سریع می‌شود. در حالی که الگوریتم‌های کنترل ازدحام (نظیر BBR یا CUBIC) ظرفیت کلی مسیر را تنظیم می‌کنند، کنترل جریان TCP به صورت سرتاسری از طریق فیلد پنجره دریافت (rcv_wnd) در سرآیند ۲۰ بایتی عمل می‌کند. هنگامی که میزبان مقصد با بار شدید پردازشی، کندی عملیات ورودی-خروجی دیسک یا پر شدن بافر مواجه می‌شود، هسته سیستم‌عامل پنجره صفر (rcv_wnd = 0) را اعلام می‌کند تا ارسال داده بلادرنگ متوقف شود.

با این حال، اعلام پنجره صفر زمینه‌ساز یک آسیب‌پذیری حیاتی یعنی بن‌بست خاموش (silent deadlock) است. اگر بسته به‌روزرسانی بعدی که آزادسازی فضای بافر را خبر می‌دهد در مسیر شبکه مفقود شود، هر دو سمت ارتباط در وضعیت انتظار ابدی گرفتار می‌شوند. پروتکل TCP برای شکستن این بن‌بست، تایمر ماندگاری (Persist Timer) و پروب‌های پنجره صفر (ZWP) را طبق استانداردهای RFC 793 و RFC 1122 به کار می‌گیرد. در درگاه‌های VPN با ده‌ها هزار تونل همزمان، مدیریت دقیق این وضعیت برای مهار هدررفت حافظه و مقابله با حملات انکار سرویس نامتقارن نقشی اساسی دارد.

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

بسته‌های تاییدیه TCP (یا همان ACK) که فاقد داده هستند، تایید دریافت دریافت نمی‌کنند؛ زیرا ارسال تاییدیه برای تاییدیه پیشین به بازگشت مداوم و حلقه‌های بی‌پایان در شبکه می‌انجامد. این منطق طراحی، هنگام بازگشایی مجدد جریان بافر، شرایط رقابتی خطرناکی را رقم می‌زند.

فرستنده (کاربر)                               گیرنده (سرور VPN)
      |                                                |
      | -------- ارسال بسته داده [Seq: 1000] --------> | (تکمیل ظرفیت بافر)
      | <------- پاسخ تاییدیه [Ack: 1000, Win: 0] ---- | (اعلام پنجره صفر)
      | [توقف موقت ارسال داده]                         |
      |                                                | (پردازش داده و تخلیه بافر)
      | < - - - - [ACK: 1000, Win: 65535] (گم شد) - - - | (بسته گشایش پنجره مفقود شد)
      |                                                |
      v [بن‌بست: در انتظار باز شدن پنجره]              v [بن‌بست: در انتظار دریافت داده]

چنانچه بسته ارتقای پنجره بر اثر نوسان فیزیکی مسیر یا تداخل بسته‌بندی تونل از بین برود، فرستنده در انتظار دریافت مجدد ACK متوقف می‌ماند. همزمان، گیرنده تصور می‌کند ظرفیت جدید با موفقیت ابلاغ شده و بی‌دلیل منتظر داده‌های بعدی می‌نشیند.

برای خروج از این بن‌بست، پشته TCP به محض ثبت نخستین بسته پنجره صفر، تایمر ماندگاری را فعال می‌کند. در هسته لینوکس، مدیریت این تایمر در فایل net/ipv4/tcp_timer.c و با شناسه ICSK_TIME_PROBE0 دنبال می‌شود.

با منقضی شدن زمان این تایمر، فرستنده یک بسته کاوشگر پنجره صفر (ZWP) گسیل می‌دارد. بخش 4.2.2.17 استاندارد RFC 1122 مشخص می‌سازد که این پروب شامل صفر یا یک بایت داده با شماره ترتیب snd_una - 1 یا snd_nxt است. از آنجا که گیرنده بایتی در محدوده ترتیبی معتبر دریافت می‌کند، استاندارد وی را ناگزیر می‌سازد که فورا با یک ACK تازه مشتمل بر ظرفیت دقیق rcv_wnd پاسخ دهد.

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

تایمر Persist از الگوی عقب‌نشینی نمایی مشابه مهلت زمان ارسال مجدد (RTO) بهره می‌برد. بازه اولیه بر مبنای زمان رفت و برگشت پکت (RTT) تنظیم شده و در بازه میان TCP_RTO_MIN (معمولا ۲۰۰ میلی‌ثانیه) و TCP_RTO_MAX (۱۲۰ ثانیه در لینوکس) قرار می‌گیرد:

۱. بازه نخستین کاوش: از طریق محاسبه min(max(RTO, TCP_RTO_MIN), TCP_RTO_MAX) تعیین می‌شود. ۲. ضریب دو برابر شدن: با هر بار عدم پاسخگویی مناسب، مدت انتظار دو برابر گشته تا در سقف ۱۲۰ ثانیه تثبیت گردد. ۳. تداوم کاوش: برخلاف بازه‌های معمول داده که پس از عبور از tcp_retries2 ارتباط را قطع می‌کنند، تایمر ماندگاری تا زمانی که گیرنده با Win: 0 تاییدیه بفرستد به کاوش ادامه می‌دهد.

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

سندرم پنجره احمقانه (SWS): روش پیشگیری دیوید کلارک

چالش آسیب‌رسان دیگر در تنظیم پنجره، سندرم پنجره احمقانه (SWS بر اساس RFC 813) است. این عارضه زمانی بروز می‌کند که فرستنده داده‌ها را در بسته‌های خرد تقسیم کند یا گیرنده به محض تخلیه چند بایت اندک، پنجره‌ای مینیاتوری را گزارش نماید.

فرض کنید برنامه‌ای کند هر بار تنها یک بایت از سوکت برمی‌دارد. اگر سیستم فورا پنجره Win: 1 را اعلام کند، فرستنده بلافاصله یک بایت داده روانه شبکه می‌سازد. انتقال یک بایت داده در کنار ۲۰ بایت سرآیند IPv4 و ۲۰ بایت سرآیند TCP به یک بسته ۴۱ بایتی منجر می‌شود. در این حالت سربار پروتکل به ۹۷.۵ درصد جهش کرده و شتاب‌دهنده‌های رمزنگاری VPN را فلج می‌سازد.

برای رفع این مشکل، دیوید کلارک رویکردی هماهنگ در دو سوی ارتباط تدوین کرد که در استانداردهای RFC 813 و RFC 1122 تثبیت شد:

بخش رفتار استاندارد (الگوریتم کلارک) آستانه فعال‌سازی
گیرنده ضد SWS تاخیر در بازگشایی تا رسیدن به فضای کافی min(MSS, فضای_بافر / 2)
فرستنده ضد SWS انباشتن داده‌ها پیش از ارسال پکت کوچک تکمیل MSS یا پنجره Win >= MSS / 2
پشتیبان Persist ارسال پروب تک‌بایتی پس از انقضای تایمر انقضای زمان در وضعیت Win: 0

در لینوکس، تابع tcp_select_initial_window() تا زمانی که دست‌کم یک اندازه قطعه بیشینه (MSS) یا نیمی از بافر دریافتی (sk_rcvbuf / 2) آزاد نشود، از تبلیغ پنجره‌های ریز ممانعت به عمل می‌آورد.

تنظیمات هسته لینوکس: بستن پنجره و حفظ منابع سوکت

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

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

مهار سقف پنجره با قابلیت Window Clamping

گزینه سوکت tcp_window_clamping و متغیرهای مرتبط با sysctl امکان تعیین سقف قطعی برای پنجره دریافتی را فراهم می‌سازند:

# تنظیم حدود حافظه عمومی TCP (صفحات حافظه: حداقل، پیش‌فرض، حداکثر)
sudo sysctl -w net.ipv4.tcp_rmem="4096 87380 6291456"
sudo sysctl -w net.ipv4.tcp_wmem="4096 65536 4194304"

# پاکسازی سریع سوکت‌های رهاشده در شرایط کمبود حافظه
sudo sysctl -w net.ipv4.tcp_orphan_retries=2
sudo sysctl -w net.ipv4.tcp_max_orphans=32768

در نرم‌افزارهای شبکه متراکم، استفاده از پارامتر TCP_WINDOW_CLAMP در فراخوانی setsockopt() توصیه می‌شود تا مانع از گسترش بی‌رویه ضریب مقیاس پنجره توسط کلاینت‌ها گردد.

مقابله با Sockstress و آزادسازی سوکت‌های معلق

از آنجا که تایمر استاندارد ماندگاری می‌تواند در واکنش به تاییدهای صفر به شکل مستمر ادامه یابد، سرویس‌های مدرن از گزینه زمان‌بندی کاربر یعنی TCP_USER_TIMEOUT (RFC 5482) بهره می‌گیرند. با تنظیم این مقدار، هسته لینوکس حداکثر زمان مجاز برای حضور در وضعیت بن‌بست پنجره را کنترل کرده و در صورت فراتر رفتن از سقف مشخص، ارتباط را مسدود و بافرها را بازمی‌گرداند.

یکپارچه‌سازی معماری در راهکارهای RiceGuard و Core L3 VPN

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

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

۱. نظارت بر جریان داخلی: لایه داده در پروتکل RiceGuard سرآیندهای TCP را پایش می‌کند. با دریافت اعلامیه پنجره صفر، صف مجازی مربوطه بدون درنگ مهار شده تا از اشباع بافرهای لایه کاربری پیشگیری شود. ۲. پس‌فشار پیش‌دستانه: موتور اختصاصی Core L3 VPN از ساختار حلقوی بدون کپی استفاده می‌کند. پشته شبکه به جای انتظار برای پر شدن کامل بافر، مهار پنجره را پیشاپیش آغاز می‌کند تا جریان ترافیک بدون افت بسته تنظیم گردد. ۳. تولید پروب‌های تطبیقی: در شرایطی که شبکه بیرونی بسته ارتقای پنجره را از دست بدهد، کنترل‌کننده تونل فورا پروب پنجره صفر اختصاصی تولید کرده و همگام‌سازی را بدون فوت وقت بازیابی می‌کند.

نتیجه‌گیری: کنترل جریان قطعی در دروازه‌های ارتباطی نوین

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

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