رفتن به محتوا
مبانی کامپیوتر و اینترنتاینترنت چطور کار می‌کنددرس ۱۰ از ۱۶

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)، چون ممکن است شماره عوض شود.

اسم دامنه را از راست به چپ بخوان: www.example.com. یعنی در «ریشه» (.، معمولاً نوشته نمی‌شود)، زیر com، زیر example، اسم www. هر سطح را یک سازمان مدیریت می‌کند:

درخت DNS: ریشه می‌داند هر پسوند (TLD) را کدام سرورها می‌شناسند، TLD می‌داند هر دامنه را کدام سرورها، و سرور خود دامنه جواب نهایی را دارد.

وقتی دامنه‌ای می‌خری (مثلاً از یک ثبت‌کننده‌ی دامنه)، در واقع حق مدیریت یک شاخه از این درخت را می‌گیری و تعیین می‌کنی کدام سرورها (nameserver) جواب سؤال‌های آن شاخه را بدهند. زیردامنه‌ها (www، mail، api) را خودت هر چقدر خواستی می‌سازی و پول جدا ندارند.

یک جست‌وجوی کامل DNS: کامپیوتر فقط از resolver می‌پرسد؛ resolver از ریشه تا سرور دامنه را دنبال می‌کند و جواب را کش می‌کند.
  • resolver (یا «DNS سرور» که در تنظیمات شبکه می‌بینی): کسی که کل کار دنبال کردن را برای تو انجام می‌دهد. معمولاً مال ISP است، یا عمومی‌هایی مثل 8.8.8.8 (گوگل) و 1.1.1.1 (کلودفلر). روتر خانه هم با DHCP آدرس resolver را به دستگاه‌ها می‌دهد.
  • سرور authoritative (مرجع): سرور خود دامنه که جواب اصلی را دارد. وقتی در پنل دامنه IP را عوض می‌کنی، اینجا عوض می‌شود.
  • کش: هر کسی در مسیر (resolver، سیستم‌عامل، مرورگر) جواب را برای مدت TTL (time to live، به ثانیه) نگه می‌دارد. بیشتر سؤال‌ها اصلاً به ریشه نمی‌رسند؛ از کش جواب می‌گیرند.

سرور یک دامنه برای هر اسم چند نوع رکورد نگه می‌دارد:

رکورد معنی مثال
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.

ابزار اصلی dig است. اگر روی Ubuntu نبود، نصبش کن (apt را در دوره‌ی لینوکس یاد می‌گیری؛ فعلاً فقط اجرایش کن):

Terminal window
sudo apt install bind9-dnsutils

خروجی‌های dig به شبکه و زمان بستگی دارند (IPها و عددهای TTL برای تو فرق می‌کنند) و برچسب «نمونه» دارند.

Terminal window
dig +short example.com
نمونه
93.184.215.14

+short یعنی فقط جواب را بده. (آدرس‌های example.com در سال‌های اخیر چند بار عوض شده‌اند؛ هر IPی که دیدی درست است.) یک سایت بزرگ ممکن است چند IP برگرداند (هر خط یکی)؛ مرورگر یکی را انتخاب می‌کند و اگر جواب نداد، سراغ بعدی می‌رود. این یک راه ساده برای پخش بار بین چند سرور است.

Terminal window
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 می‌شود: از کش.
Terminal window
dig +short www.github.com
dig +short MX gmail.com
dig +short NS example.com
نمونه
github.com.
140.82.121.4
5 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 مشخص بپرس”
Terminal window
dig +short @1.1.1.1 example.com
dig +short @8.8.8.8 example.com
نمونه
93.184.215.14
93.184.215.14

@سرور یعنی «به‌جای resolver پیش‌فرض، از این بپرس». برای تشخیص مشکل خیلی مفید است: اگر resolver خودت جواب غلط یا هیچ جوابی نمی‌دهد ولی 1.1.1.1 درست جواب می‌دهد، مشکل از resolver شبکه‌ی توست، نه از دامنه.

مثال ۵: اسمی که وجود ندارد

Section titled “مثال ۵: اسمی که وجود ندارد”
Terminal window
curl -sS http://nosuch-shop.invalid/
echo "exit=$?"
خروجی
curl: (6) Could not resolve host: nosuch-shop.invalid
exit=6

Could 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):

Terminal window
cat /etc/hosts
نمونه
127.0.0.1 localhost
127.0.1.1 ubuntu-vm
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

هر خط: «این IP، این اسم(ها)». localhost از همین‌جا می‌آید. می‌توانی اسم خودت را اضافه کنی؛ مثلاً برای آزمایش یک سایت روی کامپیوتر خودت با اسم دلخواه. اول ببین اسم الان چیزی برنمی‌گرداند:

Terminal window
getent hosts myshop.test
echo "exit=$?"
خروجی
exit=2

یک خط به فایل اضافه کن (فایل مال مدیر سیستم است، پس sudo لازم است؛ tee -a یعنی به آخر فایل اضافه کن):

Terminal window
echo "127.0.0.1 myshop.test" | sudo tee -a /etc/hosts
getent hosts myshop.test
خروجی
127.0.0.1 myshop.test
127.0.0.1 myshop.test

(خط اول را tee چاپ کرد، خط دوم جواب getent است.) حالا یک صفحه‌ی وب کوچک بساز و با اسم جدید بازش کن:

Terminal window
mkdir -p ~/site && echo "<h1>فروشگاه من</h1>" > ~/site/index.html
cd ~/site && python3 -m http.server 8000

در ترمینال دیگر:

Terminal window
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 روی همان کامپیوتر به کدام می‌رود؟

پشت پرده: کش، TTL و «انتشار» DNS

Section titled “پشت پرده: کش، TTL و «انتشار» DNS”

هر رکورد یک TTL دارد که صاحب دامنه تعیین می‌کند؛ مثلاً ۳۶۰۰ ثانیه (یک ساعت). هر resolver که جواب را گرفت، تا یک ساعت دیگر بدون پرسیدن دوباره همان را تحویل می‌دهد. این کش است که DNS را سریع و سبک نگه می‌دارد: سرورهای ریشه به‌جای میلیاردها سؤال در ثانیه، فقط سؤال‌های «تازه» را می‌بینند.

قیمتش همان سناریوی اول درس است: وقتی IP را عوض می‌کنی، هر resolverی که جواب قدیمی را کش کرده، تا تمام شدن TTL همان را می‌دهد. به این «انتشار DNS» (DNS propagation) می‌گویند، هرچند در واقع چیزی منتشر نمی‌شود؛ کش‌ها یکی‌یکی منقضی می‌شوند. ترفند حرفه‌ای: یک روز قبل از جابه‌جایی، TTL را به ۶۰ ثانیه کم کن. بعد از جابه‌جایی، همه در حداکثر یک دقیقه IP جدید را می‌بینند. وقتی همه‌چیز پایدار شد، TTL را برگردان.

ترتیبی که Ubuntu برای پیدا کردن یک اسم طی می‌کند:

  1. فایل /etc/hosts.
  2. کش و resolver داخلی (systemd-resolved روی 127.0.0.53؛ فایل /etc/resolv.conf به آن اشاره می‌کند).
  3. resolver شبکه (که روتر یا DHCP گفته، یا دستی تنظیم شده).
  4. resolver از ریشه تا سرور دامنه را دنبال می‌کند (اگر خودش کش نداشته باشد).
Terminal window
dig +trace example.com

+trace مرحله‌ی ۴ را خودش انجام می‌دهد (از ریشه، بدون کش) و هر قدم را چاپ می‌کند: اول فهرست سرورهای ریشه، بعد سرورهای com، بعد a.iana-servers.net، بعد جواب. اجرایش کن و فقط به ترتیب نگاه کن؛ همان نمودار بالای درس است.

دستور کار
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 تبدیل نشد

IP را عوض کردی و هنوز قدیمی را می‌بینی. راه‌حل: TTL را در dig ببین؛ قبل از تغییرهای مهم TTL را کم کن. برای امتحان سرور جدید قبل از تغییر DNS، از /etc/hosts روی کامپیوتر خودت استفاده کن.

رکورد A برای example.com ساختی ولی www.example.com کار نمی‌کند. این‌ها دو اسم جدا هستند. راه‌حل: برای www یک CNAME به دامنه‌ی اصلی (یا A جدا) بساز.

۳) قاطی کردن DNS با «اینترنت قطع»

Section titled “۳) قاطی کردن DNS با «اینترنت قطع»”

سایت‌ها باز نمی‌شوند ولی ping 8.8.8.8 کار می‌کند. راه‌حل: dig بزن؛ احتمالاً resolver مشکل دارد، نه اتصال.

ماه‌ها بعد، یک سایت فقط روی کامپیوتر تو به سرور قدیمی می‌رود. راه‌حل: بعد از آزمایش، خط‌های /etc/hosts را پاک کن.

۵) فکر کردن به اینکه DNS «امن» است

Section titled “۵) فکر کردن به اینکه DNS «امن» است”

پیام‌های DNS معمولی رمزنگاری نمی‌شوند و در مسیر قابل‌دیدن (و در شبکه‌های ناامن، قابل‌دستکاری) هستند. نسخه‌های رمزنگاری‌شده (DNS over HTTPS/TLS) وجود دارند، ولی HTTPS (درس بعدی‌ها) است که در نهایت تضمین می‌کند به سایت درست وصل شده‌ای.

تمرینآسان

با dig پیدا کن: IP سایت wikipedia.org، TTL آن، و کدام سرور جواب داد. دو بار پشت سر هم بپرس و Query time و TTL را مقایسه کن.

دیدن جواب
Terminal window
dig wikipedia.org
dig 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 تقریباً برای چه هستند.

دیدن جواب
Terminal window
dig +short A github.com
dig +short MX github.com
dig +short NS github.com
dig +short TXT github.com
نمونه (کوتاه‌شده)
140.82.121.4
1 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ی نمی‌دهد؟

دیدن جواب
Terminal window
python3 -c "
import socket
for 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.test
خروجی (پایتون)
localhost -> 127.0.0.1
myshop.test -> 127.0.0.1
nosuch-shop.invalid -> ERROR: [Errno -2] Name or service not known

dig برای 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» در پایتون است.

آزمونک
  1. DNS چه کاری می‌کند؟

  2. رکورد A چه چیزی را نگه می‌دارد؟

  3. TTL در جواب DNS یعنی…

  4. status: NXDOMAIN یعنی…

  5. چرا اضافه کردن یک خط به /etc/hosts روی همه‌ی کامپیوترهای دنیا اثر ندارد؟

  6. ping 8.8.8.8 جواب می‌دهد ولی هیچ سایتی باز نمی‌شود. مشکوک‌ترین بخش؟

  • 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.comIP یک اسم
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 مشکل دارد