سامانه نام دامنه و BIND

تاریخچه FreeBSD

در یک شبکه کامپیوتری، کامپیوترها با استفاده از پروتکل IP با یکدیگر ارتباط برقرار می‌کنند. این آدرس های IP برای راحتی کامپیوترها طراحی شده‌اند نه انسان‌ها و به خاطر سپردن آنها برای انسان‌ کاری سخت و مشکل است. می توان برای این آدرس‌های IP یک نام در نظر گرفت تا به خاطر سپردن آنها راحت‌ترشود. مثلاً می‌توانیم به آدرس ۶۹٫۱۴۷٫۸۳٫۳۴ نامی مانند www.FreeBSD.org اختصاص دهیم تا بتوانیم آن را راحت‌تر حفظ کنیم. اما باید روشی پیدا کرد تا بتوان از روی این نام به آدرس IP مورد نظر رسید. پروتکل DNS برای ترجمه این نام‌ها به آدرس‌های IP (و برعکس) معرفی شد. پیاده‌سازی‌های مختلفی از پروتکل DNS وجود دارد که رایج‌ترین این پیاده‌سازی‌ها برنامه BIND است. به صورت پیش فرض یک نسخه از این برنامه به همراه FreeBSD نصب می‌شود.

نحوه کارکرد

ابتدا در شبکه خود یک ماشین را به عنوان DNS Server انتخاب کرده و برنامه BIND را بر روی آن اجرا می‌کنیم. سپس تمام کلاینت ها را طوری تنظیم می‌کنیم که از این ماشین به عنوان DNS Server استفاده کنند. برای انجام این کار، بر روی کلاینت ها فایل /etc/resolv.conf را با یک ویرایشگر متن باز کرده و این خط را به آن اضافه می‌کنیم:

nameserver ip.of.dns.server

البته به جای ip.of.dns.server آدرس IP ماشین DNS Server خود را بنویسید. بدین ترتیب هر برنامه‌ای که نیاز به ترجمه یک نام به یک آدرس IP (یا برعکس) داشته باشد، به این فایل مراجعه کرده و آدرس DNS Server را از آن برمی دارد. سپس درخواست خود را از طریق پورت ۵۳ پروتکل UDP برای آنDNS Server ارسال کرده و منتظر پاسخ می‌ماند. اگر سرور پاسخ درخواست را بداند، آن را برای کلاینت ارسال می‌کند. در غیر این صورت با دیگر DNS Server ها ارتباط برقرار کرده و بعد از پیدا کردن پاسخ، آن را برای کلاینت ارسال می‌کند. از پروتکل TCP هم برای انجام عمل zone transfer استفاده می‌شود. به هر برنامه‌ای که برای DNS Server درخواستی را ارسال می‌کند resolver می‌گویند.

یک دامنه از قالبی به صورت زیر تشکیل می‌شود:

string.string.string.........string.

برای مثال:

bob.sales.example.com.

در مثال بالا نقطه‌ای که در پایان وجود دارد، مشخص کننده دامنه ریشه است. معمولاً در هنگام نوشتن یک دامنه این نقطه جا انداخته می‌شود. همچنین com یک دامنه سطح بالا یا TLD است که خود بخشی از دامنه ریشه است. example یک زیردامنه از دامنه com است. Sales هم یک زیردامنه از example.com است و به همین ترتیب. همان طور که می‌بینید یک دامنه می‌تواند به بخش‌های کوچکتری تقسیم شود که این ساختار از دامنه ریشه شروع شده و گسترش می‌یابد. این ساختار سلسله مراتبی شباهت زیادی به سیستم فایل یونیکس دارد. در سیستم فایل یونیکس هم یک دایرکتوری ریشه وجود دارد که با علامت / مشخص می‌شود. معادل آن در پروتکل DNS دامنه ریشه است که با . نشان داده می‌شود. دایرکتوری ریشه می‌تواند شامل دایرکتوری‌های دیگری هم باشد که این دایرکتوری ها هم به نوبه خود می‌توانند دایرکتوری‌های دیگر را هم دربر بگیردند. همین طور هیچ دو دایرکتوری که در یک سطح قرار دارند، نمی‌توانند نامی مشابه داشته باشند. مشابه این موارد در پروتکل DNS هم وجود دارد. همچنین در سیستم‌فایل یونیکس، اگر مسیری با یک کاراکتر / آغاز شود (مثلاً /etc/namedb/named.conf) می گوییم این مسیر یک مسیر مطلق است. اما اگر مسیری با این کاراکتر آغاز نشود (مثل namedb/named.conf) می گوییم این مسیر یک مسیر نسبی است. این مفهوم در پروتکل DNS هم صدق می‌کند. مثلاً دامنه ‎bob.sales.example.com.‎ یک دامنه مطلق است. در سیستم DNS به دامنه‌های مطلق اصطلاح FQDN اطلاق می‌شود. تصویر زیر این ساختار را به خوبی تشریح می‌کند:

۶۰۰px-Hierarchical_DNS

 مراحل تبدیل یک دامنه به آدرس IP متناظر آن چگونه است؟

فرض کنید کاربری در مرورگر خود آدرس bob.sales.example.com را تایپ می‌کند. قبل از اینکه مرورگر با سرور مربوطه ارتباط برقرار کند، احتیاج دارد تا آدرس IP آن را پیدا کند. مراحل انجام این کار به صورت زیر است:

ابتدا به فایل /etc/resolv.conf مراجعه کرده و آدرس یک nameserver را از آن می‌خواند. سپس درخواست ترجمه دامنه مورد نظر را از طریق پورت ۵۳ روی پروتکل UDP برای این سرویس‌دهنده ارسال می‌کند.

سرور درخواست کلاینت را دریافت می‌کند. سپس در cache خود جستجو کرده و اگر پاسخ آن را از cache پیدا کرد، برای کلاینت ارسال می‌کند. در غیر این صورت باید با دیگر nameserver ها ارتباط برقرار کرده و پاسخ را پیدا کند. این کار همیشه از یک root nameserver آغاز می‌شود. به همین دلیل است که همه nameserver ها باید آدرس root nameserver ها را از قبل بدانند تا بتوانند با آن‌ها ارتباط برقرار کنند. همین جا متذکر می‌شویم که ۱۳ عدد root nameserver در دنیا وجود دارد. در صورتی که این سرویس‌دهنده‌ها از کار بیفتند، دیگر دامنه مورد نظر قابل ترجمه به آدرس IP نبوده و تمام عملیات با شکست مواجه خواهد شد.

در مرحله بعد root nameserver آدرس IP دامنه .com را پیدا کرده و آن را برای nameserver ما ارسال می‌کند. سپس nameserver ما از آدرس معرفی شده در مرحله قبل (یعنی com) آدرس دامنه example.com را سؤال می‌کند. مجدداً آدرس IP دامنه example.com برای سرویس‌دهنده ما ارسال می‌شود. در مرحله بعد سرویس‌دهنده ما از آدرس برگشتی در مرحله قبل، نشانی sales.example.com را سؤال می‌کند و به همین ترتیب. همان طور که ملاحظه می‌کنید، یک دامنه در چند مرحله و از انتها به ابتدا ترجمه می‌شود. تصویر زیر به خوبی نمایانگر این مراحل است:

Resolv

مشخصات یک دامنه در داخل فایل‌هایی موسوم به zone file تعریف می‌شود. مثلاً مالک دامنه کیست، آدرس IP متناظر با آن چیست، و دیگر اطلاعات.

نصب BIND

همان طور که گفته شد برنامه BIND به صورت پیش فرض به همراه FreeBSD نصب می‌شود و شما نیازی به نصب کردن آن نخواهید داشت. تنها ممکن است بخواهید نسخه جدیدتری از BIND را با نسخه پیش فرض جایگزین کنید. برای جایگزینی یک نسخه جدیدتر (مثلاً ۹٫۹) دستورات زیر را اجرا کنید:

cd /usr/ports/dns/bind99
make config

منویی باز شده و از شما می‌خواهد تا برنامه را پیکربندی کنید. گزینه REPLACE_BASE را با استفاده از کلید space انتخاب کرده و با فشردن ↵ Enter تنظیمات را ذخیره کنید. سپس دستور زیر را اجرا کنید تا عملیات کامپایل و نصب آغاز گردد:

make install clean

بعد از اینکه نصب برنامه به پایان رسید، فایل /etc/src.conf را با یک ویرایشگر متن باز کرده و خط زیر را به آن اضافه کنید:

WITHOUT_BIND = YES

بدین ترتیب در صورتی که بخواهید FreeBSD را با استفاده از buildworld کامپایل کنید، برنامه BIND کامپایل نخواهد شد.

برای اینکه BIND همیشه در هنگام بوت شدن سیستم اجرا شود، خط زیر را به فایل /etc/rc.conf اضافه کنید:

named_enable="YES"

سپس دستور زیر را اجرا کنید:

/etc/rc.d/named start

در FreeBSD اصلاح named برای اشاره به سرویس BIND اطلاق می‌شود. همچنین ابزاری برای مدیریت این سرویس وجود دارد که به rndc معروف است.برنامه bind در مسیر /etc/namedb قرار دارد. این دایرکتوری حاوی فایل پیکربندی BIND و همچنین دایرکتوری‌هایی برای نگهداری فایل‌های zone می‌باشد. بسته به نوع zone ای که تعریف کرده‌اید، آن را در یکی از دایرکتوری‌های master, slave یا dynamic قرار دهید.

پیکربندی

فایل پیکربندی برنامه BIND در مسیر /etc/namedb/named.conf قرار دارد. این فایل را با استفاده از یک ویرایشگر متن باز کنید:

vi /etc/namedb/named.conf

توضیحات به چند روش مشخص می‌شوند. برای اینکه یک خط را به صورت توضیح درآورید از کاراکترهای // و # استفاده کنید و همچنین برای اینکه یک بلاک کد را به صورت توضیح در آورید آن را در میان ‎ /* و */ قرار دهید.

این خط را پیدا کرده و آن را از حالت توضیح خارج کنید (یعنی // ابتدای آن را بردارید)

//      listen-on       { 127.0.0.1; };

این خط مشخص می‌کند که برنامه BIND باید بر روی چه آدرسی به درخواست ها گوش دهد.

می‌توانید آدرس‌های دیگری را هم مشخص کنید. یادتان باشد که در آخر تمام آدرس ها یک کاراکتر ; قرار دهید.

نحوه تعریف zone

یک zone به صورت زیر تعریف می‌شود:

zone "example.org" {
    type master;
    file "master/example.org";
    allow-transfer { localhost; };
    allow-update { key rndc-key; };
};

در مثال بالا example.org دامنه مورد نظر ما است. این zone از نوع master است که توسط کلیدواژه type مشخص شده. اطلاعات این zone در فایل master/example.org نگهداری می‌شود. این مسیر وابسته به مسیر /etc/namedb است. در نتیجه این فایل در مسیر /etc/namedb/master/example.org قرار دارد.

همین طور برای تعریف یک zone از نوع slave هم بصورت زیر عمل می‌کنیم:

zone "example.org" {
	type slave;
	file "slave/example.org";
masters { 192.168.0.1; };
};

کافی است با استفاده از کلیدواژه type نوع slave را برای آن مشخص کنیم. در zone هایی که به صورت slave هستند، اطلاعات zone از یک سرور master دریافت شده و در یک فایل ذخیره می‌شود. در مثال بالا، این سرویس‌دهنده master نشانی ۱۹۲٫۱۶۸٫۰٫۱ دارد. در مواقعی که سرور master پاسخگو نباشد، سرور slave می‌تواند وارد عمل شده و به درخواست‌ها پاسخ دهد. در حالت master خودتان باید به صورت دستی فایل مورد نظر را ایجاد کنید. اما در حالت slave تنها کافی است مسیر آن را مشخص کنید. چون اطلاعات به صورت خودکار از سرور master دریافت می‌شود.

فایل‌های zone

این یک نمونه فایل zone برای دامنه example.org است:

$TTL 3600        ; ۱ hour default TTL
example.org.    IN      SOA      ns1.example.org. admin.example.org. (
                                ۲۰۰۶۰۵۱۵۰۱      ; Serial
                                ۱۰۸۰۰           ; Refresh
                                ۳۶۰۰            ; Retry
                                ۶۰۴۸۰۰          ; Expire
                                ۳۰۰             ; Negative Response TTL
                        )
; DNS Servers
                IN      NS      ns1.example.org.
                IN      NS      ns2.example.org.
; MX Records
                IN      MX 10   mx.example.org.
                IN      MX 20   mail.example.org.
                IN      A       192.168.1.1
; Machine Names
localhost       IN      A       127.0.0.1
ns1             IN      A       192.168.1.2
ns2             IN      A       192.168.1.3
mx              IN      A       192.168.1.4
mail            IN      A       192.168.1.5
; Aliases
www             IN      CNAME   example.org.

شاید در نگاه اول سینتکس این فایل کمی پیچیده به نظر بیاید. در ادامه به توضیح این فایل می‌پردازیم. به هر خط از این فایل یک Resource Record یا RR می‌گویند. توضیحات با استفاده از کاراکتر ; درج می‌شوند. در این فایل می‌توانید تعدادی ماکرو تعریف کنید. این ماکروها با کاراکتر $ آغاز می‌شوند. ماکروهای معروف عبارتند از:

‎ :$INCLUDE به کمک این ماکرو می‌توانید یک فایل zone را به صورت منطقی در یک فایل zone دیگر درج کنید. بدین ترتیب محویات آن فایل به صورت کامل در فایل دوم قرار خواهد گرفت. لازم به ذکر است که این محتویات در محل قرارگیری این ماکرو درج می‌شوند.

$ORIGIN: مقدار این ماکرو باید دامنه مورد نظرتان باشد. یادتان می‌آید که گفتیم دامنه‌هایی که با . تمام می‌شوند، یک دامنه مطلق هستند؟ (درست مثل مسیرهای مطلق در سیستم‌فایل) حالا اگر در آخر دامنه‌ای . قرار نگرفته باشد، مقدار این ماکرو به انتهای آن دامنه ضمیمه می‌شود. به همین دلیل یادتان باشد که قرار دادن این نقطه را فراموش نکنید وگرنه به عنوان یک دامنه نسبی در نظر گرفته شده و مقدار این ماکرو به آن ضمیمه می‌شود. مثلا اگر مقدار این ماکرو example.org باشد و شما در جایی از فایل www را بنویسید، به جای www عبارت www.example.org قرار خواهد گرفت. اگر مقداری برای این ماکرو در نظر نگرفته باشید، از مقداری که در فایل named.conf برای دامنه تعریف کرده‌اید استفاده می‌شود.

‎: $TTL هر رکورد یک فیلد time_to_live دارد. فیلد time_to_live مشخص می‌کند که اطلاعات موجود در آن رکورد تا چه مدت زمانی می‌تواند توسط سرویس‌دهنده slave کش شود. نوشتن این فیلد اختیاری است. بدین صورت که اگر آن را ننویسید، از مقداری که برای ‎ $TTL در نظر گرفته‌اید استفاده خواهد شد. حتی شما می‌توانید ‎ $TTL را هم مشخص نکنید. بدین صورت از مقدار minimum در رکورد SOA استفاده می‌شود.

در یک فایل zone هر رکورد از قالبی مانند زیر تشکیل می‌شود:

[domain_name] [time_to_live] class type value

قسمت domain_name و time_to_live اختیاری هستند و می‌توانید از نوشتن آنها صرف نظر کنید. فیلد domain_name مشخص کننده دامنه مورد نظرتان است. یعنی همان دامنه‌ای که مشغول نوشتن zone file آن هستید. اگر این فیلد را مشخص نکنید، از مقدار موجود در رکورد قبلی استفاده می‌شود. و اگر رکورد قبلی هم این فیلد را نداشته باشد، از مقدار موجود در رکورد قبل از آن استفاده می‌شود و به همین ترتیب. (اگر تمام رکوردها این فیلد را نداشته باشند، مقدار آن از فایل named.conf گرفته می‌شود.)

قسمت class برای دامنه‌های اینترنتی همیشه مقدار IN می‌گیرد.

type نوع رکورد را مشخص می‌کند. رکوردها انواع مختلفی دارند که در ادامه توضیح داده می‌شوند.

قسمت value هم مقدار مورد نظر برای رکورد را مشخص می‌کند. بسته مقدار فیلد type ممکن است طول رکورد کم یا زیاد شود.

انواع مختلف رکوردها را در جدول زیر به صورت خلاصه مشاهده می‌کنید:

نام رکوردتوضیحات
SOAمخفف start of authority پارامترهای منطقه‌ای را مشخص می‌کند.
Aاین رکورد آدرس IP دامنه مورد نظر را مشخص می‌کند. این آدرس باید از نوع IPv4 باشد.
MXنام سرویس‌دهنده ایمیل را مشخص می‌کند.
NSنام سرویس‌دهنده DNS را مشخص می‌کند.
AAAAآدرس IP دامنه مورد نظررا مشخص می‌کند. این آدرس باید از نوع IPv6 باشد.
CNAMEمی‌توانید برای دامنه‌ها نام‌های مستعار تعریف کنید.
PTRنام مستعار برای آدرس IP. برای عمل Reverse DNS استفاده می‌شود.
HINFOمشخصات سخت‌افزاری و سیستم‌عامل
TXTمتن دلخواه

رکورد SOA

این رکورد آدرس ایمیل سرپرست ناحیه، شماره سریال، تاریخ انقضا و … را مشخص می‌کند. شکل کلی این رکورد به صورت زیر است:

[domain_name] [time_to_live] class SOA name_server email-addr serial_number refresh retry expiry minimum

حال به تشریح هر یک از فیلدهای بالا می‌پردازیم.

name_server: نام سرویس‌دهنده‌ای که این فایل zone بر روی آن نگهداری می‌شود.

email-addr: آدرس ایمیل شخصی که سرپرست این فایل zone است را مشخص می‌کند. آدرس ایمیل نباید حاوی کاراکتر @ باشد. چون کاراکتر @ معنی خاصی برای یک فایل zone دارد. این کاراکتر دامنه جاری را برمی‌گرداند. به جای @ از نقطه استفاده کنید.

serial_number: شماره سریال این فایل zone را مشخص می‌کند. هر وقت که تغییری در یک فایل zone ایجاد کردید، باید این شماره سریال را به روزرسانی کنید تا دیگر سرویس‌دهنده‌ها از تغییرات اعمال شده آگاه شوند. بهتر است شماره سریال را در قالب yyyymmddnn بنویسید. yyyy به معنی سال mm به معنی ماه dd به معنی روز و nn یک عدد صحیح برای زمانی است که در یک روز چند بار فایل را تغییر می‌دهید.

refresh: این فیلد مشخص می‌کند که یک سرویس‌دهنده slave بعد از چه مدتی باید به سرویس‌دهنده master مراجعه کرده و فایل zoneاش را به روزرسانی کند.

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

expiry: تاریخ انقضای zone را مشخص می‌کند. با گذشت این زمان اطلاعات zone دیگر معتبر نیست. این مقدار فقط توسط سرویس‌دهنده slave استفاده می‌شود. فرض کنید سرویس‌دهنده slave به هیچ عنوان موفق نشود تا با سرویس‌دهنده master ارتباط برقرار کرده و فایل zone را به روزرسانی کند و تمام تلاش‌ها برای انجام این کار ناموفق باشد. بدین ترتیب بعد از گذشت مقدار این فیلد، سرویس‌دهنده slave دیگر نباید از اطلاعات این zone استفاده کند.

توصیه شده تا از این مقادیر برای این رکورد استفاده کنید (این مقادیر بر حسب ثانیه هستند)

۲۸۸۰۰		;	Refresh		۸ hours
۷۲۰۰		;	Retry		۲ hours
۶۰۴۸۰۰		;	Expire		۷ days
۸۶۴۰۰		;	Minimum TTL	۱ day

یعنی سرویس‌دهنده slave باید هر هشت ساعت به سرویس‌دهنده master مراجعه کرده و اطلاعات zone را به روزرسانی کند. اگر سرویس‌دهنده master در دسترس نباشد، سرویس‌دهنده slave دو ساعت بعد مجددا برای برقراری ارتباط با master تلاش می‌کند و این کار را مکررا ادامه خواهد داد. در این هنگام دو حالت ممکن است اتفاق بیفتد:

  1. سرویس‌دهنده slave موفق می‌شود با master ارتباط برقرار کند و فایل zone را به روزرسانی می کند.
  2. موفق به برقراری ارتباط با master نشده تا بالاخره ۷ روز از تاریخ آخرین به روزرسانی می‌گذرد و دیگر نمی‌تواند از اطلاعات zone استفاده کند. چون دیگر معتبر نیستند.

دیگر رکوردها

رکورد A مشخص کننده آدرس یک دامنه است. مثلا:

example.org.             IN      A       192.168.1.2

یعنی آدرس IP دامنه example.org برابر ۱۹۲٫۱۶۸٫۱٫۲ می‌باشد. برای آدرس‌های IPv6 هم از نوع AAAA استفاده می‌شود.

رکورد NS سرویس‌دهنده نام را مشخص می‌کند. مثلا:

example.org.       IN         NS        ns1.example.org.

رکورد CNAME برای تعریف یک نام مستعار برای یک دامنه مورد استفاده قرار می‌گیرد. مثلا:

www         IN         CNAME      example.org.

در مثال بالا ما یک نام دیگر برای دامنه example.org تعریف کردیم که این دو معادل یکدیگر هستند. (از قبل می‌دانیم که اگر در انتهای یک دامنه . قرار ندهیم، مقدار ‎ $ORIGIN به انتهای آن ضمیمه می‌شود.)

رکورد MX آدرس سرویس‌دهنده پست الکترونیک ناحیه را مشخص می‌کند. اگر در شبکه خود یک سرویس‌دهنده پست الکترونیک دارید، دامنه آن را با استفاده از این رکورد مشخص کنید. مثلا:

example.org.      IN       MX        10      mail.example.org.

این رکورد یک فیلد اضافه دارد که در مثال بالا مقدار ۱۰ به آن انتساب داده شده. این فیلد اولویت سرویس‌دهنده پست‌الکترونیک را مشخص می‌کند. اگر چند سرویس‌دهنده پست الکترونیک دارید، می توانید آنها را اولویت‌بندی کنید. هر چه این عدد پایین تر باشد، اولویت سرویس‌دهنده بالاتر می‌رود.

named-checkconf و named-checkzone

بسیار پیش می‌آید که در هنگام ویرایش فایل پیکربندی یا فایل‌های zone دچار اشتباه شویم. اشکال‌زدایی این فایل‌ها می‌تواند بسیار سخت باشد. از طریق این دو دستور می‌توانید به اشکال زدایی این فایل‌ها بپردازید. ابتدا نحوه کار با named-checkconf را مرور می‌کنیم. نحوه استفاده از این دستور بدین صورت است:

named-checkconf

با اجرای دستور بالا، فایل /etc/namedb/named.conf خوانده شده و اشکالات آن گزارش می‌شود. اگر این فایل در جای دیگری قرار دارد، به این صورت فایل مورد نظر را به آن معرفی کنید:

named-checkconf /path/to/named.conf

دستور named-checkzone هم برای اشکال‌زدایی فایل‌های zone استفاده می‌شود و نحوه استفاده از آن به صورت زیر است:

named-checkzone zonename filename

مثلا:

named-checkzone example.org /etc/namedb/master/example.org