一、什麼是DNS
DNS(Domain Name System)是互聯網中的一個命名系統,用於將域名與IP地址相互映射。藉助DNS,用戶只需要輸入易於記憶和理解的域名,即可訪問到遠程主機。
DNS是一個分佈式的數據庫系統,同時也是一個應用層協議。可提供兩種服務:解析和逆向解析。解析將域名轉換成IP地址,逆向解析將IP地址轉換成域名。
二、DNS在哪一層
DNS作為一個應用層協議,位於OSI七層模型中的應用層。DNS的數據傳輸使用的是TCP和UDP協議,TCP常用於大數據傳輸,UDP常用於小數據傳輸,例如DNS的查詢。
三、DNS的工作原理
DNS的工作可以分為兩個階段:遞歸查詢和緩存查詢。
1.遞歸查詢
當用戶查詢一個域名時,本地域名服務器(Local DNS Server)會先查詢本地緩存是否存在該域名對應的IP地址。如果存在,則直接將IP地址返回給用戶。如果不存在,則本地域名服務器需要向根域名服務器(Root DNS Server)查詢該域名對應的頂級域名服務器(TLD DNS Server)的IP地址。
然後本地域名服務器會向TLD DNS Server發送一個查詢請求,詢問負責該域名的下一級域名服務器的IP地址。例如,www.example.com的頂級域名是.com,則TLD DNS Server需要返回負責.com域名解析的域名服務器IP地址。
本地域名服務器再向負責.com域名解析的域名服務器發送詢問請求,詢問www.example.com對應的IP地址。域名服務器查詢自己的緩存。如果緩存中有該域名對應的IP地址,則返回,否則繼續向上級域名服務器查詢,直到返回該域名對應的IP地址。
最後,本地域名服務器將查詢結果返回給用戶,並將結果緩存,以備下次查詢時使用。
2.緩存查詢
緩存查詢指的是本地域名服務器在遞歸查詢過程中,將查詢結果緩存起來,以便在下次查詢時能夠更快地返回結果。緩存可以設置生存時間,超過生存時間就需要重新從根域名服務器查詢。
四、DNS的代碼示例
以下是一個使用Node.js實現的簡單DNS服務器,它可以響應簡單的DNS查詢請求。
const dns = require('dns'); const dgram = require('dgram'); const server = dgram.createSocket('udp4'); server.on('error', (err) => { console.log(`server error:\n${err.stack}`); server.close(); }); server.on('message', (msg, rinfo) => { console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`); const domain = msg.slice(12, msg.length - 5); dns.lookup(domain, (err, address) => { if (err) { console.log('lookup error:', err); return; } const response = Buffer.alloc(16); response.writeUInt16BE(msg.readUInt16BE(0), 0); // 事務ID response.writeUInt16BE(0x8180, 2); // 標準響應,無遞歸和權威答案 response.writeUInt16BE(msg.readUInt16BE(4), 4); // 問題數量 response.writeUInt16BE(1, 6); // 回答數量 response.writeUInt16BE(0, 8); // 權威域名數量 response.writeUInt16BE(0, 10); // 額外信息數量 response.write(msg.slice(12, msg.length)); // 問題部分 response.writeUInt16BE(0xc00c, response.length - 4); // 回答部分域名偏移量 response.writeUInt16BE(1, response.length - 2); // 回答部分類型 response.writeUInt16BE(1, response.length); // 回答部分類 response.writeUInt32BE(0, response.length + 2); // 回答部分緩存時間 response.writeUInt16BE(4, response.length + 6); // 回答部分數據長度 const addressParts = address.split('.'); for (let i = 0; i { const address = server.address(); console.log(`server listening ${address.address}:${address.port}`); }); server.bind(53);
原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/241329.html