چرا یک کانتینر macvlan نمیتواند به کلاینت VPN پاسخ دهد
کانتینر macvlan نمیتواند با میزبان خودش صحبت کند و پاسخهایش ممکن است از درگاه اشتباه خارج شوند. یک مسیر شیم در سمت میزبان اضافه کنید و سپس یک مدل مبدأ انتخاب کنید.
یک میزبان Linux را تصور کنید که یک VPN را خاتمه میدهد و همزمان یک کانتینر را روی شبکه macvlan اجرا میکند. شبکه محلی 192.168.60.0/24 است، کانتینر آدرس 192.168.60.210 را دارد و کلاینتهای VPN از 10.95.0.0/24 میآیند. کلاینت به سرویس میرسد، پاسخ هرگز برنمیگردد و همه قواعد فایروال روی میزبان درست به نظر میرسند. دو محدودیت جداگانه این نشانه را تولید میکنند و اصلاح یکی دیگری را سر جای خود باقی میگذارد.
دو محدودیت، یک نشانه
محدودیت اول جداسازی است: درایور macvlan در Docker اجازه نمیدهد کانتینر از طریق رابط والد با میزبان خودش صحبت کند. ترافیک میان پشته میزبان و کانتینر هیچ مسیری ندارد، هر طور که مسیرها روی میزبان نوشته شده باشند.
محدودیت دوم مسیر بازگشت است. درگاه پیشفرض کانتینر معمولاً روتر شبکه محلی است، بنابراین پاسخی که به یک کلاینت VPN آدرس داده شده از آن روتر خارج میشود. اگر روتر مسیری برای بازگشت به استخر VPN نداشته باشد، پاسخ جایی در میانه دور انداخته میشود.
این دو خرابی از دید کلاینت یکسان به نظر میرسند: درخواستی که میرسد و پاسخی که هرگز نمیآید. آنها اصلاحهای متفاوتی لازم دارند و یک قاعده گسترده masquerade میتواند پنهان کند کدام یک هنوز خراب است. به همین دلیل نخستین آزمون یک ضبط بسته در سمت کانتینر است و نه یک تغییر دیگر در فایروال. اگر درخواست هرگز آنجا ظاهر نشود، محدودیت جداسازی در کار است.
شیم سمت میزبان را باریک بسازید
یک رابط macvlan دوم روی میزبان که در حالت پل به همان والد متصل است، به پشته میزبان هویت مستقل خودش را در آن بخش از شبکه محلی میدهد. برای آن آدرسی بیرون از استخر DHCP و بیرون از محدوده کانتینر رزرو کنید و فقط کانتینر را از آن عبور دهید.
ip link add macvlan-vpn link eth0 type macvlan mode bridge ip address add 192.168.60.250/32 dev macvlan-vpn ip link set macvlan-vpn up ip route add 192.168.60.210/32 dev macvlan-vpn src 192.168.60.250
فرمان اول رابط را در حالت پل میسازد که پیشفرض مستندشده برای این درایور است و همان حالتی که برای ترافیک میان میزبان و کانتینر میخواهید. فرمان دوم یک /32 اختصاص میدهد تا آدرس با پیشوند شبکه محلی تصادم نکند و فرمان چهارم فقط آدرس کانتینر را از شیم عبور میدهد.
کل شبکه محلی را از رابط جدید عبور ندهید. مسیر متصل معمول همانطور که هست میماند و مسیر میزبان عمداً باریک است تا یک کانتینر مسیر پیدا کند بدون آنکه رفتار بقیه بخش تغییر کند. یک مسیر پیشفرض به سمت شیم طرحی دیگر با پیامدهای دیگر میبود. آن را مشخص نگه دارید تا شعاع آسیب کوچک بماند.
این فرمانها تنظیمات شبکه را روی یک میزبان فعال تغییر میدهند. روی یک دستگاه یا بستر مدیریتشده از سازوکار پیکربندی پشتیبانیشده همان بستر استفاده کنید، زیرا یک تغییر تعاملی در پوسته ریشه ممکن است از یک ارتقا جان سالم به در نبرد.
تصمیم بگیرید مبدأ چگونه حفظ میشود
با وجود شیم، کانتینر میتواند به میزبان برسد و پرسش این میشود که پاسخ کدام آدرس مبدأ را حمل میکند. حفظ مبدأ اصلی VPN مدل پاکیزهتری است: کانتینر آدرس واقعی کلاینت را میبیند و گزارشها و قواعد دسترسی سرویس میتوانند از آن استفاده کنند.
برای اینکه این کار کند، پیکربندی شبکه کانتینر باید برای این مسیر ترافیک 10.95.0.0/24 را به 192.168.60.250 به عنوان درگاه خودش بفرستد. این یک تنظیم مسیر یا درگاه پشتیبانیشده درون پیکربندی خود کانتینر است، نه یک ترفند در سمت میزبان. آن را از داخل کانتینر تأیید کنید نه اینکه فرض کنید تنظیم اعمال شده است. درگاه پیشفرضی که هنوز به روتر شبکه محلی اشاره میکند پاسخها را به همان سوراخ ادامه خواهد داد.
اگر طرح تأییدشده به جای آن مبدأهای VPN را پنهان میکند، ترجمه را باریک محدود کنید: استخر واقعی VPN، شیم به عنوان رابط خروجی و کانتینر و سرویس مشخص.
iptables -t nat -A POSTROUTING -s 10.95.0.0/24 -o macvlan-vpn -j SNAT --to-source 192.168.60.250
شیم را به عنوان رابط خروجی تطبیق دهید، نه تونل. قاعدهای که تونل را رابط خروجی مینامد با بستهای که به سمت کانتینر میرود تطبیق نمییابد و همین اشتباه است که چنین چیدمانی معمولاً در خود دارد. قاعده را به باریکی جمله بالا نگه دارید و هرگاه استخر تغییر کرد آن را بازبینی کنید.
از کلاینت بررسی کنید، نه از میزبان
درخواستی از خود میزبان که به آدرس شیم مقید شده ثابت میکند شیم میتواند به کانتینر برسد. اما ثابت نمیکند کانتینر میتواند ترافیک را به مبدأ حفظشده 10.95.0.x بازگرداند، زیرا آدرس مبدأ در آن آزمون خود شیم است.
curl -sS --interface 192.168.60.250 -o /dev/null -w '%{http_code}\n' http://192.168.60.210:8080/health
sudo tcpdump -ni macvlan-vpn host 192.168.60.210فرمان اول بخش میزبان به کانتینر را میآزماید و فرمان دوم نشان میدهد در حین درخواست یک کلاینت واقعی VPN چه چیزی واقعاً از شیم میگذرد. به آدرس مبدأ در مسیر ورود نگاه کنید و اینکه پاسخی با همان جریان ظاهر میشود یا نه.
ارسال به جلو باید روی میزبان فعال باشد و مسیر ارسال به جلو به اجازهای برای استخر VPN به سمت شیم روی درگاه سرویس بهعلاوه پاسخهای برقرارشده نیاز دارد. یک قاعده INPUT روی میزبان ترافیک ارسالشده به جلو را مجاز نمیکند و این دلیل رایجی است که بسته پس از درست به نظر رسیدن مسیریابی دور انداخته میشود.
برنامه واقعی را با اعتبارنامه واقعی اجرا کنید و سپس بررسی کنید که یک سرویس دوم و بیربط روی همان کانتینر هنوز شما را رد میکند. اگر تنها راه کار کردنش باز کردن همه قواعد ارسال به جلو بود، طرح تمام نشده است. همچنین توجه کنید سرویس کدام آدرس مبدأ را ثبت کرده، زیرا از این پس قواعد دسترسی خودش همان را به کار خواهد برد.