Просмотр исходного кода

Switch up order of query checks in server.

We should set the AA bit if it applies, even if there are things wrong
with the query. An EDNS(0)-related error supersedes all others.
David Fifield 6 лет назад
Родитель
Сommit
f8b9d73493
1 измененных файлов с 31 добавлено и 21 удалено
  1. 31 21
      dnstt-server/main.go

+ 31 - 21
dnstt-server/main.go

@@ -179,7 +179,7 @@ func responseFor(query *dns.Message, domain dns.Name) (*dns.Message, turbotunnel
 
 	resp := &dns.Message{
 		ID:       query.ID,
-		Flags:    0x8400, // QR = 1, AA = 1, RCODE = no error
+		Flags:    0x8000, // QR = 1, RCODE = no error
 		Question: query.Question,
 	}
 
@@ -234,43 +234,53 @@ func responseFor(query *dns.Message, domain dns.Name) (*dns.Message, turbotunnel
 			payloadSize = 512
 		}
 	}
+	// We will return RcodeFormatError if payloadSize is too small, but
+	// first, check the name in order to set the AA bit properly.
+
+	// There must be exactly one question.
+	if len(query.Question) != 1 {
+		resp.Flags |= dns.RcodeFormatError
+		return resp, clientID, nil
+	}
+	question := query.Question[0]
+	// Check the name to see if it ends in our chosen domain, and extract
+	// all that comes before the domain if it does. If it does not, we will
+	// return RcodeNameError below, but prefer to return RcodeFormatError
+	// for payload size if that applies as well.
+	prefix, ok := question.Name.TrimSuffix(domain)
+	if ok {
+		resp.Flags |= 0x0400 // AA = 1
+	}
+
+	// We require clients to support EDNS(0) with a minimum payload size;
+	// otherwise we would have to set a small KCP MTU (only around 200
+	// bytes). https://tools.ietf.org/html/rfc6891#section-7 "If there is a
+	// problem with processing the OPT record itself, such as an option
+	// value that is badly formatted or that includes out-of-range values, a
+	// FORMERR MUST be returned."
 	if payloadSize < maxUDPPayload {
-		// We require clients to support EDNS(0) with a minimum payload
-		// size; otherwise we would have to set a small KCP MTU (only
-		// around 200 bytes).
-		// https://tools.ietf.org/html/rfc6891#section-7
-		// "If there is a problem with processing the OPT record itself,
-		// such as an option value that is badly formatted or that
-		// includes out-of-range values, a FORMERR MUST be returned."
 		resp.Flags |= dns.RcodeFormatError
 		return resp, clientID, nil
 	}
 
+	if resp.Flags|0x0400 == 0 { // AA
+		// Not a name we are authoritative for.
+		resp.Flags |= dns.RcodeNameError
+		return resp, clientID, nil
+	}
+
 	if query.Flags&0x7800 != 0 {
 		// We don't support OPCODE != QUERY.
 		resp.Flags |= dns.RcodeNotImplemented
 		return resp, clientID, nil
 	}
 
-	if len(query.Question) != 1 {
-		// There must be exactly one question.
-		resp.Flags |= dns.RcodeFormatError
-		return resp, clientID, nil
-	}
-	question := query.Question[0]
 	if question.Type != dns.RRTypeTXT {
 		// We only support QTYPE == TXT.
 		resp.Flags |= dns.RcodeNotImplemented
 		return resp, clientID, nil
 	}
 
-	prefix, ok := question.Name.TrimSuffix(domain)
-	if !ok {
-		// Not a name we are authoritative for.
-		resp.Flags |= dns.RcodeNameError
-		return resp, clientID, nil
-	}
-
 	encoded := bytes.ToUpper(bytes.Join(prefix, nil))
 	payload := make([]byte, base32Encoding.DecodedLen(len(encoded)))
 	n, err := base32Encoding.Decode(payload, encoded)