Recursive DNS چیست و چه خطرهایی دارد؟
پاسخ کوتاه: Recursive DNS سرویسی است که بهجای کاربر، کل زنجیره جستوجو را از سرورهای ریشه تا سرور مرجع دامنه دنبال میکند و پاسخ نهایی را تحویل میدهد. خطر آن وقتی ظاهر میشود که این سرویس روی اینترنت برای همه باز بماند؛ در آن حالت مهاجم با جعل آدرس مبدأ، از سرور شما بهعنوان تقویتکننده حمله DDoS علیه دیگران استفاده میکند.
تفاوت Recursive با Authoritative
در DNS دو نقش کاملاً جدا وجود دارد و قاطی کردن این دو، ریشه بیشتر پیکربندیهای ناامن است.
- سرور Authoritative (مرجع): دادههای یک zone را نگه میدارد و فقط درباره همان دامنهها پاسخ میدهد. اگر پرسشی خارج از دامنههای خودش بگیرد، پاسخی نمیسازد.
- سرویس Recursive (بازگشتی یا resolver): خودش هیچ zone ای ندارد. کارش این است که از طرف کلاینت جستوجو کند، پاسخ را در حافظه cache نگه دارد و تحویل بدهد.
سرور مرجع باید برای همه دنیا باز باشد، وگرنه دامنه شما اصلاً resolve نمیشود. اما resolver باید فقط به کلاینتهای شناختهشده خودتان پاسخ بدهد. اگر تنها چیزی که لازم دارید نگهداری رکوردهای دامنه است، این نقش را میشود به یک سرویس هاست DNS سپرد و اصلاً سراغ راهاندازی resolver نرفت.
Recursive و Iterative دقیقاً چه فرقی دارند
وقتی مرورگر شما نشانی سایتی را میخواهد، یک پرسش recursive به resolver اپراتور یا سرور DNS داخلی سازمان میفرستد؛ یعنی «پاسخ نهایی را بده، مسیرش به من مربوط نیست». resolver از آن نقطه به بعد پرسشهای iterative میفرستد: از سرور ریشه میپرسد، ارجاع (referral) به سرورهای TLD میگیرد، از آنها ارجاع به نیمسرورهای دامنه میگیرد و در نهایت رکورد را از سرور مرجع دریافت میکند.
پس iterative «حالت امن recursive» نیست؛ این دو، دو سر یک زنجیره واحدند. سرور مرجع پرسش iterative را با ارجاع پاسخ میدهد و همین رفتار درست اوست. resolver هم نتیجه را تا پایان TTL نگه میدارد تا پرسش بعدی سریعتر جواب بگیرد.
Open resolver چیست و چرا خطرناک است
اگر سرویس recursive شما به هر آدرس IP در اینترنت پاسخ بدهد، به آن open resolver میگویند. مشکل از ماهیت پروتکل میآید: DNS بهطور پیشفرض روی UDP کار میکند و UDP دستدادن (handshake) ندارد. یعنی مهاجم میتواند بستهای بسازد که آدرس مبدأ آن، IP قربانی باشد و سرور شما پاسخ را صادقانه به سمت قربانی بفرستد.
سرور معتبر فقط زون خودش را پاسخ میدهد، اما ریزالور برای هر کسی جستوجو میکند؛ اگر روی اینترنت باز بماند، به تقویتکننده حمله تبدیل میشود.
این همان چیزی است که به آن حمله DNS amplification یا reflection میگویند: پرسش کوچک است، اما پاسخ میتواند چند برابر بزرگتر باشد. نسبت تقویت به نوع رکورد و اندازه پاسخ بستگی دارد؛ پرسشهایی مثل ANY یا zone هایی با رکوردهای TXT و DNSSEC حجیم، بیشترین بازدهی را برای مهاجم دارند. EDNS0 هم که اجازه پاسخهای UDP بزرگتر را میدهد، این نسبت را بالاتر میبرد.
نکته مهم این است که در چنین سناریویی شما قربانی نیستید، ابزار حملهاید؛ ولی هزینهاش را خودتان میدهید: مصرف پهنایباند، اشباع شدن صف پردازش، شکایت abuse از سمت دیتاسنتر و در بدترین حالت مسدود شدن IP. اگر روی سرور مجازی لینوکسی خودتان BIND را نصب کردهاید و هیچوقت پیکربندی پیشفرضش را بازبینی نکردهاید، دقیقاً همینجا باید بررسی کنید.
خطرهایی که کمتر دیده میشود
- مسمومسازی cache: resolver باز، سطح حمله بزرگتری برای تزریق پاسخ جعلی در اختیار مهاجم میگذارد. نتیجهاش هدایت کاربران به مقصد اشتباه است.
- حمله زیردامنه تصادفی: مهاجم از طریق resolver های باز، سیل پرسش برای زیردامنههای بیمعنی یک دامنه میفرستد. چون این پاسخها در cache نیستند، تمام فشار به سرور مرجع آن دامنه منتقل میشود.
- تونلزنی و خروج داده: resolver باز میتواند مسیر سادهای برای DNS tunneling و انتقال داده از داخل شبکه به بیرون باشد.
- قرار گرفتن در فهرستهای عمومی: فضای IP اینترنت مدام اسکن میشود و resolver های باز فهرست میشوند؛ یعنی پیدا شدن سرور شما فقط مسئله زمان است.
چطور بفهمم سرورم باز است
تست را باید از یک ماشین بیرون از شبکه خودتان اجرا کنید، نه از روی خود سرور:
dig @IP_SERVER example.com A
اگر برای دامنهای که سرور شما اصلاً مرجع آن نیست پاسخ کامل گرفتید و در بخش flags خروجی، پرچم ra یعنی recursion available دیده شد، سرور شما open resolver است. پاسخ درست در این حالت REFUSED است.
محدود کردن recursion در عمل
BIND
اگر سرور فقط نقش مرجع دارد (حالت رایج نیمسرورهای هاستینگ)، recursion را کامل ببندید:
options { recursion no; allow-query-cache { none; }; };
و اگر واقعاً به resolver نیاز دارید، آن را به شبکه خودتان محدود کنید:
acl trusted { 127.0.0.1; 10.0.0.0/8; };
options { recursion yes; allow-recursion { trusted; }; allow-query-cache { trusted; }; };
دقت کنید که در BIND گزینه recursion بهصورت پیشفرض روشن است و محدودسازی واقعی از طریق allow-recursion انجام میشود. اگر allow-recursion را صریح تعریف نکنید، BIND بهترتیب سراغ allow-query-cache و سپس allow-query میرود؛ یعنی باز گذاشتن allow-query روی any بدون تعریف صریح allow-recursion، سرور را عملاً به open resolver تبدیل میکند.
Unbound و PowerDNS Recursor
در Unbound با access-control کار میکنید: اول همهچیز را refuse کنید و بعد فقط شبکه خودتان را allow کنید. در PowerDNS Recursor همین کار با پارامتر allow-from انجام میشود. در هر دو، مقدار interface یا local-address را روی IP داخلی بگذارید تا سرویس اصلاً روی اینترنت گوش ندهد.
لایه شبکه و سرور مرجع
مستقل از پیکربندی نرمافزار، پورت ۵۳ را روی UDP و TCP در فایروال به مبدأهای مجاز محدود کنید. برای سرور مرجع هم فعال کردن Response Rate Limiting و پاسخ حداقلی به پرسشهای ANY (طبق RFC 8482) اثر تقویت را پایین میآورد؛ مقدار نرخ را متناسب با ترافیک واقعی خودتان تنظیم کنید نه با عدد پیشفرض. اگر سختسازی سیستمعامل و فایروال را خودتان انجام نمیدهید، سرویس پشتیبانی و مدیریت سرور همین دست کارها را پوشش میدهد.
اگر نمیخواهید سرور DNS نگه دارید
بخش بزرگی از کسانی که BIND بالا میآورند در واقع فقط به نقش مرجع نیاز دارند. سپردن این نقش به یک سرویس بیرونی، هم ریسک open resolver را از بین میبرد و هم رکوردها را از چند نیمسرور مستقل پاسخ میدهد. اگر علاوه بر پاسخدهی ساده به مسیریابی بر اساس موقعیت جغرافیایی کاربر و مانیتورینگ سلامت مقصدها هم نیاز دارید، Geo DNS برای همین ساخته شده است.
جمعبندی: recursive بودن بهخودیخود بد نیست، هر شبکهای به resolver نیاز دارد. چیزی که خطرناک است باز بودن آن روی کل اینترنت است. نقش مرجع و resolver را جدا کنید، دسترسی resolver را به شبکه خودتان ببندید و نتیجه را حتماً از بیرون تست کنید.