golang 实现 dns agent
常见DNS记录类型
| 记录类型 | 核心功能 | 应用场景 | 示例格式 |
|---|---|---|---|
| A | 域名 → IPv4 地址 | 网站基础解析、服务器绑定 | example.com. IN A 192.0.2.1 |
| AAAA | 域名 → IPv6 地址 | IPv6 网络支持、物联网设备 | example.com. IN AAAA 2001:db8::1 |
| CNAME | 域名 → 别名域名 | CDN 加速、统一域名管理 | www.example.com. IN CNAME cdn.com. |
| PTR | IP 地址 → 域名 | 反垃圾邮件、日志分析 | 1.2.0.192.in-addr.arpa. IN PTR mail.example.com. |
| NS | 指定权威 DNS 服务器 | 域名解析委派 | example.com. IN NS ns1.cloud-dns.net. |
| MX | 指定邮件服务器及优先级 | 企业邮箱配置 | example.com. IN MX 10 mail.example.com. |
| TXT | 存储任意文本信息 | SPF 反垃圾邮件、域名验证 | example.com. IN TXT "v=spf1 include:_spf.google.com ~all" |
| SRV | 指定服务地址及端口 | VoIP、LDAP 服务 | _sip._tcp.example.com. IN SRV 10 5 5060 sipserver.example.com. |
| SOA | 定义域管理元数据 | 区域传输控制、主从同步 | example.com. IN SOA ns1.example.com. admin.example.com. (2024062501 3600 900 1209600 86400) |
go常用dns解析库
Go语言中常用的DNS解析库有以下两个:
- net/dns包:是Go语言标准库的一部分,提供了DNS解析功能,如解析域名、获取主机信息、查询MX记录等。示例代码:
- miekg/dns库:是Go语言中比较流行的DNS解析库,支持自定义DNS查询(A记录、CNAME、TXT、MX等)、构建DNS服务器(拦截、解析、转发)、DNS数据包分析(流量监控、恶意检测)、DNSSEC(增强DNS安全)等功能。示例代码:
解析示例
解析配置
import "github.com/miekg/dns"
func loadResolvConf() *dns.ClientConfig {
config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
if err != nil {
log.Fatalf("Failed to load resolv.conf: %v", err)
}
return config
}
- 返回的config包含:
- servers: nameserver(IP地址)
- search: search域列表(用于域名补全)
- options: options参数(如timeout, ndots)
处理 options关键参数
- attempts: 需在代码中手动实现重试逻辑(遍历 nameserver 列表直到成功或达到重试次数)
- timeout:超时时间配置
c := new(dns.Client)
c.Timeout = time.Duration(config.Timeout) * time.Second // 默认单位秒
c.DialTimeout = c.Timeout // 连接超时
- ndots:决定是否自动添加serach域:若启用,需遍历 config.Search 列表,拼接域名后依次查询
func shouldUseSearch(domain string, ndots int) bool {
dotCount := strings.Count(domain, ".")
return dotCount < ndots // 域名中 "." 数量 < ndots 时启用 search
}
实战demo
package main
import (
"fmt"
"log"
"os"
"time"
"github.com/miekg/dns"
)
type DNSProxy struct {
upstream string
}
func main() {
addr := "127.0.0.1:5533"
proxy := &DNSProxy{upstream: "8.8.8.8:53"}
dns.HandleFunc(".", proxy.handleRequest)
server := &dns.Server{Addr: addr, Net: "udp"}
go func() {
log.Printf("Starting DNS proxy on %s", server.Addr)
if err := server.ListenAndServe(); err != nil {
log.Fatalf("Failed to start DNS server: %v", err)
}
}()
time.Sleep(2 * time.Second) // 等待代理就绪
exampleQueries(addr)
select {}
}
func (p *DNSProxy) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
c := new(dns.Client)
resp, _, err := c.Exchange(r, p.upstream)
if err != nil {
log.Printf("Failed to query upstream: %v", err)
m := new(dns.Msg)
m.SetRcode(r, dns.RcodeServerFailure)
w.WriteMsg(m)
return
}
for _, ans := range resp.Answer {
fmt.Println(ans.String())
}
w.WriteMsg(resp)
}
func queryExample(proxyAddr, domain string, qtype uint16) {
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(domain), qtype)
c := new(dns.Client)
in, _, err := c.Exchange(m, proxyAddr)
if err != nil {
fmt.Fprintf(os.Stderr, "Query failed: %v\n", err)
return
}
for _, ans := range in.Answer {
fmt.Println(ans.String())
}
time.Sleep(2 * time.Second) // 限频
}
func exampleQueries(proxyAddr string) {
domain := "example.com"
fmt.Println("=====A record:=====")
queryExample(proxyAddr, domain, dns.TypeA)
fmt.Println("=====AAAA record:=====")
queryExample(proxyAddr, domain, dns.TypeAAAA)
fmt.Println("=====CNAME record:=====")
cnameDomain := "www.google.com"
queryExample(proxyAddr, cnameDomain, dns.TypeCNAME)
fmt.Println("=====PTR record:=====")
queryExample(proxyAddr, "8.8.8.8.in-addr.arpa", dns.TypePTR)
fmt.Println("=====NS record:=====")
queryExample(proxyAddr, domain, dns.TypeNS)
fmt.Println("=====MX record:=====")
queryExample(proxyAddr, domain, dns.TypeMX)
fmt.Println("=====TXT record:=====")
queryExample(proxyAddr, domain, dns.TypeTXT)
fmt.Println("=====SRV record:=====")
srvDomain := "_xmpp-server._tcp.jabber.org"
queryExample(proxyAddr, srvDomain, dns.TypeSRV)
fmt.Println("=====SOA record:=====")
queryExample(proxyAddr, domain, dns.TypeSOA)
}
- 运行日志如下:
2025/07/03 17:15:20 Starting DNS proxy on 127.0.0.1:5533
=====A record:=====
example.com. 101 IN A 96.7.128.175
example.com. 101 IN A 23.215.0.136
example.com. 101 IN A 23.192.228.84
example.com. 101 IN A 96.7.128.198
example.com. 101 IN A 23.192.228.80
example.com. 101 IN A 23.215.0.138
example.com. 101 IN A 96.7.128.175
example.com. 101 IN A 23.215.0.136
example.com. 101 IN A 23.192.228.84
example.com. 101 IN A 96.7.128.198
example.com. 101 IN A 23.192.228.80
example.com. 101 IN A 23.215.0.138
=====AAAA record:=====
example.com. 75 IN AAAA 2600:1406:bc00:53::b81e:94ce
example.com. 75 IN AAAA 2600:1408:ec00:36::1736:7f24
example.com. 75 IN AAAA 2600:1406:3a00:21::173e:2e66
example.com. 75 IN AAAA 2600:1406:bc00:53::b81e:94c8
example.com. 75 IN AAAA 2600:1408:ec00:36::1736:7f31
example.com. 75 IN AAAA 2600:1406:3a00:21::173e:2e65
example.com. 75 IN AAAA 2600:1406:bc00:53::b81e:94ce
example.com. 75 IN AAAA 2600:1408:ec00:36::1736:7f24
example.com. 75 IN AAAA 2600:1406:3a00:21::173e:2e66
example.com. 75 IN AAAA 2600:1406:bc00:53::b81e:94c8
example.com. 75 IN AAAA 2600:1408:ec00:36::1736:7f31
example.com. 75 IN AAAA 2600:1406:3a00:21::173e:2e65
=====CNAME record:=====
www.google.com. 177 IN A 31.13.94.49
www.google.com. 177 IN A 31.13.94.49
=====PTR record:=====
8.8.8.8.in-addr.arpa. 13841 IN PTR dns.google.
8.8.8.8.in-addr.arpa. 13841 IN PTR dns.google.
=====NS record:=====
example.com. 10887 IN NS b.iana-servers.net.
example.com. 10887 IN NS a.iana-servers.net.
example.com. 10887 IN NS b.iana-servers.net.
example.com. 10887 IN NS a.iana-servers.net.
=====MX record:=====
example.com. 5189 IN MX 0 .
example.com. 5189 IN MX 0 .
=====TXT record:=====
example.com. 21341 IN TXT "_k2n1y4vw3qtb4skdx9e7dxt97qrmmq9"
example.com. 21341 IN TXT "v=spf1 -all"
example.com. 21341 IN TXT "_k2n1y4vw3qtb4skdx9e7dxt97qrmmq9"
example.com. 21341 IN TXT "v=spf1 -all"
=====SRV record:=====
_xmpp-server._tcp.jabber.org. 60 IN SRV 30 30 5269 scarlet.jabber.org.
_xmpp-server._tcp.jabber.org. 60 IN SRV 30 30 5269 scarlet.jabber.org.
=====SOA record:=====
example.com. 326 IN SOA ns.icann.org. noc.dns.icann.org. 2025011701 7200 3600 1209600 3600
example.com. 326 IN SOA ns.icann.org. noc.dns.icann.org. 2025011701 7200 3600 1209600 3600
Ref
https://man7.org/linux/man-pages/man5/resolv.conf.5.html
https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml

浙公网安备 33010602011771号