Golang中DNS CNAME记录的创建与配置
Golang中DNS CNAME记录的创建与配置 各位社区极客们好,
我是Go语言的新手,正在尝试用Go编写一个自动化脚本。 我们是一组管理员,在我们的DNS服务器上有一个托管区域。有时我们需要为用户可读性创建CNAME记录。我有手动执行此任务的有效凭据。但尝试用Go来自动化这个过程时,它就是不工作。
package main
import (
"fmt"
"github.com/miekg/dns"
// "golang.org/x/net/context"
"net"
//"crypto/tls"
//"golang.org/x/net/idna"
)
func main() {
dnsServer := "subdomain.domain.com"
dnsUsername := "111111-adm"
dnsPassword := "*******"
domain := "subdomain.domain.com"
cnameName := "prettydns-demo.subdomain.domain.com"
cnameData := "actual-cname.subdomain.domain.com"
msg := dns.Msg{}
msg.SetUpdate(domain)
cnameRecord := &dns.CNAME{
Hdr: dns.RR_Header{
Name: dns.Fqdn(cnameName),
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
},
Target: cnameData,
}
msg.Insert([]dns.RR{cnameRecord})
serverAddr := dnsServer + ":53"
// Open a TCP connection to the DNS server
conn, err := net.Dial("tcp", serverAddr)
if err != nil {
fmt.Printf("Error opening TCP connection: %v\n", err)
return
}
defer conn.Close()
// Send the update message to the DNS server
_, err = conn.Write([]byte(fmt.Sprintf("%s:%s", dnsUsername, dnsPassword)))
if err != nil {
fmt.Printf("Error sending update request: %v\n", err)
return
}
// Read the response from the DNS server Over tcp
responseBytes := make([]byte, 1024)
n, err := conn.Read(responseBytes)
if err != nil {
fmt.Printf("Error reading response: %v\n", err)
return
}
response, err := client.ReadMsg(conn)
if err != nil {
fmt.Printf("Error reading response: %v\n", err)
return
}
if response != nil && response.Rcode == dns.RcodeSuccess {
fmt.Println("CNAME record created successfully!")
} else {
fmt.Println("Error creating CNAME record.")
}
}
我之前没有Go语言的经验,所以如果我问了什么愚蠢的问题,我为此道歉。我只是从谷歌搜索中尝试了很多方法,但就是不行。对此的任何帮助对我来说都将是一次很好的学习。
更多关于Golang中DNS CNAME记录的创建与配置的实战教程也可以访问 https://www.itying.com/category-94-b0.html
感谢您的回答。然而,即使我尝试修正了所有这些,我仍然无法完成这项工作。不确定在身份验证方面我需要做什么。
更多关于Golang中DNS CNAME记录的创建与配置的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你的代码能编译吗?我遇到了两个错误:
n, err := conn.Read(responseBytes)
n 未被使用,并且
response, err := client.ReadMsg(conn)
client 未定义…
使用 miekg/dns 库进行 DNS 更新时,需要正确配置 TSIG 认证和 DNS 客户端。以下是修正后的代码示例:
package main
import (
"fmt"
"github.com/miekg/dns"
)
func main() {
dnsServer := "subdomain.domain.com"
domain := "subdomain.domain.com"
cnameName := "prettydns-demo.subdomain.domain.com"
cnameData := "actual-cname.subdomain.domain.com"
// 创建 TSIG 密钥(需要与 DNS 服务器配置匹配)
secret := "your-tsig-secret-key"
tsigKey := dns.Fqdn("tsig-key-name") + ":" + dns.HmacMD5
// 配置客户端
client := new(dns.Client)
client.TsigSecret = map[string]string{tsigKey: secret}
client.Net = "tcp" // 或 "udp"
// 创建更新消息
msg := new(dns.Msg)
msg.SetUpdate(dns.Fqdn(domain))
msg.SetTsig(tsigKey, dns.HmacMD5, 300, time.Now().Unix())
// 创建 CNAME 记录
rr := &dns.CNAME{
Hdr: dns.RR_Header{
Name: dns.Fqdn(cnameName),
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
},
Target: dns.Fqdn(cnameData),
}
// 插入记录
msg.Insert([]dns.RR{rr})
// 发送更新请求
resp, _, err := client.Exchange(msg, dnsServer+":53")
if err != nil {
fmt.Printf("DNS update failed: %v\n", err)
return
}
if resp.Rcode == dns.RcodeSuccess {
fmt.Println("CNAME record created successfully!")
} else {
fmt.Printf("DNS update failed with Rcode: %d\n", resp.Rcode)
}
}
对于不需要 TSIG 的简单更新(使用用户名/密码认证),需要实现自定义认证机制:
package main
import (
"fmt"
"github.com/miekg/dns"
"strings"
)
type authConn struct {
net.Conn
username string
password string
}
func (ac *authConn) Write(b []byte) (int, error) {
// 添加认证头
authHeader := fmt.Sprintf("%s:%s\n", ac.username, ac.password)
_, err := ac.Conn.Write([]byte(authHeader))
if err != nil {
return 0, err
}
return ac.Conn.Write(b)
}
func main() {
dnsServer := "subdomain.domain.com:53"
username := "111111-adm"
password := "*******"
domain := "subdomain.domain.com"
cnameName := "prettydns-demo.subdomain.domain.com"
cnameData := "actual-cname.subdomain.domain.com"
// 创建原始连接
conn, err := net.Dial("tcp", dnsServer)
if err != nil {
fmt.Printf("Connection failed: %v\n", err)
return
}
defer conn.Close()
// 包装连接以添加认证
authConn := &authConn{
Conn: conn,
username: username,
password: password,
}
// 创建客户端
client := new(dns.Client)
client.Net = "tcp"
client.Conn = authConn
// 创建更新消息
msg := new(dns.Msg)
msg.SetUpdate(dns.Fqdn(domain))
// 创建 CNAME 记录
rr := &dns.CNAME{
Hdr: dns.RR_Header{
Name: dns.Fqdn(cnameName),
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
},
Target: dns.Fqdn(cnameData),
}
msg.Insert([]dns.RR{rr})
// 发送请求
resp, _, err := client.Exchange(msg, dnsServer)
if err != nil {
fmt.Printf("DNS update failed: %v\n", err)
return
}
if resp.Rcode == dns.RcodeSuccess {
fmt.Println("CNAME record created successfully!")
} else {
fmt.Printf("DNS update failed with Rcode: %d\n", resp.Rcode)
}
}
如果使用 BIND 的 update-policy 认证,可以使用 TSIG 或 IP 认证。对于 IP 认证的简单示例:
package main
import (
"fmt"
"github.com/miekg/dns"
)
func main() {
dnsServer := "subdomain.domain.com:53"
domain := "subdomain.domain.com"
cnameName := "prettydns-demo.subdomain.domain.com"
cnameData := "actual-cname.subdomain.domain.com"
client := new(dns.Client)
client.Net = "tcp"
msg := new(dns.Msg)
msg.SetUpdate(dns.Fqdn(domain))
rr := &dns.CNAME{
Hdr: dns.RR_Header{
Name: dns.Fqdn(cnameName),
Rrtype: dns.TypeCNAME,
Class: dns.ClassINET,
Ttl: 300,
},
Target: dns.Fqdn(cnameData),
}
msg.Insert([]dns.RR{rr})
resp, _, err := client.Exchange(msg, dnsServer)
if err != nil {
fmt.Printf("DNS update failed: %v\n", err)
return
}
if resp.Rcode == dns.RcodeSuccess {
fmt.Println("CNAME record created successfully!")
} else {
fmt.Printf("DNS update failed: %v\n", resp)
}
}
确保 DNS 服务器配置允许来自运行脚本的 IP 地址的更新请求。

