SampleDNSTool 是DNS协议golang实现,目前已经实现简单的A/CNAME记录
作为运维小白,自己学习DNS相关协议很久了,总觉得差了点什么,后面自己想写一个简单的DNS服务器出来,所以编写了该工具,写个博客记录一下,因为 SampleDNSTool 支持CNAME了。
利用 SampleDNSTool 构建请求报文
仅需要调用GenerateHeaders
和GenerateQuestion
便可以构建相应报文
构建 【查询 www.baidu.com
的 A
记录 报文】
package main import ( "fmt" "time" "gitee.com/pdudo/SampleDNSTool" ) func main() { // 定义DnsInfo信息 var dnsInfo SampleDNSTool.DNSInfo // 构建请求报文: 请求头 和 请求 报文 // heade部分 dnsInfo.Header.ID = uint16(time.Now().Unix()) // Qcount: 报文中携带的 问题条蜜 dnsInfo.Header.QCOUNT = 1 // question部分 // 定义查询的 QNAME dnsInfo.QueryInfo.QNAMEString = "www.baidu.com" // 定义 QType 和 QClass dnsInfo.QueryInfo.QTYPE = 1 dnsInfo.QueryInfo.QCLASS = 1 // 分别生成 Header 和 question 报文 header := dnsInfo.GenerateHeaders() requests := dnsInfo.GenerateQuestion() // 组装报文 var requestBuf []byte requestBuf = append(requestBuf, header...) requestBuf = append(requestBuf,requests...) fmt.Println("请求报文: " , requestBuf) }
利用SampleDNSTool获取响应报文
将【1】中报文请求发送至 DNS 服务器,获取其 响应报文信息
package main import ( "fmt" "log" "net" "strconv" "time" "gitee.com/pdudo/SampleDNSTool" ) func main() { // 定义DnsInfo信息 var dnsInfo SampleDNSTool.DNSInfo // 构建请求报文: 请求头 和 请求 报文 // heade部分 dnsInfo.Header.ID = uint16(time.Now().Unix()) // Qcount: 报文中携带的 问题条蜜 dnsInfo.Header.QCOUNT = 1 // question部分 // 定义查询的 QNAME dnsInfo.QueryInfo.QNAMEString = "www.baidu.com" // 定义 QType 和 QClass dnsInfo.QueryInfo.QTYPE = 1 dnsInfo.QueryInfo.QCLASS = 1 // 分别生成 Header 和 question 报文 header := dnsInfo.GenerateHeaders() requests := dnsInfo.GenerateQuestion() // 组装报文 var requestBuf []byte requestBuf = append(requestBuf, header...) requestBuf = append(requestBuf,requests...) fmt.Printf("查询域名: %s \t" , dnsInfo.QueryInfo.QNAMEString) switch dnsInfo.QueryInfo.QTYPE { case 1: fmt.Printf("查询类型: A记录 \n\n") } // 发送上诉报文 udpConn , err := net.DialUDP("udp",nil,&net.UDPAddr{ IP: net.IP{114,114,114,114}, Port: 53, }) if err != nil { log.Panic("net dial udp error " , err) } // 发送报文 udpConn.Write(requestBuf) // 等待DNS服务器回应 buf := make([]byte,1024) n, err := udpConn.Read(buf) if err != nil { log.Println("udp conn read error " , err) } // 解析响应报文 answer := dnsInfo.GetAnswerInfo(buf[:n]) // 打印解析后报文值 fmt.Println("查询结果: ") for _,v := range answer { fmt.Printf("请求域名: %s \t" , v.NAME) switch v.TYPE { case 1: fmt.Printf("请求类型: A记录 \t" ) case 5: fmt.Printf("请求类型: CNAME记录 \t") } switch v.TYPE { case 1: var ipString string for i:=0;i<len(v.RDATA)-1;i++ { ipString += strconv.Itoa(int(uint8(v.RDATA[i]))) + "." } ipString += strconv.Itoa(int(uint8(v.RDATA[len(v.RDATA)-1]))) fmt.Printf("结果值: %s \t" , ipString) case 5: fmt.Printf("结果值: %s \t" , v.RDATAString) } fmt.Println() } }
执行结果
查询域名: www.baidu.com 查询类型: A记录 查询结果: 请求域名: www.baidu.com 请求类型: CNAME记录 结果值: www.a.shifen.com. 请求域名: www.a.shifen.com 请求类型: A记录 结果值: 14.215.177.39 请求域名: www.a.shifen.com 请求类型: A记录 结果值: 14.215.177.38
怎么样,通过上述2个例子,是不是发现,构建DNS协议怎么会如此得心应手呢,可以尝试一下利用该工具半个小时编写一个返回A记录的DNS服务器吧
代码放在了gitee: gitee.com/pdudo/Sampl…
溜了! 溜了!