Part 02 · Machine গুলো কীভাবে কথা বলে

DNS: Names to Addresses

DNS

codingfoding.com এর মতো নাম কীভাবে IP হয়ে যায়, আর lookup কোথায় ভুল হতে পারে।

⏱ 1-2 ঘণ্টা · Station 16 / 153

তুমি একটা নাম লিখলে। Network শুধু সংখ্যা চেনে।

তুমি codingfoding.com লিখে Enter চাপলে। কিন্তু lesson 3 থেকে 5 দেখিয়েছে network packet নেয় শুধু সংখ্যায়: একটা IP address, তারপর একটা MAC address। কোনো router "codingfoding.com" বোঝে না।

তাই website এ একটা byte পাঠানোর আগেই তোমার browser কে কাউকে জিজ্ঞেস করতে হয়: "এই নামের IP address কী?" আর সেই কাউকে খুঁজে বের করতে হয়, এমন একটা system থেকে যার কোনো একক মালিক নেই, কয়েক millisecond এ, দিনে শত শত কোটি বার।

সেই system টাই DNS, Domain Name System। ঠিক চললে কেউ টের পায় না। ভাঙলে internet এর পুরো একেকটা অংশ উধাও মনে হয়, যদিও প্রতিটা server দিব্যি চলছে।

সমস্যা: মানুষ নাম মনে রাখে, network এর লাগে সংখ্যা

দরকারএকটা সাধারণ list কেন কাজ করে না
মানুষ নাম লেখে, 203.0.113.80 নাতাই কাউকে নাম থেকে address এ অনুবাদ করতে হয়
কোটি কোটি domain আছেকোনো একটা server সব ধরে রাখতে পারবে না, ওই traffic সামলাতেও পারবে না
Domain এর মালিকরা যখন খুশি record বদলায়তাই প্রত্যেক মালিককে নিজের অংশ নিয়ন্ত্রণ করতে হয়
প্রতিটা page load এ একটা, প্রায়ই কয়েকটা খোঁজ লাগেতাই উত্তরগুলো user দের কাছাকাছি cache করতে হয়
Server নতুন IP তে সরে যায়তাই সংখ্যা বদলালেও নাম একই থাকতে হয়

শুরুর দিকের internet এ hosts.txt নামের একটা file এ প্রতিটা machine এর list থাকতো, আর সবাই সেটা download করতো। খুব দ্রুত সেটা অচল হয়ে যায়। DNS তার জায়গা নেয় একটা ছড়ানো, স্তরে স্তরে সাজানো, cache করা database হিসেবে।

বড় একটা অফিসে ফোন নম্বর খোঁজার কথা ভাবো

একটা বড় bank এর payments team এর রহিমকে ফোন করতে হবে। তার নম্বর তোমার কাছে নেই।

  1. তুমি মূল switchboard এ ফোন করলে (root)। তারা রহিমকে চেনে না, কিন্তু IT division এর নম্বর জানে।
  2. IT তে ফোন করলে (.com server)। তারাও রহিমকে চেনে না, কিন্তু payments team এর ডেস্ক জানে।
  3. Payments এর ডেস্ক (domain এর নিজের name server) জানে: রহিম extension 4512 এ।

তুমি 4512 একটা sticky note এ লিখে রাখলে (একটা cache), যাতে পরের বার আর ঘুরতে না হয়। কিন্তু এটাও জানো মানুষ ডেস্ক বদলায়, তাই কয়েক মাস পর আবার check করবে (TTL)।

who knows codingfoding.com?browserresolverhas a cacherootask a.gtld-servers.net.com serverask ns1.cfdns.netns1.cfdns.netA 203.0.113.80codingfoding.com????203.0.113.80cached for 300 sagain? from cache
Browser তার resolver কে codingfoding.com এর কথা জিজ্ঞেস করে। Resolver জিজ্ঞেস করে root কে, root দেখিয়ে দেয় .com server, সে দেখিয়ে দেয় ns1.cfdns.net, যার কাছে আসল address আছে। Resolver উত্তরটা 300 সেকেন্ডের জন্য cache করে, তাই পরের প্রশ্নের উত্তর সাথে সাথে।

Analogy টা কোথায় খাটে না। "ফোন" গুলোতে লাগে কয়েক millisecond, আর বেশিরভাগ সময় resolver এর কাছে root আর .com এর উত্তর কয়েকদিনের জন্য cache করা থাকে, তাই শুধু শেষ ধাপটা (বা কোনোটাই না) লাগে। আর switchboard এর মতো না, DNS এর উত্তর default ভাবে সত্যি কিনা কেউ check করে না; DNSSEC এটা যোগ করে।

মূল জিনিসগুলো

  1. Domain নাম স্তরে স্তরে সাজানো। api.codingfoding.com পড়ো ডান থেকে বাঁয়ে: root (শেষে একটা অদৃশ্য .), তারপর com (top-level domain, TLD), তারপর codingfoding (যেটা কেউ register করেছে), তারপর api (তার ভেতরের একটা নাম)।
  2. Authoritative name server একটা domain এর আসল record গুলো রাখে। codingfoding.com এর মালিক এগুলো বাছে (প্রায়ই তার DNS provider) আর record ওখানেই বদলায়।
  3. দায়িত্ব ভাগ (delegation)। Root server জানে প্রতিটা TLD কে চালায়। TLD server জানে প্রতিটা domain এর জন্য কোন name server authoritative। কেউ সবকিছু রাখে না; প্রতিটা স্তর পরেরটা দেখিয়ে দেয়।
  4. Recursive resolver তোমার হয়ে ঘোরাঘুরি করে। তোমার phone বা laptop একটা resolver কে জিজ্ঞেস করে (তোমার ISP এর, তোমার company র, বা 1.1.1.1 বা 8.8.8.8 এর মতো public একটা), আর resolver root → TLD → authoritative করে উত্তর ফেরত দেয়। তোমার device শুধু একটা প্রশ্ন পাঠায়।
  5. Record এর ধরন। A (একটা IPv4 address), AAAA (IPv6), CNAME (এই নামটা আরেকটা নামের ডাকনাম), MX (mail server), TXT (লেখা, check এর কাজে লাগে), NS (কোন server গুলো authoritative)।
  6. Cache আর TTL। প্রতিটা record এর একটা TTL (time to live) থাকে, সেকেন্ডে। Resolver, operating system আর browser উত্তরটা ততক্ষণ cache করে রাখতে পারে। long TTL মানে কম খোঁজ আর দ্রুত page; ছোট TTL মানে বদল দ্রুত ছড়ায়।
  7. NXDOMAIN। "এই নামের অস্তিত্ব নেই।" এটাও কিছুক্ষণের জন্য cache হয়।
আগে অনুমান করো

তুমি website নতুন server এ সরিয়ে A record update করলে। Record এর TTL ছিল 86400 (এক দিন)। ছয় ঘণ্টা পরেও কিছু user পুরনো server এ যাচ্ছে। কেন?

ভেতরে কী হয়: একটা খোঁজ, শুরু থেকে শেষ

ধাপে ধাপে দেখো

খালি cache নিয়ে codingfoding.com খোঁজা

BrowserResolverRoot.com serverns1.cfdns.net

ধাপ 1/6 Browser জিজ্ঞেস করে

Browser (OS দিয়ে) ঠিক করা resolver কে একটা প্রশ্ন করে: codingfoding.com এর A record কী? তারপর অপেক্ষা করে।

question
codingfoding.com A?

মাথায় রাখার ছবি

DNS হলো কাকে-এরপর-জিজ্ঞেস-করবো এর একটা গাছ, সবখানে cache সহ:

  • একদম ওপরে, root TLD গুলো জানে। প্রতিটা TLD তার domain গুলোর name server জানে। প্রতিটা domain এর name server তার record জানে।
  • তোমার device একটা resolver কে জিজ্ঞেস করে; resolver গাছ ঘোরে শুধু যা cache এ নেই তার জন্য।
  • প্রতিটা উত্তরের সাথে একটা TTL আসে, যেটা একটা প্রতিশ্রুতি: "এটা N সেকেন্ড পর্যন্ত পুরনো হতে পারে"।

একটা site কারো কাছে "বন্ধ" কিন্তু কারো কাছে না হলে জিজ্ঞেস করো: server এর সমস্যা, নাকি নামের? dig (lesson 14) এক লাইনে এর উত্তর দেয়।

চেষ্টা করো: DNS কী করবে?

প্রতিটা case চালিয়ে দেখো

DNS এর পরিস্থিতি পড়া

www.codingfoding.com CNAME codingfoding.com
codingfoding.com A 203.0.113.80
কাজ করে: Resolver ডাকনাম অনুসরণ করে, তারপর আসল নামের A record খোঁজে। মূল record একবার বদলাও, www ও সাথে সাথে চলে।

গোড়া থেকে code

ছোট একটা recursive resolver। তিনটা dictionary root server, .com server আর domain এর authoritative server এর জায়গায় বসানো। Resolver দুটো cache রাখে: উত্তর (TTL 300 s) আর delegation, মানে কোন domain এর জন্য কোন server কে জিজ্ঞেস করতে হবে (TTL 2 দিন)। সময় বাইরে থেকে পাঠানো হয়, যাতে একটা cache entry এর মেয়াদ শেষ হতে দেখা যায়।

package main

import (
	"fmt"
	"strings"
)

// What each name server knows. Root and TLD servers only know who to ask next;
// the authoritative server for a domain knows its actual records.
var root = map[string]string{"com": "a.gtld-servers.net"}
var tld = map[string]string{"codingfoding.com": "ns1.cfdns.net"}
var zone = map[string][2]string{ // name -> {type, value}
	"codingfoding.com":     {"A", "203.0.113.80"},
	"www.codingfoding.com": {"CNAME", "codingfoding.com"},
	"api.codingfoding.com": {"A", "203.0.113.81"},
}

const answerTTL = 300 // seconds an answer may be cached
const nsTTL = 172800  // seconds "who serves this domain" may be cached (2 days)

type entry struct {
	value   string
	expires int
}

// The resolver's cache: answers, and delegations (which server to ask for a domain).
var answers = map[string]entry{}
var delegations = map[string]entry{}

// resolve looks a name up at time `now`, and returns the answer and who it had to ask.
func resolve(name string, now int) (string, []string, string) {
	note := ""
	if e, ok := answers[name]; ok {
		if now < e.expires {
			return e.value, nil, ""
		}
		note = "cache entry expired"
	}
	labels := strings.Split(name, ".")
	domain := strings.Join(labels[len(labels)-2:], ".") // codingfoding.com
	var asked []string
	ns, ok := delegations[domain]
	if !ok || now >= ns.expires {
		// Start at the top: root says who runs ".com", and that server says who runs the domain.
		asked = append(asked, "root", root[labels[len(labels)-1]])
		ns = entry{tld[domain], now + nsTTL}
		delegations[domain] = ns
	}
	asked = append(asked, ns.value)
	rec, found := zone[name]
	switch {
	case !found:
		return "NXDOMAIN", asked, note
	case rec[0] == "CNAME":
		ip, more, _ := resolve(rec[1], now) // the real address is under another name
		answers[name] = entry{ip, now + answerTTL}
		return ip, append(asked, more...), "CNAME " + rec[1]
	}
	answers[name] = entry{rec[1], now + answerTTL}
	return rec[1], asked, note
}

func lookup(name string, now int) {
	ip, asked, note := resolve(name, now)
	who := "nobody (cache)"
	if len(asked) > 0 {
		who = strings.Join(asked, ", ")
	}
	if note != "" {
		who += " (" + note + ")"
	}
	fmt.Printf("%-21s -> %-13s asked: %s\n", name, ip, who)
}

func main() {
	lookup("codingfoding.com", 0)
	lookup("codingfoding.com", 5)
	lookup("www.codingfoding.com", 10)
	lookup("nope.codingfoding.com", 20)
	fmt.Println("... 301 s later ...")
	lookup("codingfoding.com", 301)
}

Output (পাঁচটা language এই একই):

codingfoding.com      -> 203.0.113.80  asked: root, a.gtld-servers.net, ns1.cfdns.net
codingfoding.com      -> 203.0.113.80  asked: nobody (cache)
www.codingfoding.com  -> 203.0.113.80  asked: ns1.cfdns.net (CNAME codingfoding.com)
nope.codingfoding.com -> NXDOMAIN      asked: ns1.cfdns.net
... 301 s later ...
codingfoding.com      -> 203.0.113.80  asked: ns1.cfdns.net (cache entry expired)

Output টা পড়ি:

  • প্রথম খোঁজ: তিনটা প্রশ্ন, root, .com, তারপর domain এর নিজের server। এটা ধীর পথ, আসল network এ প্রায়ই 50–200 ms।
  • দ্বিতীয় খোঁজ: কাউকে জিজ্ঞেস করা হয়নি। বাস্তবে বেশিরভাগ খোঁজ এরকমই, এজন্যই পুরো পৃথিবী জুড়ে ছড়ানো হয়েও DNS দ্রুত।
  • www: শুধু domain এর server কে জিজ্ঞেস করা হয়েছে (delegation cache এ আছে), আর CNAME এর লক্ষ্য আগে থেকেই উত্তরের cache এ।
  • nope: authoritative server বলে নামটার অস্তিত্ব নেই: NXDOMAIN।
  • 301 s পরে: উত্তরের মেয়াদ শেষ, তাই resolver আবার জিজ্ঞেস করে, কিন্তু শুধু শেষ server কে, কারণ "codingfoding.com কে চালায়" দুই দিনের জন্য cache করা। প্রতিটা স্তরের TTL ঠিক করে একটা খোঁজে কতটা কাজ লাগবে।

আসল engineering

  • TTL মাথায় রেখে DNS বদলের plan করো। একটা service সরানোর আগে TTL কমাও (60–300 s), পুরনো TTL পার হওয়া পর্যন্ত অপেক্ষা করো, তারপর record বদলাও। পরে আবার বাড়াও।
  • DNS একটা নির্ভরতা, আর এটা fail করতে পারে। তোমার resolver ধীর বা বন্ধ হলে backend এর বাইরে যাওয়া প্রতিটা call নাম খুঁজতে গিয়ে আটকে থাকে। "Network" এর ঘাড়ে চাপানো অনেক outage আসলে DNS। খোঁজার সময় নজরে রাখো, আর reliable resolver ব্যবহার করো।
  • তোমার backend ও নাম খোঁজে। Database এর host, অন্য service আর third-party API সবই নাম দিয়ে খোঁজা হয়। কিছু runtime default ভাবে DNS অনেকক্ষণ cache করে (পুরনো JVM চিরকাল করতো), তাই সরানো database পুরনো IP পেতেই থাকে। তোমার runtime এর DNS caching জেনে রাখো।
  • Cluster এর ভেতরে DNS মানে service discovery। Kubernetes এ orders.default.svc.cluster.local resolve হয় orders service এ। একই protocol, website এর বদলে service খুঁজতে ব্যবহার। (Module 8, lesson 15।)
  • যেখানে পারো সুরক্ষিত করো। DNS এর উত্তর default ভাবে encrypt বা check করা হয় না। DNSSEC record এ sign করে; DNS over HTTPS বা TLS network থেকে খোঁজ লুকায়। Domain account এর security (2FA, registrar lock) জরুরি: domain এর record দখল মানে এর পেছনের সবকিছু দখল।

যখন ভাঙে

প্রতিটা case চালিয়ে দেখো

একটা failure বাছো

10:00 এ A record বদলানো
14:00: 20% traffic এখনো পুরনো IP তে
ভাঙে: Resolver আর client পুরনো উত্তর তার TTL পর্যন্ত cache করেছে। বদলের আগে TTL কমাও, আর পুরনো TTL পার না হওয়া পর্যন্ত পুরনো server চালু রাখো (বা redirect করো)।

পড়ার আগে ভাবো

তোমার company র resolver এ codingfoding.com cache করা, মেয়াদ আর 280 সেকেন্ড বাকি। তুমি এখনই একটা ভাঙা A record ঠিক করলে। একই অফিসের এক সহকর্মী 10 সেকেন্ড পর site টা দেখলো। সে কী দেখবে, আর ঠিক করাটা কখন দেখবে?

উত্তর দেখো

সে এখনো shared resolver এর cache থেকে পুরনো উত্তর পাবে, আরো প্রায় 270 সেকেন্ড পর্যন্ত, সাথে তার নিজের browser আর OS যা cache করেছে। Cache করা entry এর মেয়াদ শেষ হলে resolver আবার authoritative server কে জিজ্ঞেস করবে আর ঠিক করা record পাবে। Cache এ বদল ঠেলে পাঠানো যায় না; শুধু মেয়াদ শেষ হওয়া পর্যন্ত অপেক্ষা করা যায়, এজন্যই TTL আগে থেকে বাছতে হয়।

নিজেকে check করো

1. একটা recursive resolver কী করে?

উত্তর

Client এর কাছ থেকে একটা প্রশ্ন নেয়, আর root → TLD → authoritative server ঘোরার পুরো কাজটা করে (যেখানে পারে cache ব্যবহার করে), তারপর উত্তর ফেরত দেয়।

2. A record আর CNAME এর পার্থক্য কী?

উত্তর

A record একটা নামকে একটা IPv4 address এর সাথে মেলায়। CNAME বলে নামটা আরেকটা নামের ডাকনাম, তাই তার বদলে ওই নামের record খুঁজতে হবে।

3. পুরো একটা খোঁজে তিনটা আলাদা server কে জিজ্ঞেস করতে হলেও DNS দ্রুত কেন?

উত্তর

Cache এর জন্য। Resolver দেখিয়ে দেওয়া গুলো (প্রায়ই কয়েকদিন) আর উত্তরগুলো (তাদের TTL পর্যন্ত) রেখে দেয়, তাই বেশিরভাগ খোঁজে শূন্য বা একটা প্রশ্ন লাগে।

4. Client এ server এর IP hard-code করা উচিত না কেন?

উত্তর

Server সরে। নাম থাকলে একটা DNS record বদলালেই হয়; IP hard-code করলে প্রতিটা client বদলাতে হয়।

তোমার challenge: negative caching

আসল resolver NXDOMAIN ও cache করে, যাতে না-থাকা একটা নামের জন্য একগাদা খোঁজ প্রতিবার authoritative server এ না যায়।

  • NXDOMAIN উত্তর 60 সেকেন্ডের জন্য cache করো।
  • nope.codingfoding.com খোঁজো 20, 30 আর 85 সময়ে।

চালানোর আগে আন্দাজ করো প্রতিবার কাকে জিজ্ঞেস করা হবে।

সফল হয়েছো যখন 20 এর খোঁজ জিজ্ঞেস করে ns1.cfdns.net কে, 30 এর টা কাউকে না (cache এ আছে), 85 এর টা আবার ns1.cfdns.net কে (60 সেকেন্ডের cache 80 এ শেষ), আর output এর আগের প্রতিটা লাইন আগের মতোই থাকে।

Mental model

DNS নামকে address বানায় server এর একটা গাছ দিয়ে: root দেখিয়ে দেয় TLD, TLD দেখিয়ে দেয় domain এর নিজের name server, আর আসল record থাকে ওদের কাছে। তোমার device একটা resolver কে জিজ্ঞেস করে, যে গাছ ঘোরে শুধু যা cache এ নেই তার জন্য। প্রতিটা উত্তরের একটা TTL থাকে, একটা প্রতিশ্রুতি যে ততক্ষণ পুরনো হতে পারে, তাই বদলের plan করো এটা মাথায় রেখে, আর মনে রেখো "site বন্ধ" কখনো কখনো আসলে "নাম ভাঙা"।

Station stamp

Chapter শেষ করো

পড়া শেষ হলে Complete চাপো, progress save হবে। XP শুধু Pro তে — Pro থাকলে এই chapter এ +10 XP পেতে।

Pro নিয়ে XP পাও →