SampleDNSTool

package module
v0.0.0-...-39ae10d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 12, 2022 License: MIT Imports: 4 Imported by: 1

README

SampleDNSTool

DNS 协议golang实现,目前已经实现简单的A/CNAME记录,具体案例参照: https://gitee.com/pdudo/SampleDNS2

从三个方面描述该工具

  • 构建请求报文
  • 解析响应报文
  • 利用该工具快速搭建DNS服务器
1. 利用SampleDNSTool快速构建请求报文

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

构建 【查询 www.baidu.comA记录 报文】

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)
}
2. 利用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

3. 利用SampleDNSTool编写简易DNS服务器

仅解析A记录 SampleDNS3

Documentation

Index

Constants

View Source
const (
	Type_A     uint16 = 1
	Type_CNAME uint16 = 5
)

Variables

This section is empty.

Functions

func GererateDNSNames

func GererateDNSNames(name string) []byte

生成 报文式的 域名

func GererateDNSNamesIP

func GererateDNSNamesIP(ips string) []byte

生成 报文 IP

func GererateDNSNamesLen

func GererateDNSNamesLen(name string) uint16

生成 报文式域名 的长度

func GererateDNSNamesString

func GererateDNSNamesString(buf []byte) string

根据报文式的 域名 获取 string式的域名

func GetOffsetNames

func GetOffsetNames(buf []byte, _id int) (string, int)

获取具有偏移量的域名

Types

type Answers

type Answers struct {
	NAME        string // NAME // 暂时不考虑用标志位来实现响应报文
	TYPE        uint16 // TYPE
	CLASS       uint16 // CLASS
	TTL         uint32 // TTL
	RDLENGTH    uint16 // RELENGTH
	RDATA       []byte // RDATA
	RDATAString string // RDATA String
}

Resource record

type DNSHeader

type DNSHeader struct {
	ID           uint16     // ID
	HeaderStatus HeaderInfo // QR QPCODE AA TC RD RA Z RCODE
	QCOUNT       uint16     //QCOUNT
	ANCOUNT      uint16     //ANCOUNT
	NSCOUNT      uint16     // NSCOUNT
	ARCOUNT      uint16     // ARCOUNT
}

Header

type DNSInfo

type DNSInfo struct {
	Header     DNSHeader
	QueryInfo  Queries
	QueryStep  QueriesStep
	AnswerInfo Answers
}

func (*DNSInfo) GenerateAnswer

func (dnsInfo *DNSInfo) GenerateAnswer() []byte

生成 响应 报文

func (*DNSInfo) GenerateHeaders

func (dnsInfo *DNSInfo) GenerateHeaders() []byte

生成 Header 报文

func (*DNSInfo) GenerateQuestion

func (dnsInfo *DNSInfo) GenerateQuestion() []byte

生成 Query 查询报文

func (*DNSInfo) GetAnswerInfo

func (dnsInfo *DNSInfo) GetAnswerInfo(buf []byte) []Answers

获取 响应 报文数据

							   1  1  1  1  1  1
 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / / / NAME / | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | CLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | TTL | | | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | RDLENGTH | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--| / RDATA / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

func (*DNSInfo) GetHeader

func (dnsInfo *DNSInfo) GetHeader(buf []byte)

获取 Header Header 协议 12 byte

							   1  1  1  1  1  1
 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ID | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |QR| Opcode |AA|TC|RD|RA| Z | RCODE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QDCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ANCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | NSCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | ARCOUNT | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

func (*DNSInfo) GetQuestion

func (dnsInfo *DNSInfo) GetQuestion(buf []byte)

获取 Query 查询报文

							   1  1  1  1  1  1
 0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | | / QNAME / / / +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QTYPE | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | QCLASS | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

type HeaderInfo

type HeaderInfo struct {
	QR     uint8 // 1 bit
	Opcode uint8 // 4 bit
	AA     uint8 // 1bit
	TC     uint8 // 1 bit
	RD     uint8 // 1 bit
	RA     uint8 // 1 bit
	Z      uint8 // 3 bit
	RCODE  uint8 // 4bit
}

Header Status

type Queries

type Queries struct {
	QNAME       []byte //QNAME
	QNAMEString string //QNAMEString
	QTYPE       uint16 //QTYPE
	QCLASS      uint16 //QClass
}

Question

type QueriesStep

type QueriesStep struct {
	QueryStart       int // headEnd Question start
	QueriesEnd       int //Question end
	QueriesDomainEnd int // QNAME end
}

Question step

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL