使用 SampleDNSTool 快速构建 DNS 服务器

SampleDNSTool 是DNS协议golang实现,目前已经实现简单的A/CNAME记录

地址: gitee.com/pdudo/Sampl…

作为运维小白,自己学习DNS相关协议很久了,总觉得差了点什么,后面自己想写一个简单的DNS服务器出来,所以编写了该工具,写个博客记录一下,因为 SampleDNSTool 支持CNAME了。

利用 SampleDNSTool 构建请求报文

仅需要调用GenerateHeadersGenerateQuestion便可以构建相应报文

构建 【查询 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…

溜了! 溜了!

猜你喜欢

转载自juejin.im/post/7074236978237014053