dso

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 4, 2026 License: Apache-2.0 Imports: 33 Imported by: 0

README

dso

Name

dso - implements RFC 8490 DNS Stateful Operations and RFC 8765 DNS Push Notifications.

Description

The dso plugin allows clients to establish DNS Stateful Operations sessions. The service runs alongside the DNS server of its server block, on its own ports (TCP and/or TLS). It reuses the listen hosts of that server block, so bind applies to it as well and only the ports differ.

A DSO service belongs to exactly one DNS server. While a single DNS server may be defined by several server blocks, only one full form is allowed. The remaining blocks may repeat bare dso so that traffic to any of them pairs the service, see Examples.

If push is enabled, RFC 8765 DNS Push Notification service is provided over TLS that notifies subscribed clients about changes in resource records. The plugin then also responds authoritatively to queries received over a session for names within the push zones; other names are answered with NOTAUTH and without push such queries are refused. TLS and TSIG configurations are taken from tls and tsig respectively, see Bugs.

Discovery of DSO services is performed by clients and is outside of the plugin's responsibilities. Typically for DNS Push Notifications the main DNS server must respond to _dns-push-tls._tcp.<ZONE> SRV query.

Syntax

Bare form:

dso

The bare form installs the handler only and starts no service. It supplements the full form which must still be defined but at least once server block of a DNS server.

Full form:

dso {
    tcp_port PORT
    tls_port PORT
    keepalive KEEPALIVE [INACTIVITY]
    reconnect ONRESTART ONSHUTDOWN
    log
    push [ZONES...] {
        classes CLASS...
        types TYPES...
        refresh DURATION
        debounce DURATION
    }
}
  • tcp_port PORT and tls_port PORT are the ports the service listens on. At least one of the two must be specified.
  • keepalive KEEPALIVE [INACTIVITY] sets keep alive and inactivity timeouts. KEEPALIVE must be at least 10s. If INACTIVITY is omitted, it is set to KEEPALIVE. Since server is a passive observer, requests for shorter timeouts are granted as it allows to shed dead connections sooner. Defaults to 1h and 1m respectively.
  • reconnect ONRESTART ONSHUTDOWN is the retry delay sent to clients when CoreDNS configuration is reloaded or the process is gracefully shut down. Defaults to 5s and 15s respectively, set to negative to disable.
  • log enables use of CoreDNS logging system to print incoming and outgoing DSO messages. If the debug plugin is enabled, malformed messages are hex dumped.
  • push [ZONES...] enables RFC 8765 DNS Push Notifications; requires tls_port. ZONES are the zones subscriptions are allowed for. If empty, the zones from the server block are used.
  • push.classes CLASS... configures list of RR classes that Class: ANY subscriptions resolve to. Defaults to IN.
  • push.types TYPE... configures list of RR types that Type: ANY subscriptions resolve to. Defaults to A, AAAA, PTR, TXT and SRV.
  • push.refresh DURATION sets delay between lookups. Defaults to 1m, set to 0 to disable.
  • push.debounce DURATION tames subscription burst by waiting before performing the first lookup. Defaults to 1s, set to 0 to disable.

Metrics

If monitoring is enabled (via the prometheus plugin) then the following metrics are exported:

  • coredns_dso_session_duration_seconds{server} - histogram of session durations.
  • coredns_dso_push_subscription_entries{server,rrtype} - if push is enabled, number of active push subscriptions.
  • coredns_dso_push_subscription_requests_total{server,rrtype} - if push is enabled, number of push subscription requests.
  • coredns_dso_push_subscription_hits_total{server,rrtype} - if push is enabled, number of successful push subscription requests.

Examples

Minimal DSO service:

example.org {
    dso {
        tcp_port 8053
    }
}

Minimal DSO service with DNS Push Notifications:

example.org {
    dso {
        tls_port 8853
        push
    }
    tls ...
}

Minimal DSO service for a DNS server defined by two server blocks:

example.org {
    dso {
        tls_port 8853
        push example.org example.net
    }
    tls ...
}

example.net {
    dso
}

Limitations

DSO service is deferred until handler installed by the plugin sees at least one message from its parent DNS server.

CoreDNS does not (and often cannot) notify plugins of changes in the zones. Thus Push must periodically poll upstream. These lookup queries can be distinguished as their local address is set to DSO's endpoint.

Since a DSO service belongs to exactly one DNS server, the Corefile is constrained in three ways:

  • dso can be used at most once per server block.
  • All keys of a server block using dso must listen on the same port.
  • At most one server block per DNS server may carry the full dso form; the others must use the bare dso form.

Bugs

Per RFC 8765, push server must respond to DNS queries for served zones. However, it's possible to define a plugin stack such that additional information present in client's DNS queries may result in answers that differ from push lookups.

See Also

RFC 8490 for DNS Stateful Operations and RFC 8765 for DNS Push Notifications. See the tls plugin for configuring certificates and the tsig plugin for configuring TSIG secrets.

Documentation

Index

Constants

View Source
const Name = "dso"

Variables

View Source
var (
	DefaultTCPPort                   = 0
	DefaultTLSPort                   = 0
	DefaultInactivityTimeout         = 1 * time.Minute
	DefaultKeepAliveInterval         = dsomessage.KeepAliveIntervalRecommended * time.Millisecond
	DefaultRestartReconnectInterval  = 5 * time.Second
	DefaultShutdownReconnectInterval = 15 * time.Second

	DefaultPushRefreshInterval       = 1 * time.Minute
	DefaultPushBurstDebounceInterval = 1 * time.Second
	DefaultPushTypes                 = [...]uint16{
		dns.TypeA,
		dns.TypePTR,
		dns.TypeTXT,
		dns.TypeAAAA,
		dns.TypeSRV,
	}
	DefaultPushClasses = [...]uint16{
		dns.ClassINET,
	}
)
View Source
var ErrServerClosed = errors.New("server closed")

Functions

This section is empty.

Types

type Config

type Config struct {
	// TCPPort is port for DSO services that don't require TLS. Set to 0 to disable.
	TCPPort int

	// TLSPort is port for DSO services that require TLS. Set to 0 to disable.
	TLSPort int

	// InactivityTimeout is maximum amount of time session can be inactive. Clients can further reduce it.
	InactivityTimeout time.Duration

	// KeepAliveInterval is maximum amount of time session can be without any traffic. Clients can further reduce it.
	KeepAliveInterval time.Duration

	// RestartReconnectInterval is RetryDelay interval for gracefully closed sessions due to Restart. Set to <0 to disable.
	RestartReconnectInterval time.Duration

	// ShutdownReconnectInterval is RetryDelay interval for gracefully closed sessions due to Shutdown. Set to <0 to disable.
	ShutdownReconnectInterval time.Duration

	// TLSConfig is TLS configuration inherited from [dnsserver.Config] plugin is part of.
	TLSConfig *tls.Config

	// Log is logging configuration. Set to nil to disable.
	Log *LogConfig

	// Push is DSO Push.
	Push *PushConfig
}

type LogConfig

type LogConfig struct{}

type PushConfig

type PushConfig struct {
	// Zones handler is authoritative for.
	//
	// See [Push] for comparison and normalization.
	Zones []string

	// Classes is sorted list of subscribable classes.
	Classes []uint16

	// Types is sorted list of subscribable types.
	Types []uint16

	// RefreshInterval is periodic refresh interval of subscriptions.
	// Set to 0 to disable and use [Server.RefreshPushSubscriptions] instead.
	RefreshInterval time.Duration

	// DebounceDelay is delay to tame burst subscriptions. Set to 0 to disable.
	DebounceDelay time.Duration
}

type Server

type Server struct {
	Config   *Config
	Upstream *dnsserver.Server
	// contains filtered or unexported fields
}

func Servers

func Servers(inst *caddy.Instance) (servers []*Server)

Servers returns DSO servers in caddy.Instance.

func (*Server) RefreshPushSubscriptions

func (s *Server) RefreshPushSubscriptions()

RefreshPushSubscriptions initiates refresh of push subscriptions. Can be called concurrently.

func (*Server) Serve

func (s *Server) Serve(ln net.Listener) error

Serve serves DSO over connections accepted from listener until shutdown or error.

Timeout errors are absorbed. Only exceptoin is os.ErrDeadlineExceeded which can be used to "release" listener.

func (*Server) ServeTLS

func (s *Server) ServeTLS(ln net.Listener) error

ServeTLS is same as Server.Serve but connections are tls-wrapped.

func (*Server) Shutdown

func (s *Server) Shutdown(ctx context.Context, reconnectInterval time.Duration) error

Shutdown tears down connections after listeners to stop accepting.

Normally each client is asked to terminate gracefully via Retry Delay. Passing negative reconnectInterval will cause connection to be closed immediately.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL