大家好,欢迎来到IT知识分享网。
文章索引:
1. DNS协议概述
2. DNS协议格式
3. DNS协议工作原理和流程
4. DNS协议使用方法
5. DNS攻击和防范
6. 代码示例
一、DNS协议概述
1.定义和作用
DNS(域名系统,Domain Name System)是一种用于将人类可读的域名(如 http://www.example.com)转换为计算机可读的 IP 地址(如 192.0.2.1)的协议。
众所周知,在网络中计算机之间是通过IP地址进行互相访问的,当我们访问某个域名时,其背后是DNS服务器进行了域名解析,并得到对应的IP地址。所以域名相比于IP地址而言,更加简单易记,从而可以更方便的访问。
2.协议层次结构
1)DNS协议运行在UDP协议之上,位于网络协议栈的 应用层, 使用端口号53;
2)DNS在协议栈中的层次如下所示:
3.域名层次结构:
域名是具有一定的层次结构的,从上到下依次为:「根域名」、「顶级域名」、「二级域名」、(三级域名), 域名的层次结构在 DNS(域名系统)中具有至关重要的作用,它不仅使得域名的管理和解析变得高效,而且确保了互联网的可扩展性、灵活性和可靠性.
1)顶级域名:就是网址的最后一个部分。即上图中www.baidu.com 的顶级域名就是 .com。由国际机构ICANN来分配,当前顶级域名共有一千多个,它们大致可以分成两类:
a. 一类是「通用顶级域名」(gTLD),比如.com、.net、.edu、.org、.xxx等等,共有 700 多个。
b. 另一类是「国家顶级域名」(ccTLD),代表不同的国家和地区,比如.cn(中国)、.io(英属印度洋领地)、.cc( 科科斯群岛)、.tv(图瓦卢)等,共有 300 多个。
2) 二级域名:是在通用顶级域名或国家顶级域名之下具有不同的意义:
a. 通用顶级域名下的二级域名:一般是指域名注册人选择使用的网上名称,如 yahoo.com(商业组织通常使用自己的商标、商号或其他商业标志作为自己的网上名称,如 baidu.com)
b. 国家顶级域名下的二级域名:一般是指类似于通用顶级域名的表示注册人类别和功能的标志。例如,在 .com.cn 域名结构中,.com 此时是置于国家顶级域名 .cn 下的二级域名,表示中国的商业性组织,以此类推。
3) 三级域名:是形如 www.baidu.com 的域名,可以当做是二级域名的子域名,特征为域名包含两个 .。对于域名所有者/使用者而言,三级域名都是二级域名的附属物而无需单独费用。
4) 根域名:由于 ICANN 管理着所有的顶级域名,所以它是最高一级的域名节点,被称为根域名(root domain)。在有些场合,http://www.xxx.com 被写成 www.xxx.com.,即最后还会多出一个点。这个点就是根域名,通常在实际使用中不显示。
由三级域名,二级域名,顶级域名可以像树型结构一样向上找。
4.查询方式:
DNS 查询是指通过 DNS(域名系统)将域名解析为相应的 IP 地址的过程。DNS 查询的方式主要有以下几种:
1) 递归查询:
在递归查询中,DNS 客户端向 DNS 服务器发出请求,并要求该服务器负责完成整个查询过程。递归查询就是从根域开始查,逐步往下,只需查询一次便能得到结果,但比较耗时.
具体步骤如下:
· 客户端向本地 DNS 服务器发送请求。
· 如果本地 DNS 服务器没有缓存该域名的解析结果,它会向根 DNS 服务器查询。
· 根 DNS 服务器返回对应的顶级域名服务器地址。
· 本地 DNS 服务器再向顶级域名服务器查询。
· 顶级域名服务器返回二级域名服务器地址。
· 本地 DNS 服务器向二级域名服务器查询,最终得到所需的 IP 地址。
· 最后,本地 DNS 服务器将解析结果返回给客户端。
2) 迭代查询:
在迭代查询中,DNS 客户端向 DNS 服务器发出请求,如果该服务器无法提供所需的结果,它会返回一个指向下一个 DNS 服务器的地址,而不是完成整个查询过程。
具体步骤如下:
· 客户端向本地 DNS 服务器发送请求。
· 如果本地 DNS 服务器没有缓存该域名的解析结果,它会向根 DNS 服务器查询。
· 根 DNS 服务器返回对应的顶级域名服务器的地址。
· 客户端再向顶级域名服务器发送请求。
· 如果顶级域名服务器没有结果,它会返回二级域名服务器的地址。
· 客户端继续向下查询,直到最终获得所需的 IP 地址。
3) 反向 DNS 查询:
反向 DNS 查询是将主机的IP地址转换为对应的域名,以便网络(服务)程序能够通过IP地址查询到主机的域名。这种查询通常用于网络管理和安全性检查。反向查询的过程如下:
a. 将 IP 地址转换为反向格式。例如,IP 地址 192.0.2.1 转换为 1.2.0.192.in-addr.arpa。
b. 向 DNS 服务器发出查询请求,要求返回该 IP 地址对应的域名。
c. DNS 服务器返回相关的域名(如果存在)。
5.DNS和mDNS区别:
DNS(域名系统)和 mDNS(多播域名系统)都是用于域名解析的协议,但它们的工作方式和应用场景有所不同。以下是它们的主要区别:
特性 |
DNS |
mDNS |
工作方式 |
客户端-服务器模式,通过 DNS 服务器进行查询和解析。 |
多播(Multicast)查询,不依赖专用服务器。 |
应用场景 |
适用于广域网(互联网)中的域名解析。 |
适用于局域网(LAN)中的设备自动发现和名称解析。 |
查询方式 |
通过单播(Unicast)进行查询。 |
通过多播(Multicast)进行查询。 |
网络拓扑 |
依赖远程 DNS 服务器,适用于全球范围。 |
仅限局域网,适用于小规模网络。 |
端口号 |
53端口,支持 TCP 和 UDP 协议。 |
5353端口,使用 UDP 协议。 |
是否需要 DNS 服务器 |
需要专用的 DNS 服务器。 |
不需要专用服务器,设备之间自动发现。 |
举例说明:
—DNS协议:当在浏览器中输入 http://www.baidu.com 时,浏览器会通过 DNS 查询解析该域名并返回 IP 地址,然后进行连接;
—mDNS协议:当你连接到局域网时,你的设备可以自动通过 mDNS 查找并连接网络中的打印机、智能电视或其他设备,例如 printer.local 或 tv.local,而无需配置 DNS 服务器。
6.名解析和动态域名解析
1) 静态域名解析:像hosts文件那样,手动配置域名和IP地址的映射关系,服务器IP发生变化时,要及时的 手动修改映射关系,否则会访问失败;
2)动态域名解析:通过本地服务每隔数分钟检查一次服务器IP,如果变化就更新到DNS服务器上,维护域名与动态IP的映射关系。
实际场景中,两种方式会同时使用。
二、DNS协议格式
DNS 消息的格式有两种:查询消息(Query Message)和响应消息(Response Message)。这些消息的格式基本相同,主要区别在于消息的内容和解析方式。
1. DNS 消息格式
DNS 消息有 12 字节的固定头部(Header),后面跟着可变长度的问题部分(Question Section)和资源记录部分(Answer Section,Authority Section 和 Additional Section)。DNS 消息结构:
1) Header 部分(12 字节):
· ID (2 bytes): 请求/响应的标识符,客户端和服务器用于匹配请求和响应。
对于请求报文和其对应的应答报文,这个字段是相同的,通过它可以区分DNS应答报文是哪个请求的响应。用于划分DNS流(一个请求对应一个响应)
· Flags (2 bytes): 标志字段,包括查询/响应标志、是否授权等信息。
— QR(1bit)查询/响应标志,0为查询,1为响应
—opcode(4bit)0表示标准查询,1表示反向查询,2表示服务器状态请求
—AA(1bit)表示授权回答
—TC(1bit)表示可截断的
—RD(1bit)表示期望递归
—RA(1bit)表示可用递归
—rcode(4bit)表示返回码,0表示没有差错,3表示名字差错,2表示服务器错误(Server Failure)
· Questions (2 bytes): 问题部分的数量,表示后续包含多少个查询问题。
· Answer RRs (2 bytes): 回答部分的资源记录数量。
· Authority RRs (2 bytes): 授权区域的资源记录数量。
· Additional RRs (2 bytes): 附加部分的资源记录数量。
2) DNS查询部分(Question):可变长度
· Name (variable): 查询的域名,以标签(Label)形式存储,长度前缀的字符串,每个标签的长度与标签本身相结合,格式如下(如:http://dns.jocent.me)
· Type (2 bytes): 查询记录的类型(如 A、MX、CNAME 等)。
· Class (2 bytes): 查询记录的类别,通常为 IN(Internet)。
Class名称 |
对应值 |
描述 |
IN |
1 |
互联网中的标准 DNS 记录类 |
CH |
3 |
CHAOS 网络记录类,现已很少使用 |
HS |
4 |
Hesiod 目录服务协议记录类 |
ANY |
255 |
请求所有记录类型的查询 |
以下为抓包的DNS查询数据信息:
3) 资源记录RR区(Answer / Authority / Additional 部分):可变长度
这些部分包含查询的结果或附加信息,包括:
· Name: 响应的域名(通常是查询的域名),当报文中域名重复出现的时候,该字段使用2个字节的偏移指针来表示;
· Type: 资源记录类型,同查询类型;
· Class: 资源记录类别, 同查询类;
· TTL (4 bytes): 生存时间,单位是秒,表示该记录在缓存中存活的时间。
· Data length (2 bytes): 数据长度。
· RData (variable): 记录的具体数据,例如 IP 地址、CNAME、MX 服务器等。
以下为抓包的DNS回复数据信息:
2. 示例 DNS 响应消息:
1.Header ID = 0x1a2b Flags = 0x8180 ( Questions = 1 Answer RRs = 1 Authority RRs = 0 Additional RRs = 0 2.Question Section: Name = "www.example.com" Type = A (IPv4 Class = IN 3.Answer Section: Name = "www.example.com" Type = A (IPv4 Class = IN TTL = 3600 Data length = 4 RData = 192.0.2.1 (
3. mDNS(Multicast DNS)协议格式
mDNS 是 DNS 的扩展,它在局部网络内使用多播地址(224.0.0.251)和 UDP(端口 5353)进行域名解析。mDNS 主要用于零配置网络(如局域网内的设备发现),并不依赖于传统的 DNS 服务器,mDNS 的消息结构与标准 DNS 消息相同,只是在传输方式和一些细节上有所不同。
三、DNS协议交互流程
当我们在IE中输入 http://www.rongcloud.cn 后,会执行以下完整的解析过程:
1. 先查「浏览器缓存」,缓存中维护一张域名与 IP 地址的对应表,有就直接访问IP;
2. 没有就查「本地缓存」,一般是指操作系统自带的 DNS 缓存;
3. 若仍然没有命中,则操作系统将域名发送至「本地域名服务器」,本地域名服务器查询自己的 DNS 缓存,查找成功则返回结果(注意:主机和本地域名服务器之间的查询方式是「递归查询」);
4. 若本地域名服务器的 DNS 缓存没有命中,则本地域名服务器向上级域名服务器进行查询,通过以下方式进行「迭代查询」(注意:本地域名服务器和其他域名服务器之间的查询方式是迭代查询,防止根域名服务器压力过大):
1)首先本地域名服务器向「根域名服务器」发起请求,根域名服务器是最高层次的,它并不会直接指明这个域名对应的 IP 地址,而是返回顶级域名服务器的地址,也就是说给本地域名服务器指明一条道路,让他去这里寻找答案;
2)本地域名服务器拿到这个「顶级域名服务器」的地址后,就向其发起请求,获取「权限域名服务器」的地址;
3)本地域名服务器根据权限域名服务器的地址向其发起请求,最终得到该域名对应的 IP 地址;
5. 本地域名服务器将得到的 IP 地址返回给操作系统,同时自己将 IP 地址缓存起来国;
6. 操作系统将 IP 地址返回给浏览器,同时自己也将 IP 地址缓存起来;
7. 至此,浏览器就得到了域名对应的 IP 地址,然后「缓存」IP和域名的映射关系;
四、DNS协议使用方法
1. Linux系统下DNS 查询命令:
1) nslookup:这个命令可以查询域名的 IP 地址以及其他 DNS 记录(正反向查询均可)
命令 |
功能 |
nslookup http://example.com |
查询 http://example.com 的 A 记录(IP 地址) |
nslookup -query=MX http://example.com |
查询 http://example.com 的 MX 记录(邮件交换) |
nslookup -query=NS http://example.com |
查询 http://example.com 的 NS 记录(名称服务器) |
nslookup -query=TXT http://example.com |
查询 http://example.com 的 TXT 记录(文本记录) |
nslookup http://example.com 8.8.8.8 |
使用 Google 的 DNS 查询 http://example.com |
nslookup 93.184.216.34 |
查询 IP 地址 93.184.216.34 的反向 DNS 记录 |
2) dig:dig 是一个功能强大的 DNS 查询工具,可以提供详细的查询结果,包括查询时间、服务器信息等;
命令 |
功能 |
dig http://example.com |
查询 http://example.com 的 A 记录(IP 地址) |
dig http://example.com MX |
查询 http://example.com 的 MX 记录(邮件交换) |
dig http://example.com NS |
查询 http://example.com 的 NS 记录(名称服务器) |
dig http://example.com TXT |
查询 http://example.com 的 TXT 记录(文本记录) |
dig @8.8.8.8 http://example.com |
使用 Google 的 DNS 查询 http://example.com |
dig -x 93.184.216.34 |
查询 IP 地址 93.184.216.34 的反向 DNS |
dig +short http://example.com |
简化输出,只显示 http://example.com 的 IP 地址 |
dig +trace http://example.com |
追踪 DNS 查询的过程 |
dig +noall +answer http://example.com |
只显示答案部分 |
3)host:host 是一个简单的命令行工具,用于查询 DNS(域名系统)记录。它通常用于获取域名的 IP 地址或查询其他类型的 DNS 记录。相较于dig和 nslookup, host的语法更为简单,适合快速查询;
命令 |
功能 |
host http://example.com |
查询 http://example.com 的 A 记录(IP 地址) |
host -t MX http://example.com |
查询 http://example.com 的 MX 记录(邮件交换) |
host -t NS http://example.com |
查询 http://example.com 的 NS 记录(名称服务器) |
host -t TXT http://example.com |
查询 http://example.com 的 TXT 记录(文本记录) |
host -t AAAA http://example.com |
查询 http://example.com 的 AAAA 记录(IPv6 地址) |
host http://example.com 8.8.8.8 |
使用 Google 的 DNS 查询 http://example.com |
host -a http://example.com |
查询 http://example.com 的所有类型的记录 |
4) ping:ping 可以通过解析域名来间接查询 DNS,因为它会将域名转换为 IP 地址并尝试与该 IP 地址建立连接;
2. Linux 系统中DNS 配置方法:
1) /etc/resolv.conf:设置使用的DNS服务器地址;
这个文件用于配置 DNS 解析器的设置。你可以在这里指定 DNS 服务器的 IP 地址。文件的格式通常如下:
nameserver 8.8.8.8 Google 的公共 DNS 服务器
nameserver 114.114.114.114 中国互联网络信息中心(CNNIC)提供的公共 DNS 服务器
2) /etc/hosts:本机的DNS服务器配置文件。
这个文件用于本地静态名称解析,可以手动添加主机名和对应的 IP 地址。例如:192.168.1.10 myserver.local,这允许在没有 DNS 服务器的情况下解析特定的主机名。
3) /etc/dhcp/dhclient.conf(如果使用 DHCP):
如果系统通过 DHCP 获取网络配置,这个文件可以用来配置 DHCP 客户端的行为,包括 DNS 设置;
4)
/etc/systemd/resolved.conf(在使用 systemd 的系统中):
在使用 systemd 的 Linux 发行版中,resolved.conf 文件用于配置 DNS 解析设置。可以通过编辑此文件来指定 DNS 服务器和其他选项。
五、DNS攻击和防范
DNS 劫持、DNS 欺骗和 DDoS 攻击都对个人用户、企业和整个互联网基础设施造成严重的危害,其影响程度因攻击目标、攻击规模和攻击持续时间而异。攻击的目的大多都是为了利益的广告费和推广费。以下简单介绍这几种DNS攻击的原理、攻击方式和防范方法。
1.DNS劫持:
1)攻击原理:DNS 劫持是指攻击者通过篡改 DNS 解析过程,劫持用户的 DNS 请求,将其引导到恶意服务器或网站。DNS 劫持通常发生在用户发起 DNS 查询时,攻击者修改了用户访问的 DNS 服务器的解析记录,从而改变了网站的实际 IP 地址。
2) 攻击方式
a. 路由器 DNS 劫持:通过攻击或篡改家庭或企业网络中的路由器设置,修改默认的 DNS 服务器地址,将所有连接到该路由器的设备的 DNS 请求指向攻击者控制的 DNS 服务器。
b. ISP 劫持:互联网服务提供商(ISP)可以劫持用户的 DNS 请求,并通过返回恶意的 DNS 记录进行攻击
3) 防范方法
a. 使用可信的 DNS 服务器(如 Google DNS 或中国电信提供的DNS)。
b. 启用 DNS SEC(DNS 安全扩展)来确保 DNS 数据的完整性和真实性。
c. 定期检查 DNS 配置,并保持路由器固件更新。
2.DNS欺骗:
1) 攻击原理:
DNS 欺骗是指攻击者向目标 DNS 服务器发送伪造的 DNS 响应,从而改变域名解析的结果。攻击者通过伪造的 DNS 响应返回恶意 IP 地址,诱使目标用户连接到恶意网站.
2) 攻击方式:
a. Man-in-the-middle 攻击:攻击者通过监听网络流量,伪造 DNS 响应来篡改目标计算机的 DNS 查询。
b. DNS 服务器攻击:攻击者直接向 DNS 服务器发送伪造的 DNS 响应,污染 DNS 缓存(即 DNS 缓存投毒)
3) 防范方法:
a. 使用 DNSSEC(DNS 安全扩展)来防止 DNS 响应被篡改。
b. 配置 DNS 服务器进行更严格的缓存验证。
c. 使用 HTTPS 和 SSL/TLS 加密传输,避免中间人攻击。
3.DDos攻击:
1) 攻击原理:
DDoS(Distributed Denial of Service)攻击是指攻击者通过大量分布在不同位置的受控设备(通常是“僵尸网络”中的计算机)向目标服务器发起大量请求,导致目标服务器无法正常响应合法用户的请求,从而使目标服务器瘫痪或无法使用。
2) 攻击方式:
a. 流量消耗型攻击(例如 SYN Flood、UDP Flood):通过发送大量无效的数据包,占用网络带宽或计算资源,导致目标系统资源耗尽。
b. 应用层攻击(例如 HTTP Flood):通过向目标网站发送大量 HTTP 请求,消耗服务器的计算资源。
c. 反射攻击:攻击者伪造源 IP 地址,向开放的第三方服务器(如 DNS 服务器、NTP 服务器等)发送请求,这些服务器会将响应发送到受害者的 IP 地址,从而造成拒绝服务攻击。
3) 防范方法:
a. 流量清洗:使用流量清洗服务(如 Cloudflare、Akamai 等),能够在流量到达目标服务器之前过滤掉恶意请求。
b. 速率限制:对单个 IP 地址或用户发出的请求设置速率限制,减少单一用户的请求量。
c. 抗 DDoS 硬件和软件:部署防火墙和反 DDoS 设备,这些设备能够识别并过滤恶意流量。
d. 分布式防御:通过部署多个服务器和负载均衡,分散攻击流量。
六、代码示例
以下是一个简单的 C 语言示例,展示了如何使用 DNS 协议进行域名解析。这个示例使用了原始套接字(raw sockets)来发送 DNS 查询,并解析返回的响应。请注意,这个例子仅用于学习目的,实际使用中可能需要更复杂的错误处理和网络配置。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <unistd.h> #define DNS_PORT 53 #define DNS_HEADER_SIZE 12 // DNS header structure struct dns_header { unsigned short id; // Identifier unsigned char rd : 1; // Recursion Desired unsigned char tc : 1; // TrunCation unsigned char aa : 1; // Authoritative Answer unsigned char opcode : 4; // Opcode unsigned char qr : 1; // Query/Response unsigned char rcode : 4; // Response code unsigned char z : 1; // Reserved unsigned char ra : 1; // Recursion Available unsigned short q_count; // Number of questions unsigned short ans_count; // Number of answers unsigned short auth_count; // Number of authority records unsigned short add_count; // Number of additional records }; // DNS question structure struct dns_question { unsigned short qtype; // Query type unsigned short qclass; // Query class }; // Function to convert domain name to DNS format void format_domain_name(unsigned char *dn, const char *domain) { char *token; char *domain_copy = strdup(domain); int len = 0; token = strtok(domain_copy, "."); while (token != NULL) { len = strlen(token); *dn++ = len; // Length of the label strcpy((char *)dn, token); // Copy the label dn += len; token = strtok(NULL, "."); } *dn = 0; // End of the domain name free(domain_copy); } // Main function int main() { int sockfd; struct sockaddr_in server_addr; unsigned char buffer[512]; struct dns_header *dns = (struct dns_header *)buffer; struct dns_question *question = (struct dns_question *)(buffer + DNS_HEADER_SIZE); const char *domain = "Example Domain"; // Domain to query sockfd = socket(AF_INET, SOCK_DGRAM, 0); // Create UDP socket if (sockfd < 0) { perror("Socket creation failed"); return 1; } // Set up the server address structure server_addr.sin_family = AF_INET; server_addr.sin_port = htons(DNS_PORT); server_addr.sin_addr.s_addr = inet_addr("114.114.114.114"); // china’s DNS server // Fill in the DNS header dns->id = htons(12345); // Transaction ID dns->qr = 0; // Query dns->opcode = 0; // Standard query dns->aa = 0; // Not authoritative dns->tc = 0; // Not truncated dns->rd = 1; // Recursion desired dns->ra = 0; // Recursion not available dns->z = 0; // Reserved dns->rcode = 0; // No error dns->q_count = htons(1); // One question dns->ans_count = 0; // No answers yet dns->auth_count = 0; // No authority records dns->add_count = 0; // No additional records // Format the domain name format_domain_name(buffer + DNS_HEADER_SIZE + sizeof(struct dns_question), domain); // Set the query type and class question->qtype = htons(1); // A record question->qclass = htons(1); // IN class // Send the DNS query if (sendto(sockfd, buffer, DNS_HEADER_SIZE + sizeof(struct dns_question) + strlen(domain) + 2, 0, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) { perror("Send failed"); close(sockfd); return 1; } // Receive the DNS response socklen_t len = sizeof(server_addr); if (recvfrom(sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&server_addr, &len) < 0) { perror("Receive failed"); close(sockfd); return 1; } // Print the response printf("Received DNS response:\n"); for (int i = 0; i < len; i++) { printf("%02x ", buffer[i]); } printf("\n"); close(sockfd); return 0; }
代码说明:
1. 结构体定义:
1)dns_header:表示 DNS 响应的头部,包含标识符、标志、问题计数等信息。
2)dns_question:表示 DNS 查询的问题部分,包含查询类型和查询类。
2. 域名格式化函数:
format_domain_name:将域名转换为 DNS 协议所需的格式。
3. 主要功能:
1)创建 UDP 套接字。
2)填充 DNS 请求的头部和问题部分。
3)发送 DNS 查询请求到指定的 DNS 服务器(在此例中为中国电信 的 DNS 服务器 114.114.114.114)。
4) 接收 DNS 响应并打印响应的原始字节(可以进一步解析以提取 IP 地址等信息)。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/169417.html