tessl install tessl/golang-github-com-miekg--dns@1.1.1Complete DNS library for Go with full protocol control, DNSSEC support, and both client and server programming capabilities
DNS server framework with handler pattern for building authoritative servers and resolvers.
DNS server with configurable parameters.
type Server struct {
Addr string // Address to listen on (":dns" if empty)
Net string // Network: "" or "udp" (default), "tcp", "tcp-tls" (DNS over TLS)
Listener net.Listener // TCP listener (for systemd socket activation)
TLSConfig *tls.Config // TLS connection configuration
PacketConn net.PacketConn // UDP listener (for systemd socket activation)
Handler Handler // Request handler (DefaultServeMux if nil)
UDPSize int // UDP buffer size (MinMsgSize/512 if not set)
ReadTimeout time.Duration // Read timeout (default: 2 seconds)
WriteTimeout time.Duration // Write timeout (default: 2 seconds)
IdleTimeout func() time.Duration // TCP idle timeout (default: 8 seconds per RFC 5966)
TsigProvider TsigProvider // Custom TSIG implementation
TsigSecret map[string]string // TSIG secrets: map[zonename]base64secret
NotifyStartedFunc func() // Callback when server starts
DecorateReader DecorateReader // Customize DNS message reading
DecorateWriter DecorateWriter // Customize DNS message writing
MaxTCPQueries int // Max TCP queries per connection (unlimited if -1)
ReusePort bool // SO_REUSEPORT socket option
ReuseAddr bool // SO_REUSEADDR socket option
MsgAcceptFunc MsgAcceptFunc // Message acceptance function
MsgInvalidFunc MsgInvalidFunc // Invalid message handler
}Interface for DNS request handlers.
type Handler interface {
ServeDNS(w ResponseWriter, r *Msg)
}Function adapter for Handler interface.
type HandlerFunc func(ResponseWriter, *Msg)
// ServeDNS calls f(w, r)
func (f HandlerFunc) ServeDNS(w ResponseWriter, r *Msg)Interface for writing DNS responses.
type ResponseWriter interface {
LocalAddr() net.Addr // Local server address
RemoteAddr() net.Addr // Client address
WriteMsg(*Msg) error // Write DNS message
Write([]byte) (int, error) // Write raw bytes
Close() error // Close connection
TsigStatus() error // TSIG validation status
TsigTimersOnly(bool) // Set TSIG timers only mode
Hijack() // Take over connection
}Interface for accessing TLS connection state.
type ConnectionStater interface {
ConnectionState() *tls.ConnectionState
}DNS request multiplexer.
type ServeMux struct {
// contains filtered or unexported fields
}
// NewServeMux creates a new ServeMux
func NewServeMux() *ServeMux
// Handle registers handler for pattern
func (mux *ServeMux) Handle(pattern string, handler Handler)
// HandleFunc registers handler function for pattern
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Msg))
// HandleRemove removes handler for pattern
func (mux *ServeMux) HandleRemove(pattern string)
// ServeDNS dispatches request to registered handler
func (mux *ServeMux) ServeDNS(w ResponseWriter, r *Msg)
// Match returns handler for name
func (mux *ServeMux) Match(name string) Handler// ListenAndServe starts DNS server
func (srv *Server) ListenAndServe() error
// ActivateAndServe activates with existing listener/conn
func (srv *Server) ActivateAndServe() error
// Shutdown performs graceful shutdown
func (srv *Server) Shutdown() error
// ShutdownContext performs graceful shutdown with context
func (srv *Server) ShutdownContext(ctx context.Context) error// ListenAndServe starts DNS server
func ListenAndServe(addr string, network string, handler Handler) error
// ListenAndServeTLS starts DNS server with TLS
func ListenAndServeTLS(addr, certFile, keyFile string, handler Handler) error
// ActivateAndServe activates with existing listener/conn
func ActivateAndServe(l net.Listener, p net.PacketConn, handler Handler) error
// Handle registers handler to DefaultServeMux
func Handle(pattern string, handler Handler)
// HandleFunc registers handler func to DefaultServeMux
func HandleFunc(pattern string, handler func(ResponseWriter, *Msg))
// HandleRemove removes handler from DefaultServeMux
func HandleRemove(pattern string)
// HandleFailed default SERVFAIL handler
func HandleFailed(w ResponseWriter, r *Msg)// MsgAcceptAction defines message acceptance
type MsgAcceptAction int
const (
MsgAccept MsgAcceptAction = iota // Accept message
MsgReject // Reject with FORMERR
MsgIgnore // Ignore silently
MsgRejectNotImplemented // Reject with NOTIMPL
)
// MsgAcceptFunc checks incoming messages
type MsgAcceptFunc func(Header) MsgAcceptAction
// DefaultMsgAcceptFunc is the default accept function
func DefaultMsgAcceptFunc(hdr Header) MsgAcceptAction// SessionUDP holds UDP session information
type SessionUDP struct {
// contains filtered or unexported fields
}
// ReadFromSessionUDP reads from UDP session
func ReadFromSessionUDP(conn *net.UDPConn, b []byte) (int, *SessionUDP, error)
// WriteToSessionUDP writes to UDP session
func WriteToSessionUDP(conn *net.UDPConn, b []byte, session *SessionUDP) (int, error)// Reader reads raw DNS messages
type Reader interface {
ReadTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
ReadUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error)
}
// PacketConnReader for generic packet connections
type PacketConnReader interface {
Reader
ReadPacketConn(conn net.PacketConn, timeout time.Duration) ([]byte, net.Addr, error)
}
// Writer writes raw DNS messages
type Writer interface {
io.Writer
}
// DecorateReader customizes message reading
type DecorateReader func(Reader) Reader
// DecorateWriter customizes message writing
type DecorateWriter func(Writer) Writer
// MsgInvalidFunc handles invalid messages
type MsgInvalidFunc func(m []byte, err error)
// DefaultMsgInvalidFunc is the default invalid handler
func DefaultMsgInvalidFunc(m []byte, err error)// DefaultServeMux is the default ServeMux instance
var DefaultServeMux = NewServeMux()dns.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
m.Authoritative = true
// Add answer
rr := &dns.A{
Hdr: dns.RR_Header{
Name: r.Question[0].Name,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 3600,
},
A: net.ParseIP("192.0.2.1"),
}
m.Answer = append(m.Answer, rr)
w.WriteMsg(m)
})
server := &dns.Server{Addr: ":53", Net: "udp"}
log.Fatal(server.ListenAndServe())dns.HandleFunc(".", handleRequest)
server := &dns.Server{
Addr: ":53",
Net: "tcp",
}
log.Fatal(server.ListenAndServe())cert, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
log.Fatal(err)
}
tlsConfig := &tls.Config{
Certificates: []tls.Certificate{cert},
}
dns.HandleFunc(".", handleRequest)
server := &dns.Server{
Addr: ":853",
Net: "tcp-tls",
TLSConfig: tlsConfig,
}
log.Fatal(server.ListenAndServe())mux := dns.NewServeMux()
// Handle example.com
mux.HandleFunc("example.com.", func(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
m.Authoritative = true
// ... add records
w.WriteMsg(m)
})
// Handle example.net
mux.HandleFunc("example.net.", func(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
m.Authoritative = true
// ... add records
w.WriteMsg(m)
})
// Catch-all
mux.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetRcode(r, dns.RcodeRefused)
w.WriteMsg(m)
})
server := &dns.Server{
Addr: ":53",
Net: "udp",
Handler: mux,
}
log.Fatal(server.ListenAndServe())type MyHandler struct {
zones map[string][]dns.RR
}
func (h *MyHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
// Lookup records
if records, ok := h.zones[r.Question[0].Name]; ok {
m.Answer = records
m.Authoritative = true
} else {
m.SetRcode(r, dns.RcodeNameError)
}
w.WriteMsg(m)
}
handler := &MyHandler{
zones: make(map[string][]dns.RR),
}
server := &dns.Server{
Addr: ":53",
Net: "udp",
Handler: handler,
}server := &dns.Server{
Addr: ":53",
Net: "udp",
TsigSecret: map[string]string{
"example.com.": "base64secret==",
},
}
dns.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) {
// Check TSIG status
if r.IsTsig() != nil {
if w.TsigStatus() == nil {
// TSIG valid
}
}
m := new(dns.Msg)
m.SetReply(r)
w.WriteMsg(m)
})
log.Fatal(server.ListenAndServe())server := &dns.Server{Addr: ":53", Net: "udp"}
go func() {
log.Fatal(server.ListenAndServe())
}()
// Wait for signal
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
<-sigChan
// Graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := server.ShutdownContext(ctx); err != nil {
log.Printf("Shutdown error: %v", err)
}server := &dns.Server{
Addr: ":53",
Net: "udp",
MsgAcceptFunc: func(hdr dns.Header) dns.MsgAcceptAction {
// Reject queries with more than 1 question
if hdr.Qdcount > 1 {
return dns.MsgReject
}
// Ignore status requests
if hdr.Bits>>11&0xF == dns.OpcodeStatus {
return dns.MsgIgnore
}
return dns.MsgAccept
},
}server := &dns.Server{
Addr: ":53",
Net: "udp",
ReusePort: true, // SO_REUSEPORT
ReuseAddr: true, // SO_REUSEADDR
}server := &dns.Server{
Addr: ":53",
Net: "tcp",
ReadTimeout: 5 * time.Second,
WriteTimeout: 5 * time.Second,
IdleTimeout: func() time.Duration {
return 10 * time.Second
},
}dns.HandleFunc(".", func(w dns.ResponseWriter, r *dns.Msg) {
// Take over the connection
w.Hijack()
// Now you have full control
// Write custom responses, etc.
})// Get listener from systemd
listeners, err := systemd.ListenersWithNames()
if err != nil {
log.Fatal(err)
}
server := &dns.Server{
Listener: listeners["dns.socket"][0].(net.Listener),
Handler: dns.HandlerFunc(handleRequest),
}
log.Fatal(server.ActivateAndServe())// IPv4 server
server4 := &dns.Server{
Addr: "0.0.0.0:53",
Net: "udp",
Handler: handler,
}
// IPv6 server
server6 := &dns.Server{
Addr: "[::]:53",
Net: "udp",
Handler: handler,
}
go server4.ListenAndServe()
go server6.ListenAndServe()udpServer := &dns.Server{
Addr: ":53",
Net: "udp",
Handler: handler,
}
tcpServer := &dns.Server{
Addr: ":53",
Net: "tcp",
Handler: handler,
}
go udpServer.ListenAndServe()
go tcpServer.ListenAndServe()ServeMux uses longest match for patterns:
"." matches all names"example.com." matches example.com and all subdomains"www.example.com." matches only www.example.comMore specific patterns take precedence:
mux.HandleFunc(".", catchAll) // Lowest priority
mux.HandleFunc("example.com.", handleExample) // Medium priority
mux.HandleFunc("www.example.com.", handleWWW) // Highest priority