DNS服务器测试

有关 DNS 协议的内容,可以看这篇文章

本文主要测试了 Cloudflare 1.1.1.1 国内知名 114.114.114.114 、 阿里 223.5.5.5 的 DNS 服务。

1. 单 DNS 报文查询多个域名信息

DNS 协议中有 Query Count 的信息,因此设计上 DNS 支持单报文查询多个域名信息,这样可以减少网络开销。但是观察 Wireshark 抓包发现,没有发现单报文查询多个域名信息的情况。

单 DNS 报文

因此下面测试一下单报文查询多个域名信息的情况。(代码附在文章后)

1.1. 发送报文内容

发送报文中查询了两个域名信息,分别是 www.baidu.comnacldragon.top

发送报文

1.2. 接收报文内容

1.2.1 Cloudflare 1.1.1.1

可以观察到,1.1.1.1 只返回了 www.baidu.com 的信息,没有返回 nacldragon.top 的信息。

接收报文

www.baidu.comnacldragon.top 调换位置,则只返回 nacldragon.top 的信息。

接收报文

1.2.2 114 114.114.114.114

将报文发送后,114.114.114.114 并没有返回任何信息,为每个域名单独查询时,则能正常的提供解析结果。

1.2.3 阿里 223.5.5.5

情况和 114 一样,将报文发送后,没有返回任何信息,为每个域名单独查询时,则能正常的提供解析结果。

2. 域名长度溢出

DNS 协议中,域名的长度是由一个字节来表示的,因此我们可以伪造一个域名长度溢出的报文,来测试 DNS 服务器的处理能力。

2.1. 发送报文内容

发送报文中查询了一个域名信息,域名最后本应是 0x00 ,但是被修改为了 0xff

2.2. 接收报文内容

三个 DNS 服务器都没有返回任何信息。

3. 代码

1. 单 DNS 报文查询多个域名信息代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package main

import (
"fmt"
"net"
"strings"
)

func getHeader() []byte {
TransactionID := []byte{0x2f, 0xcd}
Flags := []byte{0x01, 0x00}
QDCount := []byte{0x00, 0x02}
ANCount := []byte{0x00, 0x00}
NSCount := []byte{0x00, 0x00}
ARCount := []byte{0x00, 0x00}
return append(append(append(append(append(TransactionID, Flags...), QDCount...), ANCount...), NSCount...), ARCount...)
}

func getQuestionRR(domain string) []byte {
var res []byte
domainParts := strings.Split(domain, ".")
for _, part := range domainParts {
res = append(res, byte(len(part)))
res = append(res, []byte(part)...)
}
res = append(res, 0x00)
QType := []byte{0x00, 0x01}
QClass := []byte{0x00, 0x01}
res = append(res, QType...)
res = append(res, QClass...)
return res
}

func main() {
ip := "223.5.5.5"
//ip := "1.1.1.1"
//ip := "114.114.114.114"
port := 53

conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", ip, port))
if err != nil {
fmt.Println("net.Dial err:", err)
return
}

defer conn.Close()
var data []byte = append(getHeader(), getQuestionRR("www.baidu.com")...)
data = append(data, getQuestionRR("nacldragon.top")...)
_, err = conn.Write(data)

if err != nil {
fmt.Println("conn.Write err:", err)
return
}

buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}

fmt.Println("response:", buf[:n])

}

2. 域名长度溢出代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package main

import (
"fmt"
"net"
"strings"
)

func getHeader() []byte {
TransactionID := []byte{0x2f, 0xcd}
Flags := []byte{0x01, 0x00}
QDCount := []byte{0x00, 0x01}
ANCount := []byte{0x00, 0x00}
NSCount := []byte{0x00, 0x00}
ARCount := []byte{0x00, 0x00}
return append(append(append(append(append(TransactionID, Flags...), QDCount...), ANCount...), NSCount...), ARCount...)
}

func getQuestionRR(domain string) []byte {
var res []byte
domainParts := strings.Split(domain, ".")
for _, part := range domainParts {
res = append(res, byte(len(part)))
res = append(res, []byte(part)...)
}
res = append(res, 0xff)
QType := []byte{0x00, 0x01}
QClass := []byte{0x00, 0x01}
res = append(res, QType...)
res = append(res, QClass...)
return res
}

func main() {
//ip := "223.5.5.5"
//ip := "1.1.1.1"
ip := "114.114.114.114"
port := 53

conn, err := net.Dial("udp", fmt.Sprintf("%s:%d", ip, port))
if err != nil {
fmt.Println("net.Dial err:", err)
return
}

defer conn.Close()
var data []byte = append(getHeader(), getQuestionRR("www.baidu.com")...)
//data = append(data, getQuestionRR("nacldragon.top")...)
_, err = conn.Write(data)

if err != nil {
fmt.Println("conn.Write err:", err)
return
}

buf := make([]byte, 1024)
n, err := conn.Read(buf)
if err != nil {
fmt.Println("conn.Read err:", err)
return
}

fmt.Println("response:", buf[:n])

}

DNS服务器测试
https://nacldragon.top/2024/DNS-Test/
作者
NaCl
发布于
2024年3月15日
许可协议