ترافیک Docker و ماشین مجازی پشت OpenVPN: مسیریابی یا شمارهگذاری مجدد؟
کانتینرها و مهمانها روی میزبان دارای کلاینت OpenVPN یا مسیر بازگشت را از دست میدهند یا با پیشوند تونل برخورد میکنند. سه پرسش راهحل را انتخاب میکند.
میزبان از طریق تونل مرور میکند و کانتینر کنارش به هیچجا نمیرسد. انتشار یک پورت از کانتینری که کلاینت VPN خودش را اجرا میکند بدتر است: درخواست میرسد و پاسخ هرگز خارج نمیشود. هر دو تصمیم مسیریابی روی میزبان هستند و Docker فقط پیک است.
سه پرسش تعیین میکند کدام یک از این دو حالت را میبینید و حدود یک دقیقه وقت میگیرد.
دو خرابی که یکسان به نظر میرسند
اولی مشکل مسیر بازگشت است. پورت منتشرشده به کانتینر ترجمه میشود، درخواست میرسد و پاسخ از مسیر پیشفرض میزبان مسیریابی میشود، مسیری که OpenVPN کلاینت آن را به tun0 فرستاده است. پاسخ از نشانی خارج میشود که همتای دور انتظارش را ندارد و دور انداخته میشود. دومی برخورد پیشوند است: پل پیشفرض Docker مالک 172.17.0.0/16 است و یک تونل شرکتی همان بازه را هل میدهد.
یکی با جدول مسیریابی درست میشود و دیگری با شمارهگذاری مجدد یک پل. ویرایش پیش از آنکه بدانید کدام کدام است، همان راه خراب کردن یک کانتینر سالم است.
با سه پرسش تصمیم بگیرید
پرسش یک: وقتی VPN را متوقف میکنید خرابی از بین میرود؟ اگر با خاموش بودن تونل همهچیز کار میکند، به مسیر بازگشت شک کنید. پرسش دو: آیا ip route show table all همان پیشوند را دو بار فهرست میکند، یک بار روی یک پل و یک بار روی tun0؟ این همان برخورد است. پرسش سه: نشانی آسیبدیده کانتینر است، مهمان NAT یا مهمان متصل به پل؟
پرسش سوم اهمیت دارد چون هر کدام راهحل درست متفاوتی دارند و اعمال راهحل کانتینر روی مهمان libvirt یک شب را تلف میکند.
ip route
ip route show table all | grep -E '172\.1[7-9]|10\.8'
docker network inspect bridge --format '{{.IPAM.Config}}'مسیر بازگشت: جدولی برای یک نشانی مبدأ
وقتی ترافیک کانتینر باید از رابط فیزیکی خارج شود در حالی که خود میزبان از تونل استفاده میکند، مسیریابی مبتنی بر مبدأ کوچکترین تغییر است. قاعدهای اضافه کنید که با نشانی کانتینر مطابقت دارد و آن را به یک جدول اختصاصی بفرستید. چیز دیگری روی میزبان جابهجا نمیشود.
ip rule add from 172.22.0.3 lookup 10
ip route add default via 172.22.0.1 table 10هر بستهای که مبدأ آن نشانی باشد ابتدا جدول 10 را بررسی میکند و جدول 10 آن را به جای تونل به دروازه پل میفرستد.
با این مورد تأیید کنید: ip route get 1.1.1.1 from 172.22.0.3. پاسخ باید رابط پل را نام ببرد، نه tun0 را. قواعدی که به این شکل اضافه شوند در راهاندازی مجدد از بین میروند، پس آنها را در unit یا قلاب شبکهای که مالک کانتینر است بگذارید.
همین الگو برای کانتینر WireGuard هم کار میکند، جایی که مسیر پاسخ نیز به قاعدهای صریح نیاز دارد.
برخورد پیشوند: پل را شمارهگذاری مجدد کنید
یک جدول مسیریابی یک پیشوند را به یک جا میفرستد. اگر VPN پیشوند 172.17.0.0/16 را هل دهد در حالی که پل Docker از قبل آنجاست، متریک کمتر برنده است: Docker مسیر متصل خود را با متریک 0 نصب میکند و مسیر هلدادهشده با 50 میرسد. آنگاه تونل خراب به نظر میرسد در حالی که Docker کار میکند، یا برعکس، بسته به ترتیب نصب. به جای جنگیدن با متریک، پل را شمارهگذاری مجدد کنید.
{
"bip": "10.200.0.1/24",
"default-address-pools": [{"base": "10.201.0.0/16", "size": 24}]
}پس از تغییر Docker را دوباره راهاندازی کنید و شبکههای ساختهشده با استخر قدیمی را دوباره بسازید. تغییر متریک به جای آن فقط تعارض را به راهاندازی بعدی منتقل میکند.
ماشینهای مجازی دوباره پاسخ دیگری میخواهند
مهمان libvirt روی شبکه NAT پیشفرض مسیریابی میزبان را به ارث میبرد و به محض اینکه تونل میزبان مالک مسیر پیشفرض شود، دسترسی به بیرون را از دست میدهد. انتقال مهمان به یک دستگاه پل یا macvtap مسیر خودش را روی شبکه فیزیکی به آن میدهد. در virt-manager سختافزار اضافه کنید، Network را انتخاب کنید، مبدأ را روی دستگاه میزبان macvtap بگذارید، virtio را به عنوان مدل نگه دارید و سپس رابط NAT قدیمی را غیرفعال کنید.
مهمان macvtap معمولاً نمیتواند به میزبان خودش برسد. این رفتار مورد انتظار است نه خرابی، و جای آن در یادداشتی است که به جا میگذارید.
برای مهمانی که فقط به LAN میزبان نیاز دارد، ممکن است کلاینت فروشنده کلید گمشده را داشته باشد: با Mullvad، mullvad lan set allow دسترسی محلی را بدون دست زدن به libvirt بازمیگرداند. و وقتی کانتینر باید فقط از طریق تونل در دسترس باشد، پورت منتشرشده را به نشانی تونل ببندید، -p 10.8.0.5:8080:8080، به جای انتشار آن روی هر نشانی.