feat(dnssec): query the authoritative servers directly

This commit is contained in:
2025-09-04 18:11:39 +01:00
parent 1f2703df19
commit 234b1dcc86
17 changed files with 2218 additions and 4 deletions

View File

@@ -0,0 +1,97 @@
package do53
import (
"fmt"
"net"
"time"
"github.com/miekg/dns"
)
type Config struct {
HostAndPort string
DNSSEC bool
WriteTimeout time.Duration
ReadTimeout time.Duration
}
type Client struct {
hostAndPort string
config Config
}
func New(config Config) (*Client, error) {
if config.HostAndPort == "" {
return nil, fmt.Errorf("do53: HostAndPort cannot be empty")
}
if config.WriteTimeout <= 0 {
config.WriteTimeout = 2 * time.Second
}
if config.ReadTimeout <= 0 {
config.ReadTimeout = 5 * time.Second
}
return &Client{
hostAndPort: config.HostAndPort,
config: config,
}, nil
}
func (c *Client) Close() {
}
func (c *Client) createConnection() (*net.UDPConn, error) {
udpAddr, err := net.ResolveUDPAddr("udp", c.hostAndPort)
if err != nil {
return nil, fmt.Errorf("failed to resolve UDP address: %w", err)
}
return net.DialUDP("udp", nil, udpAddr)
}
func (c *Client) Query(msg *dns.Msg) (*dns.Msg, error) {
// Create connection for this query
conn, err := c.createConnection()
if err != nil {
return nil, fmt.Errorf("do53: failed to create connection: %w", err)
}
defer conn.Close()
if c.config.DNSSEC {
msg.SetEdns0(4096, true)
}
packedMsg, err := msg.Pack()
if err != nil {
return nil, fmt.Errorf("do53: failed to pack DNS message: %w", err)
}
// Send query
if err := conn.SetWriteDeadline(time.Now().Add(c.config.WriteTimeout)); err != nil {
return nil, fmt.Errorf("do53: failed to set write deadline: %w", err)
}
if _, err := conn.Write(packedMsg); err != nil {
return nil, fmt.Errorf("do53: failed to send DNS query: %w", err)
}
// Read response
if err := conn.SetReadDeadline(time.Now().Add(c.config.ReadTimeout)); err != nil {
return nil, fmt.Errorf("do53: failed to set read deadline: %w", err)
}
buffer := make([]byte, dns.MaxMsgSize)
n, err := conn.Read(buffer)
if err != nil {
return nil, fmt.Errorf("do53: failed to read DNS response: %w", err)
}
// Parse response
response := new(dns.Msg)
if err := response.Unpack(buffer[:n]); err != nil {
return nil, fmt.Errorf("do53: failed to unpack DNS response: %w", err)
}
return response, nil
}