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…
溜了! 溜了!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END