diff --git a/osbase/net/dns/dns.go b/osbase/net/dns/dns.go
new file mode 100644
index 0000000..3207622
--- /dev/null
+++ b/osbase/net/dns/dns.go
@@ -0,0 +1,468 @@
+// Package dns provides a DNS server for resolving services against.
+package dns
+
+import (
+	"context"
+	"fmt"
+	"net/netip"
+	"runtime/debug"
+	"strconv"
+	"sync/atomic"
+	"time"
+
+	"github.com/miekg/dns"
+
+	"source.monogon.dev/osbase/supervisor"
+)
+
+// Service is a DNS server service with configurable handlers.
+//
+// The number and names of handlers is fixed when New is called. For each name
+// in handlerNames there is a corresponding pointer to a handler in the handlers
+// slice at the same index, which can be atomically updated at runtime through
+// its atomic.Pointer via the SetHandler function.
+type Service struct {
+	handlerNames []string
+	handlers     []atomic.Pointer[Handler]
+}
+
+type serviceCtx struct {
+	service *Service
+	ctx     context.Context
+}
+
+// New creates a Service instance. DNS handlers with the names given in
+// handlerNames must be set with SetHandler. When serving DNS queries, they will
+// be tried in the order they appear here. Doing it this way instead of directly
+// passing a []Handler avoids circular dependencies.
+func New(handlerNames []string) *Service {
+	return &Service{
+		handlerNames: handlerNames,
+		handlers:     make([]atomic.Pointer[Handler], len(handlerNames)),
+	}
+}
+
+// Run runs the DNS service.
+func (s *Service) Run(ctx context.Context) error {
+	addr4 := "127.0.0.1:53"
+	addr6 := "[::1]:53"
+	supervisor.Run(ctx, "udp4", func(ctx context.Context) error {
+		return s.runListener(ctx, addr4, "udp")
+	})
+	supervisor.Run(ctx, "tcp4", func(ctx context.Context) error {
+		return s.runListener(ctx, addr4, "tcp")
+	})
+	supervisor.Run(ctx, "udp6", func(ctx context.Context) error {
+		return s.runListener(ctx, addr6, "udp")
+	})
+	supervisor.Run(ctx, "tcp6", func(ctx context.Context) error {
+		return s.runListener(ctx, addr6, "tcp")
+	})
+	supervisor.Signal(ctx, supervisor.SignalHealthy)
+	supervisor.Signal(ctx, supervisor.SignalDone)
+	return nil
+}
+
+// RunListenerAddr runs a DNS listener on a specific address.
+func (s *Service) RunListenerAddr(ctx context.Context, addr string) error {
+	supervisor.Run(ctx, "udp", func(ctx context.Context) error {
+		return s.runListener(ctx, addr, "udp")
+	})
+	supervisor.Run(ctx, "tcp", func(ctx context.Context) error {
+		return s.runListener(ctx, addr, "tcp")
+	})
+	supervisor.Signal(ctx, supervisor.SignalHealthy)
+	supervisor.Signal(ctx, supervisor.SignalDone)
+	return nil
+}
+
+func (s *Service) runListener(ctx context.Context, addr string, network string) error {
+	handler := &serviceCtx{service: s, ctx: ctx}
+	server := &dns.Server{Addr: addr, Net: network, ReusePort: true, Handler: handler}
+	server.NotifyStartedFunc = func() {
+		supervisor.Signal(ctx, supervisor.SignalHealthy)
+		supervisor.Logger(ctx).Infof("DNS server listening on %s %s", addr, network)
+		go func() {
+			<-ctx.Done()
+			server.Shutdown()
+		}()
+	}
+	return server.ListenAndServe()
+}
+
+// Requests
+
+// Request represents an incoming DNS query that is being handled.
+type Request struct {
+	// Reply is the reply that will be sent, and should be filled in by the
+	// handler. It is guaranteed to contain exactly one question.
+	Reply *dns.Msg
+	// Writer will be used to send the reply, and contains network information.
+	Writer dns.ResponseWriter
+
+	// Qopt is the OPT record from the query, or nil if not present.
+	Qopt *dns.OPT
+	// Ropt, if non-nil, is the OPT record that will be added to the reply. The
+	// handler can modify this as needed. Ropt is nil when Qopt is nil.
+	Ropt *dns.OPT
+
+	// Qname contains the current question name. This is different from the
+	// original question in Reply.Question[0].Name if a CNAME has been followed
+	// already.
+	Qname string
+
+	// QnameCanonical contains the canonicalized name of the question. This means
+	// that ASCII letters are lowercased.
+	QnameCanonical string
+
+	// Qtype contains the question type for convenient access.
+	Qtype uint16
+
+	// Handled is set to true when the current question name has been handled and
+	// no other handlers should be attempted.
+	Handled bool
+
+	// done is set to true when a reply has been sent. When a CNAME is
+	// encountered, Handled is set to true, but done is false.
+	done bool
+}
+
+// SetAuthoritative marks the reply as authoritative.
+func (r *Request) SetAuthoritative() {
+	// Only set the AA bit if the question has not yet been redirected by CNAME.
+	// See RFC 1034 6.2.7
+	if r.Qname == r.Reply.Question[0].Name {
+		r.Reply.Authoritative = true
+	}
+}
+
+// SendReply sends the reply. It may only be called once.
+func (r *Request) SendReply() {
+	if r.Handled {
+		panic("SendReply called twice for the same DNS request")
+	}
+	r.Handled = true
+	r.done = true
+
+	if r.Ropt != nil {
+		r.Reply.Extra = append(r.Reply.Extra, r.Ropt)
+	} else {
+		// Cannot use extended RCODEs without an OPT, so replace with SERVFAIL.
+		if r.Reply.Rcode > 0xF {
+			r.Reply.Rcode = dns.RcodeServerFailure
+		}
+	}
+
+	size := uint16(0)
+	if r.Writer.RemoteAddr().Network() == "tcp" {
+		size = dns.MaxMsgSize
+	} else if r.Qopt != nil {
+		size = r.Qopt.UDPSize()
+	}
+	if size < dns.MinMsgSize {
+		size = dns.MinMsgSize
+	}
+	r.Reply.Truncate(int(size))
+	if !r.Reply.Compress && r.Reply.Len() >= 1024 {
+		r.Reply.Compress = true
+	}
+
+	r.Writer.WriteMsg(r.Reply)
+}
+
+// SendRcode sets the reply RCODE and sends the reply.
+func (r *Request) SendRcode(rcode int) {
+	r.Reply.Rcode = rcode
+	r.SendReply()
+}
+
+// AddExtendedError adds an Extended DNS Error Option if the reply has an OPT.
+// See RFC 8914.
+func (r *Request) AddExtendedError(infoCode uint16, extraText string) {
+	if r.Ropt != nil {
+		r.Ropt.Option = append(r.Ropt.Option, &dns.EDNS0_EDE{InfoCode: infoCode, ExtraText: extraText})
+	}
+}
+
+// AddCNAME adds a CNAME record to the answer section, and either sends the
+// reply if the query is for the CNAME itself, or else marks the lookup to be
+// restarted at the new name. target must be fully qualified.
+func (r *Request) AddCNAME(target string, ttl uint32) {
+	rr := new(dns.CNAME)
+	rr.Hdr = dns.RR_Header{Name: r.Qname, Rrtype: dns.TypeCNAME, Class: dns.ClassINET, Ttl: ttl}
+	rr.Target = target
+	r.Reply.Answer = append(r.Reply.Answer, rr)
+
+	if r.Qtype == dns.TypeCNAME || r.Qtype == dns.TypeANY {
+		r.SendReply()
+	} else {
+		r.Handled = true
+		r.Qname = target
+		r.QnameCanonical = dns.CanonicalName(r.Qname)
+	}
+}
+
+// Handlers
+
+// Handler can handle DNS requests. The handler should first inspect the query
+// and decide if it wants to handle it. If not, it should return immediately.
+// The next handler will then be tried. Otherwise, it should fill in the Reply,
+// and then call SendReply. The Answer section may already contain CNAMEs that
+// have been followed.
+type Handler interface {
+	HandleDNS(r *Request)
+}
+
+// SetHandler sets the handler of the given name. This name must have been
+// registered when creating the Service. As long as SetHandler has not been
+// called for a registered name, any queries that are not already handled by an
+// earlier handler in the sequence return SERVFAIL. SetHandler may be called
+// multiple times, each call replaces the previous handler of the same name.
+func (s *Service) SetHandler(name string, h Handler) {
+	for i, iname := range s.handlerNames {
+		if iname == name {
+			s.handlers[i].Store(&h)
+			return
+		}
+	}
+	panic(fmt.Sprintf("Attempted to set undeclared DNS handler: %q", name))
+}
+
+// EmptyDNSHandler is a handler that does not handle any queries. It can be used
+// as a placeholder with SetHandler when a handler is inactive.
+type EmptyDNSHandler struct{}
+
+func (EmptyDNSHandler) HandleDNS(*Request) {}
+
+// Serving requests
+
+// advertiseUDPSize is the maximum message size that we advertise in the OPT RR
+// of UDP messages. This is calculated as the minimum IPv6 MTU (1280) minus size
+// of IPv6 (40) and UDP (8) headers.
+const advertiseUDPSize = 1232
+
+// ServeDNS implements dns.Handler.
+func (s *serviceCtx) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
+	defer func() {
+		if rec := recover(); rec != nil {
+			supervisor.Logger(s.ctx).Errorf("panic in DNS handler: %v, stacktrace: %s", rec, string(debug.Stack()))
+		}
+	}()
+
+	// Only QUERY opcode is implemented.
+	if r.Opcode != dns.OpcodeQuery {
+		m := new(dns.Msg)
+		m.SetRcode(r, dns.RcodeNotImplemented)
+		w.WriteMsg(m)
+		return
+	}
+
+	if r.Truncated {
+		m := new(dns.Msg)
+		m.RecursionAvailable = true
+		m.SetRcode(r, dns.RcodeFormatError)
+		w.WriteMsg(m)
+		return
+	}
+
+	// Look for an OPT RR.
+	var opt *dns.OPT
+	for _, rr := range r.Extra {
+		if rr, ok := rr.(*dns.OPT); ok {
+			if opt != nil {
+				// RFC 6891 6.1.1
+				// If a query has more than one OPT RR, FORMERR MUST be returned.
+				m := new(dns.Msg)
+				m.RecursionAvailable = true
+				m.SetRcode(r, dns.RcodeFormatError)
+				w.WriteMsg(m)
+				return
+			}
+			opt = rr
+		}
+	}
+
+	// RFC 6891 6.1.3
+	// If the VERSION of the query is not implemented, BADVERS MUST be returned.
+	if opt != nil && opt.Version() != 0 {
+		m := new(dns.Msg)
+		m.RecursionAvailable = true
+		m.SetRcode(r, dns.RcodeBadVers)
+		m.SetEdns0(advertiseUDPSize, false)
+		w.WriteMsg(m)
+		return
+	}
+
+	// If the OPT name is not the root, the OPT is invalid.
+	if opt != nil && opt.Hdr.Name != "." {
+		m := new(dns.Msg)
+		m.RecursionAvailable = true
+		m.SetRcode(r, dns.RcodeFormatError)
+		w.WriteMsg(m)
+		return
+	}
+
+	// Reuse the query message as the reply message.
+	r.Response = true
+	r.Authoritative = false
+	r.RecursionAvailable = true
+	r.Zero = false
+	r.AuthenticatedData = false
+	r.Rcode = dns.RcodeSuccess
+	r.Extra = nil
+
+	req := &Request{
+		Reply:  r,
+		Writer: w,
+		Qopt:   opt,
+	}
+	if opt != nil {
+		req.Ropt = new(dns.OPT)
+		req.Ropt.Hdr.Name = "."
+		req.Ropt.Hdr.Rrtype = dns.TypeOPT
+		req.Ropt.SetUDPSize(advertiseUDPSize)
+		if opt.Do() {
+			req.Ropt.SetDo()
+		}
+	}
+
+	// Refuse queries that don't have exactly one question of class INET, or that
+	// have non-empty answer or authority sections.
+	if len(r.Question) != 1 || r.Question[0].Qclass != dns.ClassINET || len(r.Answer) != 0 || len(r.Ns) != 0 {
+		r.Answer = nil
+		r.Ns = nil
+		req.SendRcode(dns.RcodeRefused)
+		return
+	}
+	req.Qtype = r.Question[0].Qtype
+	req.Qname = r.Question[0].Name
+	req.QnameCanonical = dns.CanonicalName(req.Qname)
+
+	switch req.Qtype {
+	case dns.TypeOPT:
+		// OPT is a pseudo-RR and may only appear in the additional section.
+		req.SendRcode(dns.RcodeFormatError)
+		return
+	case dns.TypeAXFR, dns.TypeIXFR:
+		// Zone transfer is not supported.
+		req.AddExtendedError(dns.ExtendedErrorCodeNotSupported, "")
+		req.SendRcode(dns.RcodeRefused)
+		return
+	}
+
+	// If we encounter a CNAME, DNS resolution must be restarted with the new
+	// name. That's what this loop is for.
+	i := 0
+	seen := make(map[string]bool)
+	for {
+		prevName := req.QnameCanonical
+		s.service.HandleDNS(req)
+		if req.done {
+			break
+		}
+		req.Handled = false
+		i++
+		seen[prevName] = true
+		if seen[req.QnameCanonical] || i > 7 {
+			if seen[req.QnameCanonical] {
+				req.AddExtendedError(dns.ExtendedErrorCodeOther, "CNAME loop")
+			} else {
+				req.AddExtendedError(dns.ExtendedErrorCodeOther, "too many CNAME redirects")
+			}
+			req.SendRcode(dns.RcodeServerFailure)
+			break
+		}
+	}
+}
+
+func (s *Service) HandleDNS(r *Request) {
+	start := time.Now()
+
+	// Handle localhost.
+	if IsSubDomain("localhost.", r.QnameCanonical) {
+		handleLocalhost(r)
+		return
+	}
+	if IsSubDomain("127.in-addr.arpa.", r.QnameCanonical) ||
+		IsSubDomain("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", r.QnameCanonical) {
+		handleLocalhostPtr(r)
+		return
+	}
+
+	// Serve NXDOMAIN for the "invalid." domain, see RFC 6761.
+	if IsSubDomain("invalid.", r.QnameCanonical) {
+		r.SetAuthoritative()
+		r.SendRcode(dns.RcodeNameError)
+		return
+	}
+
+	for i := range s.handlers {
+		handler := s.handlers[i].Load()
+		if handler == nil {
+			// The application is still starting up. Fail queries instead of leaking
+			// local queries to the Internet and sending the wrong reply.
+			r.AddExtendedError(dns.ExtendedErrorCodeNotReady, fmt.Sprintf("%s handler not ready", s.handlerNames[i]))
+			r.SendRcode(dns.RcodeServerFailure)
+			handlerDuration.WithLabelValues(s.handlerNames[i], "not_ready").Observe(time.Since(start).Seconds())
+			return
+		}
+		(*handler).HandleDNS(r)
+		if r.Handled {
+			rcode, ok := dns.RcodeToString[r.Reply.Rcode]
+			if !ok {
+				// There are 4096 possible Rcodes, so it's probably still fine to put it
+				// in a metric label.
+				rcode = strconv.Itoa(r.Reply.Rcode)
+			}
+			if !r.done {
+				rcode = "redirected"
+			}
+			handlerDuration.WithLabelValues(s.handlerNames[i], rcode).Observe(time.Since(start).Seconds())
+			return
+		}
+	}
+
+	// No handler can handle this request.
+	r.SendRcode(dns.RcodeRefused)
+}
+
+var (
+	localhostA    = netip.MustParseAddr("127.0.0.1").AsSlice()
+	localhostAAAA = netip.MustParseAddr("::1").AsSlice()
+)
+
+const localhostTtl = 60 * 5
+
+func handleLocalhost(r *Request) {
+	r.SetAuthoritative()
+	if r.Qtype == dns.TypeA || r.Qtype == dns.TypeANY {
+		rr := new(dns.A)
+		rr.Hdr = dns.RR_Header{Name: r.Qname, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: localhostTtl}
+		rr.A = localhostA
+		r.Reply.Answer = append(r.Reply.Answer, rr)
+	}
+	if r.Qtype == dns.TypeAAAA || r.Qtype == dns.TypeANY {
+		rr := new(dns.AAAA)
+		rr.Hdr = dns.RR_Header{Name: r.Qname, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: localhostTtl}
+		rr.AAAA = localhostAAAA
+		r.Reply.Answer = append(r.Reply.Answer, rr)
+	}
+	r.SendReply()
+}
+
+func handleLocalhostPtr(r *Request) {
+	r.SetAuthoritative()
+	ip, bits, extra := ParseReverse(r.QnameCanonical)
+	if extra {
+		// Name with extra labels does not exist (e.g. foo.1.0.0.127.in-addr.arpa.)
+		r.Reply.Rcode = dns.RcodeNameError
+	} else if bits != ip.BitLen() {
+		// Partial reverse name (e.g. 127.in-addr.arpa.) exists but has no records.
+	} else if r.Qtype == dns.TypePTR || r.Qtype == dns.TypeANY {
+		rr := new(dns.PTR)
+		rr.Hdr = dns.RR_Header{Name: r.Qname, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: localhostTtl}
+		rr.Ptr = "localhost."
+		r.Reply.Answer = append(r.Reply.Answer, rr)
+	}
+	r.SendReply()
+}
