محمدرضا نیل‌فروش
محمدرضا نیل‌فروش
خواندن ۱۳ دقیقه·۳ سال پیش

پروتکل WireGuard

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

سایت رسمی این پروتکل https://www.wireguard.com است. نسخه لینوکس این پروتکل در ماه مارس سال 2020 پس از رسیدن به یک وضعیت پایدار، منتشر شد و در کرنل 5.6 قرار گرفت. این پروتکل در ابتدا تنها برای کرنل لینوکس منتشر شد ولی اکنون به صورت cross-platform می‌باشد و داخل سیستم‌عامل‌های دیگری از جمله iOS ،BSD ،macOS ،Windows و Android قابل استفاده است.

یکی از اهداف پروتکل WireGuard این است که همانند SSH به سادگی قابل پیاده‌سازی باشد. یک اتصال VPN با تبادل کلید عمومی‌های بسیار ساده (دقیقا مشابه تبادل کلیدهای SSH) ساخته می‌شود و مابقی اتفاقات به صورت خودکار توسط پروتکل WireGuard انجام می‌شود و از دید کاربران پنهان است. تمامی مسائل مربوط به توزیع کلید و ارسال تنظیمات، خارج از حوزه WireGuard است و این مسائل بهتر است به لایه‌های دیگر واگذار شود تا دچار پیچیدگی‌های IPsec یا OpenVPN نشویم. جهت آشنایی با نحوه راه‌اندازی این پروتکل می‌توانید به این لینک مراجعه کنید.

یکی از نکاتی که در مورد پروتکل WireGuard وجود دارد این است که همانند IPsec می‌تواند هم به صورت client-server و هم به صورت site-to-site مورد استفاده قرار گیرد. لازم به ذکر است که در هر صورت، به هر کدام از طرفین تونل یک peer گفته می‌شود.

در حالت client-server یک تونل رمزنگاری شده بین کلاینت و سرور شکل می‌گیرد و اطلاعات کلاینت و سرور به صورت رمزنگاری شده از داخل این تونل تبادل می‌شود. در این حالت با توجه به اینکه ابتدا کلاینت‌ها نشست را آغاز می‌کنند و از آدرس IP ثابت سرور مطلع هستند، طراحی پروتکل به نحوی انجام شده است که کلاینت‌ها می‌توانند آدرس IP پویا داشته باشند و در صورت تغییر آدرس IP کلاینت‌ها مشکلی ایجاد نمی‌شود. به این ویژگی Roaming گفته می‌شود که به صورت ذاتی توسط پروتکل فراهم می‌شود.

پروتکل WireGuard در حالت Client-Server
پروتکل WireGuard در حالت Client-Server

در حالت site-to-site نیز یک تونل رمزنگاری شده بین دو دستگاه شکل می‌گیرد. هر کدام از این دو دستگاه، نماینده تمامی دستگاه‌های طرف خود هستند و اطلاعات بین دو طرف به صورت رمزنگاری شده از داخل این تونل عبور می‌کند.

پروتکل WireGuard در حالت Site-to-Site
پروتکل WireGuard در حالت Site-to-Site

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

واسط‌های شبکه‌ای پروتکل

پروتکل WireGuard با اضافه کردن یک یا چند واسط شبکه کار خود را انجام می‌دهد. این واسط‌ها به عنوان واسط تونل عمل می‌کنند. این واسط‌ها همانند eth0 و wlan0 هستند و wg0 (یا wg2 ،wg‌1 یا غیره) نامیده می‌شوند. سپس این واسط‌های شبکه می‌توانند به صورت عادی توسط ابزارهای ifconfig و یا ip-address تنظیم شوند و همچنین جدول مسیریابی مربوط به آن‌ها می‌تواند توسط ابزارهای route یا ip-route تغییر کند و همچنین تغییرات دیگری که می‌تواند توسط دیگر ابزارهای متعارف شبکه انجام شود. جنبه‌های خاصی از پروتکل ‌WireGuard که مربوط به این واسط است نیز می‌تواند توسط ابزار wg تنظیم شود.

نحوه ارسال و دریافت بسته‌ها

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

پروتکل WireGuard آدرس IPهایی که قرار است از داخل تونل عبور کنند را با کلیدهای عمومی و endpointهای راه دور مرتبط می‌کند. در حقیقت این آدرس IPها مقصد بسته‌های رمز نشده هستند که سیستم مجاز است از داخل تونل با آن‌ها ارتباط داشته باشد و این آدرس‌ها در هنگام انجام تنظیمات مربوط به پروتکل به صورت subnet و تحت عنوان Allowed IPs مشخص می‌شوند. به عنوان مثال جدول زیر بخشی از تنظیمات یک peer را نشان می‌دهد که قادر است با سه peer دیگر ارتباط رمزنگاری شده برقرار کند.

تنظیمات یک دستگاه نمونه
تنظیمات یک دستگاه نمونه

هنگامی که یک دستگاه توسط واسط شبکه خود بسته‌ای را به سمت یک peer ارسال می‌کند، کارهای زیر انجام می‌شود.

  1. بسته قرار است برای 192.168.30.8 ارسال شود. ابتدا باید دید که این آدرس مربوط به کدام peer است؟ با توجه به تنظیمات بالا و مقادیر Allowed IPs این بسته مربوط به دومین peer است (یا اینکه اگر در تنظیمات هیچ peer مرتبطی یافت نشود، بسته دور انداخته می‌شود).
  2. کل بسته IP با استفاده از کلید عمومی مربوط به دومین peer رمزنگاری می‌شود.
  3. حال باید دید که endpoint مربوط به peer مورد نظر چیست؟ endpoint مورد انتظار، پورت 53133 بر روی میزبان 216.58.211.110 است.
  4. در انتها بایت‌های رمزنگاری شده در مرحله دوم از طریق اینترنت و با استفاده از پروتکل UDP برای 216.58.211.110:53133 ارسال می‌شود.

زمانی که واسط شبکه دستگاه بسته‌ای را دریافت می‌کند، کارهای زیر انجام می‌شود.

  1. بسته‌ای از طرف پورت 7361 پروتکل UDP و از طرف میزبان 98.139.183.24 دریافت شده است. این بسته ابتدا باید رمزگشایی شود.
  2. این بسته پس از رمزگشایی با کمک کلید خصوصی دستگاه، به صورت کامل و صحیح برای اولین peer در جدول بالا احراز هویت می‌شود. احراز هویت طرف مقابل با کمک تطابق کلید عمومی آن حاصل می‌شود. بنابراین آدرس مشاهده شده که برابر با 98.139.183.24:7361 است به عنوان endpoint متناظر با اولین peer ثبت می‌شود (اگر این peer قبلا دارای endpoint متفاوتی بوده است، اکنون به مقدار جدید تغییر پیدا می‌کند).
  3. بسته پس از رمزگشایی دارای آدرس IP مبدا 10.192.124.89 می‌باشد. آیا peer مربوطه مجاز است که بسته‌هایی را با این آدرس IP مبدا ارسال کند؟ این مساله با توجه به اطلاعات موجود در جدول بالا قابل انجام است.
  4. اگر چنین آدرسی مجاز باشد، بسته‌ها بر روی این واسط شبکه پذیرفته می‌شود. در غیر این ‌صورت بسته‌ها دور انداخته می‌شود.

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

مفهوم Cryptokey Routing

در قلب WireGuard مفهومی به نام Cryptokey Routing وجود دارد و اینگونه کار می‌کند که کلیدهای عمومی را با لیستی از آدرس‌های IP که داخل تونل مجاز به استفاده هستند مرتبط می‌کند.

هر واسط شبکه (network interface) یک کلید خصوصی و لیستی از peerها دارد. هر کدام از peerها نیز یک کلید عمومی دارد. کلیدهای عمومی کوتاه و ساده هستند و توسط peerها برای احراز هویت همدیگر استفاده می‌شوند. این کلیدها می‌توانند در قالب فایل‌های تنظیمات برای دیگران ارسال شوند، مشابه عملی که در هنگام SSH انجام می‌شود.

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

تنظیمات یک سرور نمونه
تنظیمات یک سرور نمونه

همچنین تنظیمات یک کلاینت می‌تواند مشابه زیر باشد.

تنظیمات یک کلاینت نمونه
تنظیمات یک کلاینت نمونه

مطابق تنظیمات سرور، هر peer (کلاینت) قادر است بسته‌های خود را به سمت واسط شبکه سرور ارسال کند به شرطی که آدرس IP مبدا آن، با لیست مجاز آدرس‌های IP که درون تنظیمات سرور مشخص شده است مطابقت داشته باشد. به عنوان مثال زمانی که یک بسته از طرف کلاینت ...gN65BkIK دریافت می‌شود، بعد از رمزگشایی و احراز هویت، در صورتی که آدرس IP مبدا آن معادل 10.10.10.230 باشد اجازه دریافت دارد و در غیر این صورت بسته دور انداخته می‌شود.

مطابق تنظیمات سرور، زمانی که واسط شبکه سرور قصد ارسال بسته به سمت یکی از کلاینت‌ها داشته باشد، به مقصد بسته نگاه می‌کند و آن را با لیست آدرس‌های IP مربوط به peerها مقایسه می‌کند تا ببیند مقصد بسته، مربوط به کدام کلاینت است. به عنوان مثال اگر از واسط شبکه سرور درخواست شده باشد تا بسته‌ای را به مقصد 10.10.10.230 ارسال کند، سرور این بسته را با استفاده از کلید عمومی کلاینت متناظر یعنی ...gN65BkIK رمزنگاری می‌کند و سپس آن را به سمت Internet endpoint اخیر کلاینت ارسال می‌کند.

مطابق با تنظیمات کلاینت، تنها peer کلاینت که سرور می‌باشد قادر است بسته‌ها را به سمت واسط شبکه‌ کلاینت با هر آدرس IP مبدا ارسال کند (به خاطر اینکه آدرس IP مجاز به صورت 0.0.0.0/0 مشخص شده است که شامل تمام آدرس‌ها می‌شود). به عنوان مثال زمانی که یک بسته از طرف peer متناظر با ...HIgo9xNz دریافت می‌شود، اگر به درستی رمزگشایی و احراز هویت شود، با هر آدرس IP مبدا که داشته باشد، اجازه دریافت خواهد داشت.

مطابق با تنظیمات کلاینت، زمانی که از واسط شبکه کلاینت خواسته شود بسته‌ای را به سمت تنها peer خود که سرور است ارسال کند، کلاینت این بسته را با هر آدرس IP مقصدی که داشته باشد (به خاطر آدرس 0.0.0.0/0) برای peer مربوطه رمزنگاری می‌کند. به عنوان مثال اگر واسط شبکه کلاینت بخواهد بسته‌ای را ارسال کند، این بسته با هر آدرس IP مقصدی که داشته باشد، توسط کلید عمومی تنها peer مربوطه یعنی ...HIgo9xNz رمزنگاری می‌شود و سپس به سمت Internet endpoint اخیر سرور ارسال می‌شود.

به عبارت دیگر هنگام ارسال بسته‌ها، لیست آدرس IPهای مجاز مشابه جدول مسیریابی عمل می‌کند و هنگام دریافت بسته‌ها، لیست آدرس IPهای مجاز همانند لیست کنترل دسترسی (access control list) عمل می‌کند.

روشی که در این بخش توضیح داده شد، توسط پروتکل WireGuard با نام Cryptokey Routing Table شناخته می‌شود که عبارت است از یک ارتباط و به هم پیوستگی ساده از کلیدهای عمومی و IPهای مجاز.

مفاهیم Endpoint و Roaming

در مورد ارتباطات کلاینت‌ها و سرور، کلاینت‌ها تنها یک peer دارند که آن هم سرور است. در صورتی که سرور ممکن است چند peer مختلف داشته باشد.

تنظیمات کلاینت‌ها شامل یک endpoint اولیه از سرور است. بنابراین کلاینت‌ها می‌دانند که داده‌های رمزنگاری شده خود را به کجا باید ارسال کنند. اگر سرور آدرس مربوط به خود را تغییر دهد و داده‌هایی را به سمت کلاینت‌ها ارسال کند، کلاینت‌ها endpoint جدید سرور را کشف می‌کنند و تنظیمات خود را بروزرسانی ‌ می‌کنند.

اما در تنظیمات سرور هیچ endpoint اولیه‌ای از کلاینت‌ها وجود ندارد. این مساله به خاطر این است که سرور، endpoint مربوط به کلاینت‌ها را با بررسی مبدا بسته‌ها کشف می‌کند (البته پس از اینکه بسته‌ها احراز هویت شدند).

بنابراین هم کلاینت‌ها و هم سرور داده‌های رمزنگاری شده خود را به جدیدترین endpoint از طرف مقابل خود ارسال می‌کنند. در نتیجه IP roaming به صورت کامل برای هر دو طرف وجود دارد.

تنظیمات کلاینت
تنظیمات کلاینت

به عنوان مثال میزبانی با مشخصات بالا تنظیم شده است. این میزبان (یعنی gN65...z6EA) یک بسته رمزنگاری شده به سمت HIgo...f8yk با آدرس 192.95.5.69:41414 ارسال می‌کند. سپس HIgo...f8yk یک بسته دریافت می‌کند و جدول خود را مطابق با تصویر زیر بروزرسانی می‌کند تا بداند که endpoint مورد نظر برای ارسال پاسخ، به عنوان مثال 192.95.5.64:21841 است.

تنظیمات سرور
تنظیمات سرور

پیام‌ها

مطالب ذکر شده در این بخش، برگرفته از این مقاله می‌باشد.

در این پروتکل، ابتدا یک عمل دست‌تکانی اتفاق می‌افتد و سپس داده‌های رمزنگاری شده تبادل می‌شود. در اکثر مواقع، عمل دست‌تکانی در یک RTT یا Round Trip Time انجام می‌شود. نمودار تبادل پیام‌ها در این حالت مطابق شکل زیر است.

اگر یکی از peerها زیر بار باشد، آنگاه یک پیام cookie reply به مرحله دست‌تکانی اضافه می‌شود تا جلوی حملات DoS گرفته شود. در این حالت نمودار تبادل پیام‌ها به صورت زیر تغییر می‌کند.



اولین پیام: Initiator به سمت Responder

این پیام، اولین پیام نشست است که توسط آغازگر نشست تولید می‌شود و به سمت مقابل ارسال می‌شود. ساختار این پیام به صورت زیر است.

ساختار اولین پیام: Initiator به سمت Responder
ساختار اولین پیام: Initiator به سمت Responder

مقادیر موجود در این پیام به این صورت هستند.

  1. فیلد type: نوع پیام را مشخص می‌کند که در این مورد برابر با 0x01 است.
  2. فیلد reserved: یک مقدار 3 بایتی رزرو شده است که برابر با 0x000000 می‌باشد.
  3. فیلد sender: این بخش، ارسال‌کننده پیام را مشخص می‌کند و در این مورد برابر است با یک مقدار 4 بایتی تصادفی که در هنگام ارسال این پیام ایجاد می‌شود و با Ii نمایش داده می‌شود. اندیس i در اینجا به نشانه Initiator یا آغازگر نشست آمده است. این مقدار در پیام‌های بعدی مورد استفاده قرار می‌گیرد.
  4. فیلد ephemeral: یک مقدار 32 بایتی است که کلید عمومی موقتی مربوط به آغازگر نشست می‌باشد.
  5. فیلد static: یک مقدار 32 بایتی است که نتیجه محاسبات مربوط به ChaCha20Poly1305 AEAD است. همچنین 16 بایت اضافه در این بخش مربوط به Poly1305 authentication tag است.
  6. فیلد timestamp: یک مقدار 12 بایتی است که بیانگر برچسب زمانی است و به صورت رمزنگاری شده و احراز هویت شده درون پیام قرار داده می‌شود. این مقدار در حقیقت نتیجه محاسبات ChaCha20Poly1305 AEAD بر روی برچسب زمانی می‌باشد. این فیلد برای جلوگیری از حملات ارسال مجدد مورد استفاده قرار می‌گیرد. همچنین 16 بایت اضافه در این بخش مربوط به Poly1305 authentication tag است.
  7. فیلدهای mac1 و mac2: هر کدام از این موارد یک مقدار 16 بایتی MAC یا Message Authentication Code است که در مقاله مربوطه نحوه محاسبه آن توضیح داده شده است.

برای کسب اطلاعات بیشتر در مورد جزئیات (برای مثال الگوریتم‌های رمزنگاری مورد استفاده، نحوه محاسبات دقیق هر کدام از این فیلدها و موارد دیگر) می‌توانید به بخش 5.4 از مقاله مورد نظر مراجعه کنید.


دومین پیام: Responder به سمت Initiator

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

ساختار دومین پیام: Responder به سمت Initiator
ساختار دومین پیام: Responder به سمت Initiator

مقادیر موجود در این پیام به این صورت هستند.

  1. فیلد type: نوع پیام را مشخص می‌کند که در این مورد برابر با 0x02 است.
  2. فیلد reserved: یک مقدار 3 بایتی رزرو شده است که برابر با 0x000000 می‌باشد.
  3. فیلد sender: این بخش، ارسال‌کننده پیام را مشخص می‌کند و در این مورد برابر است با یک مقدار 4 بایتی تصادفی که در هنگام ارسال این پیام ایجاد می‌شود و با Ir نمایش داده می‌شود. اندیس r در اینجا به نشانه Responder یا طرف پاسخگو در نشست آمده است. این مقدار در پیام‌های بعدی مورد استفاده قرار می‌گیرد.
  4. فیلد receiver: این بخش، دریافت‌کننده پیام را مشخص می‌کند و برابر با Ii است که در پیام اول دریافت شده است.
  5. فیلد ephemeral: یک مقدار 32 بایتی است که کلید عمومی موقتی مربوط به طرف پاسخگو در نشست می‌باشد.
  6. فیلد empty: یک بخش خالی است که 16 بایت اضافه در آن مربوط به Poly1305 authentication tag است که به این بخش اضافه می‌شود. این مقدار اضافه شده در حقیقت نتیجه محاسبات ChaCha20Poly1305 AEAD بر روی این بخش خالی می‌باشد.
  7. فیلدهای mac1 و mac2: هر کدام از این موارد یک مقدار 16 بایتی MAC یا Message Authentication Code است که در مقاله مربوطه نحوه محاسبه آن توضیح داده شده است.

پیام‌های ارسال داده

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

ساختار پیام‌های ارسال داده
ساختار پیام‌های ارسال داده

مقادیر موجود در این پیام به این صورت هستند.

  1. فیلد type: نوع پیام را مشخص می‌کند که در این مورد برابر با 0x04 است.
  2. فیلد reserved: یک مقدار 3 بایتی رزرو شده است که برابر با 0x000000 می‌باشد.
  3. فیلد receiver: این بخش، دریافت‌کننده پیام را مشخص می‌کند و بسته به جهت پیام می‌تواند برابر با یکی از مقادیر Ir یا Ii باشد که در پیام‌های قبلی دریافت شده‌اند.
  4. فیلد counter: یک شمارنده 8 بایتی است که تعداد بسته‌های ارسال شده توسط فرستنده پیام را مشخص می‌کند.
  5. فیلد packet: در این بخش داده‌ها به صورت رمزنگاری شده و احراز هویت شده (توسط الگوریتم ChaCha20Poly1305 AEAD) ارسال می‌شود. متغیر p در این بخش بیانگر طول داده‌ها می‌باشد که بسته به میزان حجم داده‌ها تغییر می‌کند. همچنین 16 بایت اضافه در این بخش مربوط به Poly1305 authentication tag است.

پیام Cookie Reply

زمانی که یک پیام با mac1 معتبر و mac2 نامعتبر و یا منقضی شده دریافت شود و همچنین peer مربوطه زیر بار باشد، آنگاه ممکن است peer مورد نظر، یک پیام cookie reply ارسال کند. ساختار این پیام‌ها به صورت زیر است.

ساختار پیام Cookie Reply
ساختار پیام Cookie Reply

مقادیر موجود در این پیام به این صورت هستند.

  1. فیلد type: نوع پیام را مشخص می‌کند که در این مورد برابر با 0x03 است.
  2. فیلد reserved: یک مقدار 3 بایتی رزرو شده است که برابر با 0x000000 می‌باشد.
  3. فیلد receiver: این بخش، دریافت‌کننده پیام را مشخص می‌کند و بسته به جهت پیام می‌تواند برابر با یکی از مقادیر Ir یا Ii باشد که در پیام‌های قبلی دریافت شده‌اند.
  4. فیلد nonce: یک مقدار 24 بایتی تصادفی است که در محاسبه cookie مورد استفاده قرار می‌گیرد.
  5. فیلد cookie: این بخش شامل 16 بایت cookie است که به صورت رمزنگاری شده و احراز هویت شده (توسط الگوریتم ChaCha20Poly1305 AEAD) ارسال می‌شود. همچنین 16 بایت اضافه در این بخش مربوط به Poly1305 authentication tag است.
wireguardپروتکلشبکهرمزنگاری
شاید از این پست‌ها خوشتان بیاید