git » dnss » commit d9c8bd2

Split but DNS all the way

author Alberto Bertogli
2015-09-06 22:14:22 UTC
committer Alberto Bertogli
2015-09-06 22:14:22 UTC
parent 94ba7d7f57d888333a018f256bdafc97600b4279

Split but DNS all the way

dnss.go +32 -3
dnstogrpc/dnstogrpc.go +5 -6
grpctodns/grpctodns.go +81 -0

diff --git a/dnss.go b/dnss.go
index ea6df66..9c30f84 100644
--- a/dnss.go
+++ b/dnss.go
@@ -5,14 +5,23 @@ package main
 
 import (
 	"flag"
+	"sync"
 
 	"blitiri.com.ar/go/dnss/dnstogrpc"
+	"blitiri.com.ar/go/dnss/grpctodns"
 	"blitiri.com.ar/go/profile"
 )
 
 var (
-	dnsaddr     = flag.String("dnsaddr", ":53", "address to listen on")
-	dnsupstream = flag.String("dnsupstream", "8.8.8.8:53", "upstream address")
+	dnsaddr = flag.String("dnsaddr", ":53",
+		"address to listen on for DNS")
+	grpcupstream = flag.String("grpcupstream", "localhost:9953",
+		"address of the upstream GRPC server")
+
+	grpcaddr = flag.String("grpcaddr", ":9953",
+		"address to listen on for GRPC")
+	dnsupstream = flag.String("dnsupstream", "8.8.8.8:53",
+		"address of the upstream DNS server")
 )
 
 func main() {
@@ -20,9 +29,29 @@ func main() {
 
 	profile.Init()
 
+	var wg sync.WaitGroup
+
+	// DNS to GRPC.
 	dtg := &dnstogrpc.Server{
 		Addr:     *dnsaddr,
+		Upstream: *grpcupstream,
+	}
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		dtg.ListenAndServe()
+	}()
+
+	// GRPC to DNS.
+	gtd := &grpctodns.Server{
+		Addr:     *grpcaddr,
 		Upstream: *dnsupstream,
 	}
-	dtg.ListenAndServe()
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		gtd.ListenAndServe()
+	}()
+
+	wg.Wait()
 }
diff --git a/dnstogrpc/dnstogrpc.go b/dnstogrpc/dnstogrpc.go
index ced0d05..e59c59f 100644
--- a/dnstogrpc/dnstogrpc.go
+++ b/dnstogrpc/dnstogrpc.go
@@ -38,25 +38,24 @@ type Server struct {
 }
 
 func (s *Server) Handler(w dns.ResponseWriter, r *dns.Msg) {
-	fmt.Printf("%v %v\n", l(w, r), questionsToString(r.Question))
+	fmt.Printf("DNS  %v %v\n", l(w, r), questionsToString(r.Question))
 
 	// TODO: we should create our own IDs, in case different users pick the
 	// same id and we pass that upstream.
 
 	from_up, err := dns.Exchange(r, s.Upstream)
 	if err != nil {
-		fmt.Printf("%v  ERR: %v\n", l(w, r), err)
-		fmt.Printf("%v  UP: %v\n", l(w, r), from_up)
+		fmt.Printf("DNS  %v  ERR: %v\n", l(w, r), err)
+		fmt.Printf("DNS  %v  UP: %v\n", l(w, r), from_up)
 	}
 
 	if from_up != nil {
 		if from_up.Rcode != dns.RcodeSuccess {
 			rcode := dns.RcodeToString[from_up.Rcode]
-			fmt.Printf("%v  !->  %v\n", l(w, r), rcode)
-
+			fmt.Printf("DNS  %v  !->  %v\n", l(w, r), rcode)
 		}
 		for _, rr := range from_up.Answer {
-			fmt.Printf("%v  ->  %v\n", l(w, r), rr)
+			fmt.Printf("DNS  %v  ->  %v\n", l(w, r), rr)
 		}
 		w.WriteMsg(from_up)
 	}
diff --git a/grpctodns/grpctodns.go b/grpctodns/grpctodns.go
new file mode 100644
index 0000000..37771fc
--- /dev/null
+++ b/grpctodns/grpctodns.go
@@ -0,0 +1,81 @@
+// GRPC to DNS.
+
+package grpctodns
+
+import (
+	"fmt"
+	"strings"
+	"sync"
+
+	"github.com/miekg/dns"
+)
+
+func questionsToString(qs []dns.Question) string {
+	var s []string
+	for _, q := range qs {
+		s = append(s, fmt.Sprintf("(%s %s %s)", q.Name,
+			dns.TypeToString[q.Qtype], dns.ClassToString[q.Qclass]))
+	}
+	return "Q[" + strings.Join(s, " ") + "]"
+}
+
+func rrsToString(rrs []dns.RR) string {
+	var s []string
+	for _, rr := range rrs {
+		s = append(s, fmt.Sprintf("(%s)", rr))
+	}
+	return "RR[" + strings.Join(s, " ") + "]"
+
+}
+
+func l(w dns.ResponseWriter, r *dns.Msg) string {
+	return fmt.Sprintf("%v %v", w.RemoteAddr(), r.Id)
+}
+
+type Server struct {
+	Addr     string
+	Upstream string
+}
+
+func (s *Server) Handler(w dns.ResponseWriter, r *dns.Msg) {
+	fmt.Printf("GRPC %v %v\n", l(w, r), questionsToString(r.Question))
+
+	// TODO: we should create our own IDs, in case different users pick the
+	// same id and we pass that upstream.
+
+	from_up, err := dns.Exchange(r, s.Upstream)
+	if err != nil {
+		fmt.Printf("GRPC %v  ERR: %v\n", l(w, r), err)
+		fmt.Printf("GRPC %v  UP: %v\n", l(w, r), from_up)
+	}
+
+	if from_up != nil {
+		if from_up.Rcode != dns.RcodeSuccess {
+			rcode := dns.RcodeToString[from_up.Rcode]
+			fmt.Printf("GPRC %v  !->  %v\n", l(w, r), rcode)
+		}
+		for _, rr := range from_up.Answer {
+			fmt.Printf("GRPC %v  ->  %v\n", l(w, r), rr)
+		}
+		w.WriteMsg(from_up)
+	}
+}
+
+func (s *Server) ListenAndServe() {
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		err := dns.ListenAndServe(s.Addr, "udp", dns.HandlerFunc(s.Handler))
+		fmt.Printf("Exiting UDP: %v\n", err)
+	}()
+
+	wg.Add(1)
+	go func() {
+		defer wg.Done()
+		err := dns.ListenAndServe(s.Addr, "tcp", dns.HandlerFunc(s.Handler))
+		fmt.Printf("Exiting TCP: %v\n", err)
+	}()
+
+	wg.Wait()
+}