قبلا مفصل در مورد DNS و طرز کار آن صحبت کردیم. کیفیت این سرویس مهم و حیاتی دنیای شبکه و اینترنت، نقش مهمی در بالا رفتن کیفیت دسترسی کاربران به منابع آن شبکه دارد. تقریبا تمام سیستمعاملهای سرور به شما امکاناتی برای راهاندازی یک سرور DNS را میدهند از جمله سیستمعامل محبوب لینوکس که از یکی از مشهورترین و قدرتمندترین نرمافزارهای DNS سرور به نام BIND (بایند یا Named) استفاده میکند. بایند در سال ۱۹۸۴ و در دانشگاه برکلی خلق شد و وظیفه آن ترجمه نامهای دامنه به آدرسهای IP می باشد. در نوشته امروز قصد داریم روش راهاندازی یک Caching DNS Server در سیستمعامل CentOS 8 را با هم بررسی کنیم. اما قبل از آن توضیح کوتاهی در مورد این سیستمعامل و این سرویس بخوانید.
چرا لینوکس و چرا CentOS؟
فارغ از انواع مقایسههای فنی و علمی و دعواها و تعصبها در مورد این که لینوکس بهتر است یا ویندوز و یا سایر سیستمعامل ها، به عنوان یک مدیر شبکه که تقریبا بیشتر از ۱۰ سال است که از سیستمعامل لینوکس در سرورهای اصلی استفاده میکنم، به جرات میتوانم ادعا کنم که تا به حال به مشکلی از بابت این انتخاب بر نخوردم و پایداری، امنیت و سرعت این سیستمعامل همیشه یکی از نقاط قوت شبکههایی بوده است که سرپرستی کردهام. البته سیستمعامل Windows Server هم ابزارهای قدرتمندی برای راهاندازی DNS Server دارد و علاوه بر آن BIND نیز امکان نصب و اجرا بر روی ویندوز را دارد (هرچند معمولا این اتفاق نمیافتد). CentOS هم یکی از توزیعهای مشهور لینوکس است که در واقع نسخه رایگان و متن باز لینوکس تجاری Red Hat است و در کاربردهای محیط Production بسیار موفق عمل کرده است. آخرین نسخه این توزیع ۸ است که من برای این آموزش از آن استفاده کردهام.
Caching DNS چیست؟
فرض کنیم شما مسئول شبکهای هستید که تعداد زیادی کاربر به روشهای مختلف از طریق آن به اینترنت متصل هستند. مثلا شبکه داخلی یک شرکت که در آن تعداد زیادی کامپیوتر و دستگاه قابل حمل (تلفن هوشمند، تبلت یا لپتاپ) در حال استفاده از خط ارتباطی اینترنت شرکت هستند. تمام این تجهیزات هر زمان که بخواهند به یک وبسایت و یا سرویس اینترنت دسترسی داشته باشند، لازم است ابتدا نام دامنه آن را (مثلا google.com) از سرور DNS پرس و جو کرده، آدرس IP آن را به دست بیاورند و سپس با آن ارتباط بگیرند. هر پرس و جو علاوه بر این که بخشی از پهنای باند اینترنت شما را اشغال میکند، به مقداری زمان برای برگرداندن نتیجه نیاز دارد. مثلا هر بار که کاربر بخواهد سایت گوگل را ببیند باید به عنوان مثال حدود ۲۰۰ میلی ثانیه در انتظار دریافت آدرس IP آن از سرور DNS باشد. جالب است که بدانید هر گوشی اپل به تنهایی طی ۲۴ ساعت بیش از ۵۰۰۰ بار فقط دامنهها و زیردامنههای apple.com و icloud.com را به IP آنها تبدیل کرده و به اصلاح Resolve می کند. یعنی با فرض عدد ۲۰۰ میلی ثانیه برای هر resolve کاربر این گوشی باید حدود ۱۶ دقیقه در روز منتظر پاسخ DNS سرورها باشد! البته این فقط مربوط به سرویسهای داخلی گوشی است و با در نظر گرفتن اپلیکیشنها و سایتهایی که کاربر از آنها استفاده میکند این عدد بسیار بزرگتر خواهد بود.
حالا، اگر ما یک سرور DNS در شبکه داخلی خود داشته باشیم که دستگاههای موجود در شبکه به جای ارتباط با DNS راه دور پرس و جوهای خود را از طریق آن انجام دهند، سرعت resolve آنها و در نتیجه کیفیت ارتباط اینترنتی بسیار بهینهتر خواهد بود. از طرفی با توجه به این که DNS داخلی نیز باید درخواستهای کاربران را از سایر سرورهای راه دور بپرسد و در اصطلاح آنها را Forward کند، پس وقتی که یکی از دستگاههای موجود در شبکه یک آدرس را پرس و جو کند، DNS سرور داخلی میتواند نتیجه پرس و جو را در حافظه خود نگه دارد و در پرس و جوهای بعدی به جای forward کردن آن به راه دور، نتیجهای را که در حافظه نگه داشته یا در اصطلاح cache کرده است به کاربر متقاضی برمیگرداند. این یعنی صرفهجویی در پهنای باند اینترنت و در کنار آن کاهش زمان پاسخ به کاربر و بالا رفتن کیفیت دسترسی به اینترنت در شبکه. وقتی یک DNS سرور به این صورت عمل میکند، به آن Caching DNS Server میگوییم.
ممکن است برای شما سوال باشد این است که اگر آدرس IP مربوط به یک دامنه تغییر کند، و از طرفی اطلاعات قبلی آن در حافظه cache سرور داخلی موجود باشد، تکلیف به روز شدن این اطلاعات چیست؟ سرور داخلی ما چگونه می تواند همیشه آدرس به روز یک دامنه را به کاربران ارائه کند؟ جواب در اطلاعات اضافهای است که DNS سرور راه دور برای سرور ما ارسال می کند. در جواب پرس و جوهای انجام شده، هر DNS سرور رکوردهای مختلفی ارسال میکند که یک فیلد اطلاعاتی موجود در آن TTL است. این رکورد به درخواست کننده میگوید که پاسخ ارسال شده تا چه زمانی اعتبار دارد. یک Caching DNS Server وقتی متوجه شود که تاریخ اعتبار اطلاعات یک دامنه به پایان رسیده است، به صورت خودکار اطلاعات آن را از سرور راه دور به روز کرده و در حافظه خود ذخیره می کند.
نصب Caching DNS
بعد از توضیحات بالا، به سراغ نصب یک Caching DNS Server می رویم. برای این کار من از یک سرور مجازی با ۸ گیگابایت حافظه، دو هسته پردازنده و ۶۴ گیگابایت هارد دیسک استفاده کردم. روی این سرور سیستم عامل CentOS 8 شصت و چهار بیتی به صورت Minimal (فقط با پکیج های ضروری مورد نیاز) نصب شده است. میتوانید آخرین نسخه CentOS را از اینجا دانلود کنید.
این سرور دو کارت شبکه دارد که یکی به اینترنت متصل شده و دیگری به شبکه داخلی و آدرس داخلی آن هم ۱۹۲٫۱۶۸٫۸٫۲۵۰ است. درخواستهای کاربران شبکه از طریق شبکه داخلی دریافت می شود و forward درخواستها به سرورهای راه دور از طریق کارت شبکه ای که به اینترنت متصل است صورت میگیرد.
برای شروع با حساب کاربری root به سرور لاگین میکنیم. قبل از شروع هر کاری با دستور زیر سیستم عامل و پکیج های آن را آپدیت میکنیم تا از نصب آخرین نسخه ها و ایمن بودن سرور مطمئن باشیم. توجه کنید که وجود اتصال اینترنتی برای اجرای دستور yum ضروری است:
حالا با دستور زیر نرم افزارهای مورد نیاز را نصب میکنیم.
[pastacode lang=”haml” manual=”%23%20yum%20install%20bind%20bind-utils%20nano%20policycoreutils-python-utils%20-y” message=”” highlight=”” provider=”manual”/]این دستور ۴ پکیج را نصب می کند.
Bind: نرم افزار اصلی DNS Server یا همان Bind با استفاده از این پکیج نصب می شود.
Bind-utils: ابزارهای جانبی همراه Bind با استفاده از این پکیج نصب می شوند.
Nano: نانو یک ادیتور متن خوش دست، پر طرفدار و بسیار ساده برای لینوکس است. با توجه به این که پیکربندی سرور از طریق ویرایش فایلهای متنی انجام می شود، یک ادیتور خوب برای انجام این کار ابزار بسیار مهم و موثری خواهد بود.
Policycoreutils: این پکیج ابزارهایی برای انجام تنظیمات Policy های امنیتی سرور دارد. با نصب پکیج دستور semanage فعال می شود که از آن برای انجام تنظیمات مربوط به SeLinux (سپر امنیتی CentOS) استفاده میکنیم.
پیکربندی سرور
بعد از نصب پکیجهای مورد نیاز، لازم است تا پیکربندی سرور DNS را انجام دهیم. دستورات پیکربندی در یک فایل متنی در مسیر etc/named.conf/ قرار دارد که با استفاده از ادیتور nano آن را ویرایش میکنیم. دستور زیر این فایل را برای ویرایش باز می کند:
[pastacode lang=”haml” manual=”%23%20nano%20%2Fetc%2Fnamed.conf” message=”” highlight=”” provider=”manual”/]در ابتدا شما پیکربندی پیش فرض BIND را مشاهده میکنید. اولین بلاک این فایل، بلاک options بوده که به صورت پیش فرض شبیه به کد زیر است. چند تنظیم مهم باید در این بلاک انجام شود.
[pastacode lang=”haml” manual=”options%20%7B%0A%09listen-on%20port%2053%20%7B%20127.0.0.1%3B%20%7D%3B%0A%09listen-on-v6%20port%2053%20%7B%20%3A%3A1%3B%20%7D%3B%0A%09directory%20%09%22%2Fvar%2Fnamed%22%3B%0A%09dump-file%20%09%22%2Fvar%2Fnamed%2Fdata%2Fcache_dump.db%22%3B%0A%09statistics-file%20%22%2Fvar%2Fnamed%2Fdata%2Fnamed_stats.txt%22%3B%0A%09memstatistics-file%20%22%2Fvar%2Fnamed%2Fdata%2Fnamed_mem_stats.txt%22%3B%0A%09secroots-file%09%22%2Fvar%2Fnamed%2Fdata%2Fnamed.secroots%22%3B%0A%09recursing-file%09%22%2Fvar%2Fnamed%2Fdata%2Fnamed.recursing%22%3B%0A%09allow-query%20%20%20%20%20%7B%20localhost%3B%20%7D%3B%0A%0A%09recursion%20yes%3B%0A%0A%09dnssec-enable%20yes%3B%0A%09dnssec-validation%20yes%3B%0A%0A%09managed-keys-directory%20%22%2Fvar%2Fnamed%2Fdynamic%22%3B%0A%0A%09pid-file%20%22%2Frun%2Fnamed%2Fnamed.pid%22%3B%0A%09session-keyfile%20%22%2Frun%2Fnamed%2Fsession.key%22%3B%0A%0A%09include%20%22%2Fetc%2Fcrypto-policies%2Fback-ends%2Fbind.config%22%3B%0A%7D%3B” message=”” highlight=”” provider=”manual”/]دستور listen-on در خط دوم مشخص میکند که DNS سرور باید به چه آدرسی و روی چه پورتی گوش بدهد و پرس و جوها را دریافت کند. پیشنهاد میکنم پورت پیش فرض ۵۳ را که پورت استاندارد سرویس DNS است تغییر ندهید. من گوش دادن به آدرس ۱۲۷٫۰٫۰٫۱ (لوکال هاست) و ۱۹۲٫۱۶۸٫۸٫۲۵۰ که آدرس داخلی سرور است را فعال میکنم:
[pastacode lang=”haml” manual=”listen-on%20port%2053%20%7B%20127.0.0.1%3B%20192.168.8.250%3B%20%7D%3B” message=”” highlight=”” provider=”manual”/]می توانید در خط سوم و با دستور listen-on-v6 به همان ترتیب بالا پورت و آدرس را برای IPv6 تنظیم کنید. چون برای کارت شبکه داخلی این سرور IPv6 تعریف نشده این گزینه را بدون تغییر میگذاریم تا سرور فقط به آدرس ::۱ (لوکال هاست IPv6) گوش بدهد.
در خط دهم گزینه allow-query قرار دارد. در این بلاک میتوانید بازههای آدرسهای IP را که اجازه پرس و جو از سرور را دارند مشخص کنید. من لوکال هاست و بازه ۱۹۲٫۱۶۸٫۸٫۰/۲۴ که آدرسهای شبکه داخلی است اضافه میکنم:
اگر خواستید سرور به پرس و جوهای تمام درخواست کنندگان پاسخ دهد، می توانید در این بلاک گزینه any را قرار دهید. اما مواظب باشید! در این صورت سرور درخواستهای رسیده از خارج شبکه را نیز پردازش میکند و این میتواند سرور شما را در معرض حملات dos یا ddos قرار دهد.
بعد از این خط، با دستور allow-query-cache امکان cache کردن نتایج پرس و جو ها را برای همان آدرسهای بلاک allow-query فعال میکنیم. این خط را اضافه کنید:
DNS سرورهایی که پرس و جوها را با استفاده از سرورهای راه دور resolve میکنند، باید در حالت بازگشتی و با فعال کردن گزینه recursion به عملیات بپردازند. با تنظیم این گزینه روی مقدار yes میتوانید این حالت را فعال کنید:
[pastacode lang=”haml” manual=”recursion%20yes%3B” message=”” highlight=”” provider=”manual”/]برای انجام عملیات به عنوان forwarder با اضافه کردن دستور زیر به همراه بلاک فورواردرها که در واقع آدرس سرورهای راه دور متصل به سرور ما میباشد، این قابلیت را فعال میکنیم:
[pastacode lang=”haml” manual=”forward%20only%3B%0Aforwarders%20%7B%20%0A%20%20%20%20%201.0.0.1%3B%0A%20%20%20%20%208.8.8.8%3B%0A%20%20%20%20%20217.218.155.155%3B%0A%20%20%20%20%20208.67.220.220%3B%0A%7D%3B” message=”” highlight=”” provider=”manual”/]آدرسهایی که من در بلاک forwarders قرار دادم مربوط به DNS سرورهای عمومی مشهور و پرسرعت است. انتخاب بهینه فورواردرها با توجه به موقعیت جغرافیایی و دسترسی شبکه ای سرور تاثیر مهمی بر بالا بردن سرعت پاسخگویی DNS سرور داخلی ما دارد. اگر میخواهید بیشتر درباره این سرورها و انتخاب مناسب ترین حالت بدانید، این نوشته را مطالعه کنید.
در پایان این دو خط را هم به داخل بلاک options اضافه کنید:
دستور max-cache-size مشخص میکند که DNS سرور میتواند چه مقدار از حافظه Ram سرور را برای cache کردن پرس و جوها استفاده کند. مقدار این گزینه بر حسب مقدار حافظه سخت افزاری سرور تنظیم می شود و من آن را روی ۴۰۹۶ مگابایت یا ۴ گیگابایت تنظیم کردم. فراموش نکنید همیشه مقداری از Ram را برای مصرف سیستم عامل خالی بگذارید.
دستور version برای امنیت سرور شما مهم است. در صورتی که این مقدار تنظیم نشود، سایرین می توانند نسخه دقیق DNS سروری که نصب کردهاید ببینند که ممکن است باعث بعضی خطرات امنیتی به خاطر مشخص بودن باگهای هر نسخه می شود. حالا با تنظیم این مقدار، سرور عبارت not available را به عنوان نسخه خود نمایش خواهد داد.
در نهایت محتوای فایل /etc/named.conf/ باید به صورت زیر باشد:
[pastacode lang=”haml” manual=”fault_debug%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20file%20%22data%2Fnamed.run%22%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20severity%20dynamic%3B%0A%20%20%20%20%20%20%20%20%7D%3B%0A%7D%3B%0A%0Azone%20%22.%22%20IN%20%7B%0A%09type%20hint%3B%0A%09file%20%22named.ca%22%3B%0A%7D%3B%0A%0Ainclude%20%22%2Fetc%2Fnamed.rfc1912.zones%22%3B%0Ainclude%20%22%2Fetc%2Fnamed.root.key%22%3B” message=”” highlight=”” provider=”manual”/]اگر از ادیتور nano برای ویرایش فایل استفاده کردهاید، با فشردن کلیدهای Shift+X میتوانید تغییرات را ذخیره کنید.
دوباره به محیط ترمینال برمیگردیم، برای این که مطمئن شویم فایل کانفیگ ما به درستی نوشته شده و خطا ندارد، دستور زیر را اجرا کنید:
اگر با اجرای این دستور خطایی مشاهده نکردید، به این معناست که فایل شما بدون ایراد تنظیم شده است.
پیکربندیهای امنیتی و دسترسی
برای عملکرد درست DNS سرور، لازم است مالکیت فایلهای تنظیمات سرور برای کاربر named و گروه root تنظیم شود. با اجرای دستورات زیر از این بابت مطمئن می شویم:
[pastacode lang=”haml” manual=”%23%20chown%20root%3Anamed%20%2Fetc%2Fnamed.conf%0A%23%20chown%20root%3Anamed%20%2Fetc%2F%2Fetc%2Fnamed.rfc1912.zones” message=”” highlight=”” provider=”manual”/]در صورتی که SeLinux روی سرور فعال باشد، با اجرای دو دستور زیر مجوز لازم را به پردازه BIND برای دسترسی به فایلهای تنظیمات صادر میکنیم:
[pastacode lang=”haml” manual=”%23%20semanage%20fcontext%20-a%20-t%20named_conf_t%20%2Fetc%2Fnamed.conf%0A%23%20semanage%20fcontext%20-a%20-t%20named_conf_t%20%2Fetc%2Fnamed.rfc1912.zones” message=”” highlight=”” provider=”manual”/]پیکربندی Firewall
با توجه به این که CentOS 8 به صورت پیش فرض همراه با فایروال داخلی خود نصب می شود، لازم است که پورت شماره ۵۳ روی پروتکل UDP برای دسترسی کاربران به سرویس باز شود. سه دستور زیر این کار را برای ما انجام می دهد:
[pastacode lang=”haml” manual=”%23%20firewall-cmd%20–add-port%3D53%2Fudp%0A%23%20firewall-cmd%20–add-port%3D53%2Fudp%20–permanent%0A%23%20firewall-cmd%20–reload” message=”” highlight=”” provider=”manual”/]اجرا و تست سرویس DNS
حالا نوبت راه اندازی سرور است. دستورات زیر را به ترتیب اجرا کنید:
[pastacode lang=”haml” manual=”%23%20systemctl%20start%20named%0A%23%20systemctl%20enable%20named” message=”” highlight=”” provider=”manual”/]دستور اول سرویس DNS را راهاندازی میکند و دستور دوم سرویس را به صورت خودکار با هر بار ریبوت شدن سیستمعامل اجرا خواهد کرد.
حالا وقت آن رسیده که از عملکرد صحیح DNS سرور مطمئن شویم. در ترمینال دستور زیر را اجرا کنید. این دستور دامنه apple.com را از طریق لوکال هاست resolve میکند:
[pastacode lang=”haml” manual=”%23%20nslookup%20apple.com%20127.0.0.1″ message=”” highlight=”” provider=”manual”/]نتیجه کار باید چیزی شبیه تصویر زیر باشد.
برای این که از cache شدن پرس و جوهای انجام شده مطمئن شویم، از ابزار dig استفاده میکنیم. دستور زیر را اجرا کنید:
[pastacode lang=”haml” manual=”%23%20dig%20apple.com” message=”” highlight=”” provider=”manual”/]نتیجه کار چیزی شبیه تصویر زیر است:
به شاخص Query Time دقت کنید. طبق این اطلاعات مدت زمانی که طول کشید تا دامنه apple.com از طریق سرورهای راه دور resolve شود ۱۹۰ میلیثانیه است. اگر دوباره دستور dig را برای همان دامنه اجرا کنیم، متوجه کاهش زیاد زمان پاسخ میشویم:
در واقع در اولین اجرای دستور dig دامنه apple.com از طریق یکی از سرورهای forwarder پرس و جو شده و نتیجه آن به کاربر برگردانده میشود. این پروسه ۱۹۰میلیثانیه زمان برده است. اما در مرتبه دوم با توجه به این که دامنه apple.com قبلا resolve شده و در حافظه cache سرور قرار گرفته است، پروسه resolve به صورت داخلی در سرور انجام شده و در نتیجه پاسخ کاربر به سرعت و با تاخیر کم (در اینجا صفر میلیثانیه) برگردانده میشود. این همان چیزی است که انتظار داشتیم.
تغییر Name Server پیشفرض سرور
با توجه به این که سرور ما حالا دیگر یک Caching DNS Server آماده به کار است، میتوانیم Name Server پیشفرض آن را بر روی لوکال هاست تنظیم کنیم تا سرور برای resolve کردن دامنههایش از سرویس DNS داخلی خود استفاده کند. برای این کار باید فایل etc/resolv.conf/ را ویرایش کنیم. فایل را با استفاده از nano باز کنید:
[pastacode lang=”haml” manual=”%23%20nano%20%2Fetc%2Fresolv.conf” message=”” highlight=”” provider=”manual”/]بعد از دستور search یک یا چند خط با دستور nameserver وجود دارد. خطوط اضافه را حذف کنید و فقط یک nameserver با مقدار ۱۲۷٫۰٫۰٫۱ تعریف کنید. Network Manager را مجددا راه اندازی کنید تا تغییرات اعمال شود:
[pastacode lang=”haml” manual=”%23%20systemctl%20restart%20NetworkManager.service” message=”” highlight=”” provider=”manual”/]نصب سرویس DNS در حالت chroot
chroot یک فراخوان سیستمی در سیستم عامل های شبه یونیکس است که طی آن یک پردازه به دایرکتوری دیگری به عنوان دایرکتوری ریشه سیستم دسترسی دارد. در ویکی پدیا میتوانید بیشتر درباره حالت chroot و کاربردهای آن مطالعه کنید.
انجام این تنظیمات اختیاری ست، اما اگر بخواهید سرور DNS خود را در حالت chroot پیکربندی کنید، ابتدا پکیج نرم افزاری مربوطه را با دستور زیر نصب میکنیم:
حالا یک لینک از فایل تنظیمات سرور در دایرکتوری پیش فرض named chroot ایجاد میکنیم. به این ترتیب شما هر بار که فایل تنظیمات اصلی را ویرایش کنید، سرور chroot شده شما نیز به آخرین تنظیمات دسترسی خواهد داشت.
[pastacode lang=”haml” manual=”%23%20ln%20-s%20%2Fetc%2Fnamed.conf%20%2Fvar%2Fnamed%2Fchroot%2Fetc%2Fnamed.conf” message=”” highlight=”” provider=”manual”/]برای اعمال تغییرات، سرویس named را مجددا راه اندازی میکنیم:
[pastacode lang=”haml” manual=”%23%20systemctl%20restart%20named” message=”” highlight=”” provider=”manual”/]پس گفتار
کار ما اینجا به پایان رسیده است. Caching DNS Server ما به همین سادگی آماده سرویس دهی و ورود به محیط production است. البته هنوز امکان انجام پیکربندی های پیشرفته تری مثل logging و ثبت وقایع عملکرد DNS سرور و یا مانیتورینگ سرور (با استفاده از ابزارهای مختلف، از جمله PRTG یا Zabbix) وجود دارد که در حوصله این نوشته نیست. با جستجو در گوگل میتوانید مطالب سودمندی در خصوص این پیکربندیها مطالعه کنید.