سرویس شروع می‌شود، نمایه را بدون هیچ شکایتی می‌خواند و سپس روی خطی می‌میرد که بی‌ربط به نظر می‌رسد: نمی‌تواند ca.crt را باز کند. هیچ چیز در گواهی تغییر نکرده است، و مسیر نمایه در فایل unit مطلق است. همین ترکیب نشانه است. مسیری که داده‌اید یک فایل را مشخص می‌کند، و نام‌های داخل آن فایل کاملاً جای دیگری حل می‌شوند، بنابراین راه‌اندازی‌ای که کاملاً واجد شرایط به نظر می‌رسد می‌تواند همچنان کلیدهایش را از دایرکتوری بخواند که هیچ‌کس قصدش را نداشته است.

شکست دلایل کمی دارد، و ارزش دارد که به ترتیب از هم جدا شوند: دایرکتوری پایه‌ای که فرآیند واقعاً داشت، بستر راه‌اندازی سرویس، و مجوزها یا سندباکس پیرامون فایل وقتی مسیر درست است. هر کدام ردپای متفاوتی به جا می‌گذارند — در unit، در فرآیند و در سیستم فایل.

مسیر نمایه یک دایرکتوری پایه نیست

فرآیندی را تصور کنید که در /tmp شروع می‌شود و /etc/vpn/prod/tenant-a.ovpn به آن داده می‌شود. در داخل آن نمایه، خط ca ca.crt یک مسیر نسبی را نام می‌برد. هیچ چیز در آرگومانی که نمایه را پیدا کرد آن نام را بازنویسی نمی‌کند، بنابراین فرآیند /tmp/ca.crt را جست‌وجو می‌کند و فایل گمشده را گزارش می‌دهد.

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

آنچه دفترچه راهنما جدا می‌کند: --config و --cd

دفترچه راهنمای OpenVPN 2.6 دو گزینه متمایز را توصیف می‌کند. یکی فایل پیکربندی را بارگذاری می‌کند. دیگری دایرکتوری فرآیند را پیش از خواندن پیکربندی، کلید، اسکریپت و فایل‌های دیگر تغییر می‌دهد، و دایرکتوری مطلقی را بدون هیچ ارجاعی به دایرکتوری کنونی می‌طلبد.

openvpn --cd /etc/vpn/prod --config tenant-a.ovpn

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

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

سرویس جای دیگری شروع می‌شود

یک پوسته تعاملی در دایرکتوری نمایه هیچ چیزی درباره یک unit بسته‌بندی‌شده ثابت نمی‌کند. مدیرها دایرکتوری کار خودشان را تعیین می‌کنند، و یک اسکریپت پوشش ممکن است پیش از اجرای باینری دوباره آن را تغییر دهد. unitی که شکست می‌خورد تنها راه‌اندازی‌ای است که ارزش استدلال دارد.

systemctl show -p WorkingDirectory -p ExecStart --value openvpn@tenant-a
ls -l /proc/$(pgrep -n openvpn)/cwd

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

پس از جست‌وجو: مجوزها، chroot و سندباکس

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

سه گونه رایج خطای یکسانی تولید می‌کنند. فایل فقط برای root خواندنی است در حالی که سرویس پیش از باز کردن آن از امتیازات دست می‌کشد. unit یک نمای محافظتی از سیستم فایل تنظیم می‌کند که دایرکتوری نمایه را شامل نمی‌شود. دیمن با chroot اجرا می‌شود، پس مسیری که روی میزبان وجود دارد در داخل آن نما وجود ندارد.

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

اصلاح را با راه‌اندازی خودتان ثابت کنید

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

systemctl restart openvpn@tenant-a
systemctl status openvpn@tenant-a --no-pager
journalctl -u openvpn@tenant-a -n 20 --no-pager

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

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

مقالات مرتبط