通过UDP发送DNS协议报文取得域名对应的IP地址

通过UDP发送DNS协议报文取得域名对应的IP地址:源地址

DNS数据包格式及内容详解:原地址

只要向网关或都域名服务器的53端口发送一个DNS查询报文,就可以收到服务器响应的报文,解析这个报文就可以得到域名对应的IP地址。

 

DNS查询包的编码:(以www.baidu.com为例)

 

3E 3A //为标识字段
01 00 //为标志字段,该字段设置了TC表示该报文是可截断的
00 01 //查询报文数量为1
00 00 00 00 00 00 //表示回答,授权和额外信息都为0
03 77 77 77 05 62 61 69 64 75 03 63 6F 6D 00 //表示查询的名字为www.baidu.com
00 01 //为类型,1表示A查询
00 01 //为类型,1表示Internet数据

 

DNS响应包:(以www.baidu.com为例)


3E 3A //为标识字段
81 80 //为标志字段,其中设置了QR = 1,RD = 1,RA = 1
00 01 //问题数1
00 03 //回答数3
00 00 00 00
03 77 77 77 05 62 61 69 64 75 03 63 6F 6D 00 //表示查询的名字为www.baidu.com
00 01 //为类型,1表示A查询
00 01 //为类型,1表示Internet数据
C0 0C //为域名指针
00 05 //表示CNAME(规范名称)
00 01 //为类型,1表示Internet数据
00 00 03 4B //生存时间
00 0F //数据长度
03 77 77 77 01 61 06 73 68 69 66 65 6E C0 16
C0 2B 00 01 00 01 00 00 00 63
00 04 //IP v4
79 0E 59 0A //IP1
C0 2B 00 01 00 01 00 00 00 63
00 04 //IP v4
79 0E 58 4C //IP2

 

简单点的话就是回复包的最后四字节就是域名对应的一个IP,稍微有点注意的是查询包里的域名的编码。
域名的编码格式:以'.'把域名分成多个标示符序列,每个序列的首字节说明该标示符的长度,最后以0结束。
www.baidu.com 对应 03 77 77 77 05 62 61 69 64 75 03 63 6F 6D 00
www  03 77 77 77
baidu  05 62 61 69 64 75
com  03 63 6F 6D

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当构造 DNS 查询报文和解析 DNS 响应报文时,可以将相关的功能封装为两个单独的函数。下面是一个示例代码,其中 `construct_dns_query` 函数用于构造 DNS 查询报文,`parse_dns_response` 函数用于解析 DNS 响应报文,并打印出目标地址的 IP 地址: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #define DNS_SERVER "8.8.8.8" // 目标 DNS 服务器地址 #define DNS_PORT 53 // DNS 服务器端口 // 构造 DNS 查询报文 void construct_dns_query(char* query, const char* domain) { // ... 在这里添加构造 DNS 查询报文的代码 ... } // 解析 DNS 响应报文,打印目标地址的 IP 地址 void parse_dns_response(const char* response) { // ... 在这里添加解析 DNS 响应报文并打印 IP 地址的代码 ... } int main() { // 创建 UDP socket int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock < 0) { perror("Socket creation failed"); return 1; } // 设置目标 DNS 服务器地址 struct sockaddr_in server_addr; memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(DNS_PORT); if (inet_pton(AF_INET, DNS_SERVER, &(server_addr.sin_addr)) <= 0) { perror("Invalid server address"); return 1; } // 发送 DNS 查询请求 const char* domain = "www.example.com"; // 要解析的域名 char query[1024]; memset(query, 0, sizeof(query)); // 构造 DNS 查询报文 construct_dns_query(query, domain); // 发送查询报文到目标 DNS 服务器 if (sendto(sock, query, sizeof(query), 0, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0) { perror("Failed to send query"); return 1; } // 接收 DNS 响应报文 char response[1024]; memset(response, 0, sizeof(response)); // ... 在这里添加接收 DNS 响应报文的代码 ... // 解析 DNS 响应报文并打印 IP 地址 parse_dns_response(response); // 关闭 socket close(sock); return 0; } ``` 在上述代码中,`construct_dns_query` 函数用于构造 DNS 查询报文,接收一个 `query` 字符串和要解析的域名作为参数,在函数内部实现构造报文的逻辑。 `parse_dns_response` 函数用于解析 DNS 响应报文,接收一个 `response` 字符串作为参数,在函数内部实现解析报文并打印 IP 地址的逻辑。 你可以根据具体的 DNS 协议规范实现构造和解析报文的逻辑。在解析报文时,你可以使用相应的数据结构和算法来解析报文中的信息,并提取出目标地址的 IP 地址进行打印。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值