加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Golang实现发送DNS请求

发布时间:2020-12-16 18:54:48 所属栏目:大数据 来源:网络整理
导读:关于DNS协议的具体内容可以查看RFC1035,如果英语不太好我推荐下面这个人的译文: http://www.jb51.cc/article/p-xeasbmxg-qx.html翻译的足够详尽了。 那么来看下Go的实现 : package mainimport ("bytes""encoding/binary""fmt""net""strings")type DNSHead

关于DNS协议的具体内容可以查看RFC1035,如果英语不太好我推荐下面这个人的译文:

http://www.52php.cn/article/p-xeasbmxg-qx.html翻译的足够详尽了。



那么来看下Go的实现

package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"net"
	"strings"
)

type DNSHeader struct {
	ID            uint16
	Flag          uint16
	QuestionCount uint16
	AnswerRRs     uint16 //RRs is Resource Records
	AuthorityRRs  uint16
	AdditionalRRs uint16
}

func (header *DNSHeader) SetFlag(QR uint16,OperationCode uint16,AuthoritativeAnswer uint16,Truncation uint16,RecursionDesired uint16,RecursionAvailable uint16,ResponseCode uint16) {
	header.Flag = QR<<15 + OperationCode<<11 + AuthoritativeAnswer<<10 + Truncation<<9 + RecursionDesired<<8 + RecursionAvailable<<7 + ResponseCode
}

type DNSQuery struct {
	QuestionType  uint16
	QuestionClass uint16
}

func ParseDomainName(domain string) []byte {
	//要将域名解析成相应的格式,例如:
	//"www.google.com"会被解析成"0x03www0x06google0x03com0x00"
	//就是长度+内容,长度+内容……最后以0x00结尾
	var (
		buffer   bytes.Buffer
		segments []string = strings.Split(domain,".")
	)
	for _,seg := range segments {
		binary.Write(&buffer,binary.BigEndian,byte(len(seg)))
		binary.Write(&buffer,[]byte(seg))
	}
	binary.Write(&buffer,byte(0x00))

	return buffer.Bytes()
}

func main() {
	var (
		dns_header   DNSHeader
		dns_question DNSQuery
	)

	//填充dns首部
	dns_header.ID = 0xFFFF
	dns_header.SetFlag(0,1,0)
	dns_header.QuestionCount = 1
	dns_header.AnswerRRs = 0
	dns_header.AuthorityRRs = 0
	dns_header.AdditionalRRs = 0

	//填充dns查询首部
	dns_question.QuestionType = 1  //IPv4
	dns_question.QuestionClass = 1  

	var (
		conn net.Conn
		err  error

		buffer bytes.Buffer
	)

	//DNS服务器的端口一般是53,IP你自己ipconfig查一下
	//别忘了DNS是基于UDP协议的
	if conn,err = net.Dial("udp","211.137.191.26:53"); err != nil {
		fmt.Println(err.Error())
		return
	}
	defer conn.Close()

	//buffer中是我们要发送的数据,里面的内容是DNS首部+查询内容+DNS查询首部
	binary.Write(&buffer,dns_header)
	binary.Write(&buffer,ParseDomainName("www.baidu.com"))
	binary.Write(&buffer,dns_question)
	fmt.Println(buffer.Bytes())

	if _,err := conn.Write(buffer.Bytes()); err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Println("send success.")
}



用Wireshark来检查一下是否正确(截一张太长了不方便看,所以截成了两段):




看看我们构造的DNS请求数据包:





如果转载请注明出处:http://blog.csdn.net/gophers/article/details/22942457

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读