Skip to content

Commit

Permalink
[1.2.0更新] 重写文档及README,修复Responser错误。
Browse files Browse the repository at this point in the history
  • Loading branch information
TochusC committed Nov 9, 2024
1 parent 4e13c1b commit 2ef016e
Show file tree
Hide file tree
Showing 7 changed files with 511 additions and 200 deletions.
170 changes: 117 additions & 53 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,106 +12,170 @@ GoDNS 是一个快速、灵活的**实验用** DNS 服务器,旨在帮助开

## 目录

- [概述](#概述)
- [GoDNSServer](#godnsserver)
- [示例](#示例)
- [构造和生成 DNS 回复](#构造和生成-dns-回复)
- [dns 包](#dns-包)
- [xlayers 子包](#xlayers-子包)
- [xperi 子包](#xperi-子包)

## 概述
## GoDNSServer

GoDNSServer 由三部分组成
`GoDNSServer` 是对 DNS 服务器的最顶层封装, 其由三部分组成

1. **ServerConfig**: DNS 服务器的配置
2. **Netterr**: 网络处理器,用于监听数据包,发送DNS回复
3. **Responser**: 数据包处理器,负责处理 DNS 请求并生成响应。
1. **ServerConfig**: DNS 服务器配置
2. **Netter**: 数据包处理器:接收、解析、发送数据包,并维护连接状态
3. **Responser**: DNS回复器:响应、解析、构造DNS回复

## GoDNSServer
```go
type GoDNSServer struct {
ServerConfig DNSServerConfig
Netter Netter
Responer Responser
}

// GoDNSServer 启动!
func (s *GoDNSServer) Start()
```

### Netter

*`Netter` 数据包监听器:接收、解析、发送数据包,并维护连接状态。*

```go
type Netter struct { // size=16 (0x10)
Config NetterConfig
}

`GoDNSServer` 是对 DNS 服务器的最顶层封装,提供了灵活的接口和功能。
// Send 函数用于发送数据包
func (n *Netter) Send(connInfo ConnectionInfo, data []byte)

### Sniffer
// Sniff 函数用于监听指定端口,并返回链接信息通道
func (n *Netter) Sniff() chan ConnectionInfo

`Netter` 用于监听指定的协议和端口,嗅探 DNS 请求。
// handleListener 函数用于处理 TCP 链接
func (n *Netter) handleListener(lstr net.Listener, connChan chan
ConnectionInfo)

### Handler
// handlePktConn 函数用于处理 数据包 链接
func (n *Netter) handlePktConn(pktConn net.PacketConn, connChan chan
ConnectionInfo)

`Handler` 负责处理 DNS 请求并生成回复,内部包含以下四部分:
// handleStreamConn 函数用于处理 流式链接
func (n *Netter) handleStreamConn(conn net.Conn, connChan chan ConnectionInfo)
```
### Responser

- **Parser**: 解析 DNS 请求。
- **Responser**: 生成 DNS 回复。
- **Sender**: 发送 DNS 回复。
- **DNSServerConfig**: 记录 DNS 服务器的配置。
*`Responser` DNS回复器:响应、解析、构造DNS回复。*

`Responser`是一个接口。 实现该接口的结构体将根据 DNS 查询信息生成 DNS 回复信息。
```go
type Responser interface { // size=16 (0x10)
// Response 根据 DNS 查询信息生成 DNS 回复信息。
// 其参数为:
// - qInfo QueryInfo,DNS 查询信息
// 返回值为:
// - ResponseInfo,DNS 回复信息
// - error,错误信息
Response(ConnectionInfo) (dns.DNSMessage, error)
}

```

## 示例

通过下述几行代码,可以一键启动一个基础的 GoDNS 服务器:

```go
// 创建一个 DNS 服务器
server := &GoDNSServer{
ServerConfig: serverConf,
Sniffer: []*Sniffer{
NewSniffer(SnifferConfig{
Device: serverConf.NetworkDevice,
Port: serverConf.Port,
PktMax: 65535,
Protocol: ProtocolUDP,
}),
server := godns.GoDNSServer{
ServerConfig: sConf,
Netter: godns.Netter{
Config: godns.NetterConfig{
Port: sConf.Port,
MTU: sConf.MTU,
},
},
Responer: &DullResponser{
ServerConf: sConf,
},
Handler: NewHandler(serverConf, &DullResponser{}),
}
server.Start()
```

## 构造和生成 DNS 回复

`Handler` 用于响应、处理 DNS 请求并回复。实现 `Responser` 接口,可以自定义 DNS 回复的生成方式。
通过实现 `Responser` 接口,可以自定义 DNS 回复的生成方式。

`responser.go` 文件中提供了若干的 `Responser` 实现示例,以供参考。
`responser.go` 文件中提供了若干的 `Responser` 实现示例及许多辅助函数,以供参考。

## dns 包

`dns` 包使用 Go 的内置函数提供对 DNS 消息的编解码实现
`dns` 包使用Go的内置实现,提供了 DNS消息 的编解码功能,可以用于任意构造和解析 DNS消息

### DNSMessage
`DNSMessage`表示 DNS协议 的消息结构。
```go
type DNSMessage struct {
// DNS消息头部
Header DNSHeader // DNS 头部(Header)
// DNS消息的各个部分(Section)
Question DNSQuestionSection // DNS 查询部分(Questions Section)
Answer DNSResponseSection // DNS 回答部分(Answers Section)
Authority DNSResponseSection // DNS 权威部分(Authority Section)
Additional DNSResponseSection // DNS 附加部分(Additional Section)
}
```

`DNSMessage` 结构表示 DNS 协议的消息,包括:
`dns`包中的每个结构体基本都实现了以下方法:
```go
// 从缓冲区中自解码
func (s *struct) DecodeFromBuffer(buffer []byte, offset int) (int, error)

- **Header**: DNS 头部。
- **Question**: DNS 查询部分。
- **Answer**: DNS 回答部分。
- **Authority**: 权威部分。
- **Additional**: 附加部分。
// 编码为字节流
func (s *struct) Encode() []byte

dns包支持对未知类型的资源记录进行编解码,灵活满足实验需求。
// 编码到缓冲区
func (s *struct) EncodeToBuffer(buffer []byte) (int, error)

## xlayers 子包
// 获取结构体的*实际*大小
func (s *struct) Size() int

`xlayers` 包提供了实现 `gopacket.Layer` 接口的 DNS 封装结构,可用于替换 `gopacket.Layer` 中原有的 DNS 实现。
// 获取结构体的字符串表示
func (s *struct) String() string

```go
// DNS 结构体可用于替换 gopacket.Layer 中原有的 DNS 实现
type DNS struct {
layers.BaseLayer
DNSMessage dns.DNSMessage
}
// [部分实现]判断两个结构体是否相等
func (s *struct) Equal(other *struct) bool
```

这些方法使得可以方便地对 DNS 消息进行编解码。

`dns`包对 DNS 消息的格式没有强制限制,并且支持对 未知类型的资源记录 进行编解码,
这使得其可以随意构造和解析 DNS 消息,来满足实验需求。
## xperi 子包

`xperi` 包实现了一些实验用函数,特别是 DNSSEC 相关的辅助函数,包括:

- `ParseKeyBase64`: 解析 Base64 编码的 DNSKEY。
- `CalculateKeyTag`: 计算 DNSKEY 的 Key Tag。
- `GenerateDNSKEY`: 生成 DNSKEY RDATA。
- `GenerateRRSIG`: 对 RRSET 进行签名生成 RRSIG RDATA。
- `GenerateDS`: 生成 DNSKEY 的 DS RDATA。
- `GenRandomRRSIG`: 生成随机的 RRSIG RDATA。
- `GenWrongKeyWithTag`: 生成错误的 DNSKEY RDATA,带有指定 KeyTag。
- `GenKeyWithTag`: 生成具有指定 KeyTag 的 DNSKEY(此函数较耗时)。
- `ParseKeyBase64` 用于解析 Base64 编码的 DNSKEY 为字节形式。

- `CalculateKeyTag` 用于计算 DNSKEY 的 Key Tag。

- `GenerateRDATADNSKEY` 根据参数生成 DNSKEY RDATA。

- `GenerateRDATARRSIG` 根据参数对RRSET进行签名,生成 RRSIG RDATA。

- `GenerateRDATADS` 根据参数生成 DNSKEY 的 DS RDATA。

- `GenerateRRDNSKEY` 根据参数生成 DNSKEY RR。

- `GenerateRRRRSIG` 根据参数对RRSET进行签名,生成 RRSIG RR。

- `GenerateRRDS` 根据参数生成 DNSKEY 的 DS RR。

- `GenRandomRRSIG` 用于生成一个随机的 RRSIG RDATA。

- `GenWrongKeyWithTag` 用于生成错误的,但具有指定 KeyTag 的 DNSKEY RDATA。

- `GenKeyWithTag` **[该函数十分耗时]** 用于生成一个具有指定 KeyTag 的 DNSKEY。

## 许可证

Expand Down
18 changes: 13 additions & 5 deletions dns/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
/*
dns 使用Go的内置实现,提供了 DNS消息 的编解码功能,可以用于任意构造和解析 DNS消息。
// DNSMessage 表示 DNS协议 的消息结构。
[DNSMessage] 表示 DNS协议 的消息结构。
type DNSMessage struct {
// DNS消息 头部
// DNS消息
Header DNSHeader // DNS 头部(Header)
// DNS消息的各个部分(Section)
Question DNSQuestionSection // DNS 查询部分(Questions Section)
Expand All @@ -15,9 +15,17 @@ dns 使用Go的内置实现,提供了 DNS消息 的编解码功能,可以用
Additional DNSResponseSection // DNS 附加部分(Additional Section)
}
子模块dns/xlayers则提供了实现gopacket接口的DNS封装结构,
dns包中的每个结构体基本都实现了以下方法:
- func (s *struct) DecodeFromBuffer(buffer []byte, offset int) (int, error)
- func (s *struct) Encode() []byte
- func (s *struct) EncodeToBuffer(buffer []byte) (int, error)
- func (s *struct) Size() int
- func (s *struct) String() string
- [少部分实现]func (s *struct) Equal(other *struct) bool
可以把dns包看作是 gopacket 中 DNS 相关部分的重新实现,目的是使其更加易用。
也可以将其单独作为一个独立的DNS消息编解码库来使用。
这些方法使得可以方便地对 DNS 消息进行编解码。
dns包对 DNS 消息的格式没有强制限制,并且支持对 未知类型的资源记录 进行编解码,
这使得其可以随意构造和解析 DNS 消息,来满足实验需求。
*/
package dns
5 changes: 3 additions & 2 deletions dns/xperi/dnssec.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,11 @@ func GenerateRDATADNSKEY(algo dns.DNSSECAlgorithm, flag dns.DNSKEYFlag) (dns.DNS
// 返回值:
// - DNSKEY RR
// - 私钥字节
func GenerateRRDNSKEY(algo dns.DNSSECAlgorithm, flag dns.DNSKEYFlag) (dns.DNSResourceRecord, []byte) {
func GenerateRRDNSKEY(
zName string, algo dns.DNSSECAlgorithm, flag dns.DNSKEYFlag) (dns.DNSResourceRecord, []byte) {
rdata, privKey := GenerateRDATADNSKEY(algo, flag)
rr := dns.DNSResourceRecord{
Name: "example.com.",
Name: zName,
Type: dns.DNSRRTypeDNSKEY,
Class: dns.DNSClassIN,
TTL: 86400,
Expand Down
Loading

0 comments on commit 2ef016e

Please sign in to comment.