SSD Nodes Learn 🎉 VPS از $5.50/ماه
راهنماها Matt Connorتوسط Matt Connor

نحوه عملکرد پروتکل WireGuard و مفهوم Cryptokey Routing

پارامتر AllowedIPs در فایل wg0.conf همزمان نقش جدول مسیریابی و لیست کنترل دسترسی را دارد. با مکانیزم Cryptokey Routing و پروتکل Noise در WireGuard آشنا شوید.

نحوه عملکرد WireGuard در یک ایده

عملکرد WireGuard بر پایه پیوند دادن هر بسته (packet) به یک کلید عمومی است. این مکانیزم که cryptokey routing نام دارد، کل طراحی این پروتکل را تشکیل می‌دهد: خط AllowedIPs در کنار یک peer، در واقع جدول مسیریابی برای بسته‌هایی است که از ماشین شما خارج می‌شوند و همچنین لیست کنترل دسترسی برای بسته‌هایی است که از آن peer دریافت می‌شوند. یک تنظیم، دو وظیفه. فایل AllowedIPs را با این دیدگاه بخوانید تا هر فایل پیکربندی WireGuard برایتان قابل‌فهم شود.

در اینجا هیچ جدول نشست (session table) مبتنی بر آدرس IP و هیچ پایگاه داده کاربری وجود ندارد. یک peer ترکیبی از یک کلید عمومی و مجموعه‌ای از آدرس‌هایی است که آن کلید مجاز به استفاده از آن‌هاست. فرآیند handshake و تایمرها برای این وجود دارند که این پیوند را در حین تغییرات شبکه زیرساختی، معتبر نگه دارند. اگر پیش از درک تئوری، به دنبال یک تونل عملیاتی هستید، آن را با یک VPN شخصی WireGuard روی VPS خود بسازید و سپس زمانی که یک خط پیکربندی برایتان مبهم بود، به اینجا بازگردید.

پارامتر AllowedIPs هم یک جدول مسیریابی است و هم یک لیست دسترسی

ابتدا جهت خروجی را در نظر بگیرید. هسته سیستم‌عامل شما یک بسته را از طریق جدول مسیریابی اصلی به دستگاه wg0 هدایت می‌کند. سپس WireGuard آدرس مقصد آن بسته را با جدولی که شامل پیشوندهای مجاز هر همتا (peer) است مطابقت می‌دهد؛ این تطبیق بر اساس طولانی‌ترین پیشوند انجام می‌شود. یک تطبیق موفق، همتایی را مشخص می‌کند که دارای یک کلید عمومی، یک کلید نشست و یک نقطه پایانی UDP است. بسته برای آن همتا رمزنگاری شده و به مقصد ارسال می‌شود.

اگر هیچ‌کدام از AllowedIPs همتاها مقصد بسته را پوشش ندهند، بسته‌ای ارسال نمی‌شود، زیرا کلیدی برای رمزنگاری آن وجود ندارد.

ping: sendmsg: Required key not available

این خطا تنها یک معنی دارد: آدرس مورد نظر شما در لیست هیچ همتایی تعریف نشده است. خطای متفاوت ping: sendmsg: Destination address required به این معناست که همتایی با مقصد مطابقت داشته، اما WireGuard هیچ نقطه پایانی برای آن ندارد، زیرا هیچ‌کدام پیکربندی نشده و هنوز هیچ مقداری یاد گرفته نشده است.

حالا جهت ورودی را بررسی می‌کنیم. یک بسته UDP به پورت گوش‌دهنده (listen port) می‌رسد. WireGuard نشست را از طریق ایندکس گیرنده در هدر پیدا می‌کند، شمارنده را با پنجره بازپخش (replay window) مقایسه کرده و سپس محتوا را رمزگشایی و احراز هویت می‌کند. تنها پس از این مرحله است که بسته داخلی خوانده می‌شود و آدرس مبدأ آن بسته داخلی باید در محدوده AllowedIPs همتای فرستنده باشد. اگر چنین نباشد، بسته حذف می‌شود. با فعال بودن dynamic debug، هسته دلیل این کار را در خطی مشابه زیر چاپ می‌کند:

wg0: Packet has unallowed src IP (10.8.0.9) from peer 2 (203.0.113.10:51820)

به همین دلیل است که یک همتا در سمت سرور با /32 مواجه می‌شود. همتایی که با AllowedIPs = 10.8.0.2/32 پیکربندی شده است، فقط می‌تواند بسته‌هایی را از 10.8.0.2 ارسال کند و نه از هیچ آدرس دیگری. اگر به جای آن 0.0.0.0/0 را بنویسید، آن کلاینت اجازه می‌یابد بسته‌هایی با هر آدرس مبدأیی که داخل تونل شما باشد، از جمله آدرس‌های متعلق به کلاینت‌های دیگر، تزریق کند.

پیشوندهای همپوشانی بر اساس اختصاصی بودن حل می‌شوند، زیرا جستجو بر مبنای طولانی‌ترین تطبیق پیشوند است. پیشوندهای یکسان در دو همتا رفتار متفاوتی دارند: ورودی به همتایی منتقل می‌شود که آخرین بار پیکربندی شده است و همتای اول بدون چاپ هیچ خطایی، دریافت آن ترافیک را متوقف می‌کند. دستور wg show wg0 allowed-ips جدولی را که در حال حاضر در هسته فعال است چاپ می‌کند؛ این همان چیزی است که در صورت مغایرت فایل روی دیسک با وضعیت در حال اجرا، ملاک عمل قرار می‌گیرد.

خواندن فایل پیکربندی با در نظر گرفتن مسیریابی کلید رمزنگاری

سمت سرور:

[Interface]
Address = 10.8.0.1/24
ListenPort = 51820
PrivateKey = <server private key>

[Peer]
PublicKey = <laptop public key>
AllowedIPs = 10.8.0.2/32

سمت کلاینت:

[Interface]
Address = 10.8.0.2/32
PrivateKey = <laptop private key>

[Peer]
PublicKey = <server public key>
Endpoint = vpn.example.com:51820
AllowedIPs = 0.0.0.0/0, ::/0
PersistentKeepalive = 25

یک کلمه کلیدی واحد، در دو سمت وزن متفاوتی دارد. در سمت کلاینت، این عبارت به معنای «ارسال تمام مقاصد به این همتا» است. در سمت سرور، به معنای «پذیرش تنها این یک آدرس از این همتا» است. این عدم تقارن در مقادیر نهفته است، نه در نقش‌ها.

نیمی از این کلیدها اصلاً بخشی از پروتکل نیستند. Address، DNS، MTU، PostUp و SaveConfig متعلق به wg-quick هستند؛ همان اسکریپت شلی که رابط شبکه را بالا می‌آورد. هسته سیستم‌عامل هرگز آن‌ها را نمی‌بیند. wg-quick strip wg0 پیکربندی کاهش‌یافته‌ای را چاپ می‌کند که ابزار wg واقعاً آن را بارگذاری می‌کند؛ این سریع‌ترین راه برای مشاهده این تفکیک است.

عملکرد واقعی handshake

handshake در WireGuard از پروتکل Noise_IKpsk2 از چارچوب Noise Protocol Framework استفاده می‌کند. بخش IK برای یک مدیر سیستم بخش کاربردی است: کلید عمومی ثابت پاسخ‌دهنده (responder) از قبل برای آغازگر (initiator) شناخته‌شده است، زیرا این کلید همان PublicKey در بلوک [Peer] شماست و آغازگر کلید عمومی ثابت خود را در اولین پیام به‌صورت رمزنگاری‌شده ارسال می‌کند. بنابراین هیچ تبادل گواهی و رفت‌وبرگشت اضافی برای احراز هویت وجود ندارد. یک ناظر غیرفعال نمی‌تواند تشخیص دهد کدام کلید در حال برقراری تماس است، مگر اینکه کلید خصوصی پاسخ‌دهنده را در اختیار داشته باشد.

هزینه این کار یک رفت‌وبرگشت (round trip) است. پیام آغازین 148 بایت و پاسخ 92 بایت است و داده‌ها بلافاصله پس از آن جریان می‌یابند. هر طرف برای هر handshake یک جفت‌کلید ephemeral از نوع Curve25519 تولید می‌کند و کلیدهای نشست (session keys) از زنجیره‌ای از نتایج Diffie-Hellman حاصل می‌شوند که کلیدهای ثابت و ephemeral را با هم ترکیب می‌کند. کلیدهای خصوصی ephemeral سپس حذف می‌شوند که این امر باعث ایجاد forward secrecy می‌شود: کسی که ترافیک شما را امروز ضبط کند و سال آینده کلید خصوصی سرور را بدزدد، همچنان نمی‌تواند آنچه را ضبط کرده است، بخواند.

یک آغازگر handshake حاوی یک timestamp از نوع TAI64N است و هر peer بزرگ‌ترین timestamp دیده‌شده از طرف مقابل را به خاطر می‌سپارد، بنابراین آغازگرهای تکراری (replayed) رد می‌شوند. بسته‌های داده دارای یک counter 64 بیتی هستند که به عنوان nonce استفاده می‌شود و گیرنده یک پنجره لغزان (sliding window) از counterهای اخیر را نگه می‌دارد، بنابراین حملات بازپخش (replay) و تغییر ترتیب شدید بسته‌ها بدون نیاز به وضعیت اتصال (connection state) مشابه TCP مدیریت می‌شوند.

کلیدهای نشست عمر کوتاهی دارند و تایمرها به جای اینکه قابل تنظیم باشند، در کد کامپایل شده‌اند.

ChartWireGuard protocol timers, in seconds
The data behind this chart
[
  {
    "label": "REKEY_TIMEOUT",
    "seconds": 5,
    "notes": "resend a handshake initiation that got no answer"
  },
  {
    "label": "KEEPALIVE_TIMEOUT",
    "seconds": 10,
    "notes": "send a keepalive after receiving data and sending none back"
  },
  {
    "label": "REKEY_ATTEMPT_TIME",
    "seconds": 90,
    "notes": "give up on the handshake and report the peer as down"
  },
  {
    "label": "REKEY_AFTER_TIME",
    "seconds": 120,
    "notes": "sender begins a fresh handshake for a new session key"
  },
  {
    "label": "REJECT_AFTER_TIME",
    "seconds": 180,
    "notes": "the old session key is refused and traffic stops"
  }
]

این‌ها ثابت‌هایی از مشخصات پروتکل هستند، نه اندازه‌گیری‌های تجربی. 5 مورد از آن‌ها کل چرخه حیات نشست را هدایت می‌کنند. پس از 120 ثانیه استفاده، فرستنده یک handshake جدید را آغاز می‌کند و پس از 180 ثانیه، کلید قدیمی کاملاً رد می‌شود، بنابراین تا زمانی که یک handshake جدید کامل نشود، ترافیک متوقف می‌ماند. آغازگری که پاسخی دریافت نکند، هر 5 ثانیه دوباره ارسال شده و پس از 90 ثانیه رها می‌شود. به همین دلیل است که wg show مقدار latest handshake را به عنوان یک سن نسبی چاپ می‌کند و به همین دلیل است که یک تونل فعال و سالم، آن سن را کوچک نگه می‌دارد. اگر در حالی که فعالانه در حال ارسال ترافیک هستید، این سن افزایش می‌یابد، به این معنی است که handshakeها با شکست مواجه می‌شوند، نه اینکه تونل بیکار است.

چرا یک همتا (peer) نقش کلاینت یا سرور ندارد

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

یک همتا با داشتن endpoint پیکربندی‌شده می‌تواند یک handshake را آغاز کند. همتایی که فاقد آن است، منتظر می‌ماند و سپس آدرس و پورت طرف مقابل را از اولین بسته‌ای که به‌درستی احراز هویت شده است، یاد می‌گیرد. آن endpoint آموخته‌شده ذخیره می‌شود و هر زمان که بسته معتبری از یک آدرس جدید برسد، به‌روزرسانی می‌گردد. رومینگ به همین شکل کار می‌کند: لپ‌تاپی که از وای‌فای به شبکه موبایل منتقل می‌شود، همان تونل را حفظ می‌کند، زیرا نشست (session) به جای آدرس IP، توسط کلید و ایندکس شناسایی می‌شود. هیچ چیزی دوباره متصل نمی‌شود، زیرا در معنای TCP، هیچ‌گاه اتصالی برقرار نبوده است.

همین مکانیزم واقعیتی را ایجاد می‌کند که دانستن آن مفید است: همتایی که آدرس عمومی دارد، همیشه آخرین IP عمومی شناخته‌شده طرف مقابل را در اختیار دارد و wg show آن را نمایش می‌دهد.

پریمیتیوهای ثابت، بدون نیاز به مذاکره

در WireGuard هیچ فهرستی از ciphersuite وجود ندارد. برای رمزنگاری احراز هویت‌شده از ChaCha20-Poly1305، برای توافق کلید از Curve25519، برای هش کردن از BLAKE2s و برای مشتق‌سازی کلید از HKDF استفاده می‌شود. تمامی پیاده‌سازی‌ها از همین موارد استفاده می‌کنند، بنابراین مرحله‌ای برای مذاکره (negotiation) جهت تحلیل و یا مسیری برای تنزل (downgrade) به گزینه‌های ضعیف‌تر وجود ندارد. این یک بده‌بستان واقعی است: اگر یکی از این پریمیتیوها شکسته شود، راه‌حل، ارائه نسخه جدیدی از کل پروتکل و به‌روزرسانی در هر دو سمت است، نه تغییر در پیکربندی. همین تصمیم واحد، بخش بزرگی از کد و اکثر حالت‌های شکست (failure modes) موجود در تونل‌های مبتنی بر TLS را حذف می‌کند؛ این همان نکته‌ای است که مقایسه در WireGuard در برابر OpenVPN عمدتاً بر آن استوار است.

چرا پورت به اسکنر پاسخ نمی‌دهد

هر پیام handshake دارای فیلدی به نام mac1 است. این فیلد یک MAC (کد احراز اصالت پیام) است که با استفاده از کلیدی که از کلید عمومی ثابت پاسخ‌دهنده مشتق شده، روی پیام محاسبه می‌شود. فرستنده‌ای که آن کلید عمومی را نداشته باشد، نمی‌تواند یک mac1 معتبر تولید کند و گیرنده چنین بسته‌ای را بدون هیچ پاسخی دور می‌ریزد. نه خطایی، نه reset و نه پیام ICMP.

نتیجهٔ مشهود این است که اسکن UDP هیچ پاسخی دریافت نمی‌کند.

sudo nmap -sU -p 51820 vpn.example.com

ابزار nmap وضعیت open|filtered را گزارش می‌دهد که همان پاسخی است که برای پورتی که فایروال به‌صورت بی‌صدا بسته‌ها را در آن دور می‌ریزد، ارائه می‌دهد. رفتار پورت، چه WireGuard در حال گوش دادن باشد و چه نباشد، برای هر کسی که کلید عمومی شما را در اختیار نداشته باشد، یکسان است.

فیلد دوم، یعنی mac2، فشار ناشی از حملات منع سرویس (DoS) را مدیریت می‌کند. هنگامی که گیرنده تحت بار کاری است، به یک initiation معتبر با یک پاسخ cookie به طول 64 بایت که به آدرس مبدأ فرستنده متصل است پاسخ می‌دهد و تا زمانی که فرستنده آن cookie را بازنگرداند، از انجام محاسبات سنگین کلید عمومی خودداری می‌کند. این کار پیش از صرف هرگونه توان پردازشی، واقعی بودن آدرس مبدأ را اثبات می‌کند و تنها در زمان تحت بار بودن سیستم فعال می‌شود.

چرا 0.0.0.0/0 یک peer را به default route شما تبدیل می‌کند

زیرا AllowedIPs جدول مسیریابی است و AllowedIPs = 0.0.0.0/0, ::/0 تمام مقاصد را برای آن peer مطالبه می‌کند. این همان تنظیم کامل full tunnel است.

مسیریابی‌ای که این کار را ممکن می‌کند، از خودِ خط دستور جالب‌تر است. یک default route ساده از طریق wg0 باعث ایجاد حلقه (loop) می‌شود، زیرا بسته UDP رمزنگاری‌شده‌ای که ترافیک شما را حمل می‌کند نیز باید از دستگاه خارج شود و با همان default route خودش مطابقت پیدا می‌کند. wg-quick با استفاده از policy routing از این اتفاق جلوگیری می‌کند. این ابزار بسته‌های خروجی خودِ WireGuard را با یک fwmark علامت‌گذاری می‌کند، default route تونل را در یک جدول مسیریابی جداگانه قرار می‌دهد و قوانینی اضافه می‌کند تا فقط ترافیک علامت‌گذاری‌نشده به آن برسد. دستور ip rule show را اجرا کنید تا نتیجه را ببینید:

32764:	from all lookup main suppress_prefixlength 0
32765:	not from all fwmark 0xca6c lookup 51820
32766:	from all lookup main

مقدار 0xca6c در مبنای شانزده برابر با 51820 است و 51820 همان شماره جدول است. قانون suppress_prefixlength 0 باعث می‌شود جدول اصلی از default route خودش صرف‌نظر کند، بنابراین مسیرهای خاص مانند زیرشبکه محلی شما همچنان اولویت دارند، در حالی که بقیه ترافیک به جدول تونل هدایت می‌شود. یک split tunnel به هیچ‌کدام از این‌ها نیاز ندارد: یک لیست محدودتر مانند AllowedIPs = 10.8.0.0/24, 10.20.0.0/16 به مسیرهای عادی در جدول اصلی تبدیل می‌شود.

یک نکته که full tunnel به‌تنهایی آن را حل نمی‌کند، name resolution است؛ زیرا resolverای که کلاینت شما از شبکه محلی دریافت کرده معمولاً فعال باقی می‌ماند و مسیر آن خاص‌تر است. این یک وظیفه جداگانه است که در DNS که به خارج از تونل WireGuard نشت می‌کند به آن پرداخته شده است.

هدف اصلی PersistentKeepalive چیست

WireGuard زمانی که ترافیکی وجود ندارد، هیچ بسته‌ای ارسال نمی‌کند. نه ضربان قلب (heartbeat)، نه تازه‌سازی نشست (session refresh) و نه هیچ چیز دیگری روی شبکه وجود ندارد. این سکوت به حفظ عمر باتری و همچنین در سناریوی اسکنر که در بالا ذکر شد کمک می‌کند، اما یک پیکربندی خاص را مختل می‌سازد.

یک peer که پشت NAT (ترجمه آدرس شبکه) یا پشت یک فایروال stateful قرار دارد، تنها زمانی از بیرون قابل دسترسی است که یک نگاشت (mapping) در آن دستگاه وجود داشته باشد؛ این نگاشت توسط یک بسته خروجی ایجاد می‌شود. طول عمر معمول نگاشت‌های UDP از حدود 30 ثانیه شروع می‌شود. هنگامی که این نگاشت منقضی شود، بسته‌هایی که از سمت عمومی (public) می‌آیند توسط دستگاه میانی (middlebox) دور ریخته می‌شوند و تونل تا زمانی که peer پشت NAT چیزی ارسال نکند، قطع به نظر می‌رسد. PersistentKeepalive = 25 هر 25 ثانیه یک بسته احراز هویت‌شدهٔ خالی ارسال می‌کند که زمان آن کمتر از کوتاه‌ترین طول عمر معمول است، بنابراین نگاشت باز می‌ماند.

این تنظیم را روی peer که پشت NAT قرار دارد اعمال کنید. سروری که دارای آدرس عمومی و پورت UDP باز است به آن نیازی ندارد و فعال کردن آن در آنجا فقط باعث ایجاد ترافیک اضافه می‌شود. آن را با keepalive خودکار اشتباه نگیرید؛ keepalive خودکار 10 ثانیه پس از اینکه یک peer داده‌ای دریافت می‌کند و چیزی برای ارسال به عقب ندارد، فعال می‌شود. آن قابلیت همیشه روشن است و قابل پیکربندی نیست.

مسیریابی شبکه محلی (LAN) از طریق تونل، قابلیتی در WireGuard نیست

فرض کنید peer B در یک شبکه خانگی 192.168.50.0/24 قرار دارد و peer A باید به آن دسترسی داشته باشد. دو سیستم مجزا باید با هم هماهنگ شوند و تنها یکی از آن‌ها WireGuard است.

بخش مربوط به WireGuard: باید 192.168.50.0/24 را به AllowedIPs در peer B روی سیستم A اضافه کنید. این کار باعث می‌شود A ترافیک مربوط به آن پیشوند را به سمت B مسیریابی کند و همچنین بسته‌هایی را که از سمت B با آن آدرس‌های مبدأ می‌آیند، بپذیرد. بدون این تنظیم، مسیریابی کلید رمزنگاری (cryptokey routing) نه کلیدی برای مقصد دارد و نه مجوزی برای مبدأ.

بخش مربوط به هسته سیستم‌عامل (Kernel): در سیستم B، مقدار net.ipv4.ip_forward باید 1 باشد؛ در غیر این صورت، هسته هر بسته رمزگشایی‌شده‌ای را که مستقیماً به خود B آدرس‌دهی نشده باشد، حذف می‌کند. زنجیره forward در فایروال B نیز باید اجازه عبور این ترافیک را بدهد. میزبان‌های موجود در شبکه محلی (LAN) نیاز به یک مسیر بازگشت به سمت 10.8.0.0/24 دارند، یا اینکه B باید از source NAT استفاده کند تا پاسخ‌ها از طریق B بازگردند.

وظیفه WireGuard زمانی به پایان می‌رسد که بسته رمزگشایی‌شده را به هسته تحویل می‌دهد. هر اتفاقی که پس از آن می‌افتد، مربوط به مسیریابی و فیلترینگ عادی در لینوکس است؛ به همین دلیل است که این خطا در شمارنده‌های nft list ruleset یا در ip -s link show wg0 دیده می‌شود و نه در wg show. اگر ترجیح می‌دهید مدیریت peerها را از طریق یک رابط وب انجام دهید، اجرای wg-easy در Docker ورودی‌های peer را برای شما ایجاد می‌کند، هرچند قوانین مربوط به فوروارد کردن ترافیک همچنان بر عهده میزبان است.

چرا WireGuard در هسته (Kernel) قرار دارد

wg0 یک درایور دستگاه شبکه است. بسته‌ها از طریق پشته مسیریابی عادی به آن می‌رسند، در کانتکست softirq رمزگذاری می‌شوند و بدون اینکه هرگز وارد فضای کاربری (userspace) شوند، از طریق یک سوکت UDP خارج می‌شوند. این همان دلیلی است که باعث افزایش نرخ انتقال داده (throughput) می‌شود و همچنین دلیل آن است که این ماژول در حدود چهار هزار خط کد باقی مانده است؛ کدی که به اندازه کافی کوچک است تا بازبینی شود و در مارس 2020 به هسته اصلی Linux 5.6 ادغام گردد. توزیع‌های Ubuntu 24.04 و Debian 13 آن را به همراه دارند، بنابراین تنها بسته wireguard-tools است که در آن‌ها وجود ندارد.

یک رابط عادی بودن، پیامدهای عملی به همراه دارد. tcpdump -ni wg0 بسته‌های داخلی متن‌باز (plaintext) را نشان می‌دهد، در حالی که tcpdump -ni eth0 udp port 51820 بسته‌های خارجی رمزگذاری‌شده را نمایش می‌دهد و مقایسه این دو به شما بلافاصله می‌گوید که کدام جهت دچار اختلال شده است. netfilter و ابزارهای شکل‌دهی ترافیک (traffic shaping)، با wg0 مانند هر لینک دیگری رفتار می‌کنند. در مواردی که ماژول هسته در دسترس نیست، مانند مجازی‌سازی کانتینری که هسته میزبان را به اشتراک می‌گذارد، wireguard-go همان پروتکل را در فضای کاربری و از طریق یک دستگاه TUN پیاده‌سازی می‌کند که هزینه واقعی آن کاهش نرخ انتقال داده است، زیرا هر بسته دو بار از مرز هسته عبور می‌کند.

مواردی که WireGuard از آن‌ها محافظت نمی‌کند

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

  • این پروتکل پنهان نمی‌کند که شما از WireGuard استفاده می‌کنید. پیام‌های Handshake اندازه‌های ثابتی دارند، بایت اول نوع پیام را مشخص می‌کند و بستر انتقال UDP است. بازرسی عمیق بسته (DPI) به‌راحتی آن را شناسایی می‌کند و شبکه‌هایی که با VPN مخالف هستند، می‌توانند آن را مسدود کنند. قابلیت Obfuscation (مبهم‌سازی) به‌طور عمدی در طراحی لحاظ نشده است.
  • این پروتکل حجم یا زمان‌بندی ترافیک را پنهان نمی‌کند. Payloadها فقط تا مرز 16 بایت Padding می‌شوند، بنابراین ناظر شبکه همچنان متوجه می‌شود که چه زمانی داده ارسال می‌کنید و حجم تقریبی آن چقدر است.
  • آخرین نقطه پایانی (endpoint) شناخته‌شده را نگه می‌دارد. همتایی که آدرس عمومی دارد، IP عمومی فعلی طرف مقابل را ذخیره می‌کند و wg show آن را نمایش می‌دهد. این موضوع در کنار آدرس تونل که در فایل پیکربندی ثابت است، یک شناسه پایدار ایجاد می‌کند که کاربر را بین شبکه‌های مختلف دنبال می‌کند. روی VPS شخصی خودتان، این مسئله مشکلی ایجاد نمی‌کند. به همین دلیل است که سرویس‌های تجاری، لایه‌ای اضافه بر روی این پروتکل قرار می‌دهند.
  • این پروتکل یک کلید را احراز هویت می‌کند، نه یک شخص را. هر کسی که فایل کلید خصوصی را در اختیار داشته باشد، همان همتا محسوب می‌شود. دسترسی /etc/wireguard را روی 700 و فایل‌های کلید را روی 600 تنظیم کنید.
  • هیچ لیست ابطال (revocation list) یا تاریخ انقضایی وجود ندارد. دسترسی زمانی پایان می‌یابد که ورودی همتا را از تمام سرورهایی که آن را دارند حذف کنید؛ کلیدهای استاتیک تا زمانی که آن‌ها را حذف نکنید، معتبر باقی می‌مانند.

هیچ‌کدام از این موارد WireGuard را ضعیف نمی‌کند. این ویژگی‌ها باعث کوچک ماندن آن شده‌اند و کوچک بودن، هدف اصلی است: این پروتکل احراز هویت و رمزنگاری را انجام می‌دهد و مدیریت هویت و تخصیص آدرس را به هر آنچه شما بر روی آن می‌سازید، واگذار می‌کند. یک لایه هماهنگ‌کننده از نوعی که در مقایسه WireGuard با Tailscale توضیح داده شد، دقیقاً برای پر کردن همین شکاف وجود دارد و از همان صفحه داده‌ای (data plane) استفاده می‌کند که به‌تازگی درباره آن خواندید.

FAQ

مسیریابی کلید رمزنگاری (cryptokey routing) در WireGuard چیست؟

مسیریابی کلید رمزنگاری قانونی است که هر بسته را به یک کلید عمومی متصل می‌کند. هر ورودی همتا (peer) شامل فهرستی از پیشوندها در AllowedIPs است. در مسیر خروجی، WireGuard همتا را با تطبیق مقصد بسته با فهرست هر همتا انتخاب می‌کند (اولویت با طولانی‌ترین پیشوند است)، بنابراین این فهرست مانند یک جدول مسیریابی عمل می‌کند. در مسیر ورودی، پس از رمزگشایی و احراز هویت بسته، آدرس منبع داخلی آن باید در همان فهرست همتا قرار داشته باشد، در غیر این صورت بسته حذف می‌شود؛ بنابراین این فهرست به عنوان یک لیست کنترل دسترسی (ACL) نیز عمل می‌کند. WireGuard پیکربندی مسیریابی جداگانه یا فایروال داخلی مجزا ندارد، زیرا همان یک فهرست هر دو وظیفه را انجام می‌دهد.

آیا به PersistentKeepalive در هر دو سمت نیاز دارم؟

خیر. آن را فقط در سمتی تنظیم کنید که پشت NAT (ترجمه آدرس شبکه) یا پشت یک فایروال stateful قرار دارد؛ که معمولاً سمت کلاینت است. WireGuard در زمان بیکاری هیچ داده‌ای ارسال نمی‌کند، بنابراین نگاشتی که به سمت مقابل اجازه می‌دهد به آن همتا دسترسی داشته باشد، اغلب ظرف یک دقیقه منقضی می‌شود و تونل در یک جهت غیرفعال به نظر می‌رسد. PersistentKeepalive = 25 هر 25 ثانیه یک بسته خالی احراز هویت‌شده ارسال می‌کند و نگاشت را باز نگه می‌دارد. همتایی که دارای آدرس عمومی و پورت UDP باز است، به این تنظیم نیاز ندارد.

چرا پینگ روی تونل خطای "Required key not available" می‌دهد؟

زیرا آدرس مقصد در هیچ‌کدام از AllowedIPs همتاها وجود ندارد، بنابراین مسیریابی کلید رمزنگاری هیچ کلیدی برای رمزنگاری بسته پیدا نکرده و هسته سیستم‌عامل از ارسال آن خودداری کرده است. دستور wg show wg0 allowed-ips را اجرا کنید و خروجی آن را با آدرسی که پینگ می‌کنید مقایسه نمایید. خطای مشابه Destination address required مشکل متفاوتی است: یک همتا مطابقت داده شده، اما WireGuard هیچ endpoint برای آن ندارد، زیرا هیچ‌کدام پیکربندی نشده و هنوز هیچ بسته احراز هویت‌شده‌ای از آن همتا دریافت نشده است.

آیا فایروال می‌تواند WireGuard را شناسایی و مسدود کند؟

بله. WireGuard ترافیک شما را احراز هویت و رمزنگاری می‌کند و هیچ تلاشی برای پنهان‌سازی خود انجام نمی‌دهد. پیام‌های دست‌دادن (handshake) دارای اندازه ثابت 148 و 92 بایت هستند، بایت اول هر پیام نوع آن را مشخص می‌کند و پروتکل انتقال UDP است؛ بنابراین بازرسی عمیق بسته (DPI) به راحتی این پروتکل را شناسایی می‌کند. شبکه‌هایی که UDP را مسدود می‌کنند یا پروتکل‌ها را انگ‌گذاری (fingerprint) می‌کنند، آن را متوقف خواهند کرد. پنهان کردن تونل به معنای بسته‌بندی آن در یک پروتکل دیگر است که این کار نیازمند ابزاری جداگانه است و جزو تنظیمات WireGuard محسوب نمی‌شود.