تصاویر کانتینر می‌توانند همه فایل‌های دودویی و پیکربندی OpenVPN را که نیاز دارند همراه داشته باشند و باز هم در نخستین فراخوانی شبکه شکست بخورند. خطا نام /dev/net/tun را می‌آورد چون برنامه از هسته یک رابط TUN خواسته بود و کانتینر نه گره دستگاه را داشت و نه توانایی ساختن آن را. این‌ها دو مجوز جداگانه‌اند و اصلاح یکی، دیگری را دقیقاً همان‌جا که بود رها می‌کند.

جدا کردن آن‌ها برای هر کدام یک فرمان می‌خواهد. پیام خطای بعدی به شما می‌گوید واقعاً پشت کدام مرز ایستاده بودید.

گره دستگاه و توانایی دو در هستند

گره دستگاه یک شیء در سیستم فایل است، پس کانتینر باید آن را در فضای نام اتصال خودش ببیند. توانایی یک مجوز است، پس فرایند به CAP_NET_ADMIN در فضای نامی نیاز دارد که رابط در آن ساخته می‌شود. عبور دادن دستگاه بدون توانایی به شما گره‌ای می‌دهد که باز می‌شود و ioctl ای که شکست می‌خورد. دادن توانایی بدون دستگاه برنامه را از باز کردن هر چیزی ناتوان می‌گذارد، و به همین دلیل این دو معمولاً در مثال‌ها با هم می‌آیند.

تنظیم devices در Docker دستگاه میزبان را درون کانتینر نگاشت می‌کند، در حالی که cap_add مجموعه توانایی‌ها را تنظیم می‌کند. یک bind mount از همان مسیر فایل را در دید می‌گذارد بدون اعمال معنای دسترسی به دستگاه.

آن را بیرون از فایل Compose بازتولید کنید

پیش از ویرایش سرویس، بررسی کنید که میزبان دستگاه را دارد و یک کانتینر خالی می‌تواند رابط بسازد. فرمان زیر عمداً کمینه است و تنها هدفش جدا کردن مشکل میزبان از مشکل compose است. اگر شکست بخورد، هیچ تغییری در compose کمکی نمی‌کند.

ls -l /dev/net/tun
docker run --rm --cap-add NET_ADMIN --device /dev/net/tun:/dev/net/tun alpine sh -c 'apk add -q iproute2 && ip tuntap add dev tun9 mode tun && ip link show tun9'

نبود گره روی میزبان یعنی ماژول tun در دسترس نیست، که اصلاحی در سمت میزبان است نه کانتینر. گره‌ای که وجود دارد ولی درون کانتینر باز نمی‌شود به دسترسی به دستگاه اشاره دارد، و پیام به جای no such file خواهد گفت permission denied. ترتیب این دو شکست تمام تشخیص است. پیش از تغییر هر پرچمی بنویسید کدام را دیدید.

خطاهای پس از TUN مشکلات متفاوتی هستند

به محض اینکه رابط ظاهر شود، شکست بعدی صاحب دیگری دارد. خطاهای احراز هویت یعنی تونل به سرور رسیده و اعتبارنامه‌ها رد شده‌اند، پس تغییر توانایی‌ها کمکی نمی‌کند. تونلی که برقرار می‌شود در حالی که برنامه‌ها هنوز شکست می‌خورند به مسیرها، ارسال، حل DNS درون کانتینر یا چیدمان شبکه خود کانتینر اشاره دارد. هر یک از این‌ها یک پرسش معمولی شبکه است که مجوز TUN نمی‌تواند پاسخش را بدهد. تکرار آزمون اصلی پس از هر تغییر مانع می‌شود که شکست‌ها در یک برداشت یکی شوند.

کپی کردن هر تنظیم از یک مثال کارا همان راهی است که یک اصلاح کمینه را به تعریفی ناخوانا از سرویس تبدیل می‌کند. فقط آن‌هایی را که این استقرار نیاز دارد بیاورید و بنویسید چرا هر کدام آنجاست.

رابط را درون کانتینر بررسی کنید

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

ls -l /dev/net/tun
capsh --print | grep -i net_admin
ip link add dev tun9 type tun && ip link show tun9

توانایی‌ای که در bounding set هست ولی در effective set نیست، متفاوت از توانایی‌ای رفتار می‌کند که هرگز داده نشده، و capsh هر دو را نشان می‌دهد. اگر گره وجود دارد و توانایی هم هست ولی ساخت هنوز شکست می‌خورد، محیط اجرا چیز دیگری را اعمال می‌کند، مانند یک پروفایل seccomp یا یک سیاست AppArmor که عملیات را محدود می‌کند. این مرز سومی است که محیط اجرا مستندش می‌کند نه برنامه.

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

مقالات مرتبط