دیاناس net/dns
پیدا کردن نشانی نامها و پرسیدن هر نوع رکورد DNS.
واردسازی شبکه.دیاناس
DNS نامهایی مثل salamlang.ir را به نشانی IP تبدیل میکند. جستجو سادهترین راه است و همان کاری را میکند که مرورگر میکند. تابعهای جستجوی ... رکوردهای ویژه را مستقیم از کارگزار DNS میپرسند و برای ساختن ابزارهای شبکه یا بررسی پیکربندی دامنه به کار میآیند.
یک جستجو ممکن است به دلیلهای عادی شکست بخورد: نام وجود ندارد، شبکه قطع است یا کارگزار کند است. هیچکدام از این تابعها برنامه را متوقف نمیکنند. جستجو و جستجوی سینیم رشتهی خالی برمیگردانند و بقیه فهرست خالی، پس پیش از استفاده نتیجه را بررسی کنید.
دو حلکنندهی متفاوت
جستجواز سیستمعامل میپرسد، درست مثل وقتی که با نام وصل میشوید: پروندهی hosts،localhost، دامنههای جستجو و حافظهی نهان سیستم همه اثر دارند. یک نشانی IPv4 برمیگرداند.- تابعهای رکوردی
جستجوی ...پرسشهایشان را خودشان روی UDP به کارگزارهایکارگزارهای پیشفرضمیفرستند: سطرهایnameserverدر/etc/resolv.confروی لینوکس، مک و BSD. پروندهی hosts به کار نمیرود. وقتی چنین پروندهای نباشد، که روی ویندوز همیشه همینطور است، به حلکنندههای عمومی8.8.8.8و1.1.1.1برمیگردند، پس نامهایی که جستجو میکنید از شبکهی شما بیرون میروند. هر کارگزار ۳ ثانیه فرصت دارد و بعد سراغ بعدی میرود.
اشتباههای رایج
- پاسخهای بزرگ ممکن است ناقص باشند. پاسخی که در یک بستهی UDP جا نشود با
tcروشن برمیگردد و روی TCP دوباره پرسیده نمیشود، پس رکوردهای TXT خیلی بلند یا فهرستهای بلند نشانی ممکن است بریده شوند. پرسش از کارگزارشناسهی پاسخ را با پرسش مقایسه نمیکند. روی شبکهی نامطمئنMessage.idرا خودتان مقایسه کنید یا حلکنندهای را به کار ببرید که به آن اعتماد دارید.- همه چیز متن ساده روی درگاه ۵۳ است. نه اعتبارسنجی DNSSEC هست و نه DNS روی TLS یا HTTPS.
جستجوی معکوسفقط نشانی IPv4 میگیرد.
یافتن نشانی و سپس اتصال
تی سی پی و یو دی پی نام میزبان یا نشانی را میپذیرند، ولی اگر خودتان اول نام را به نشانی تبدیل کنید میتوانید پیش از تلاش برای اتصال خطای روشنی گزارش دهید. جستجو از حلکنندهی سیستم عامل استفاده میکند، پس localhost و نامهای پروندهی hosts هم بدون اینترنت کار میکنند.
واردسازی شبکه.دیاناس
واردسازی شبکه.تی سی پی
ناپایا سرور := تی سی پی.سرور {}
تابع خوشامد():
ا := تی سی پی.پذیرش(سرور)
_ := تی سی پی.نوشتن(ا، "سلام، پیدایم کردی")
تی سی پی.بستن(ا)
پایان
تابع وصل شو(میزبان: رشته، درگاه: صحیح): تی سی پی.اتصال شبکه:
نشانی := دیاناس.جستجو(میزبان)
اگر نشانی == "":
سرچاپ "نشانی"، میزبان، "پیدا نشد"
برگشت تی سی پی.اتصال شبکه {}
پایان
سرچاپ میزبان، "یعنی"، نشانی
برگشت تی سی پی.شماره گیری(نشانی، درگاه)
پایان
تابع ریشه:
سرور = تی سی پی.پیوند(۰)
ن := نخساز(خوشامد)
ا := وصل شو("localhost"، تی سی پی.درگاه(سرور))
اگر تی سی پی.اتصال معتبر(ا):
تی سی پی.تنظیم مهلت خواندن(ا، ۲۰۰۰)
سرچاپ تی سی پی.خواندن(ا، ۱۰۲۴)
تی سی پی.بستن(ا)
پایان
نخپیوند(ن)
تی سی پی.بستن سرور(سرور)
بد := وصل شو("no-such-host.invalid"، ۸۰)
سرچاپ "وصل شد:"، تی سی پی.اتصال معتبر(بد)
پایاندامنهی سطح بالای .invalid رزرو شده و هیچوقت وجود ندارد، برای همین برای آزمودن مسیر خطا مناسب است.
بررسی تنظیمات نامهی یک دامنه
نامههای یک دامنه به کارگزارهای رکوردهای MX آن میروند، اول آن که عدد اولویتش کوچکتر است؛ بقیه پشتیباناند. رکوردهای TXT دامنه سیاست SPF را نگه میدارند که میگوید کدام کارگزارها حق فرستادن نامه از طرف دامنه را دارند، و سیاست DMARC در رکورد TXTِ _dmarc. بهعلاوهی نام دامنه است. این برنامه به اینترنت نیاز دارد و اینجا فقط کامپایل میشود. در برابر DNS واقعی این را چاپ کرد:
واردسازی شبکه.دیاناس
تابع ریشه:
دامنه := "gmail.com"
سرورهای نامه := دیاناس.جستجوی امایکس(دامنه)
اگر سرورهای نامه.رکوردها.طول() == ۰:
سرچاپ دامنه، "رکورد MX ندارد و نامه به رکورد A آن میرود"
پایان
ناپایا بهترین := دیاناس.رکورد {}
هر ر در سرورهای نامه.رکوردها:
سرچاپ "MX"، ر.اولویت، ر.داده
اگر بهترین.داده == "" یا ر.اولویت < بهترین.اولویت:
بهترین = ر
پایان
پایان
سرچاپ "اول به این سرور تحویل بده:"، بهترین.داده
هر متن در دیاناس.جستجوی تیایکستی(دامنه):
اگر متن.شروع با("v=spf1"):
سرچاپ "SPF:"، متن
پایان
پایان
هر متن در دیاناس.جستجوی تیایکستی("_dmarc." + دامنه):
اگر متن.شروع با("v=DMARC1"):
سرچاپ "DMARC:"، متن
پایان
پایان
پایانMX 10 alt1.gmail-smtp-in.l.google.com
MX 20 alt2.gmail-smtp-in.l.google.com
MX 40 alt4.gmail-smtp-in.l.google.com
MX 30 alt3.gmail-smtp-in.l.google.com
MX 5 gmail-smtp-in.l.google.com
اول به این سرور تحویل بده: gmail-smtp-in.l.google.com
SPF: v=spf1 redirect=_spf.google.com
DMARC: v=DMARC1; p=none; sp=quarantine; rua=mailto:[email protected]
رکوردها به هر ترتیبی که کارگزار بخواهد برمیگردند، پس خودتان بر اساس priority مرتب کنید یا انتخاب کنید، همان کاری که حلقه میکند.
پرسیدن مستقیم از یک کارگزار
پرسش از کارگزار حلکنندهی سیستم را کنار میگذارد و از کارگزاری که نام میبرید میپرسد؛ با آن میتوانید پاسخ حلکنندههای مختلف را مقایسه کنید یا کارگزار DNS خودتان را بیازمایید. کل پیام را برمیگرداند: rcode برابر ۳ یعنی نام وجود ندارد، و پیام خالی (بدون پرچم qr و با شناسهی ۰) یعنی در زمان تعیینشده پاسخی نرسید. هر رکورد یک ttl دارد، یعنی چند ثانیه میشود آن را در حافظهی نهان نگه داشت. نامی که نام دیگرِ نامی دیگر است پیش از نشانی با یک رکورد CNAME پاسخ میدهد، برای همین حلقه به rtype نگاه میکند. این یکی هم به اینترنت نیاز دارد.
واردسازی شبکه.دیاناس
تابع نمایش(کارگزار: رشته، نام: رشته):
پ := دیاناس.پرسش از کارگزار(کارگزار، نام، دیاناس.نوع آ، ۲۰۰۰)
اگر پ.شناسه == ۰ و وارونه پ.نشانه پاسخ:
سرچاپ کارگزار، "پاسخی نداد"
برگشت
پایان
اگر پ.کد نتیجه == ۳:
سرچاپ کارگزار، "میگوید"، نام، "وجود ندارد"
برگشت
پایان
هر ر در پ.پاسخها.رکوردها:
اگر ر.نوع رکورد == دیاناس.نوع آ:
سرچاپ کارگزار، نام، "->"، ر.داده، "برای"، ر.زمان ماندگاری، "ثانیه"
وگرنه:
سرچاپ کارگزار، نام، "نام دیگرِ"، ر.داده، "است"
پایان
پایان
پایان
تابع ریشه:
کارگزارها := دیاناس.کارگزارهای پیشفرض()
سرچاپ "کارگزارهای سیستم:"، کارگزارها
نمایش(کارگزارها.بگیر(۰)، "www.github.com")
نمایش("1.1.1.1"، "salamlang.ir")
نمایش("1.1.1.1"، "no-such-name.invalid")
نمایش("192.0.2.1"، "salamlang.ir")
پایان192.0.2.1 از محدودهای است که برای مستندات رزرو شده، پس کسی آنجا پاسخ نمیدهد و برنامه حالت تمام شدن زمان را نشان میدهد. نشانیها و TTLهایی که میبینید از اجرایی به اجرای دیگر فرق میکنند.
حرف زدن به زبان خود پروتکل
DNS چیزی جز بستههای دودویی کوچک روی UDP نیست و کدگذاری پرسش و کدگشایی آنها را میسازند و میخوانند. همین برای ساختن یک بدلِ آزمایشی کافی است: برنامهی زیر یک کارگزار DNS اسباببازی روی 127.0.0.1 اجرا میکند که به هر پرسشی با چنین نامی نیست پاسخ میدهد؛ دو بایت پرچمِ پرسش را عوض میکند و آن را برمیگرداند. کارخواه یک پرسش واقعی را با یو دی پی میفرستد و پاسخ را کدگشایی میکند، همه بدون اینترنت.
واردسازی شبکه.دیاناس
واردسازی شبکه.یو دی پی
واردسازی حافظه
ناپایا سرور := یو دی پی.سوکت یو دی پی {}
تابع پاسخ نبودن():
یو دی پی.تنظیم زمان انتظار(سرور، ۲۰۰۰)
بافر := حافظه.تخصیص صفرشده(۵۱۲ برگردان طبیعی۶۴)
ناپایا میزبان := ""
ناپایا درگاه := ۰
تعداد := یو دی پی.دریافت بایت(سرور، بافر، ۵۱۲، میزبان، درگاه)
پرسش := دیاناس.کدگشایی(بافر، تعداد)
سرچاپ "سرور: پرسش"، پرسش.شناسه، "برای"، پرسش.پرسشها.پرسشها[۰].نام دامنه
ب := بافر برگردان طبیعی۸*
ب[۲] = ب[۲] | (۱۲۸ برگردان طبیعی۸)
ب[۳] = ۱۳۱ برگردان طبیعی۸
_ := یو دی پی.ارسال بایت(سرور، میزبان، درگاه، بافر، تعداد)
حافظه.آزادسازی(بافر)
پایان
تابع نام کد(کد: صحیح): رشته:
ترابرد کد:
۰: برگشت "NOERROR" پایان
۲: برگشت "SERVFAIL" پایان
۳: برگشت "NXDOMAIN" پایان
۵: برگشت "REFUSED" پایان
پایان
برگشت "دیگر"
پایان
تابع ریشه:
سرور = یو دی پی.پیوند روی("127.0.0.1"، ۰)
ن := نخساز(پاسخ نبودن)
پرسش := دیاناس.کدگذاری پرسش("shop.example"، دیاناس.نوع آ، ۷)
کارخواه := یو دی پی.باز کردن()
یو دی پی.تنظیم زمان انتظار(کارخواه، ۲۰۰۰)
_ := یو دی پی.ارسال بایت(کارخواه، "127.0.0.1"، یو دی پی.درگاه(سرور)، پرسش.داده، پرسش.طول)
پاسخ := حافظه.تخصیص صفرشده(۵۱۲ برگردان طبیعی۶۴)
ناپایا میزبان := ""
ناپایا درگاه := ۰
تعداد := یو دی پی.دریافت بایت(کارخواه، پاسخ، ۵۱۲، میزبان، درگاه)
نخپیوند(ن)
پ := دیاناس.کدگشایی(پاسخ، تعداد)
سرچاپ "کارخواه: پاسخ"، پ.شناسه، "qr"، پ.نشانه پاسخ، "ra"، پ.جستجوی بازگشتی ممکن
سرچاپ "کارخواه: کد نتیجه"، پ.کد نتیجه، نام کد(پ.کد نتیجه)، "پاسخها"، پ.پاسخها.رکوردها.طول()
حافظه.آزادسازی(پاسخ)
یو دی پی.بستن(کارخواه)
یو دی پی.بستن(سرور)
پایانشناسهی پاسخ با شناسهی پرسش (اینجا ۷) یکی است. یک کارخواه واقعی شناسهی تصادفی میفرستد و هر پاسخی را که شناسهاش نخواند نادیده میگیرد، تا بستهای سرگردان یا جعلی به جای پاسخ گرفته نشود.
کدام تابع برای کدام کار
| کار | تابع |
|---|---|
| گرفتن نشانی برای اتصال | جستجو |
| همهی نشانیهای IPv4 یا IPv6 یک نام | جستجوی آ، جستجوی کواداِی |
| نامههای یک دامنه کجا میروند | جستجوی امایکس |
| SPF، DMARC و کدهای تایید دامنه | جستجوی تیایکستی |
| نام اصلی پشت یک نام دیگر | جستجوی سینیم |
| نامِ یک نشانی IP | جستجوی معکوس |
| پرسیدن از کارگزار دلخواه، دیدن TTL و کد خطا | پرسش از کارگزار |
| ساختن یا خواندن بستههای خام DNS | کدگذاری پرسش، کدگشایی |
گونهها
پرسش Question
ساختار پرسش| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| نام دامنه | name | رشته = "" | نام دامنه. |
| نوع رکورد | qtype | صحیح = 0 | نوع رکورد. |
| رده | qclass | صحیح = 0 | رده. |
واردسازی شبکه.دیاناس
واردسازی فشرده سازی
تابع ریشه:
پرسش := دیاناس.کدگذاری پرسش("salamlang.ir"، دیاناس.نوع آ، ۴۲)
سرچاپ فشرده سازی.طول بافر(پرسش)، فشرده سازی.بافر به پایه۶۴(پرسش)
پ := دیاناس.کدگشایی(پرسش.داده، پرسش.طول)
سرچاپ پ.شناسه، پ.نشانه پاسخ، پ.جستجوی بازگشتی خواسته، پ.نوع عمل، پ.کد نتیجه، پ.پرسشها.پرسشها.طول()
س := پ.پرسشها.پرسشها[۰]
سرچاپ س.نام دامنه، س.نوع رکورد == دیاناس.نوع آ، س.رده == دیاناس.رده اینترنت
سرچاپ پ.پاسخها.رکوردها.طول()، پ.رکوردهای صاحباختیار.رکوردها.طول()، پ.رکوردهای اضافی.رکوردها.طول()، پ.پاسخ صاحباختیار، پ.بریدهشده، پ.جستجوی بازگشتی ممکن
سرچاپ دیاناس.نوع اناس، دیاناس.نوع سینیم، دیاناس.نوع اساُاِی، دیاناس.نوع پیتیآر، دیاناس.نوع امایکس، دیاناس.نوع تیایکستی، دیاناس.نوع کواداِی
سرچاپ دیاناس.جستجو("localhost")
سرچاپ دیاناس.کارگزارهای پیشفرض().طول() > ۰
پایانپرسشها Questions
ساختار پرسشها| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| پرسشها | items | وکتور<پرسش> | پرسشها. |
نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
رکورد Record
ساختار رکورد| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| نام دامنه | name | رشته = "" | نام دامنه. |
| نوع رکورد | rtype | صحیح = 0 | نوع رکورد. |
| رده | rclass | صحیح = 0 | رده. |
| زمان ماندگاری | ttl | صحیح = 0 | چند ثانیه میشود پاسخ را نگه داشت. |
| اولویت | priority | صحیح = 0 | اولویت رکورد MX؛ عدد کمتر یعنی اولویت بیشتر. |
| داده | data | رشته = "" | دادهی رکورد به شکل متن: نشانی، نام یا متن. |
واردسازی شبکه.دیاناس
تابع ریشه:
سرچاپ دیاناس.جستجوی آ("salamlang.ir")
سرچاپ دیاناس.جستجوی کواداِی("salamlang.ir")
سرچاپ دیاناس.جستجوی سینیم("www.github.com")
ر := دیاناس.جستجوی امایکس("gmail.com")
هر م در ر.رکوردها:
سرچاپ م.اولویت، م.داده، م.زمان ماندگاری، م.نوع رکورد، م.رده، م.نام دامنه
پایان
سرچاپ دیاناس.جستجوی تیایکستی("salamlang.ir")
سرچاپ دیاناس.جستجوی معکوس("8.8.8.8")
پ := دیاناس.پرسش از کارگزار("1.1.1.1"، "salamlang.ir"، دیاناس.نوع آ، ۲۰۰۰)
سرچاپ پ.پاسخها.رکوردها.طول()
پایانرکوردها Records
ساختار رکوردها| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| رکوردها | items | وکتور<رکورد> | رکوردها. |
نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Lookup.salam
پیام Message
ساختار پیام| نام | انگلیسی | گونه | توضیح |
|---|---|---|---|
| شناسه | id | صحیح = 0 | شناسهای که پاسخ را به پرسش گره میزند. |
| نشانه پاسخ | qr | منطقی = نادرست | پیام پاسخ است. |
| نوع عمل | opcode | صحیح = 0 | نوع عمل؛ صفر پرسش معمولی. |
| پاسخ صاحباختیار | aa | منطقی = نادرست | پاسخ از کارگزار صاحباختیار است. |
| بریدهشده | tc | منطقی = نادرست | پاسخ بریده شده. |
| جستجوی بازگشتی خواسته | rd | منطقی = نادرست | درخواست جستجوی بازگشتی. |
| جستجوی بازگشتی ممکن | ra | منطقی = نادرست | کارگزار جستجوی بازگشتی را پشتیبانی میکند. |
| کد نتیجه | rcode | صحیح = 0 | کد نتیجه؛ صفر یعنی بدون خطا، ۳ یعنی نام وجود ندارد. |
| پرسشها | questions | پرسشها | پرسشها. |
| پاسخها | answers | رکوردها | پاسخها. |
| رکوردهای صاحباختیار | authorities | رکوردها | رکوردهای صاحباختیار. |
| رکوردهای اضافی | extras | رکوردها | رکوردهای اضافی. |
نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
پایاها و متغیرها
نوع آ TypeA
پایا نوع آ: صحیح۳۲ = 1نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
نوع اناس TypeNS
پایا نوع اناس: صحیح۳۲ = 2نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
نوع سینیم TypeCNAME
پایا نوع سینیم: صحیح۳۲ = 5نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
نوع اساُاِی TypeSOA
پایا نوع اساُاِی: صحیح۳۲ = 6نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
نوع پیتیآر TypePTR
پایا نوع پیتیآر: صحیح۳۲ = 12نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
نوع امایکس TypeMX
پایا نوع امایکس: صحیح۳۲ = 15نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
نوع تیایکستی TypeTXT
پایا نوع تیایکستی: صحیح۳۲ = 16نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
نوع کواداِی TypeAAAA
پایا نوع کواداِی: صحیح۳۲ = 28نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
رده اینترنت ClassIN
پایا رده اینترنت: صحیح۳۲ = 1نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
تابعها
کدگذاری پرسش EncodeQuery
تابع کدگذاری پرسش(name: رشته، qtype: صحیح، id: صحیح): compress.ByteBufنمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
کدگشایی Decode
تابع کدگشایی(data: تهی*، n: صحیح): پیامنمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
جستجو Lookup
تابع جستجو(host: رشته): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
پرسش از کارگزار QueryServer
تابع پرسش از کارگزار(server: رشته، name: رشته، qtype: صحیح، timeout_ms: صحیح): پیامtimeout_ms پاسخی نرسد، پیام خالی. شناسهی پاسخ با پرسش مقایسه نمیشود.نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Lookup.salam
کارگزارهای پیشفرض DefaultServers
تابع کارگزارهای پیشفرض(): وکتور<رشته>nameserver در /etc/resolv.conf؛ اگر نباشند 8.8.8.8 و 1.1.1.1، که روی ویندوز همیشه همینطور است.نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Message.salam
جستجوی آ LookupA
تابع جستجوی آ(name: رشته): وکتور<رشته>نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Lookup.salam
جستجوی کواداِی LookupAAAA
تابع جستجوی کواداِی(name: رشته): وکتور<رشته>نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Lookup.salam
جستجوی سینیم LookupCNAME
تابع جستجوی سینیم(name: رشته): رشتهنمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Lookup.salam
جستجوی امایکس LookupMX
تابع جستجوی امایکس(name: رشته): رکوردهانمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Lookup.salam
جستجوی تیایکستی LookupTXT
تابع جستجوی تیایکستی(name: رشته): وکتور<رشته>نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Lookup.salam
جستجوی معکوس LookupPTR
تابع جستجوی معکوس(ip: رشته): وکتور<رشته>نمونهی این مورد همراه با موارد بالاتر آمده است: net-dns-Lookup.salam