dns

DNS client and server implementations using the Go project's dnsmessage package
Log | Files | Refs | README | LICENSE

server.go (5828B)


      1 package dns
      2 
      3 import (
      4 	"net"
      5 
      6 	"golang.org/x/net/dns/dnsmessage"
      7 )
      8 
      9 type Zone struct {
     10 	Name      dnsmessage.Name
     11 	SOA       dnsmessage.SOAResource
     12 	Resources []dnsmessage.Resource
     13 }
     14 
     15 // Server contains settings for running a DNS server. An empty Server
     16 // with a nil Handler is a valid configuration.
     17 type Server struct {
     18 	network string
     19 	addr    string
     20 	// Handler is the function which responds to each DNS request
     21 	// received by the server.
     22 	Handler Handler
     23 }
     24 
     25 type response struct {
     26 	raddr net.Addr
     27 	pconn net.PacketConn
     28 	conn  net.Conn
     29 }
     30 
     31 func (r *response) Write(p []byte) (n int, err error) {
     32 	if r.pconn != nil {
     33 		return r.pconn.WriteTo(p, r.raddr)
     34 	}
     35 	return send(p, r.conn)
     36 }
     37 
     38 func (r *response) WriteMsg(msg dnsmessage.Message) error {
     39 	if r.pconn != nil {
     40 		return sendMsgTo(msg, r.pconn, r.raddr)
     41 	}
     42 	return sendMsg(msg, r.conn)
     43 }
     44 
     45 // The ResponseWriter interface is used by a Handler to reply to
     46 // DNS requests.
     47 type ResponseWriter interface {
     48 	// Write writes the data to the underlying connection as a DNS response.
     49 	Write(p []byte) (n int, err error)
     50 	// WriteMsg writes the DNS message to the connection.
     51 	WriteMsg(dnsmessage.Message) error
     52 }
     53 
     54 // A Handler responds to a DNS message. The function should write a reply
     55 // message to ResponseWriter then return.
     56 type Handler func(ResponseWriter, *dnsmessage.Message)
     57 
     58 func (srv *Server) ServePacket(conn net.PacketConn) error {
     59 	if srv.Handler == nil {
     60 		srv.Handler = DefaultHandler
     61 	}
     62 	for {
     63 		buf := make([]byte, 512)
     64 		n, raddr, err := conn.ReadFrom(buf)
     65 		if err != nil {
     66 			return err
     67 		}
     68 		go func() {
     69 			var msg dnsmessage.Message
     70 			if err := msg.Unpack(buf[:n]); err != nil {
     71 				msg.Header.RCode = dnsmessage.RCodeRefused
     72 				sendMsgTo(msg, conn, raddr)
     73 				return
     74 			}
     75 			resp := &response{raddr: raddr, pconn: conn}
     76 			srv.Handler(resp, &msg)
     77 		}()
     78 	}
     79 	return nil
     80 }
     81 
     82 func (srv *Server) Serve(l net.Listener) error {
     83 	defer l.Close()
     84 	if srv.Handler == nil {
     85 		srv.Handler = DefaultHandler
     86 	}
     87 	for {
     88 		conn, err := l.Accept()
     89 		if err != nil {
     90 			return err
     91 		}
     92 		msg, _ := receive(conn)
     93 		resp := &response{conn: conn}
     94 		go srv.Handler(resp, &msg)
     95 	}
     96 }
     97 
     98 func ServePacket(conn net.PacketConn, handler Handler) error {
     99 	srv := &Server{Handler: handler}
    100 	return srv.ServePacket(conn)
    101 }
    102 
    103 func Serve(l net.Listener, handler Handler) error {
    104 	srv := &Server{Handler: handler}
    105 	return srv.Serve(l)
    106 }
    107 
    108 func (srv *Server) ListenAndServe() error {
    109 	if srv.addr == "" {
    110 		srv.addr = ":53"
    111 	}
    112 	switch srv.network {
    113 	case "", "udp", "udp4", "udp6", "unixgram":
    114 		if srv.network == "" {
    115 			srv.network = "udp"
    116 		}
    117 		conn, err := net.ListenPacket(srv.network, srv.addr)
    118 		if err != nil {
    119 			return err
    120 		}
    121 		return srv.ServePacket(conn)
    122 	default:
    123 		l, err := net.Listen(srv.network, srv.addr)
    124 		if err != nil {
    125 			return err
    126 		}
    127 		return srv.Serve(l)
    128 	}
    129 }
    130 
    131 func ListenAndServe(network, addr string, handler Handler) error {
    132 	srv := &Server{network: network, addr: addr, Handler: handler}
    133 	return srv.ListenAndServe()
    134 }
    135 
    136 // DefaultHandler responds to all DNS messages identically; all messages
    137 // are refused. It is intended as a safe default for a Server which
    138 // does not set a Handler.
    139 var DefaultHandler = Refuse
    140 
    141 func respError(w ResponseWriter, msg *dnsmessage.Message, rcode dnsmessage.RCode) {
    142 	w.WriteMsg(dnsmessage.Message{
    143 		Header: dnsmessage.Header{
    144 			ID:               msg.Header.ID,
    145 			Response:         true,
    146 			RecursionDesired: msg.Header.RecursionDesired,
    147 			RCode:            rcode,
    148 		},
    149 		Questions: msg.Questions,
    150 	})
    151 }
    152 
    153 // FormatError replies to the message with a Format Error message.
    154 func FormatError(w ResponseWriter, msg *dnsmessage.Message) {
    155 	respError(w, msg, dnsmessage.RCodeFormatError)
    156 }
    157 
    158 // ServerFailure replies to the message with a Server Failure (SERVFAIL) message.
    159 func ServerFailure(w ResponseWriter, msg *dnsmessage.Message) {
    160 	respError(w, msg, dnsmessage.RCodeServerFailure)
    161 }
    162 
    163 // NotImplemented replies to the message with a Not Implemented
    164 // (NOTIMP) message.
    165 func NotImplemented(w ResponseWriter, msg *dnsmessage.Message) {
    166 	respError(w, msg, dnsmessage.RCodeNotImplemented)
    167 }
    168 
    169 // Refuse replies to the message with a Refused message.
    170 func Refuse(w ResponseWriter, msg *dnsmessage.Message) {
    171 	respError(w, msg, dnsmessage.RCodeRefused)
    172 }
    173 
    174 // NameError replies to the message with a Name error (NXDOMAIN) message.
    175 // The SOA resource and resource header are included in the reply.
    176 // Authoritative servers for the domain in msg should set authoritative to true.
    177 // Others, such as recursive resolvers answers queries, should set this to false.
    178 func NameError(w ResponseWriter, msg *dnsmessage.Message, rh dnsmessage.ResourceHeader, soa dnsmessage.SOAResource, authoritative bool) {
    179 	buf := make([]byte, 2, 512)
    180 	header := dnsmessage.Header{
    181 		ID:               msg.Header.ID,
    182 		Response:         true,
    183 		RecursionDesired: msg.Header.RecursionDesired,
    184 		Authoritative:    authoritative,
    185 		RCode:            dnsmessage.RCodeNameError,
    186 	}
    187 	builder := dnsmessage.NewBuilder(buf, header)
    188 	builder.EnableCompression()
    189 	if err := builder.StartQuestions(); err != nil {
    190 		panic(err)
    191 	}
    192 	for _, q := range msg.Questions {
    193 		if err := builder.Question(q); err != nil {
    194 			panic(err)
    195 		}
    196 	}
    197 	if err := builder.StartAuthorities; err != nil {
    198 		panic(err)
    199 	}
    200 	if err := builder.SOAResource(rh, soa); err != nil {
    201 		panic(err)
    202 	}
    203 	buf, err := builder.Finish()
    204 	if err != nil {
    205 		panic(err)
    206 	}
    207 	w.Write(buf[2:])
    208 }
    209 
    210 // ExtractIPs extracts any IP addresses from resources. An empty slice is
    211 // returned if there are no addresses.
    212 func ExtractIPs(resources []dnsmessage.Resource) []net.IP {
    213 	var ips []net.IP
    214 	for _, r := range resources {
    215 		switch b := r.Body.(type) {
    216 		case *dnsmessage.AResource:
    217 			ips = append(ips, net.IP(b.A[:]))
    218 		case *dnsmessage.AAAAResource:
    219 			ips = append(ips, net.IP(b.AAAA[:]))
    220 		}
    221 	}
    222 	return ips
    223 }