هنگامی که یک شبکه خصوصی مجازی برای انتقال تمامی داده‌های خروجی یک سیستم (0.0.0.0/0 و ::/0) پیکربندی می‌شود، تمام بسته‌های تولیدشده باید از تونل رمزگذاری‌شده عبور کنند. این طراحی یک چالش ساختاری ایجاد می‌کند که با عنوان بازگشت تکراری مسیریابی (routing recursion) شناخته می‌شود. داده‌های رمزگذاری‌شده باید از طریق یک سوکت UDP بیرونی در بستر شبکه فیزیکی ارسال شوند. اگر سیستم‌عامل تمام ترافیک خروجی را به سمت رابط مجازی تونل هدایت کند، بسته بیرونی مجدداً به همان درایور بازگردانده شده و یک چرخه بی‌پایان بسته‌بندی رخ می‌دهد.

پروتکل‌های پیشین مانند OpenVPN یا IPsec سنتی تلاش می‌کردند با افزودن مسیرهای ثابت به جدول اصلی و نشانه رفتن به نشانی سرور از طریق دروازه فیزیکی، این تداخل را حل کنند. اما این روش در زمان جابه‌جایی میان شبکه‌های وای‌فای و سلولی، تغییر نشانی‌های پویا و توزیع بار Anycast کارایی خود را از دست می‌دهد.

پروتکل WireGuard در لینوکس با ترکیب نشانه‌های دیواره آتش (fwmark)، گزینه سوکت SO_MARK و پایگاه داده قواعد مسیریابی (RPDB)، بازگشت ناخواسته مسیرها را به‌طور بنیادین متوقف می‌کند.

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

برای درک اهمیت مسیریابی مبتنی بر سیاست، چرخه عبور یک بسته اطلاعاتی را در یک سامانه لینوکسی با رابط فعال wg0 در نظر بگیرید.

هنگامی که یک برنامه داده‌ای را به سمت یک سرور در نشانی 203.0.113.50 ارسال می‌کند، هسته سیستم‌عامل مسیر خروجی را برمی‌گزیند. اگر مدیر شبکه از دستور ساده ip route add default dev wg0 استفاده کرده باشد، هسته رابط wg0 را به عنوان مقصد بعدی انتخاب می‌کند. درایور WireGuard بسته را دریافت کرده، پس از تطبیق با جدول Cryptokey Routing، داده‌ها را با استفاده از ChaCha20-Poly1305 رمزگذاری نموده و آن را درون یک بسته بیرونی UDP به نشانی 198.51.100.10:51820 قرار می‌دهد.

بسته نرم‌افزاری کاربر (مقصد: 203.0.113.50)
        │
        ▼
   جدول مسیرهای هسته: default dev wg0
        │
        ▼
درایور WireGuard (wg0): بسته‌بندی خارجی UDP (مقصد: 198.51.100.10:51820)
        │
        ▼
   جدول مسیرهای هسته: انطباق دوباره با default dev wg0! ──> ایجاد حلقه تکرار

در لحظه‌ای که سوکت UDP بسته را به پشته شبکه تحویل می‌دهد، هسته لینوکس بار دیگر جدول پایگاه داده فوروارد (FIB) را بررسی می‌کند. از آنجا که مسیر پیش‌فرض سیستم همچنان به سمت wg0 تنظیم شده است، بسته بیرونی دوباره به درون رابط wg0 بازگردانده می‌شود. درایور تلاش می‌کند بسته‌ای را که پیش‌تر رمزگذاری شده دوباره رمزگذاری کند؛ این اتفاق باعث پر شدن صف بافر سوکت، فراتر رفتن از حد اندازه بسته (MTU) و در نهایت دور ریخته شدن بسته‌ها توسط هسته می‌گردد و ارتباط فوراً قطع می‌شود.

پایگاه قواعد مسیریابی RPDB و معماری دو جدول مجزا

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

پیکربندی پایه لینوکس شامل سه جدول استاندارد است:

  1. local (جدول 255): رسیدگی به نشانی‌های داخلی و پخش همگانی.
  2. main (جدول 254): شامل مسیرهای اختصاص داده شده توسط رابط‌های فیزیکی و سرویس‌های DHCP.
  3. default (جدول 253): جدول پشتیبان برای سیاست‌های تکمیلی.

ابزارهای راه‌اندازی WireGuard مانند wg-quick به مسیرهای پیش‌فرض موجود در جدول main دست نمی‌زنند. در عوض، یک جدول اختصاصی — معمولاً با شناسه 51820 — ایجاد شده و مسیر پیش‌فرض تونل wg0 در آن قرار می‌گیرد:

# ایجاد مسیر پیش‌فرض در جدول اختصاصی
ip route add default dev wg0 table 51820
ip -6 route add default dev wg0 table 51820

با جداسازی مسیر پیش‌فرض تونل از دروازه شبکه فیزیکی، دو محیط مسیریابی موازی شکل می‌گیرد. چالش اصلی هدایت ترافیک برنامه‌ها به سمت جدول 51820 و فراهم کردن امکان دسترسی سوکت انتقال WireGuard به جدول main است.

نشانه‌گذاری سوکت با SO_MARK و سنجش fwmark

پل ارتباطی برای عبور ایمن سوکت به سمت کارت شبکه فیزیکی، نشانه‌های دیواره آتش (fwmark) است. در هسته لینوکس، هر ساختار بافر داده شبکه (struct sk_buff) یک فیلد ۳۲ بیتی به نام skb->mark دارد. این نشانه تنها در حافظه کاری هسته پایدار است و در طول کابل شبکه یا سربرگ‌های بسته IP ظاهر نمی‌شود.

هنگامی که ماژول WireGuard سوکت بیرونی UDP را ایجاد می‌کند، گزینه SO_MARK را روی آن اعمال می‌نماید:

int fwmark = 51820;
setsockopt(sock_fd, SOL_SOCKET, SO_MARK, &fwmark, sizeof(fwmark));

تمامی بسته‌های خروجی این سوکت نشانه عددی 51820 را دریافت می‌کنند. برای مدیریت مسیر این بسته‌ها، قواعد متناسب در RPDB افزوده می‌شود:

# تعریف قواعد برای تفکیک ترافیک
ip rule add not fwmark 51820 table 51820
ip rule add table main suppress_prefixlength 0

فرآیند تصمیم‌گیری هسته به شرح زیر صورت می‌پذیرد:

  1. ترافیک برنامه‌های عادی: یک مرورگر بسته‌ای را به سمت نشانی 203.0.113.50 می‌فرستد. سوکت مرورگر بدون نشانه است، بنابراین مقدار skb->mark برابر با 0 خواهد بود. هسته قاعده not fwmark 51820 را ارزیابی می‌کند. با توجه به این که 0 != 51820 است، قاعده تطبیق یافته و بسته به جدول 51820 و رابط wg0 فرستاده می‌شود.
  2. ترافیک انتقال پروتکل: پس از رمزگذاری، بسته بیرونی از سوکت نشانه‌دار خارج می‌شود (skb->mark = 51820). هسته قاعده not fwmark 51820 را بررسی می‌کند. از آنجا که بسته دارای همین نشانه است، شرط منفی نقض می‌گردد. هسته جدول 51820 را نادیده گرفته و به اولویت بعدی یعنی جدول main مراجعه می‌کند. در جدول main، رابط فیزیکی eth0 یا wlan0 بسته را مستقیماً به مودم یا روتر فیزیکی منتقل می‌سازد.

این رویکرد دوگانه تضمین می‌کند که بسته‌های رمزگذاری‌شده بدون بازگشت به wg0، شبکه را به مقصد رابط فیزیکی ترک کنند.

پالایش مسیر بازگشتی و پیامدهای rp_filter

اگرچه ترافیک ارسالی به درستی هدایت می‌شود، در صورت فعال بودن بررسی‌های سخت‌گیرانه ورودی، بسته‌های پاسخ دریافتی ممکن است حذف شوند. سازوکار اصلی در این بخش، پالایش مسیر بازگشتی (Reverse Path Filtering یا RPF) است که در RFC 3704 تعریف شده و با متغیر rp_filter کنترل می‌شود.

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

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

  • 0 (غیرفعال): هیچ آزمایشی انجام نمی‌گیرد.
  • 1 (سخت‌گیرانه): بسته ورودی حتماً باید از رابطی برسد که جدول مسیر برای فرستادن پاسخ برمی‌گزیند.
  • 2 (منعطف): نشانی مبدأ تنها کافی است در یکی از جدول‌های سیستم مسیری معتبر داشته باشد.

در حالت سخت‌گیرانه (rp_filter = 1)، عدم تقارن مسیرهای سیاست‌گذاری‌شده سبب حذف بسته‌ها می‌شود. وقتی پاسخ از اینترنت به رابط فیزیکی eth0 می‌رسد، هسته مسیر بازگشت را استعلام می‌نماید. از آنجا که این بررسی نشانه fwmark ندارد، به جدول 51820 ارجاع داده شده و جدول می‌گوید تمامی ترافیک به wg0 تعلق دارد. ناهمخوانی رابط‌ها باعث می‌شود هسته بسته دریافتی را مشکوک دانسته و حذف کند.

برای جلوگیری از این اختلال خاموش، تنظیمات WireGuard حالت RPF را روی وضعیت منعطف قرار می‌دهند:

sysctl -w net.ipv4.conf.all.rp_filter=2
sysctl -w net.ipv4.conf.eth0.rp_filter=2
sysctl -w net.ipv4.conf.wg0.rp_filter=2

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

مقایسه محیط‌های همراه با رایانه‌ها: Android VpnService و فضاهای نام شبکه

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

در سیستم‌عامل اندروید، برنامه‌ها به شکل مستقیم قادر به فراخوانی setsockopt(SO_MARK) نیستند. فریم‌ورک اندروید قابلیت android.net.VpnService را عرضه می‌کند. در این ساختار، هنگام باز شدن سوکت، برنامه توصیف‌گر فایل را با تابع VpnService.protect(int socketFd) به سیستم می‌سپارد تا سوکت به طور مستقیم به شبکه فیزیکی متصل گردد و از ورود به رابط مجازی مصون بماند.

لینوکس رایانه:      سوکت -> SO_MARK (51820) -> قاعده RPDB (not fwmark) -> جدول main
اندروید همراه:       سوکت -> VpnService.protect() -> اتصال مستقیم به شبکه فیزیکی
فضاهای نام شبکه:    رابط eth0 در netns0 <-> رابط wg0 در init_net (تفکیک کامل)

در سرورها نیز فضاهای نام شبکه (ip netns) راهکار کارآمدی ارائه می‌دهند. با قرار دادن کارت شبکه فیزیکی در یک فضای نام جداگانه و نگه‌داشتن wg0 در فضای نام اصلی، بدون نیاز به علامت‌گذاری ترافیک، احتمال بروز چرخه بازگشتی از میان برداشته می‌شود.

معماری چندجدولی RiceGuard و مهار نشت DNS

در کاربری‌های روزمره، نرم‌افزارها باید تبادل ترافیک هنگام جابه‌جایی میان شبکه‌ها و ارتباط با سرویس‌های نام‌گذاری محلی مانند systemd-resolved روی 127.0.0.53 را مدیریت کنند.

فناوری RiceGuard ساختار پیشرفته‌ای را به کار می‌بندد:

  1. زنجیره قواعد اولویت‌بندی‌شده: پردازش داده‌های محلی، بسته‌های چندپخشی و شبکه‌های داخلی پیش از اعمال مسیرهای تونل مجازی.
  2. قفل ایمنی دیواره آتش: همگام‌سازی قواعد با فیلترهای nftables. چنانچه تونل ناپایدار شود، بسته‌های بدون علامت معتبر مسدود می‌شوند تا اطلاعات رمزنشده نشت نکند.
  3. جداسازی درخواست‌های سامانه نام دامنه: تمامی پرس‌وجوهای DNS سامانه‌ای به درون بستر امن هدایت می‌شوند تا خطر رهگیری نشانی‌ها از بین برود.

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

دانلود VPNRice