2024-10-14 17:44:24 +03:00
|
|
|
// Copyright (C) 2022-2024 AdGuard Software Ltd.
|
2022-08-26 14:18:35 +03:00
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify it under
|
|
|
|
// the terms of the GNU Affero General Public License as published by the Free
|
|
|
|
// Software Foundation, version 3.
|
|
|
|
|
|
|
|
package dnsserver
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"net"
|
|
|
|
|
|
|
|
"github.com/miekg/dns"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Handler is an interface that defines how the DNS server would process DNS
|
2024-06-07 14:27:46 +03:00
|
|
|
// queries. Inspired by net/http.Server and it's Handler.
|
2022-08-26 14:18:35 +03:00
|
|
|
type Handler interface {
|
|
|
|
// ServeDNS should process the request and write a DNS response to the
|
|
|
|
// specified ResponseWriter.
|
|
|
|
//
|
|
|
|
// It accepts context.Context argument which has some additional info
|
2024-01-04 19:22:32 +03:00
|
|
|
// attached to it. This context always contains [ServerInfo] which can be
|
|
|
|
// retrieved using [ServerInfoFromContext] or [MustServerInfoFromContext].
|
|
|
|
// It also must contain [RequestInfo] that can be retrieved with
|
|
|
|
// [RequestInfoFromContext] or [MustRequestInfoFromContext].
|
2022-11-07 10:21:24 +03:00
|
|
|
ServeDNS(context.Context, ResponseWriter, *dns.Msg) (err error)
|
2022-08-26 14:18:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// The HandlerFunc type is an adapter to allow the use of ordinary functions
|
2024-06-07 14:27:46 +03:00
|
|
|
// as DNS handlers. If f is a function with the appropriate signature,
|
2022-08-26 14:18:35 +03:00
|
|
|
// HandlerFunc(f) is a Handler that calls f.
|
2022-11-07 10:21:24 +03:00
|
|
|
type HandlerFunc func(context.Context, ResponseWriter, *dns.Msg) (err error)
|
2022-08-26 14:18:35 +03:00
|
|
|
|
|
|
|
// ServeDNS implements the Handler interface for HandlerFunc.
|
|
|
|
func (f HandlerFunc) ServeDNS(ctx context.Context, rw ResponseWriter, req *dns.Msg) (err error) {
|
|
|
|
return f(ctx, rw, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
// notImplementedHandlerFunc is used if no Handler is configured for a server.
|
|
|
|
var notImplementedHandlerFunc HandlerFunc = func(
|
|
|
|
ctx context.Context,
|
|
|
|
w ResponseWriter,
|
|
|
|
r *dns.Msg,
|
|
|
|
) (err error) {
|
|
|
|
res := new(dns.Msg)
|
|
|
|
res.SetRcode(r, dns.RcodeNotImplemented)
|
|
|
|
|
|
|
|
return w.WriteMsg(ctx, r, res)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Server represents a DNS server.
|
2022-11-07 10:21:24 +03:00
|
|
|
//
|
|
|
|
// TODO(ameshkov): move validation to ctors (for all structs that inherit this).
|
|
|
|
//
|
|
|
|
// TODO(ameshkov): consider Proto()/Network()/Addr() -> single Info() func.
|
2022-08-26 14:18:35 +03:00
|
|
|
type Server interface {
|
2022-11-07 10:21:24 +03:00
|
|
|
// Name returns the server name.
|
|
|
|
Name() (name string)
|
|
|
|
// Proto returns the protocol of the server.
|
|
|
|
Proto() (proto Protocol)
|
|
|
|
// Network is a network (tcp, udp or empty) this server listens to. If it
|
|
|
|
// is empty, the server listens to all networks that are supposed to be
|
|
|
|
// used by its protocol.
|
|
|
|
Network() (network Network)
|
|
|
|
// Addr returns the address the server was configured to listen to.
|
|
|
|
Addr() (addr string)
|
2022-08-26 14:18:35 +03:00
|
|
|
// Start starts the server, exits immediately if it failed to start
|
|
|
|
// listening. Start returns once all servers are considered up.
|
|
|
|
Start(ctx context.Context) (err error)
|
|
|
|
// Shutdown stops the server and waits for all active connections to close.
|
|
|
|
Shutdown(ctx context.Context) (err error)
|
2022-11-07 10:21:24 +03:00
|
|
|
// LocalTCPAddr returns the TCP address the server listens to at the moment
|
|
|
|
// or nil if it does not listen to TCP. Depending on the server protocol
|
|
|
|
// it may correspond to DNS-over-TCP, DNS-over-TLS, HTTP2, DNSCrypt (TCP).
|
|
|
|
LocalTCPAddr() (addr net.Addr)
|
|
|
|
// LocalUDPAddr returns the UDP address the server listens to at the moment or
|
|
|
|
// nil if it does not listen to UDP. Depending on the server protocol
|
|
|
|
// it may correspond to DNS-over-UDP, HTTP3, QUIC, DNSCrypt (UDP).
|
|
|
|
LocalUDPAddr() (addr net.Addr)
|
2022-08-26 14:18:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// A ResponseWriter interface is used by a DNS handler to construct a DNS
|
|
|
|
// response.
|
|
|
|
type ResponseWriter interface {
|
|
|
|
// LocalAddr returns the net.Addr of the server.
|
|
|
|
LocalAddr() net.Addr
|
|
|
|
|
|
|
|
// RemoteAddr returns the net.Addr of the client that sent the current
|
|
|
|
// request.
|
|
|
|
RemoteAddr() net.Addr
|
|
|
|
|
|
|
|
// WriteMsg writes a reply back to the client.
|
|
|
|
//
|
|
|
|
// Handlers must not modify req and resp after the call to WriteMsg, since
|
|
|
|
// their ResponseWriter implementation may be a recorder.
|
2024-01-04 19:22:32 +03:00
|
|
|
//
|
|
|
|
// TODO(a.garipov): Store bytes written to the socket.
|
2022-08-26 14:18:35 +03:00
|
|
|
WriteMsg(ctx context.Context, req, resp *dns.Msg) error
|
|
|
|
}
|