dns

package
v0.2.8 Latest Latest
Warning

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

Go to latest
Published: Jun 30, 2026 License: GPL-3.0 Imports: 19 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DbusTimeout = time.Second
)

Variables

View Source
var (
	SysdResolver = netip.MustParseAddr("127.0.0.53")
)

Functions

func DbusPing

func DbusPing(ctx context.Context, name, objectPath string) error

NOTE: Borrowed from github.com/tailscale/tailscale

func DbusReadString

func DbusReadString(
	ctx context.Context,
	name, objectPath, iface, member string,
) (string, error)

DbusReadString reads a string property from the provided name and object path. property must be in "interface.member" notation.

NOTE: Borrowed from github.com/tailscale/tailscale

func DnsMode

func DnsMode(ctx context.Context, env Env) (ret string, err error)

direct | systemd-resolved | debian-resolvconf | openresolv

NOTE: Borrowed from github.com/tailscale/tailscale

func IsLibnssResolveUsed

func IsLibnssResolveUsed(env Env) error

IsLibnssResolveUsed reports whether libnss_resolve is used for resolving names. Returns nil if it is, and an error otherwise. NOTE: Borrowed from github.com/tailscale/tailscale

func NmIsUsingResolved

func NmIsUsingResolved() error

NOTE: Borrowed from github.com/tailscale/tailscale

func ResolvOwner

func ResolvOwner(bs []byte) string

ResolvOwner returns the apparent owner of the resolv.conf configuration in bs - one of "resolvconf", "systemd-resolved" or "NetworkManager", or "" if no known owner was found.

NOTE: Borrowed from github.com/tailscale/tailscale

func ResolvconfStyle

func ResolvconfStyle() string

NOTE: Borrowed from github.com/tailscale/tailscale

func ResolvedIsActuallyResolver

func ResolvedIsActuallyResolver(env Env, bs []byte) error

ResolvedIsActuallyResolver reports whether the system is using systemd-resolved as the resolver. There are two different ways to use systemd-resolved:

  • libnss_resolve, which requires adding `resolve` to the "hosts:" line in /etc/nsswitch.conf
  • setting the only nameserver configured in `resolv.conf` to systemd-resolved IP (127.0.0.53)

Returns an error if the configuration is something other than exclusively systemd-resolved, or nil if the config is only systemd-resolved.

NOTE: Borrowed from github.com/tailscale/tailscale

Types

type Cmd

type Cmd interface {
	SetStdin(reader io.Reader)
	Run() error
}

Cmd is the subset of exec.Cmd used by DNS providers that configure the host through external commands.

type DBusConn

type DBusConn interface {
	Object(dest string, path dbus.ObjectPath) dbus.BusObject
	AddMatchSignal(options ...dbus.MatchOption) error
	Signal(ch chan<- *dbus.Signal)
	Close() error
}

DBusConn is the subset of a D-Bus connection used by resolved integration.

type DNSProvider

type DNSProvider interface {
	// Requests() chan <- Request
	// Close() error
	dns.Interface

	// SetDNS should set server as a default one for whole system.
	// ALL DNS resolving mechanisms controlled by specific DNSProvider
	// implementation should go use this server for all requests in system except
	// ones done via DNSProvider.Requests queue.
	// All changes done by SetDNS should have lifetime bounded to DNSProvider
	// object and rolled back on close.
	SetDNS(server netip.Addr) error

	// UnsetDNS should roll back changes done by SetDNS, if any. It should be
	// valid to call SetDNS and UnsetDNS multiple times in any order.
	UnsetDNS() error
}

DNSProvider implementation should track original upstream DNS resolver (e.g. static configured one or DHCP sourced) and use it to serve Requests queue regardless of SetDNS being called or not. Note that upstream may be dynamic and change over time (e.g. when host connects to new network and receive config via DHCP).

DNSProvider should NEVER use server set up via SetDNS to serve Requests queue to avoid loops.

After UnsetDNS, DNSProvider implementations that actively maintain the server installed by SetDNS by watching system configuration changes and rewriting it should stop doing so until SetDNS is called again.

If there are multiple original upstreams (e.g. resolved split dns configuration) DNSProvider implementation should handle it correctly under the hood routing each request from Requests queue to matching upstream.

It is common for DNSProvider implementations to accept fallback dns server at construction time to use in case there is no original upstream provided.

type DebianResolvconf

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

DebianResolvconf is a DNSProvider backed by Debian's resolvconf package.

The provider owns one resolvconf record, named by iface. SetDNS writes that record with `resolvconf -a <iface>` and Close or UnsetDNS removes it with `resolvconf -d <iface>`. It does not try to reconstruct global resolver state; resolvconf is responsible for regenerating /etc/resolv.conf after the provider-owned record is added or removed.

Requests are forwarded directly to the nameservers present in /etc/resolv.conf at construction time, excluding the server installed by SetDNS. This avoids forwarding loops after resolvconf points the host at this provider. Fallback servers are used only when no original upstream remains. Debian resolvconf does not expose an event stream here, so dynamic upstream changes are not tracked by this provider.

func NewDebianResolvconf

func NewDebianResolvconf(
	env Env,
	listenNetwork gonnect.Network,
	dialNetwork gonnect.Network,
	iface string,
	fallback ...netip.AddrPort,
) (*DebianResolvconf, error)

NewDebianResolvconf returns a DNSProvider backed by Debian resolvconf.

env provides access to the host environment. Any nil callbacks are replaced with production defaults. listenNetwork is used for listening operations and dialNetwork is used for all outgoing upstream DNS requests. iface is the resolvconf record name to own, for example "sysnet-linux". fallback is used only when /etc/resolv.conf has no original nameserver after excluding the managed server installed by SetDNS.

func (*DebianResolvconf) Close

func (r *DebianResolvconf) Close() error

Close rolls back active Debian resolvconf configuration and releases forwarding resources. Close is idempotent.

func (*DebianResolvconf) Requests

func (r *DebianResolvconf) Requests() chan<- gdns.Request

Requests returns the queue consumed by the internal forwarding client.

Requests are forwarded to the original resolv.conf nameservers or fallbacks, not to the server most recently installed with SetDNS.

func (*DebianResolvconf) SetDNS

func (r *DebianResolvconf) SetDNS(server netip.Addr) error

SetDNS installs server as this provider's Debian resolvconf nameserver.

The change is bounded by this DebianResolvconf object's lifetime. Repeated calls replace the provider-owned resolvconf record and rebuild the forwarding client so Requests never forward to the managed server.

func (*DebianResolvconf) UnsetDNS

func (r *DebianResolvconf) UnsetDNS() error

UnsetDNS removes the Debian resolvconf record previously applied by SetDNS. It is valid to call multiple times and in any order with SetDNS.

type Direct

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

Direct is a DNSProvider that directly owns /etc/resolv.conf.

NewDirect reads the original resolv.conf nameservers once and Requests forwards directly to those upstreams, excluding the DNS server most recently installed by SetDNS. If no usable original upstream remains, constructor fallbacks are used instead. Direct does not watch resolv.conf for dynamic upstream changes because plain resolv.conf provides no ownership-safe update notification mechanism.

SetDNS writes a provider-owned /etc/resolv.conf containing only the managed server. UnsetDNS and Close restore the saved original contents, or remove the file when it was absent originally, but only while the current file still looks provider-owned to avoid clobbering unrelated host changes.

func NewDirect

func NewDirect(
	env Env,
	listenNetwork gonnect.Network,
	dialNetwork gonnect.Network,
	fallback ...netip.AddrPort,
) (*Direct, error)

NewDirect returns a DNSProvider backed by direct /etc/resolv.conf writes.

env provides access to the host environment. Any nil callbacks are replaced with production defaults. listenNetwork is used for listening operations and dialNetwork is used for all outgoing upstream DNS requests. fallback is used only when /etc/resolv.conf has no original nameserver after excluding the managed server installed by SetDNS.

func (*Direct) Close

func (d *Direct) Close() error

Close rolls back active Direct configuration and releases forwarding resources. Close is idempotent.

func (*Direct) Requests

func (d *Direct) Requests() chan<- gdns.Request

Requests returns the queue consumed by the internal forwarding client.

Requests are forwarded to the original resolv.conf nameservers or fallbacks, not to the server most recently installed with SetDNS.

func (*Direct) SetDNS

func (d *Direct) SetDNS(server netip.Addr) error

SetDNS writes /etc/resolv.conf with server as the system nameserver.

The change is bounded by this Direct object's lifetime. Repeated calls update the managed file and rebuild the forwarding client so Requests never forward to the managed server.

func (*Direct) UnsetDNS

func (d *Direct) UnsetDNS() error

UnsetDNS rolls back the /etc/resolv.conf change previously applied by SetDNS. It is valid to call multiple times and in any order with SetDNS.

type Env

type Env struct {
	Logf func(format string, args ...any)

	ReadFile       func(path string) ([]byte, error)
	WriteFile      func(path string, data []byte, perm os.FileMode) error
	Remove         func(path string) error
	CommandContext func(
		ctx context.Context,
		name string,
		args ...string,
	) Cmd

	DbusReadString func(ctx context.Context, name, objectPath, iface, member string) (string, error)
	DbusPing       func(ctx context.Context, name, objectPath string) error
	SystemBus      func() (*dbus.Conn, error)
	ResolvedBus    func() (DBusConn, error)

	ResolvconfStyle func() string

	NmIsUsingResolved func() error
}

type Openresolv

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

Openresolv is a DNSProvider backed by the openresolv resolvconf program.

The provider owns one openresolv record, named by iface. SetDNS writes that record with `resolvconf -m 0 -x -a <iface>` so the managed DNS server becomes the exclusive, highest-priority resolver configuration. Close or UnsetDNS removes the record with `resolvconf -f -d <iface>`. It does not reconstruct global resolver state; openresolv regenerates /etc/resolv.conf after records are added or removed.

Requests are forwarded directly to the nameservers present in /etc/resolv.conf at construction time, excluding the server installed by SetDNS. This avoids forwarding loops after openresolv points the host at this provider. Fallback servers are used only when no original upstream remains. Openresolv is not watched for dynamic upstream changes by this provider.

func NewOpenresolv

func NewOpenresolv(
	env Env,
	listenNetwork gonnect.Network,
	dialNetwork gonnect.Network,
	iface string,
	fallback ...netip.AddrPort,
) (*Openresolv, error)

NewOpenresolv returns a DNSProvider backed by openresolv.

env provides access to the host environment. Any nil callbacks are replaced with production defaults. listenNetwork is used for listening operations and dialNetwork is used for all outgoing upstream DNS requests. iface is the openresolv record key to own, for example "sysnet-linux". fallback is used only when /etc/resolv.conf has no original nameserver after excluding the managed server installed by SetDNS.

func (*Openresolv) Close

func (r *Openresolv) Close() error

Close rolls back active openresolv configuration and releases forwarding resources. Close is idempotent.

func (*Openresolv) Requests

func (r *Openresolv) Requests() chan<- gdns.Request

Requests returns the queue consumed by the internal forwarding client.

Requests are forwarded to the original resolv.conf nameservers or fallbacks, not to the server most recently installed with SetDNS.

func (*Openresolv) SetDNS

func (r *Openresolv) SetDNS(server netip.Addr) error

SetDNS installs server as this provider's openresolv nameserver.

The change is bounded by this Openresolv object's lifetime. Repeated calls replace the provider-owned openresolv record and rebuild the forwarding client so Requests never forward to the managed server.

func (*Openresolv) UnsetDNS

func (r *Openresolv) UnsetDNS() error

UnsetDNS removes the openresolv record previously applied by SetDNS. It is valid to call multiple times and in any order with SetDNS.

type Resolved

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

Resolved is a DNSProvider backed by systemd-resolved.

A Resolved instance owns one system bus connection and, when configured with an interface index, one resolved link. The link is identified by Linux interface index, because that is what resolved's Manager.SetLink* methods accept. Close reverts the link configuration and releases the internal forwarding client.

Resolved deliberately does not use systemd-resolved itself as its request forwarder. It forwards through direct gonnect DNS clients backed by the upstream servers reported by resolved, and refreshes that client when resolved reports dynamic configuration changes. This avoids loops after SetDNS points the host at this provider while still following DHCP and other resolved upstream changes.

func NewResolved

func NewResolved(
	env Env,
	listenNetwork gonnect.Network,
	dialNetwork gonnect.Network,
	ifidx int,
	fallback ...netip.AddrPort,
) (*Resolved, error)

NewResolved returns a DNSProvider backed by systemd-resolved.

env provides access to the host environment. Any nil callbacks are replaced with production defaults.

ifidx is the kernel network interface index to configure through resolved's per-link D-Bus API. Pass 0 when the interface does not exist yet, then call SetInterfaceIndex before SetDNS. Requests are forwarded directly to the DNS servers that resolved reports for that link, so SetDNS does not create a DNS loop through the newly installed server. listenNetwork is used for listening operations and dialNetwork is used for all outgoing upstream DNS requests. fallback is used only if resolved does not report any usable link or global DNS servers.

func (*Resolved) Close

func (r *Resolved) Close() error

Close reverts the resolved link configuration and releases all resources.

Close is idempotent. It attempts every cleanup step and returns the joined error, if any, so a failure to revert the link does not prevent the internal DNS client or D-Bus connection from being closed.

func (*Resolved) InterfaceIndex

func (r *Resolved) InterfaceIndex() int

InterfaceIndex returns the current resolved link interface index, or 0 when no link is configured.

func (*Resolved) Requests

func (r *Resolved) Requests() chan<- gdns.Request

Requests returns the queue consumed by the internal forwarding client.

Requests sent to this channel are forwarded to the current resolved upstream servers, not to the server most recently installed with SetDNS.

func (*Resolved) SetDNS

func (r *Resolved) SetDNS(server netip.Addr) error

SetDNS installs server as the default DNS server for this resolved link.

The method configures a per-link nameserver, adds a routing-only root domain so all names prefer the link, marks the link as a default route when the running resolved version supports it, and flushes resolved's caches. LLMNR, multicast DNS, DNSSEC, and DNS-over-TLS are disabled on a best-effort basis for this link because this provider expects plain DNS forwarding to the supplied server.

The configuration lifetime is bounded by the Resolved object. UnsetDNS and Close call RevertLink to ask resolved to discard the per-link settings applied here.

Resolved watches resolved configuration changes and rewrites this setup when it is changed externally. Calling UnsetDNS stops that active maintenance until SetDNS is called again.

func (*Resolved) SetInterfaceIndex

func (r *Resolved) SetInterfaceIndex(ifidx int) error

SetInterfaceIndex changes the resolved link managed by this provider.

Passing 0 clears the configured link. If managed DNS is active, the old link is reverted and the DNS configuration is reapplied to the new link. Clearing the link while managed DNS is active is rejected; call UnsetDNS first.

func (*Resolved) UnsetDNS

func (r *Resolved) UnsetDNS() error

UnsetDNS rolls back resolved link configuration previously applied by SetDNS.

After this method returns, Resolved no longer rewrites the SetDNS server in response to resolved configuration changes. Calling SetDNS later enables that maintenance again.

func (*Resolved) UpdateInterfaceIndex

func (r *Resolved) UpdateInterfaceIndex(ifidx int) error

UpdateInterfaceIndex is an alias for SetInterfaceIndex.

Directories

Path Synopsis
Package dnsname contains string functions for working with DNS names.
Package dnsname contains string functions for working with DNS names.
Package resolvconffile parses & serializes /etc/resolv.conf-style files.
Package resolvconffile parses & serializes /etc/resolv.conf-style files.

Jump to

Keyboard shortcuts

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