dns

package
v0.0.1-dev.43 Latest Latest
Warning

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

Go to latest
Published: May 13, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package dns implements the per-node embedded DNS server (RUNE-063).

The agent serves an authoritative zone for `.rune` and forwards every other query to host upstream resolvers read from /etc/resolv.conf. Records are A only and resolve `<service>.<namespace>.rune` to the service's stable VIP allocated by the control plane (RUNE-040). TTL is intentionally short (5s) so dropped/replaced services are noticed quickly.

Bind addresses default to 127.0.0.123:53 (UDP+TCP). 127.0.0.123 is chosen rather than 127.0.0.53 because the latter is reserved by systemd-resolved on most Linux distributions and would conflict. Additional bind addresses (typically Docker bridge gateways) can be supplied at construction time so containers reach the DNS server through their own gateway IP.

The Subsystem implements the same Name / Start / Ready / Stop contract as the agent's other subsystems (see internal/agent), but does not import the agent package directly to avoid cycles.

Index

Constants

View Source
const (
	// DefaultBindAddr is the loopback address the agent binds for
	// host-side DNS injection. Avoids systemd-resolved on .53.
	DefaultBindAddr = "127.0.0.123:53"

	// Zone is the authoritative zone (always trailing dot for miekg).
	Zone = "rune."

	// DefaultTTL is the TTL stamped on every answer.
	DefaultTTL uint32 = 5

	// DefaultStaleBudget mirrors the dataplane: after this much time
	// without a refresh signal, the resolver returns SERVFAIL for
	// .rune queries instead of stale data.
	DefaultStaleBudget = 30 * time.Second
)

Defaults.

Variables

This section is empty.

Functions

func ResolvConfUpstreams

func ResolvConfUpstreams() func() []string

ResolvConfUpstreams returns an UpstreamProvider that re-reads /etc/resolv.conf on every call. Loopback servers (e.g. systemd-resolved) are filtered to avoid forwarding loops back into our own bind.

Types

type Config

type Config struct {
	// Zone provides the in-zone resolutions. Required.
	Zone ZoneProvider

	// Freshness gates .rune answers; nil means always fresh.
	Freshness Freshness

	// BindAddrs are host:port pairs to bind. If empty, defaults to
	// just DefaultBindAddr. Each address is bound on both UDP and TCP.
	BindAddrs []string

	// TTL stamped on answers; defaults to DefaultTTL.
	TTL uint32

	// StaleBudget; informational, used by callers to align with the
	// dataplane budget. The Freshness interface is the actual gate.
	StaleBudget time.Duration

	// UpstreamProvider, if set, is consulted for the forwarder
	// upstream list on every query. If nil, /etc/resolv.conf is
	// parsed at Start and on each Refresh() call.
	UpstreamProvider func() []string

	// ForwardTimeout caps each upstream query; defaults to 2s.
	ForwardTimeout time.Duration

	// Logger; defaults to the global logger with component "dns".
	Logger log.Logger
}

Config bundles the parameters for constructing a Subsystem.

type EndpointPublisher

type EndpointPublisher struct {
	// contains filtered or unexported fields
}

EndpointPublisher fans the orchestrator's endpoint + local-instance updates into the OrderedLog-backed publishers from pkg/networking/endpoints and pkg/networking/localinstances.

It implements the pkg/orchestrator/controllers.EndpointPublisher interface (kept loose-coupled to avoid an import cycle: this package only refers to pkg/types).

func NewEndpointPublisher

func NewEndpointPublisher(olog orderedlog.OrderedLog, logger log.Logger) (*EndpointPublisher, error)

NewEndpointPublisher constructs an EndpointPublisher. Both underlying publishers are required.

func (*EndpointPublisher) PublishLocalInstances

func (p *EndpointPublisher) PublishLocalInstances(ctx context.Context, nodeID string, table map[string]types.InstanceIdentity) error

PublishLocalInstances implements controllers.EndpointPublisher.

func (*EndpointPublisher) PublishService

func (p *EndpointPublisher) PublishService(ctx context.Context, service *types.Service, eps []types.Endpoint) error

PublishService implements controllers.EndpointPublisher.

type Freshness

type Freshness interface {
	IsFresh() bool
}

Freshness reports whether the underlying state (orderedlog watch) is fresh enough to answer authoritatively. When false, .rune queries are answered with SERVFAIL.

func AlwaysFresh

func AlwaysFresh() Freshness

AlwaysFresh returns a Freshness that always reports fresh.

func FreshnessFromDataplane

func FreshnessFromDataplane(isFresh func() bool) Freshness

FreshnessFromDataplane builds a Freshness implementation from any type that exposes an IsFresh() bool method (e.g. dataplane.Subsystem once it grows that accessor). When the supplied function is nil, the DNS server treats the data plane as always fresh — appropriate for dev/standalone mode.

type StoreZone

type StoreZone struct {
	// contains filtered or unexported fields
}

StoreZone is a ZoneProvider that resolves <svc>.<ns>.rune queries against the agent's store.Store. The VIP for a service is read from Service.Discovery.VIP (populated by RUNE-040).

Lookups are memoized for a short TTL to avoid hammering the store on bursts of repeated DNS queries from a single client.

func NewStoreZone

func NewStoreZone(s store.Store, logger log.Logger) *StoreZone

NewStoreZone constructs a StoreZone with a 1s lookup cache.

func (*StoreZone) LookupA

func (z *StoreZone) LookupA(ns, name string) ([]net.IP, bool)

LookupA implements ZoneProvider.

type Subsystem

type Subsystem struct {
	// contains filtered or unexported fields
}

Subsystem is the per-node embedded DNS server.

func New

func New(cfg Config) (*Subsystem, error)

New constructs a Subsystem. The server is not bound until Start.

func (*Subsystem) Name

func (s *Subsystem) Name() string

Name implements the agent Subsystem contract.

func (*Subsystem) Ready

func (s *Subsystem) Ready() <-chan struct{}

Ready returns a channel closed when the server has bound and is serving on at least one address.

func (*Subsystem) Refresh

func (s *Subsystem) Refresh() error

Refresh re-reads /etc/resolv.conf for upstream resolvers. Wire this to SIGHUP at the daemon level. Returns an error if no upstreams could be loaded; the previous list is retained on error.

func (*Subsystem) Start

func (s *Subsystem) Start(ctx context.Context) error

Start binds the configured addresses on UDP+TCP and begins serving. It blocks until at least one bind succeeds or all binds fail.

func (*Subsystem) Stop

func (s *Subsystem) Stop(ctx context.Context) error

Stop shuts down all listeners.

type ZoneProvider

type ZoneProvider interface {
	// LookupA returns the IPv4 addresses for service `name` in
	// namespace `ns`. ok=false means the service is not known.
	LookupA(ns, name string) (ips []net.IP, ok bool)
}

ZoneProvider resolves an in-zone name to one or more A records. LookupA is called for every <service>.<namespace>.rune query the server receives.

Jump to

Keyboard shortcuts

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