此处实现的是功能局限的 DNS 中继服务器,本地解析仅限于将域名解析为 IPv4 地址。
git clone git@github.com:Gh-Shinku/BUPT-NetworkDesign.git
mkdir build && cd build
cmake ..
make
需要注意的是,当前在main.c中,并未将监听端口设置为 53,实际测试时需要进行修改。
DNS response 的报文格式,相较于 request 仅仅添加了 Answers 段
QR需从 query(0) 修改成 response(1)OPCODE不用改,还是0AA设置成0,表示 not authorityTC不用改,设置成0表示没有没截断RD不用改RA不用改Z不用改,保留段RCODE改为5,表示因政策原因拒绝请求
改成1,只有一个 Answer
NAME指针格式指向 query 中的domainTYPE本项目设置成 1,将域名解析为 IPv4 地址CLASS本项目设置成 0x0001,表示网络地址TTL时延RDLENGTHRDATA段的长度RDATAresponse的内容,取决于TYPE,在本项目中是4个字节的 IPv4 地址
dns_table 是一个g_hash_table,key 是char *,value 是GArray *
value 是存储char *的动态数组
目前来看,response中的answer(struct DnsMessageAnswer类型)中的
address成员是uint32_t,因此,在插入dns_table之前,需要做一次转换
需要重新实现线程池和哈希表,还需要加入对IPv6的支持,TTL延时的处理,LRU 缓存策略
使用 dnsperf 进行压测:
[Version 1 use glib and third thread pool]
Statistics:
Queries sent: 2997056
Queries completed: 2997051 (100.00%)
Queries lost: 5 (0.00%)
Response codes: NOERROR 2457621 (82.00%), SERVFAIL 30 (0.00%), NXDOMAIN 3 (0.00%), REFUSED 539397 (18.00%)
Average packet size: request 33, response 59
Run time (s): 60.002875
Queries per second: 49948.456636
Average Latency (s): 0.001973 (min 0.000032, max 4.105776)
Latency StdDev (s): 0.015811
[Version 2 self implemente except thread pool]
dnsperf -s localhost -d testdata.txt -l 60 -p 4090
DNS Performance Testing Tool
Version 2.9.0
[Status] Command line: dnsperf -s localhost -d testdata.txt -l 60 -p 4090
[Status] Sending queries (to 127.0.0.1:4090)
[Status] Started at: Fri May 2 19:05:04 2025
[Status] Stopping after 60.000000 seconds
[Status] Testing complete (time limit)
Statistics:
Queries sent: 1935031
Queries completed: 1935031 (100.00%)
Queries lost: 0 (0.00%)
Response codes: NOERROR 1935031 (100.00%)
Average packet size: request 33, response 38
Run time (s): 60.002351
Queries per second: 32249.253033
Average Latency (s): 0.003074 (min 0.000233, max 2.112497)
Latency StdDev (s): 0.021553
[Version 3 self implemented totally]
DNS Performance Testing Tool
Version 2.9.0
[Status] Command line: dnsperf -s localhost -d testdata.txt -l 60 -p 4090
[Status] Sending queries (to 127.0.0.1:4090)
[Status] Started at: Sun May 4 22:33:08 2025
[Status] Stopping after 60.000000 seconds
[Status] Testing complete (time limit)
Statistics:
Queries sent: 3707137
Queries completed: 3707137 (100.00%)
Queries lost: 0 (0.00%)
Response codes: NOERROR 3707137 (100.00%)
Average packet size: request 33, response 35
Run time (s): 60.001023
Queries per second: 61784.563240
Average Latency (s): 0.001585 (min 0.000174, max 2.880180)
Latency StdDev (s): 0.014155
简要说明一下DNS中继服务器当前畸形设计的缘由。
DNS 请求有多种类型,正确的缓存做法应当是将"domain + TYPE"作为缓存的key。但由于我初期编写代码时没有把握这一点,导致所有的键都仅仅是 domain。举个例子,在这种情况下,如果缓存了 IPv4 的记录,但是客户端下次请求 IPv6,而服务器认为缓存命中就直接返回 IPv4,导致出现问题。
若要修改这点,项目要改动的地方过多,于是我生硬了地切割了除 IPv4 外所有其他类型的 DNS 请求的缓存。
以后也许会填上这个坑(