git » dnss » commit d2b7394

dnstogrpc: Create our own request IDs

author Alberto Bertogli
2015-10-24 01:05:26 UTC
committer Alberto Bertogli
2015-10-24 15:48:31 UTC
parent d8e5ab77f9137a9e6d12d616325c176a85a2e47c

dnstogrpc: Create our own request IDs

If we have multiple users, it's not that unlikely that they will pick the same
ID, causing problems with replies.

This patch makes dnss create its own request IDs for outgoing requests.
We create them at random so responses are more difficult to fake.

dnstogrpc/dnstogrpc.go +33 -2

diff --git a/dnstogrpc/dnstogrpc.go b/dnstogrpc/dnstogrpc.go
index 7cd0135..9dac93d 100644
--- a/dnstogrpc/dnstogrpc.go
+++ b/dnstogrpc/dnstogrpc.go
@@ -3,6 +3,9 @@
 package dnstogrpc
 
 import (
+	"crypto/rand"
+	"encoding/binary"
+	"fmt"
 	"strings"
 	"sync"
 	"time"
@@ -17,6 +20,31 @@ import (
 	"google.golang.org/grpc/credentials"
 )
 
+// newID is a channel used to generate new request IDs.
+// There is a goroutine created at init() time that will get IDs randomly, to
+// help prevent guesses.
+var newId chan uint16
+
+func init() {
+	// Buffer 100 numbers to avoid blocking on crypto rand.
+	newId = make(chan uint16, 100)
+
+	go func() {
+		var id uint16
+		var err error
+
+		for {
+			err = binary.Read(rand.Reader, binary.LittleEndian, &id)
+			if err != nil {
+				panic(fmt.Sprintf("error creating id: %v", err))
+			}
+
+			newId <- id
+		}
+
+	}()
+}
+
 type grpcclient struct {
 	Upstream string
 	CAFile   string
@@ -109,8 +137,10 @@ func (s *Server) Handler(w dns.ResponseWriter, r *dns.Msg) {
 		}
 	}
 
-	// TODO: we should create our own IDs, in case different users pick the
-	// same id and we pass that upstream.
+	// Create our own IDs, in case different users pick the same id and we
+	// pass that upstream.
+	oldid := r.Id
+	r.Id = <-newId
 
 	from_up, err := s.client.Query(r)
 	if err != nil {
@@ -124,6 +154,7 @@ func (s *Server) Handler(w dns.ResponseWriter, r *dns.Msg) {
 		util.TraceAnswer(tr, from_up)
 	}
 
+	from_up.Id = oldid
 	w.WriteMsg(from_up)
 }