کلاینت به سرور OpenVPN روی یک ماشین Compute Engine وصل می‌شود، پنجره وضعیت می‌گوید متصل است، اما ping به میزبان داخل VPC هنوز به جایی نمی‌رسد. غریزه می‌گوید یک خط push دیگر اضافه کنید و این هرگز مشکل را درست نمی‌کند. Compute Engine بر اساس جدول مسیرهای خودش و آدرس‌هایی که رابط ماشین مجازی واقعاً دارد تصمیم می‌گیرد بسته‌ها کجا بروند، پس pool تونلی که ماشین مجازی مالک آن نیست poolی است که هیچ‌کس به آن تحویل نمی‌دهد.

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

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

بسته SYN از کلاینت خارج می‌شود، وارد تونل می‌شود و به‌صورت بسته‌ای کپسوله برای مقصدی درون VPC به ماشین مجازی می‌رسد. OpenVPN آن را از کپسوله خارج می‌کند و می‌کوشد آن را از eth0 عبور دهد، جایی که fabric پیش از هر چیز دیگری یک پرسش می‌گذارد: آیا این نمونه مالک آدرس مقصد است. pool تونلی که از subnet دیگری بریده شده در آن پرسش شکست می‌خورد و بسته پیش از بررسی هر مسیر یا قاعده فایروال دور انداخته می‌شود.

پس جهت کلاینت به VPC دو نیاز جداگانه دارد و هیچ‌کدام دستور push نیست. ماشین مجازی به محدوده alias نیاز دارد که pool تونل را بپوشاند و همین آن را مالک مشروع آن آدرس‌ها می‌کند. VPC به مسیری نیاز دارد که ماشین مجازی را برای هر پیشوند محافظت‌شده next hop بنامد. اگر یکی کم باشد بسته جای دیگری می‌میرد، در حالی که کلاینت همان سکوت را می‌بیند.

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

آیا نمونه مالک pool تونل است

به ماشین مجازی محدوده‌ای ثانویه درون subnet خودش بدهید و سپس بگذارید OpenVPN آدرس‌ها را دقیقاً از همان محدوده توزیع کند. روی نمونه‌ای که آدرس اصلی‌اش 10.156.0.10/20 است، یک alias /28 pool را از آدرس‌هایی که نمونه‌های دیگر دارند جدا نگه می‌دارد:

gcloud compute instances network-interfaces update openvpn-vm \
  --zone=europe-west1-b \
  --aliases=eth0:10.156.1.0/28

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

server 10.156.1.0 255.255.255.240

تأیید کنید که آدرس واقعاً روی رابط نشسته است و نه فقط درون پیکربندی OpenVPN. fabric آنچه را کارت شبکه گزارش می‌کند عبور می‌دهد، نه آنچه daemon باور دارد. یک فرمان این را روشن می‌کند:

ip -4 addr show dev eth0

آدرس ثانویه‌ای که هرگز به eth0 نمی‌رسد، یا poolی که با subnet دیگری همپوشانی دارد، بعداً به‌صورت افت‌های متناوب ظاهر می‌شود نه خطای راه‌اندازی. daemon بالا می‌آید، کلاینت‌ها وصل می‌شوند و فقط بعضی مقصدها بدرفتاری می‌کنند. محدوده alias را کوچک نگه دارید تا pool در جدول مسیرها آسان شناخته شود. هرگز آن را از subnetی که نمونه دیگری استفاده می‌کند نبرید.

به ترافیک بازگشت next hop بدهید

پاسخ میزبان داخل VPC به آدرس کلاینتی در pool تونل نشانه می‌رود که به هیچ subnet شناخته‌شده VPC تعلق ندارد. بدون مسیر برای آن pool، پاسخ در نخستین hopی که تطابقی ندارد می‌ایستد و ممکن است درخواست در آن سوی راه با موفقیت انجام شده باشد.

gcloud compute routes create openvpn-return \
  --network=prod-vpc \
  --destination-range=192.168.127.0/24 \
  --next-hop-instance=openvpn-vm \
  --next-hop-instance-zone=europe-west1-b \
  --priority=800

همان مسیر برای هر پیشوندی لازم است که پشت کلاینت است نه درون VPC. آن پیشوندها به یک ورودی iroute در فایل ccd همان کلاینت هم نیاز دارند. آن ورودی حسابداری سمت سرور است: به سرور می‌گوید کدام کلاینت مالک پیشوند است و چیزی روی خود کلاینت نصب نمی‌کند.

فهرست push را برای سمت کلاینت گفتگو نگه دارید، چون فقط مسیرهایی به ماشین متصل‌شونده اضافه می‌کند. یک خط push برای subnet در VPC و یک مسیر VPC بازگشت به pool دو نیمه از یک مسیرند و هر نیمه به‌تنهایی تونلی می‌سازد که درخواست‌ها را می‌برد اما پاسخ‌ها را نه.

فایروال‌ها، عبوردهی و hopهای میان آن‌ها

فایروال VPC بسته کپسوله‌زدایی‌شده را ارزیابی می‌کند، پس قاعده ingress باید pool تونل و هر پیشوند سایتی را که از آن راه به ماشین مجازی می‌رسد بپذیرد. موضع default-deny اینجا بی‌صدا شکست می‌خورد: بسته پس از کپسوله‌زدایی دور انداخته می‌شود و گزارش OpenVPN نشستی سالم نشان می‌دهد.

روی هر میزبان Linux که عبور می‌دهد و پایان نمی‌دهد، بررسی کنید که net.ipv4.ip_forward فعال است. قاعده مالکیت آنجا هم برقرار است: ماشینی که برای subnetی که مالکش نیست عبور می‌دهد بسته را درست مانند ماشین مجازی دور می‌اندازد. پیش از سرزنش تونل مقدار را بخوانید.

وقتی دقیقاً یک پیشوند شکست می‌خورد

خرابی جزئی خواناترین حالت است، چون همه چیز دیگر مسیر پیش‌تر اثبات شده است. از فهرست مسیرها شروع کنید و محدوده مقصد و next hop ورودی‌ای را که باید پیشوند را بپوشاند بخوانید، سپس توصیف نمونه را بخوانید و محدوده alias آن را با poolی که سرور توزیع می‌کند مقایسه کنید.

gcloud compute routes list --filter=destination-range~10.164.0.0
 gcloud compute instances describe openvpn-vm --format=get(networkInterfaces[0].aliasIpRanges)

مسیر گم‌شده به‌صورت نبود next hop برای پیشوند ظاهر می‌شود، در حالی که alias گم‌شده به‌صورت بسته‌ای که در رابط دور انداخته شده ظاهر می‌شود؛ از سمت کلاینت آن دو شبیه‌اند و در آن دو خروجی کاملاً متفاوت. اگر هر دو باشند، مظنون باقی‌مانده iroute در ccd کلاینتی است که مدعی پیشوند است.

چهار مقدار را کنار تونل بنویسید: محدوده alias، pool سرور، پیشوندهای push شده، مسیرهای VPC. alias کهنه هر آدرس pool را می‌شکند، مسیر کهنه یک جهت را می‌شکند، push گم‌شده پیشوند را از کلاینت پنهان می‌کند و iroute نادرست پیشوند را به peer نادرست می‌فرستد. نفر بعدی که subnet اضافه می‌کند هر چهار مورد را در یک جا لازم دارد و آن یادداشت از یک شب ارزان‌تر است.

مقالات مرتبط