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 }