百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

「GCTT 出品」使用 Golang 构建 DNS 服务器

toyiye 2024-06-24 19:11 23 浏览 0 评论

需求:对 DNS 查询进行转发和缓存的本地 DNS 服务器。

补充 1:提供一个记录管理的接口(HTTP handler)。

补充 2:提供一个名字(name)。

DNS 服务器的相关要点如下:

  • DNS 服务器把域名转换为 IP。
  • DNS 主要使用 UDP 协议,其端口为 53。
  • DNS 消息的长度最多为 512 字节,若超过这个长度,则必须使用 EDNS。

需要的组成部分有:

  • UDP
  • DNS 消息解析器(DNS message parser)
  • 转发
  • 缓存
  • HTTP handler

我们的解决方案是:

  • UDP:标准包 net 支持 UDP。
  • DNS 消息解析器:需要一些工作,来根据特定协议(UDP)的通信,处理报文。为了更快地实现,我们使用 golang.org/x/net/dns/dnsmessage。
  • 转发:实现方式有很多,我们使用了 Cloudflare 公共解析器(Cloudflare public resolver):1.1.1.1。
  • 缓存:持久性存储。为了持久化写入数据,我们使用标准包 gob 来编码数据。
  • HTTP handler:应该能够添加、查询、更新和删除 DNS 记录。不需要使用配置文件。

开启 UDP socket,监听 53 端口,可以接收 DNS 查询。需要注意的是,UDP 只需要一个 socket 来处理多条“连接”,而 TCP 对于每条连接都需要一个 socket。因此,我们在程序中,会重复使用 conn。

conn, _ = net.ListenUDP("udp", &net.UDPAddr{Port: 53})

defer conn.Close()

for {

buf := make([]byte, 512)

_, addr, _ := conn.ReadFromUDP(buf)

...

}

解析报文,检查是否是 DNS 消息。

var m dnsmessage.Message

err = m.Unpack(buf)

如果你想知道一条 DNS 消息长什么样,请查看下图:

转发消息到公共解析器

// re-pack
packed, err = m.Pack()
resolver := net.UDPAddr{IP: net.IP{1, 1, 1, 1}, Port: 53}
_, err = conn.WriteToUDP(packed, &resolver)

公共解析器会返回一条 anwser,我们会抓取信息,返回给客户端。

if m.Header.Response {

packed, err = m.Pack()

_, err = conn.WriteToUDP(packed, &addr)

}

当然并发使用 conn 很安全,所以 WriteToUDP 应该在 Go 协程中运行。

存储 answer

我们会使用 map,简单采用“ question-anwser ”的键值对,这会让查询变得很容易。同样不要忘了 RWMutex,对于并发操作,map 使用起来并不安全。需要提醒的是,从理论上讲,在一次 DNS 查询中,可能会有多个 question,但是大多数 DNS 服务器,都只会接收一条 question。

func questionToString(q dnsmessage.Question) string {

...

}

type store struct {

sync.RWMutex

data map[string][]dnsmessage.Resource

}

q := m.Questions[0]

var s store

s.Lock()

s.data[questionToString(q)] = m.Answers

s.Unlock()

持久化缓存(persistent cache)

我们需要把 s.data 写入到文件中,以便以后重新获取它。我们使用了标准包 gob,而无需自定义解析。

f, err := os.Create(filepath.Join("path", "file"))
enc := Gob.NewEncoder(f)
err = enc.Encode(s.data)

需要注意,gob 在编码前需要知道数据类型。

func INIt() {

Gob.Register(&dnsmessage.AResource{})

...

}

记录管理

这个相对来说就比较简单了,Create handler 如下所示:

type request struct {
 Host string
 TTL uint32
 Type string
 Data string
}
func toResource(req request) (dnsmessage.Resource, error) {
 ...
}
// POST handler
err = JSON.NewDecoder(r.Body).Decode(&req)
// transform req to a dnsmessage.Resource
r, err := toResource(req)
// write r to the store

理所当然是吧?

完整的代码在这里。我将其命名为 rind(REST interface name domain)。

以上就是用 Go 实现这个网络程序的简述。

欢迎任何反馈。编程愉快,Gopher !


via: https://medium.com/@owlwalks/build-a-dns-server-in-golang-fec346c42889

作者:Khoa Pham 译者:Noluye 校对:polaris1119

本文由 GCTT 原创编译,Go语言中文网 荣誉推出

  • 本文由 GCTT 原创翻译,Go语言中文网 首发。也想加入译者行列,为开源做一些自己的贡献么?欢迎加入 GCTT!
  • 翻译工作和译文发表仅用于学习和交流目的,翻译工作遵照 CC-BY-NC-SA 协议规定,如果我们的工作有侵犯到您的权益,请及时联系我们。
  • 欢迎遵照 CC-BY-NC-SA 协议规定 转载,敬请在正文中标注并保留原文/译文链接和作者/译者等信息。
  • 文章仅代表作者的知识和看法,如有不同观点,请楼下排队吐槽

入群交流(该群和以上内容无关):Go中文网

QQ交流群:731990104

加微信入微信群:274768166 备注:头条

加入微信公众号:Go语言中文

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码