DNS: اسم به آدرس
مرورگر چطور از «example.com» به یک IP میرسد: DNS مثل دفترچهی تلفن اینترنت، ساختار درختی دامنهها (ریشه، .com و .ir، دامنه)، resolver و سرورهای authoritative، کش و TTL، رکوردهای A و AAAA و CNAME و MX و TXT و NS، فایل /etc/hosts، دیدن جوابها با dig، و خطای Could not resolve host.
- حدود ۲۱ دقیقه مطالعه
- ۶ مثال اجراشده
- ۳ تمرین با جواب
- مقدماتی (از صفر مطلق)
- بهروزرسانی: ۲۹ مهر ۱۴۰۵
توی این درس یاد میگیری وقتی در مرورگر example.com مینویسی، کامپیوتر چطور IP آن را پیدا میکند. با DNS (Domain Name System) آشنا میشوی: ساختار درختی اسمها، سرورهایی که سؤال را از ریشه تا مقصد دنبال میکنند، کش و TTL (و اینکه چرا «تغییر DNS چند ساعت طول میکشد»)، و رکوردهای اصلی (A، CNAME، MX، …). با دستور dig جوابها را با چشم خودت میبینی و با فایل /etc/hosts یک اسم دلخواه برای کامپیوتر خودت میسازی.
مسئله: آدمها اسم یادشان میماند، کامپیوترها عدد میخواهند
Section titled “مسئله: آدمها اسم یادشان میماند، کامپیوترها عدد میخواهند”در درس شبکه دیدی هر سرور با یک آدرس IP مثل 93.184.215.14 پیدا میشود. هیچکس آدرس دهها سایتی را که هر روز باز میکند حفظ نیست؛ اسمهایی مثل google.com یا loopx.ir را حفظیم. از طرف دیگر، IP سایتها عوض میشود: سایت به سرور جدید منتقل میشود، یا یک سایت بزرگ برای هر کشور سرور جدا دارد. پس لازم است یک سیستم باشد که همیشه بگوید «این اسم، الان، کدام IP است». این سیستم DNS است و تقریباً هر کاری در اینترنت با یک سؤال DNS شروع میشود.
تشبیه: دفترچهی تلفن و ۱۱۸
Section titled “تشبیه: دفترچهی تلفن و ۱۱۸”DNS مثل دفترچهی تلفن اینترنت است: اسم را میدهی، شماره (IP) را میگیری. ولی هیچ دفترچهای همهی اسمهای دنیا را ندارد. پس DNS مثل یک زنجیره از مرکز اطلاعات کار میکند: به ۱۱۸ (resolver) زنگ میزنی و میپرسی «شمارهی دفتر شرکت فلان در تهران؟». ۱۱۸ اگر قبلاً پرسیده باشد، از یادداشتهایش (کش) جواب میدهد. اگر نه، به مرکز کشوری زنگ میزند («اطلاعات تهران کجاست؟»)، بعد به مرکز تهران («شرکت فلان کدام شماره؟») و بالاخره به خود شرکت. جواب را به تو میدهد و برای دفعهی بعد یادداشت میکند، ولی فقط برای مدتی که شرکت گفته (TTL)، چون ممکن است شماره عوض شود.
اسمها درختیاند
Section titled “اسمها درختیاند”اسم دامنه را از راست به چپ بخوان: www.example.com. یعنی در «ریشه» (.، معمولاً نوشته نمیشود)، زیر com، زیر example، اسم www. هر سطح را یک سازمان مدیریت میکند:
وقتی دامنهای میخری (مثلاً از یک ثبتکنندهی دامنه)، در واقع حق مدیریت یک شاخه از این درخت را میگیری و تعیین میکنی کدام سرورها (nameserver) جواب سؤالهای آن شاخه را بدهند. زیردامنهها (www، mail، api) را خودت هر چقدر خواستی میسازی و پول جدا ندارند.
چه کسی جواب میدهد؟
Section titled “چه کسی جواب میدهد؟”- resolver (یا «DNS سرور» که در تنظیمات شبکه میبینی): کسی که کل کار دنبال کردن را برای تو انجام میدهد. معمولاً مال ISP است، یا عمومیهایی مثل
8.8.8.8(گوگل) و1.1.1.1(کلودفلر). روتر خانه هم با DHCP آدرس resolver را به دستگاهها میدهد. - سرور authoritative (مرجع): سرور خود دامنه که جواب اصلی را دارد. وقتی در پنل دامنه IP را عوض میکنی، اینجا عوض میشود.
- کش: هر کسی در مسیر (resolver، سیستمعامل، مرورگر) جواب را برای مدت TTL (time to live، به ثانیه) نگه میدارد. بیشتر سؤالها اصلاً به ریشه نمیرسند؛ از کش جواب میگیرند.
رکوردها
Section titled “رکوردها”سرور یک دامنه برای هر اسم چند نوع رکورد نگه میدارد:
| رکورد | معنی | مثال |
|---|---|---|
A |
اسم → آدرس IPv4 | example.com → 93.184.215.14 |
AAAA |
اسم → آدرس IPv6 | example.com → 2606:2800:21f:cb07:6820:80da:af6b:8b2c |
CNAME |
اسم → اسم دیگر (نام مستعار) | www.example.com → example.com |
MX |
سرور ایمیل این دامنه | example.com → mail.example.com (با اولویت) |
TXT |
متن دلخواه؛ برای تأیید مالکیت و تنظیمات ایمیل (SPF) | "v=spf1 -all" |
NS |
nameserverهای این دامنه | a.iana-servers.net. |
مثالهای عملی
Section titled “مثالهای عملی”ابزار اصلی dig است. اگر روی Ubuntu نبود، نصبش کن (apt را در دورهی لینوکس یاد میگیری؛ فعلاً فقط اجرایش کن):
sudo apt install bind9-dnsutilsخروجیهای dig به شبکه و زمان بستگی دارند (IPها و عددهای TTL برای تو فرق میکنند) و برچسب «نمونه» دارند.
مثال ۱: سادهترین سؤال
Section titled “مثال ۱: سادهترین سؤال”dig +short example.com93.184.215.14+short یعنی فقط جواب را بده. (آدرسهای example.com در سالهای اخیر چند بار عوض شدهاند؛ هر IPی که دیدی درست است.) یک سایت بزرگ ممکن است چند IP برگرداند (هر خط یکی)؛ مرورگر یکی را انتخاب میکند و اگر جواب نداد، سراغ بعدی میرود. این یک راه ساده برای پخش بار بین چند سرور است.
مثال ۲: جواب کامل
Section titled “مثال ۲: جواب کامل”dig example.com; <<>> DiG 9.18.39-0ubuntu0.24.04.1-Ubuntu <<>> example.com;; global options: +cmd;; Got answer:;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 40213;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; OPT PSEUDOSECTION:; EDNS: version: 0, flags:; udp: 65494;; QUESTION SECTION:;example.com. IN A
;; ANSWER SECTION:example.com. 3021 IN A 93.184.215.14
;; Query time: 38 msec;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP);; WHEN: Wed Oct 21 21:10:43 +0330 2026;; MSG SIZE rcvd: 56خطهای مهم:
status: NOERROR: جواب پیدا شد. اگر اسم وجود نداشته باشد،NXDOMAIN(non-existent domain) میبینی.QUESTION SECTION: سؤال تو؛ رکوردAبرایexample.com.(نقطهی آخر همان ریشه است).ANSWER SECTION:example.com. 3021 IN A 93.184.215.14؛ یعنی اسم، TTL (این جواب تا ۳۰۲۱ ثانیهی دیگر معتبر است؛ عدد کم میشود چون از کش آمده)،IN(اینترنت)، نوع رکورد و مقدار.SERVER: 127.0.0.53#53: چه کسی جواب داد؛ پورت ۵۳ (درس پورت) و UDP.127.0.0.53یک resolver کوچک داخل خود Ubuntu است (سرویسsystemd-resolved) که جوابها را کش میکند و سؤالهای جدید را به resolver شبکه میفرستد.Query time: 38 msec: اگر دوباره بپرسی، احتمالاً0 msecمیشود: از کش.
مثال ۳: رکوردهای دیگر
Section titled “مثال ۳: رکوردهای دیگر”dig +short www.github.comdig +short MX gmail.comdig +short NS example.comgithub.com.140.82.121.45 gmail-smtp-in.l.google.com.10 alt1.gmail-smtp-in.l.google.com.20 alt2.gmail-smtp-in.l.google.com.30 alt3.gmail-smtp-in.l.google.com.40 alt4.gmail-smtp-in.l.google.com.a.iana-servers.net.b.iana-servers.net.www.github.comیک CNAME است: «بروgithub.comرا بپرس»؛digآن را دنبال کرد و IP نهایی را هم داد.- رکوردهای MX جیمیل عدد اولویت دارند: ایمیل اول به سرور با عدد کمتر (۵) فرستاده میشود و اگر جواب نداد، به بعدی. ایمیلها از وبسایت جدا هستند؛ یک دامنه میتواند سایتش روی یک سرور و ایمیلش روی سرویس دیگری باشد.
- NS میگوید کدام سرورها برای
example.comجواب اصلی را دارند.
مثال ۴: از یک resolver مشخص بپرس
Section titled “مثال ۴: از یک resolver مشخص بپرس”dig +short @1.1.1.1 example.comdig +short @8.8.8.8 example.com93.184.215.1493.184.215.14@سرور یعنی «بهجای resolver پیشفرض، از این بپرس». برای تشخیص مشکل خیلی مفید است: اگر resolver خودت جواب غلط یا هیچ جوابی نمیدهد ولی 1.1.1.1 درست جواب میدهد، مشکل از resolver شبکهی توست، نه از دامنه.
مثال ۵: اسمی که وجود ندارد
Section titled “مثال ۵: اسمی که وجود ندارد”curl -sS http://nosuch-shop.invalid/echo "exit=$?"curl: (6) Could not resolve host: nosuch-shop.invalidexit=6Could not resolve host یعنی کار حتی به اتصال نرسید: اسم به هیچ IPی تبدیل نشد. (پسوند .invalid برای همین آزمایشها رزرو شده و هرگز وجود ندارد.) این پیام را زیاد میبینی و قدم بعدی همیشه یکی است: dig بزن. NXDOMAIN یعنی اسم غلط است (یا دامنه منقضی شده)؛ timeout یعنی resolver در دسترس نیست (مثال ۶ درس شبکه: «ping به 8.8.8.8 کار میکند ولی سایتها باز نمیشوند»).
مثال ۶: /etc/hosts، دفترچهی شخصی
Section titled “مثال ۶: /etc/hosts، دفترچهی شخصی”قبل از هر سؤال DNS، سیستمعامل یک فایل کوچک را نگاه میکند: /etc/hosts (در ویندوز C:\Windows\System32\drivers\etc\hosts):
cat /etc/hosts127.0.0.1 localhost127.0.1.1 ubuntu-vm
# The following lines are desirable for IPv6 capable hosts::1 ip6-localhost ip6-loopbackff02::1 ip6-allnodesff02::2 ip6-allroutersهر خط: «این IP، این اسم(ها)». localhost از همینجا میآید. میتوانی اسم خودت را اضافه کنی؛ مثلاً برای آزمایش یک سایت روی کامپیوتر خودت با اسم دلخواه. اول ببین اسم الان چیزی برنمیگرداند:
getent hosts myshop.testecho "exit=$?"exit=2یک خط به فایل اضافه کن (فایل مال مدیر سیستم است، پس sudo لازم است؛ tee -a یعنی به آخر فایل اضافه کن):
echo "127.0.0.1 myshop.test" | sudo tee -a /etc/hostsgetent hosts myshop.test127.0.0.1 myshop.test127.0.0.1 myshop.test(خط اول را tee چاپ کرد، خط دوم جواب getent است.) حالا یک صفحهی وب کوچک بساز و با اسم جدید بازش کن:
mkdir -p ~/site && echo "<h1>فروشگاه من</h1>" > ~/site/index.htmlcd ~/site && python3 -m http.server 8000در ترمینال دیگر:
curl -s http://myshop.test:8000/<h1>فروشگاه من</h1>python3 -m http.server یک وبسرور ساده است که فایلهای پوشهی فعلی را نشان میدهد (درس بعد). myshop.test اسمی است که فقط روی کامپیوتر تو وجود دارد؛ هیچ DNSی در دنیا آن را نمیشناسد. (.test هم مثل .invalid برای آزمایش رزرو شده.) سرور را با Ctrl+C ببند و آخر کار، آن خط را از /etc/hosts پاک کن (با sudo nano /etc/hosts؛ ویرایشگر را در دورهی لینوکس یاد میگیری).
در /etc/hosts خط «10.0.0.5 api.shop.com» هست، ولی DNS واقعی برای api.shop.com آدرس 203.0.113.9 را میدهد. curl روی همان کامپیوتر به کدام میرود؟
جواب درست: 10.0.0.5، چون hosts قبل از DNS خوانده میشود
hosts اولویت دارد؛ برای همین برای آزمایش (و متأسفانه برای بدافزار) استفاده میشود.
پشت پرده: کش، TTL و «انتشار» DNS
Section titled “پشت پرده: کش، TTL و «انتشار» DNS”هر رکورد یک TTL دارد که صاحب دامنه تعیین میکند؛ مثلاً ۳۶۰۰ ثانیه (یک ساعت). هر resolver که جواب را گرفت، تا یک ساعت دیگر بدون پرسیدن دوباره همان را تحویل میدهد. این کش است که DNS را سریع و سبک نگه میدارد: سرورهای ریشه بهجای میلیاردها سؤال در ثانیه، فقط سؤالهای «تازه» را میبینند.
قیمتش همان سناریوی اول درس است: وقتی IP را عوض میکنی، هر resolverی که جواب قدیمی را کش کرده، تا تمام شدن TTL همان را میدهد. به این «انتشار DNS» (DNS propagation) میگویند، هرچند در واقع چیزی منتشر نمیشود؛ کشها یکییکی منقضی میشوند. ترفند حرفهای: یک روز قبل از جابهجایی، TTL را به ۶۰ ثانیه کم کن. بعد از جابهجایی، همه در حداکثر یک دقیقه IP جدید را میبینند. وقتی همهچیز پایدار شد، TTL را برگردان.
ترتیبی که Ubuntu برای پیدا کردن یک اسم طی میکند:
- فایل
/etc/hosts. - کش و resolver داخلی (
systemd-resolvedروی127.0.0.53؛ فایل/etc/resolv.confبه آن اشاره میکند). - resolver شبکه (که روتر یا DHCP گفته، یا دستی تنظیم شده).
- resolver از ریشه تا سرور دامنه را دنبال میکند (اگر خودش کش نداشته باشد).
dig +trace example.com+trace مرحلهی ۴ را خودش انجام میدهد (از ریشه، بدون کش) و هر قدم را چاپ میکند: اول فهرست سرورهای ریشه، بعد سرورهای com، بعد a.iana-servers.net، بعد جواب. اجرایش کن و فقط به ترتیب نگاه کن؛ همان نمودار بالای درس است.
جدولهای مرجع
Section titled “جدولهای مرجع”| دستور | کار |
|---|---|
dig +short name |
فقط جواب (A) |
dig name |
جواب کامل با TTL و سرور |
dig +short MX name |
سرور ایمیل (و AAAA، NS، TXT، CNAME) |
dig @1.1.1.1 name |
پرسیدن از resolver مشخص |
dig +trace name |
دنبال کردن از ریشه |
getent hosts name |
جواب سیستمعامل (شامل /etc/hosts) |
cat /etc/hosts |
دفترچهی محلی |
| پیام | معنی |
|---|---|
NOERROR |
جواب پیدا شد |
NXDOMAIN |
این اسم وجود ندارد |
SERVFAIL |
resolver نتوانست جواب بگیرد (مشکل سرور دامنه یا resolver) |
Could not resolve host (curl و مرورگر) |
اسم به IP تبدیل نشد |
اشتباهات رایج
Section titled “اشتباهات رایج”۱) انتظار تغییر فوری
Section titled “۱) انتظار تغییر فوری”IP را عوض کردی و هنوز قدیمی را میبینی. راهحل: TTL را در dig ببین؛ قبل از تغییرهای مهم TTL را کم کن. برای امتحان سرور جدید قبل از تغییر DNS، از /etc/hosts روی کامپیوتر خودت استفاده کن.
۲) فراموش کردن www
Section titled “۲) فراموش کردن www”رکورد A برای example.com ساختی ولی www.example.com کار نمیکند. اینها دو اسم جدا هستند. راهحل: برای www یک CNAME به دامنهی اصلی (یا A جدا) بساز.
۳) قاطی کردن DNS با «اینترنت قطع»
Section titled “۳) قاطی کردن DNS با «اینترنت قطع»”سایتها باز نمیشوند ولی ping 8.8.8.8 کار میکند. راهحل: dig بزن؛ احتمالاً resolver مشکل دارد، نه اتصال.
۴) خط فراموششده در hosts
Section titled “۴) خط فراموششده در hosts”ماهها بعد، یک سایت فقط روی کامپیوتر تو به سرور قدیمی میرود. راهحل: بعد از آزمایش، خطهای /etc/hosts را پاک کن.
۵) فکر کردن به اینکه DNS «امن» است
Section titled “۵) فکر کردن به اینکه DNS «امن» است”پیامهای DNS معمولی رمزنگاری نمیشوند و در مسیر قابلدیدن (و در شبکههای ناامن، قابلدستکاری) هستند. نسخههای رمزنگاریشده (DNS over HTTPS/TLS) وجود دارند، ولی HTTPS (درس بعدیها) است که در نهایت تضمین میکند به سایت درست وصل شدهای.
با dig پیدا کن: IP سایت wikipedia.org، TTL آن، و کدام سرور جواب داد. دو بار پشت سر هم بپرس و Query time و TTL را مقایسه کن.
دیدن جواب
dig wikipedia.orgdig wikipedia.org;; ANSWER SECTION:wikipedia.org. 600 IN A 185.15.59.224;; Query time: 61 msec;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)...;; ANSWER SECTION:wikipedia.org. 592 IN A 185.15.59.224;; Query time: 0 msecدفعهی دوم جواب از کش resolver داخلی آمد: زمان صفر و TTL هشت ثانیه کمتر (هشت ثانیه از جواب قبلی گذشته). وقتی TTL به صفر برسد، دوباره از بیرون پرسیده میشود.
برای دامنهی github.com رکوردهای A، MX، NS و TXT را بگیر. بگو ایمیلهای این دامنه به کدام سرویس میروند و رکوردهای TXT تقریباً برای چه هستند.
دیدن جواب
dig +short A github.comdig +short MX github.comdig +short NS github.comdig +short TXT github.com140.82.121.41 aspmx.l.google.com.5 alt1.aspmx.l.google.com.dns1.p08.nsone.net.ns-1283.awsdns-32.org."v=spf1 ip4:192.30.252.0/22 include:_netblocks.google.com include:_spf.google.com ... ~all""google-site-verification=..."ایمیل github.com با Google Workspace است (MX به google.com)، در حالی که خود سایت روی سرورهای خود GitHub است: هر رکورد مستقل است. nameserverها مال دو شرکت مختلفاند (NS1 و Amazon) تا اگر یکی از کار افتاد، DNS سرپا بماند. رکوردهای TXT اینجا دو کار رایج دارند: SPF (v=spf1 ...) که میگوید کدام سرورها اجازه دارند از طرف این دامنه ایمیل بفرستند (ضد جعل ایمیل)، و تأیید مالکیت (google-site-verification) که سرویسها از تو میخواهند تا ثابت کنی دامنه مال توست.
با پایتون (کتابخانهی socket که در هر نصب پایتون هست) سه اسم را به IP تبدیل کن: localhost، myshop.test (بعد از اضافه کردن به /etc/hosts) و nosuch-shop.invalid. ببین برای سومی چه خطایی میگیری. چرا جواب دومی را هیچ digی نمیدهد؟
دیدن جواب
python3 -c "import socketfor name in ['localhost', 'myshop.test', 'nosuch-shop.invalid']: try: print(name, '->', socket.gethostbyname(name)) except socket.gaierror as e: print(name, '-> ERROR:', e)"dig +short myshop.testlocalhost -> 127.0.0.1myshop.test -> 127.0.0.1nosuch-shop.invalid -> ERROR: [Errno -2] Name or service not knowndig برای myshop.test هیچ چیزی چاپ نمیکند. چرا؟ socket.gethostbyname (مثل مرورگر، curl و getent) از سیستمعامل میپرسد و سیستمعامل اول /etc/hosts را نگاه میکند. ولی dig ابزار DNS خالص است: مستقیم از سرور DNS میپرسد و /etc/hosts را نمیخواند. برای همین، برای اینکه بفهمی «برنامهها چه میبینند» از getent hosts استفاده کن، و برای اینکه بفهمی «DNS واقعی چه میگوید» از dig. gaierror (get address info error) همان خطای «Could not resolve host» در پایتون است.
آزمونک
Section titled “آزمونک”DNS چه کاری میکند؟
جواب درست: اسم دامنه را به IP (و اطلاعات دیگر) تبدیل میکند
دفترچهی تلفن اینترنت.
رکورد A چه چیزی را نگه میدارد؟
جواب درست: آدرس IPv4 یک اسم
AAAA برای IPv6، MX برای ایمیل، CNAME برای مستعار.
TTL در جواب DNS یعنی…
جواب درست: مدتی که این جواب میتواند کش شود
برای همین تغییر IP فوری دیده نمیشود.
status: NXDOMAIN یعنی…
جواب درست: این اسم وجود ندارد
اسم غلط یا دامنه منقضی.
چرا اضافه کردن یک خط به /etc/hosts روی همهی کامپیوترهای دنیا اثر ندارد؟
جواب درست: چون hosts فقط روی همان کامپیوتر و قبل از DNS خوانده میشود
دفترچهی شخصی؛ برای آزمایش عالی است.
ping 8.8.8.8 جواب میدهد ولی هیچ سایتی باز نمیشود. مشکوکترین بخش؟
جواب درست: DNS (resolver)
با dig و dig @1.1.1.1 بررسی کن.
جمعبندی
Section titled “جمعبندی”- DNS اسمها را به IP تبدیل میکند؛ اسمها درختیاند (ریشه ← TLD ← دامنه ← زیردامنه) و از راست به چپ خوانده میشوند.
- resolver از ریشه تا سرور authoritative دامنه را دنبال میکند و جواب را برای TTL کش میکند.
- رکوردها:
A/AAAA(IP)،CNAME(مستعار)،MX(ایمیل)،TXT(تأیید، SPF)،NS(nameserver). /etc/hostsقبل از DNS خوانده میشود: برای آزمایش اسم دلخواه روی کامپیوتر خودت.digبرای دیدن DNS واقعی؛getent hostsبرای دیدن چیزی که برنامهها میبینند.Could not resolve hostیعنی مشکل در مرحلهی اسم است، نه اتصال.
| دستور | کاری که میکند |
|---|---|
dig +short example.com | IP یک اسم |
dig example.com | جواب کامل، TTL، سرور |
dig +short MX gmail.com | سرور ایمیل |
dig @1.1.1.1 example.com | پرسیدن از resolver دیگر |
dig +trace example.com | دنبال کردن از ریشه |
getent hosts name | جواب سیستمعامل |
/etc/hosts | دفترچهی محلی، قبل از DNS |
NXDOMAIN / SERVFAIL | اسم نیست / resolver مشکل دارد |