چرا resolv.conf دیاناس VPN شما را نشان میدهد اما جستوجوها آن را نادیده میگیرند
روی میزبان دارای resolved فایل یک نما است، نه خود وضعیت. stub، سرورهای هر پیوند و خط nsswitch را دنبال کنید تا ببینید یک جستوجو واقعاً از کدام استفاده میکند.
در گزارشها هیچ چیز اشتباه به نظر نمیرسد: واسط بالاست، حلکننده سرور DNS مربوط به VPN را گزارش میدهد و فایل روی دیسک آن را فهرست میکند. با این حال یک نام میزبان داخلی هنوز از طریق مسیریاب محلی حل میشود. این سه گزاره متناقض نیستند، زیرا فایل، وضعیت هر پیوند و مسیر جستوجو اشیاء متفاوتی هستند که تصادفاً نامی مشترک دارند. آنچه میآید مسیری است که یک پرسوجو واقعاً روی میزبان دارای systemd-resolved طی میکند.
سه شیء به نام resolv.conf
روی میزبان دارای resolved، /etc/resolv.conf معمولاً پیوند نمادین به /run/systemd/resolve/stub-resolv.conf است. آن مقصد آدرس یک شنونده stub محلی، 127.0.0.53، بههمراه دامنههای جستوجویی را دارد که resolved محاسبه کرده است. این نمایی از وضعیت است، نه خود وضعیت.
وضعیت در پیکربندی resolved برای هر پیوند زندگی میکند، و به همین دلیل resolvectl status میتواند با فایل اختلاف داشته باشد و همچنان درست باشد. هر پیوند سرورها و دامنههای مسیریابی خودش را حمل میکند، و stub هنگام رسیدن پرسوجو به آن دادهها مراجعه میکند. راهنمای systemd-resolved فایلهای تولیدشده و مدل هر پیوند را توصیف میکند؛ جدایی نما از وضعیت بخشی است که ارزش بهخاطر سپردن دارد. تغییر مقصد پیوند نمادین چیزی را عوض میکند که کارخواههای سنتی میخوانند، نه چیزی را که حلکننده میداند.
شیء سوم، /run/systemd/resolve/resolv.conf، هر پیوند را در یک فهرست سرور تخت میکند. برنامهای که به آن فایل اشاره میکند پرسوجوها را مستقیم به سرورهای فهرستشده میفرستد و stub را دور میزند، پس سیاست هر پیوند دیگر بر آن اعمال نمیشود. بنابراین دو برنامه روی یک ماشین میتوانند به یک نام پاسخ متفاوت بدهند و هیچکدام خراب نیست.
یک جستوجو را از مسیر NSS دنبال کنید
glibc فایل /etc/nsswitch.conf را میخواند تا تصمیم بگیرد چه کسی به یک نام پاسخ میدهد. خط hosts که resolve را دارد پرسش را به nss-resolve میفرستد، که از resolved روی D-Bus میپرسد و پاسخ هر پیوند را میگیرد. خطی که فقط files dns دارد پرسوجو را به آدرسی میفرستد که /etc/resolv.conf نگه میدارد.
همین یک خط بیشتر اختلافها میان مرورگر و dig را توضیح میدهد. dig فایل resolv.conf را مستقیم میخواند و هرگز به NSS دست نمیزند، پس stub یا یک سرور بالادستی را میآزماید نه مسیری را که برنامه استفاده میکند. اما getent hosts internal.example از NSS میگذرد، و مقایسه پاسخ آن با پاسخ dig نخستین اندازهگیری سودمند است.
برنامههایی که حلکننده خودشان را همراه دارند یا DNS را روی HTTPS با نقطه پایانی ثابت صحبت میکنند، هر دو مسیر را دور میزنند. هیچ چیز در resolv.conf یا در وضعیت resolved آنها را محدود نمیکند.
بررسی کنید فایل مال کیست و به کجا اشاره میکند
پیش از تغییر هر چیزی زنجیره پیوندها را بخوانید، چون مالکیت تعیین میکند کدام فایل مرجع است. هر فرمان زیر فقط وضعیت را میخواند.
stat -c '%N' /etc/resolv.conf
resolvectl status --no-pager
grep '^hosts' /etc/nsswitch.conf
ls -l /run/systemd/resolve/
خط اول پیوند و مقصدش را با هم چاپ میکند، و فایل معمولی که مالکش یک اسکریپت VPN است یعنی حلکننده هرگز آن نوشتن را ورودی نمیداند. خروجی وضعیت سرورهای هر پیوند را بههمراه دامنههای مسیریابی که تعیین میکنند هر پرسوجو کجا میرود فهرست میکند. خط nsswitch میگوید آیا اصلاً به stub مراجعه میشود، پس آدرس stub در فایل بدون resolve در آنجا یعنی پرسوجوها به شنونده محلی میرسند در حالی که هیچ چیز تقسیم را مدیریت نمیکند. آن فهرست آخر هم مهم است، چون میزبانی بدون stub-resolv.conf ترتیبی را که اینجا توصیف شد اجرا نمیکند.
اگر زنجیره به فایلی ختم شود که بسته دیگری آن را مدیریت میکند، کارخواه VPN و آن بسته دو مالکی هستند که باید سازش داده شوند. جایگزینی پیوند کار یک مالک را دور میریزد و کار دیگری را سر جایش میگذارد.
در مالک پیوند تعمیر کنید
اتصال VPN باید سرورها و دامنههایش را روی پیوند خودش ثبت کند و سپس هنگام قطع اتصال آنها را پس بگیرد. یکپارچگی resolved در NetworkManager و کمککننده خود کارخواه هر دو اینگونه کار میکنند؛ اسکریپی که فقط resolv.conf را بازنویسی میکند اینگونه نیست.
روی پیوندی که از قبل وجود دارد، تنظیمات زمان اجرا سازوکار را نشان میدهند. resolvectl dns tun0 10.40.0.53 یک سرور را متصل میکند و resolvectl domain tun0 '~corp.example' یک دامنه مسیریابی را. مدک (~) نویسه باربر است: پرسوجوهای آن پسوند را به این پیوند محدود میکند و بقیه را به حال خود میگذارد، در حالی که همان مقدار بدون آن به دامنه جستوجو تبدیل میشود و تقسیم بخار میشود. آن آدرسها نمونههای آزمایشگاهیاند، نه پیکربندی پایدار. با resolvectl query host.corp.example تأیید کنید و بخوانید کدام پیوند پاسخ داد.
سرور ثبتشده هنوز به مسیر نیاز دارد. وقتی پرسوجو به پیوند درست میرسد و زمانش تمام میشود، نقص در دسترسپذیری از طریق تونل است نه در مالکیت حلکننده.
وضعیت کارآمد چگونه است
نتیجه سالم در هر سه نما سازگار است: سرورهای هر پیوند با آنچه VPN توزیع کرده میخواند، دامنههای مسیریابی فقط پسوندهای داخلی را پوشش میدهند، و برنامهای که مهم است یک نام داخلی را حل میکند در حالی که نام عمومی هنوز مسیر محلی را دنبال میکند. یک پرسوجوی موفق کمتر از این همخوانی را اثبات میکند.
سپس قطع کنید و هر دو پرسوجو را تکرار کنید. کارخواهی که دامنههایش را پس از برچیدن ثبتشده رها میکند ماشینی میسازد که ساعتها بعد در جستوجوهای داخلی شکست میخورد، بدون تونل باز و بدون علت آشکار.