or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

client.mdconstants.mddnssec.mddynamic-updates.mdedns0.mdindex.mdmessaging.mdrr-types.mdserver.mdtsig.mdutilities.mdzone-parsing.mdzone-transfer.md
tile.json

client.mddocs/

DNS Client Operations

DNS client for making queries with support for UDP, TCP, and TLS transports.

Core Types

Client

DNS client for performing queries with various network transports.

type Client struct {
	Net            string                // Network type: "" or "udp" (default), "tcp", "tcp-tls" (DNS over TLS)
	UDPSize        uint16                // EDNS0 UDP message size
	TLSConfig      *tls.Config           // TLS connection configuration
	Dialer         *net.Dialer           // Custom dialer for local address, timeouts, etc
	Timeout        time.Duration         // Cumulative timeout (overrides individual timeouts when non-zero)
	DialTimeout    time.Duration         // Dial timeout (default: 2 seconds)
	ReadTimeout    time.Duration         // Read timeout (default: 2 seconds)
	WriteTimeout   time.Duration         // Write timeout (default: 2 seconds)
	TsigSecret     map[string]string     // TSIG secrets: map[zonename]base64secret
	TsigProvider   TsigProvider          // Custom TSIG implementation
	SingleInflight bool                  // Deprecated: no-op
}

Conn

Active DNS connection for reading and writing messages.

type Conn struct {
	net.Conn                         // Underlying network connection
	UDPSize        uint16            // EDNS0 UDP message size
	TsigSecret     map[string]string // TSIG secrets
	TsigProvider   TsigProvider      // Custom TSIG implementation
	tsigRequestMAC string            // Internal TSIG state
}

ClientConfig

Configuration parsed from resolv.conf.

type ClientConfig struct {
	Servers  []string // Nameserver addresses
	Search   []string // Search domains
	Port     string   // Port number
	Ndots    int      // Ndots threshold
	Timeout  int      // Timeout in seconds
	Attempts int      // Number of attempts
}

Client Methods

Exchange Operations

// Exchange performs synchronous query
// Returns response, round-trip time, and error
func (c *Client) Exchange(m *Msg, address string) (r *Msg, rtt time.Duration, err error)

// ExchangeContext performs query with context support
func (c *Client) ExchangeContext(ctx context.Context, m *Msg, address string) (r *Msg, rtt time.Duration, err error)

// ExchangeWithConn performs synchronous query on existing connection
// Useful for persistent connections
func (c *Client) ExchangeWithConn(m *Msg, conn *Conn) (r *Msg, rtt time.Duration, err error)

// ExchangeWithConnContext performs query on existing connection with context
func (c *Client) ExchangeWithConnContext(ctx context.Context, m *Msg, co *Conn) (r *Msg, rtt time.Duration, err error)

Connection Management

// Dial creates connection to DNS server
func (c *Client) Dial(address string) (conn *Conn, err error)

// DialContext creates connection with context support
func (c *Client) DialContext(ctx context.Context, address string) (conn *Conn, err error)

Conn Methods

Message Operations

// ReadMsg reads DNS message from connection
func (co *Conn) ReadMsg() (*Msg, error)

// ReadMsgHeader reads only message header
func (co *Conn) ReadMsgHeader(h *Header) ([]byte, error)

// WriteMsg writes DNS message to connection
func (co *Conn) WriteMsg(m *Msg) error

I/O Operations

// Read reads raw bytes
func (co *Conn) Read(b []byte) (int, error)

// Write writes raw bytes
func (co *Conn) Write(b []byte) (int, error)

Timeout Control

// SetDeadline sets read and write deadlines
func (co *Conn) SetDeadline(t time.Time) error

// SetReadDeadline sets read deadline
func (co *Conn) SetReadDeadline(t time.Time) error

// SetWriteDeadline sets write deadline
func (co *Conn) SetWriteDeadline(t time.Time) error

Package-Level Functions

Simple Query Functions

// Exchange performs simple synchronous UDP query
func Exchange(m *Msg, address string) (*Msg, error)

// ExchangeContext performs simple query with context
func ExchangeContext(ctx context.Context, m *Msg, address string) (*Msg, error)

// ExchangeConn exchanges on existing connection
func ExchangeConn(conn net.Conn, m *Msg) (*Msg, error)

Connection Functions

// Dial creates connection to DNS server
func Dial(network, address string) (*Conn, error)

// DialTimeout creates connection with timeout
func DialTimeout(network, address string, timeout time.Duration) (*Conn, error)

// DialWithTLS creates TLS connection
func DialWithTLS(network, address string, tlsConfig *tls.Config) (*Conn, error)

// DialTimeoutWithTLS creates TLS connection with timeout
func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (*Conn, error)

ClientConfig Methods

// NameList generates search list for name
func (c *ClientConfig) NameList(name string) []string

ClientConfig Functions

// ClientConfigFromFile parses resolv.conf file
func ClientConfigFromFile(resolvconf string) (*ClientConfig, error)

// ClientConfigFromReader parses resolv.conf from reader
func ClientConfigFromReader(resolvconf io.Reader) (*ClientConfig, error)

Usage Examples

Basic Query

c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)
m.RecursionDesired = true

r, rtt, err := c.Exchange(m, "8.8.8.8:53")
if err != nil {
	log.Fatal(err)
}

fmt.Printf("Response time: %v\n", rtt)
for _, ans := range r.Answer {
	fmt.Println(ans)
}

TCP Query

c := &dns.Client{
	Net: "tcp",
}

m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeAXFR)

r, _, err := c.Exchange(m, "ns1.example.com:53")
if err != nil {
	log.Fatal(err)
}

DNS over TLS

tlsConfig := &tls.Config{
	ServerName: "dns.example.com",
}

c := &dns.Client{
	Net:       "tcp-tls",
	TLSConfig: tlsConfig,
}

m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)

r, _, err := c.Exchange(m, "1.1.1.1:853")
if err != nil {
	log.Fatal(err)
}

Query with Timeout

c := &dns.Client{
	Timeout: 2 * time.Second,
}

m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)

r, rtt, err := c.Exchange(m, "8.8.8.8:53")
if err != nil {
	if err == dns.ErrTimeout {
		log.Println("Query timed out")
	}
	log.Fatal(err)
}

Query with Context

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)

r, rtt, err := c.ExchangeContext(ctx, m, "8.8.8.8:53")
if err != nil {
	log.Fatal(err)
}

Using EDNS0

c := &dns.Client{
	UDPSize: 4096,
}

m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)
m.SetEdns0(4096, true) // 4096 byte UDP size, DNSSEC OK

r, _, err := c.Exchange(m, "8.8.8.8:53")

Persistent Connection

c := new(dns.Client)
conn, err := c.Dial("8.8.8.8:53")
if err != nil {
	log.Fatal(err)
}
defer conn.Close()

// Send multiple queries on same connection
for _, name := range []string{"example.com", "example.net", "example.org"} {
	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(name), dns.TypeA)

	err = conn.WriteMsg(m)
	if err != nil {
		log.Fatal(err)
	}

	r, err := conn.ReadMsg()
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("Response for %s: %v\n", name, r.Answer)
}

Using Custom Dialer

dialer := &net.Dialer{
	LocalAddr: &net.UDPAddr{
		IP: net.ParseIP("192.0.2.100"),
	},
	Timeout: 3 * time.Second,
}

c := &dns.Client{
	Dialer: dialer,
}

m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)

r, _, err := c.Exchange(m, "8.8.8.8:53")

Using ClientConfig

config, err := dns.ClientConfigFromFile("/etc/resolv.conf")
if err != nil {
	log.Fatal(err)
}

c := new(dns.Client)
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)
m.RecursionDesired = true

// Query first nameserver from resolv.conf
server := config.Servers[0]
port := config.Port
if port == "" {
	port = "53"
}

r, _, err := c.Exchange(m, net.JoinHostPort(server, port))
if err != nil {
	log.Fatal(err)
}

Using TSIG

c := &dns.Client{
	TsigSecret: map[string]string{
		"example.com.": "base64secret==",
	},
}

m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)
m.SetTsig("example.com.", dns.HmacSHA256, 300, time.Now().Unix())

r, _, err := c.Exchange(m, "ns1.example.com:53")

Simple Package-Level Query

m := new(dns.Msg)
m.SetQuestion(dns.Fqdn("example.com"), dns.TypeA)
m.RecursionDesired = true

r, err := dns.Exchange(m, "8.8.8.8:53")
if err != nil {
	log.Fatal(err)
}

Error Handling

var (
	ErrConnEmpty error // Connection not initialized
	ErrId        error // Message ID mismatch
	ErrShortRead error // Short read from connection
)

Network Types

The Net field in Client supports:

  • "" or "udp" - UDP (default)
  • "tcp" - TCP
  • "tcp-tls" - DNS over TLS (DoT)

Related Topics

  • DNS Messaging - Message construction
  • TSIG Authentication - Transaction signatures
  • EDNS0 Extensions - Extended DNS options
  • Zone Transfers - AXFR/IXFR operations