LXD یک دستگاه نویسه‌ای میزبان را با افزودن یک گره دستگاه به کانتینر عرضه می‌کند، نه با آموزش ساختن آن به مهمان. اگر کانتینر /dev/net/tun نداشته باشد، ممکن است دستگاه روی میزبان باشد و مهمان هنوز نتواند آن را باز کند. ورودی unix-char نیمه‌ی سمت مدیر این مسیر است و عامدانه از یک کانتینر ویژه‌بخش باریک‌تر است. به همین دلیل گره میزبان و گره کانتینر سزاوار بررسی‌های جداگانه‌اند.

سازوکار آنقدر کوتاه است که بتوان آن را در دید نگه داشت: LXD مسیری روی میزبان را حل می‌کند، گره‌ای متناظر درون نمونه می‌سازد و دستگاه را به cgroup دستگاه‌های کانتینر می‌افزاید. سپس فرایند مهمان به اجازه و توانایی خودش نیاز دارد تا از گره برای کاری استفاده کند.

ورودی unix-char در واقع چه چیزی را تغییر می‌دهد

دستگاه unix-char به LXD می‌گوید یک دستگاه نویسه‌ای میزبان را در مسیری برگزیده درون کانتینر عرضه کند. این ورودی سه بخش مهم دارد: برچسب دستگاهی که مدیر به کار می‌برد، مسیر source روی میزبان و path که مهمان می‌بیند. تنها دو مورد آخر خود دستگاه را توصیف می‌کنند. یک غلط تایپی در هر یک از آن دو، گره‌ای در جایی می‌سازد که کلاینت هرگز باز نمی‌کند.

روی میزبان، دستگاه معمولاً /dev/net/tun است. درون کانتینر می‌توانید همان مسیر را نگه دارید یا مسیر دیگری برگزینید، اما مسیر باید با آنچه کلاینت VPN انتظار دارد بخواند. نگه داشتن /dev/net/tun از یک مشکل دوم پیکربندی جلوگیری می‌کند، چون بیشتر کلاینت‌ها آن مسیر را بی‌پرسش باز می‌کنند.

مدیر ورودی را هنگام آغاز نمونه یا هنگام اتصال گرم دستگاه اعمال می‌کند. نه راه‌اندازی را در مهمان کپی می‌کند و نه یک واسط تونل می‌سازد. گره را دیدنی می‌کند و دسترسی را از طریق گروه کنترل دستگاه‌های کانتینر مجاز می‌داند.

دستگاه را روی نمونه اعلام کنید، نه درون مهمان

ورودی را از بستر مدیریت LXD بیفزایید، با نام بردن نمونه و برچسبی که بعداً بشناسید. برای کانتینری به نام vpnbox فرمان چنین است:

lxc config device add vpnbox tun unix-char source=/dev/net/tun path=/dev/net/tun
lxc config device show vpnbox

برچسب tun محلی برای پیکربندی نمونه است. نام واسط نیست و لازم نیست با چیزی در مهمان بخواند. اگر نمایه‌ای از پیش همان دستگاه را فراهم می‌کند، افزودن ورودی دوم تعارض می‌سازد نه افزونگی، پس نخست پیکربندی کارآمد را بررسی کنید.

ویرایش پرونده‌ها درون کانتینر لایه‌ی نادرستی است. یک mknod در اسکریپت آغاز به نظر می‌رسد روی یک کانتینر ویژه‌بخش کار می‌کند و سپس در بازسازی ناپدید می‌شود یا در یکی با امتیاز کمتر شکست می‌خورد. مدیر مالک مجموعه دستگاه‌های نمونه است؛ بگذارید مالک گره هم باشد.

مالکیت و حالت را با فرایند مهمان هم‌خوان کنید

ورودی unix-char می‌تواند uid، gid و mode را برای گره درون کانتینر تعیین کند. از آن‌ها برای هم‌خوانی با حسابی که کلاینت VPN را اجرا می‌کند استفاده کنید، به جای باز کردن دستگاه برای همه کاربران یا بردن کانتینر به حالت ویژه‌بخش.

دیدنی بودن با اجازه یکی نیست. گره‌ای که مالکش root است و حالت 600 دارد برای سرویسی که با کاربر بی‌امتیاز اجرا می‌شود دیدنی است و همچنان از سوی آن بازشدنی نیست. نخست حساب مهمان را بررسی کنید، سپس مالکیت را به آن حساب بدهید و حالت را از آنچه کلاینت نیاز دارد فراتر نبرید.

فرایند همچنین به توانایی پیکربندی یک واسط تونل نیاز دارد، معمولاً CAP_NET_ADMIN در فضای نام شبکه‌ی کانتینر. دادن دستگاه آن توانایی را نمی‌دهد و دادن توانایی دستگاه را فراهم نمی‌کند؛ این‌ها نیازهای مستقل‌اند.

بدانید ورودی چه چیزی نمی‌دهد

یک گره دیدنی به معنای VPN کارکننده نیست. بسته‌ی کلاینت هنوز باید نصب شود، نمایه هنوز باید معتبر باشد و سرویس هنوز باید آغاز شود. احراز هویت، مسیرها و DNS کار کلاینت می‌ماند و شکست در آنجا مدرکی بر نادرست بودن ورودی دستگاه نیست.

systemd می‌تواند محدودیت دیگری بیفزاید. واحدی با DeviceAllow یا سیاست سخت‌شده‌ی دستگاه می‌تواند دسترسی به گره‌ای را که مدیر کانتینر فراهم کرده است منع کند. وقتی گره هست اما سرویس خطای اجازه گزارش می‌کند، سیاست دستگاه واحد را بررسی کنید و همان سیاست را تغییر دهید، نه کانتینر را پهن‌تر کنید.

اتصال گرم اختیاری و صریح است. ورودی با required=false به مسیر منبع نیاز دارد و می‌تواند با تغییر دستگاه میزبان ظاهر یا ناپدید شود. این چرخه‌ی عمر به سخت‌افزاری می‌خورد که می‌آید و می‌رود؛ برای دستگاه TUN که VPN هنگام راه‌اندازی می‌خواهد، ورودی اختیاری می‌تواند سرویس را پیش از موجود بودن پیش‌نیازش آغاز کند.

دیدنی بودن، باز شدن و واسط را به همین ترتیب بررسی کنید

نخست گره را درون کانتینر مورد نظر تأیید کنید. مسیر، شماره‌های اصلی و فرعی و مالکیت باید با دستگاه میزبان و ورودی‌ای که افزودید بخواند. نبودِ گره یعنی مدیر ورودی را اعمال نکرده یا آن را روی نمونه‌ی دیگری اعمال کرده است.

lxc exec vpnbox -- ls -l /dev/net/tun
lxc exec vpnbox -- sh -c 'test -c /dev/net/tun && echo char-device-ok'

سپس تأیید کنید که حساب سرویس می‌تواند آن را باز کند. آزمون کوتاهی با آن حساب مشکل مالکیت را از مشکل سرویس جدا می‌کند. در پایان کلاینت را آغاز کنید و تأیید کنید که واسط تونل پدیدار می‌شود؛ تنها این گام سوم کل مسیر را اثبات می‌کند، چون دو گام نخست می‌توانند بگذرند در حالی که نمایه یا توانایی کلاینت هنوز نادرست است.

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

مقالات مرتبط