git » dnss » commit bea88d7

Drop GRPC support

author Alberto Bertogli
2017-07-20 20:19:30 UTC
committer Alberto Bertogli
2017-07-20 20:55:36 UTC
parent d910982e989036db80259653a5d08d204a9fa31e

Drop GRPC support

With HTTPS support, the GRPC mode is not very practical, but it adds
significant complexity and overhead.

This patch removes it, leaving only the dns-to-https mode.

In the future, an https-to-dns mode will be added, so that end-to-end
operation is still possible.

README.md +1 -27
dnss.go +8 -72
etc/systemd/dns-to-grpc/dnss.service +0 -35
etc/systemd/dns-to-grpc/dnss.socket +0 -11
etc/systemd/grpc-to-dns/dnss.service +0 -24
glide.lock +2 -39
glide.yaml +0 -8
internal/{dnstox => dnstohttps}/caching_test.go +1 -1
internal/{dnstox => dnstohttps}/resolver.go +4 -72
internal/{dnstox/dnstox.go => dnstohttps/server.go} +4 -4
internal/grpctodns/grpctodns.go +0 -109
internal/proto/dnss.pb.go +0 -134
internal/proto/dnss.proto +0 -15
internal/proto/dummy.go +0 -4
monitoring_test.go +0 -6
testing/grpc/grpc.go +0 -4
testing/grpc/grpc_test.go +0 -243
testing/https/https_test.go +3 -3

diff --git a/README.md b/README.md
index 4cbc71f..3493e96 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,7 @@
 
 # dnss
 
-dnss is a tool for encapsulating DNS over more secure protocols, like HTTPS or
-GRPC.
+dnss is a tool for encapsulating DNS over HTTPS.
 
 ## Quick start
 
@@ -43,31 +42,6 @@ server.
 ```
 
 
-## DNS over GRPC
-
-dnss can encapsulate DNS over GRPC.
-
-It can be useful when you want to use a particular DNS server, but don't want
-some parts of the network in between to be able to see your traffic.
-
-
-```
-+--------+       +---------------+        +---------------+      +------------+
-|        |       |     dnss      |        |     dnss      |      |            |
-| client +-------> (dns-to-grpc) +--------> (grpc-to-dns) +------> DNS server |
-|        |  DNS  |               |  DNS   |               | DNS  |            |
-+--------+  UDP  +---------------+  GRPC  +---------------+ UDP  +------------+
-                                    SSL
-                                    TCP
-```
-
-In "dns-to-grpc" mode, it listens to DNS requests and pass them on to a server
-using GRPC. It also has a small cache.
-
-In "grpc-to-dns" mode, it receives DNS requests via GRPC, and resolves them
-using a normal, fixed DNS server.
-
-
 ## Alternatives
 
 https://dnscrypt.org/ is a great, more end-to-end alternative to dnss.
diff --git a/dnss.go b/dnss.go
index 3912fa0..387f675 100644
--- a/dnss.go
+++ b/dnss.go
@@ -8,17 +8,12 @@ import (
 	"sync"
 	"time"
 
-	"blitiri.com.ar/go/dnss/internal/dnstox"
-	"blitiri.com.ar/go/dnss/internal/grpctodns"
+	"blitiri.com.ar/go/dnss/internal/dnstohttps"
 
 	"github.com/golang/glog"
-	"google.golang.org/grpc"
 
 	// Register pprof handlers for monitoring and debugging.
 	_ "net/http/pprof"
-
-	// Make GRPC log to glog.
-	_ "google.golang.org/grpc/grpclog/glogger"
 )
 
 var (
@@ -34,20 +29,6 @@ var (
 		"Domains we resolve via DNS, using --fallback_upstream"+
 			" (space-separated list)")
 
-	enableDNStoGRPC = flag.Bool("enable_dns_to_grpc", false,
-		"enable DNS-to-GRPC server")
-	grpcUpstream = flag.String("grpc_upstream", "localhost:9953",
-		"address of the upstream GRPC server")
-	grpcClientCAFile = flag.String("grpc_client_cafile", "",
-		"CA file to use for the GRPC client")
-
-	enableGRPCtoDNS = flag.Bool("enable_grpc_to_dns", false,
-		"enable GRPC-to-DNS server")
-	grpcListenAddr = flag.String("grpc_listen_addr", ":9953",
-		"address to listen on for GRPC")
-	dnsUpstream = flag.String("dns_upstream", "8.8.8.8:53",
-		"address of the upstream DNS server")
-
 	enableDNStoHTTPS = flag.Bool("enable_dns_to_https", false,
 		"enable DNS-to-HTTPS proxy")
 	httpsUpstream = flag.String("https_upstream",
@@ -56,11 +37,6 @@ var (
 	httpsClientCAFile = flag.String("https_client_cafile", "",
 		"CA file to use for the HTTPS client")
 
-	grpcCert = flag.String("grpc_cert", "",
-		"certificate file for the GRPC server")
-	grpcKey = flag.String("grpc_key", "",
-		"key file for the GRPC server")
-
 	logFlushEvery = flag.Duration("log_flush_every", 30*time.Second,
 		"how often to flush logs")
 	monitoringListenAddr = flag.String("monitoring_listen_addr", "",
@@ -81,63 +57,24 @@ func main() {
 
 	go flushLogs()
 
-	grpc.EnableTracing = false
 	if *monitoringListenAddr != "" {
 		launchMonitoringServer(*monitoringListenAddr)
 	}
 
-	if !*enableDNStoGRPC && !*enableGRPCtoDNS && !*enableDNStoHTTPS {
+	if !*enableDNStoHTTPS {
 		glog.Error("Need to set one of the following:")
 		glog.Error("  --enable_dns_to_https")
-		glog.Error("  --enable_dns_to_grpc")
-		glog.Error("  --enable_grpc_to_dns")
-		glog.Fatal("")
-	}
-
-	if *enableDNStoGRPC && *enableDNStoHTTPS {
-		glog.Error("The following options cannot be set at the same time:")
-		glog.Error("  --enable_dns_to_grpc and --enable_dns_to_https")
 		glog.Fatal("")
 	}
 
 	var wg sync.WaitGroup
 
-	// DNS to GRPC.
-	if *enableDNStoGRPC {
-		r := dnstox.NewGRPCResolver(*grpcUpstream, *grpcClientCAFile)
-		cr := dnstox.NewCachingResolver(r)
-		cr.RegisterDebugHandlers()
-		dtg := dnstox.New(*dnsListenAddr, cr, *dnsUnqualifiedUpstream)
-		dtg.SetFallback(
-			*fallbackUpstream, strings.Split(*fallbackDomains, " "))
-		wg.Add(1)
-		go func() {
-			defer wg.Done()
-			dtg.ListenAndServe()
-		}()
-	}
-
-	// GRPC to DNS.
-	if *enableGRPCtoDNS {
-		gtd := &grpctodns.Server{
-			Addr:     *grpcListenAddr,
-			Upstream: *dnsUpstream,
-			CertFile: *grpcCert,
-			KeyFile:  *grpcKey,
-		}
-		wg.Add(1)
-		go func() {
-			defer wg.Done()
-			gtd.ListenAndServe()
-		}()
-	}
-
 	// DNS to HTTPS.
 	if *enableDNStoHTTPS {
-		r := dnstox.NewHTTPSResolver(*httpsUpstream, *httpsClientCAFile)
-		cr := dnstox.NewCachingResolver(r)
+		r := dnstohttps.NewHTTPSResolver(*httpsUpstream, *httpsClientCAFile)
+		cr := dnstohttps.NewCachingResolver(r)
 		cr.RegisterDebugHandlers()
-		dth := dnstox.New(*dnsListenAddr, cr, *dnsUnqualifiedUpstream)
+		dth := dnstohttps.New(*dnsListenAddr, cr, *dnsUnqualifiedUpstream)
 		dth.SetFallback(
 			*fallbackUpstream, strings.Split(*fallbackDomains, " "))
 		wg.Add(1)
@@ -152,7 +89,6 @@ func main() {
 
 func launchMonitoringServer(addr string) {
 	glog.Infof("Monitoring HTTP server listening on %s", addr)
-	grpc.EnableTracing = true
 
 	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
 		if r.URL.Path != "/" {
@@ -183,10 +119,10 @@ const monitoringHTMLIndex = `<!DOCTYPE html>
           <small><a href="https://godoc.org/golang.org/x/net/trace">
             (ref)</a></small>
         <ul>
-          <li><a href="/debug/requests?fam=dnstox&b=11">dnstox latency</a>
-          <li><a href="/debug/requests?fam=dnstox&b=0&exp=1">dnstox trace</a>
+          <li><a href="/debug/requests?fam=dnstohttp&b=11">dnstohttp latency</a>
+          <li><a href="/debug/requests?fam=dnstohttp&b=0&exp=1">dnstohttp trace</a>
         </ul>
-      <li><a href="/debug/dnstox/cache/dump">cache dump</a>
+      <li><a href="/debug/dnstohttp/cache/dump">cache dump</a>
       <li><a href="/debug/pprof">pprof</a>
           <small><a href="https://golang.org/pkg/net/http/pprof/">
             (ref)</a></small>
diff --git a/etc/systemd/dns-to-grpc/dnss.service b/etc/systemd/dns-to-grpc/dnss.service
deleted file mode 100644
index bf4e3d8..0000000
--- a/etc/systemd/dns-to-grpc/dnss.service
+++ /dev/null
@@ -1,35 +0,0 @@
-[Unit]
-Description = dnss daemon - DNS to GRPC mode
-
-# Note we get the sockets via systemd, see the matching .socket configuration.
-Requires=dnss.socket
-
-
-[Service]
-ExecStart = /usr/bin/dnss \
-        --dns_listen_addr=systemd \
-        --logtostderr \
-        --monitoring_listen_addr=127.0.0.1:8081 \
-        --grpc_upstream=1.2.3.4:9953 \
-        --grpc_client_cafile=/etc/ssl/dnss/1.2.3.4-cert.pem \
-        --enable_dns_to_grpc
-
-
-Type = simple
-Restart = always
-
-# The user can be created with no permissions using:
-#
-#   sudo useradd -U dnss -M -d /nonexistent -s /bin/false
-User = ddns
-Group = ddns
-
-# Simple security measures just in case.
-CapabilityBoundingSet = CAP_NET_BIND_SERVICE
-ProtectSystem = full
-
-
-[Install]
-Also=dnss.socket
-WantedBy = multi-user.target
-
diff --git a/etc/systemd/dns-to-grpc/dnss.socket b/etc/systemd/dns-to-grpc/dnss.socket
deleted file mode 100644
index b73523c..0000000
--- a/etc/systemd/dns-to-grpc/dnss.socket
+++ /dev/null
@@ -1,11 +0,0 @@
-# Sockets for dnss.
-#
-# This lets dnss run unprivileged.
-# We typically want one UDP and one TCP socket.
-
-[Socket]
-ListenDatagram=53
-ListenStream=53
-
-[Install]
-WantedBy=sockets.target
diff --git a/etc/systemd/grpc-to-dns/dnss.service b/etc/systemd/grpc-to-dns/dnss.service
deleted file mode 100644
index 8fa8086..0000000
--- a/etc/systemd/grpc-to-dns/dnss.service
+++ /dev/null
@@ -1,24 +0,0 @@
-[Unit]
-Description = dnss daemon - GRPC to DNS mode
-
-[Service]
-ExecStart = /usr/bin/dnss --enable_grpc_to_dns \
-        --grpc_key=/etc/ssl/dnss/key.pem \
-        --grpc_cert=/etc/ssl/dnss/cert.pem
-        --monitoring_listen_addr=127.0.0.1:9981 \
-        --logtostderr
-
-Type = simple
-Restart = always
-
-User = ddns
-Group = ddns
-
-# Simple security measures just in case.
-CapabilityBoundingSet =
-ProtectSystem = full
-
-
-[Install]
-WantedBy = multi-user.target
-
diff --git a/glide.lock b/glide.lock
index 2724777..b9758bb 100644
--- a/glide.lock
+++ b/glide.lock
@@ -1,5 +1,5 @@
-hash: 7c3cf09373a10a9df1e6cd5211536c7df297cec6a21fabe892e1fe6bb0ae9299
-updated: 2017-07-20T21:39:59.861060145+01:00
+hash: cd4dafdd5dd49f7f5d85dd415a539241f92f43a98c217988b923600a41e5ba20
+updated: 2017-07-20T21:55:24.1551437+01:00
 imports:
 - name: github.com/coreos/go-systemd
   version: 24036eb3df68550d24a2736c5d013f4e83366866
@@ -7,49 +7,12 @@ imports:
   - activation
 - name: github.com/golang/glog
   version: 23def4e6c14b4da8ac2ed8007337bc5eb5007998
-- name: github.com/golang/protobuf
-  version: 0a4f71a498b7c4812f64969510bcb4eca251e33a
-  subpackages:
-  - proto
-  - ptypes/any
 - name: github.com/miekg/dns
   version: 0559e6d230af0a3a7273853cb6994ebea21bfbe5
 - name: golang.org/x/net
   version: 7b7efd8000731a766f6cbfa2c04010627521c66e
   subpackages:
   - context
-  - http2
-  - http2/hpack
-  - idna
   - internal/timeseries
-  - lex/httplex
   - trace
-- name: golang.org/x/text
-  version: 836efe42bb4aa16aaa17b9c155d8813d336ed720
-  subpackages:
-  - secure/bidirule
-  - transform
-  - unicode/bidi
-  - unicode/norm
-- name: google.golang.org/genproto
-  version: b0a3dcfcd1a9bd48e63634bd8802960804cf8315
-  subpackages:
-  - googleapis/rpc/status
-- name: google.golang.org/grpc
-  version: 98eab9baf699acbb896058ccc7ae946afce855ac
-  subpackages:
-  - codes
-  - credentials
-  - grpclb/grpc_lb_v1
-  - grpclog
-  - grpclog/glogger
-  - internal
-  - keepalive
-  - metadata
-  - naming
-  - peer
-  - stats
-  - status
-  - tap
-  - transport
 testImports: []
diff --git a/glide.yaml b/glide.yaml
index 74eea02..8ea24ac 100644
--- a/glide.yaml
+++ b/glide.yaml
@@ -4,15 +4,7 @@ import:
   subpackages:
   - activation
 - package: github.com/golang/glog
-- package: github.com/golang/protobuf
-  subpackages:
-  - proto
 - package: github.com/miekg/dns
 - package: golang.org/x/net
   subpackages:
-  - context
   - trace
-- package: google.golang.org/grpc
-  subpackages:
-  - credentials
-  - grpclog/glogger
diff --git a/internal/dnstox/caching_test.go b/internal/dnstohttps/caching_test.go
similarity index 99%
rename from internal/dnstox/caching_test.go
rename to internal/dnstohttps/caching_test.go
index 778972d..9c35eee 100644
--- a/internal/dnstox/caching_test.go
+++ b/internal/dnstohttps/caching_test.go
@@ -1,4 +1,4 @@
-package dnstox
+package dnstohttps
 
 // Tests for the caching resolver.
 // Note the other resolvers have more functional tests in the testing/
diff --git a/internal/dnstox/resolver.go b/internal/dnstohttps/resolver.go
similarity index 87%
rename from internal/dnstox/resolver.go
rename to internal/dnstohttps/resolver.go
index f0e6f54..2ebf82c 100644
--- a/internal/dnstox/resolver.go
+++ b/internal/dnstohttps/resolver.go
@@ -1,4 +1,4 @@
-package dnstox
+package dnstohttps
 
 import (
 	"crypto/tls"
@@ -14,14 +14,9 @@ import (
 
 	"github.com/golang/glog"
 	"github.com/miekg/dns"
-	"golang.org/x/net/context"
 	"golang.org/x/net/trace"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/credentials"
 
 	"bytes"
-
-	pb "blitiri.com.ar/go/dnss/internal/proto"
 )
 
 // Interface for DNS resolvers that can answer queries.
@@ -37,69 +32,6 @@ type Resolver interface {
 	Query(r *dns.Msg, tr trace.Trace) (*dns.Msg, error)
 }
 
-///////////////////////////////////////////////////////////////////////////
-// GRPC resolver.
-
-// grpcResolver implements the Resolver interface by querying a server via
-// GRPC.
-type grpcResolver struct {
-	Upstream string
-	CAFile   string
-	client   pb.DNSServiceClient
-}
-
-func NewGRPCResolver(upstream, caFile string) *grpcResolver {
-	return &grpcResolver{
-		Upstream: upstream,
-		CAFile:   caFile,
-	}
-}
-
-func (g *grpcResolver) Init() error {
-	var err error
-	var creds credentials.TransportCredentials
-	if g.CAFile == "" {
-		creds = credentials.NewClientTLSFromCert(nil, "")
-	} else {
-		creds, err = credentials.NewClientTLSFromFile(g.CAFile, "")
-		if err != nil {
-			return err
-		}
-	}
-
-	conn, err := grpc.Dial(g.Upstream, grpc.WithTransportCredentials(creds))
-	if err != nil {
-		return err
-	}
-
-	g.client = pb.NewDNSServiceClient(conn)
-	return nil
-}
-
-func (g *grpcResolver) Maintain() {
-}
-
-func (g *grpcResolver) Query(r *dns.Msg, tr trace.Trace) (*dns.Msg, error) {
-	buf, err := r.Pack()
-	if err != nil {
-		return nil, err
-	}
-
-	// Give our RPCs 2 second timeouts: DNS usually doesn't wait that long
-	// anyway.
-	ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
-	defer cancel()
-
-	reply, err := g.client.Query(ctx, &pb.RawMsg{Data: buf})
-	if err != nil {
-		return nil, err
-	}
-
-	m := &dns.Msg{}
-	err = m.Unpack(reply.Data)
-	return m, err
-}
-
 ///////////////////////////////////////////////////////////////////////////
 // HTTPS resolver.
 
@@ -358,8 +290,8 @@ func (c *cachingResolver) Init() error {
 // Note these are global by nature, if you try to register them multiple
 // times, you will get a panic.
 func (c *cachingResolver) RegisterDebugHandlers() {
-	http.HandleFunc("/debug/dnstox/cache/dump", c.DumpCache)
-	http.HandleFunc("/debug/dnstox/cache/flush", c.FlushCache)
+	http.HandleFunc("/debug/dnstohttps/cache/dump", c.DumpCache)
+	http.HandleFunc("/debug/dnstohttps/cache/flush", c.FlushCache)
 }
 
 func (c *cachingResolver) DumpCache(w http.ResponseWriter, r *http.Request) {
@@ -405,7 +337,7 @@ func (c *cachingResolver) Maintain() {
 	go c.back.Maintain()
 
 	for range time.Tick(maintenancePeriod) {
-		tr := trace.New("dnstox.Cache", "GC")
+		tr := trace.New("dnstohttps.Cache", "GC")
 		var total, expired int
 
 		c.mu.Lock()
diff --git a/internal/dnstox/dnstox.go b/internal/dnstohttps/server.go
similarity index 97%
rename from internal/dnstox/dnstox.go
rename to internal/dnstohttps/server.go
index 3fce7c4..8ee13f7 100644
--- a/internal/dnstox/dnstox.go
+++ b/internal/dnstohttps/server.go
@@ -1,6 +1,6 @@
-// DNS to GRPC.
-
-package dnstox
+// Package dnstohttps implements a DNS proxy that uses HTTPS to resolve the
+// requests.
+package dnstohttps
 
 import (
 	"crypto/rand"
@@ -69,7 +69,7 @@ func (s *Server) SetFallback(upstream string, domains []string) {
 }
 
 func (s *Server) Handler(w dns.ResponseWriter, r *dns.Msg) {
-	tr := trace.New("dnstox", "Handler")
+	tr := trace.New("dnstohttp", "Handler")
 	defer tr.Finish()
 
 	tr.LazyPrintf("from:%v   id:%v", w.RemoteAddr(), r.Id)
diff --git a/internal/grpctodns/grpctodns.go b/internal/grpctodns/grpctodns.go
deleted file mode 100644
index 3ddf5a8..0000000
--- a/internal/grpctodns/grpctodns.go
+++ /dev/null
@@ -1,109 +0,0 @@
-// GRPC to DNS.
-
-package grpctodns
-
-import (
-	"fmt"
-	"net"
-	"strings"
-
-	pb "blitiri.com.ar/go/dnss/internal/proto"
-	"blitiri.com.ar/go/dnss/internal/util"
-	"github.com/golang/glog"
-	"github.com/miekg/dns"
-	"golang.org/x/net/context"
-	"golang.org/x/net/trace"
-	"google.golang.org/grpc"
-	"google.golang.org/grpc/credentials"
-)
-
-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, " ") + "]"
-
-}
-
-type Server struct {
-	Addr     string
-	Upstream string
-	CertFile string
-	KeyFile  string
-}
-
-func (s *Server) Query(ctx context.Context, in *pb.RawMsg) (*pb.RawMsg, error) {
-	tr := trace.New("grpctodns", "Query")
-	defer tr.Finish()
-
-	r := &dns.Msg{}
-	err := r.Unpack(in.Data)
-	if err != nil {
-		return nil, err
-	}
-
-	if glog.V(3) {
-		tr.LazyPrintf(util.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 {
-		msg := fmt.Sprintf("dns exchange error: %v", err)
-		glog.Info(msg)
-		tr.LazyPrintf(msg)
-		tr.SetError()
-		return nil, err
-	}
-
-	if from_up == nil {
-		err = fmt.Errorf("no response from upstream")
-		tr.LazyPrintf(err.Error())
-		tr.SetError()
-		return nil, err
-	}
-
-	if glog.V(3) {
-		util.TraceAnswer(tr, from_up)
-	}
-
-	buf, err := from_up.Pack()
-	if err != nil {
-		glog.Infof("   error packing: %v", err)
-		tr.LazyPrintf("error packing: %v", err)
-		tr.SetError()
-		return nil, err
-	}
-
-	return &pb.RawMsg{Data: buf}, nil
-}
-
-func (s *Server) ListenAndServe() {
-	lis, err := net.Listen("tcp", s.Addr)
-	if err != nil {
-		glog.Fatalf("failed to listen: %v", err)
-	}
-
-	ta, err := credentials.NewServerTLSFromFile(s.CertFile, s.KeyFile)
-	if err != nil {
-		glog.Fatalf("failed to create TLS transport auth: %v", err)
-	}
-
-	grpcServer := grpc.NewServer(grpc.Creds(ta))
-	pb.RegisterDNSServiceServer(grpcServer, s)
-
-	glog.Infof("GRPC listening on %s", s.Addr)
-	err = grpcServer.Serve(lis)
-	glog.Fatalf("GRPC exiting: %s", err)
-}
diff --git a/internal/proto/dnss.pb.go b/internal/proto/dnss.pb.go
deleted file mode 100644
index 78db3a0..0000000
--- a/internal/proto/dnss.pb.go
+++ /dev/null
@@ -1,134 +0,0 @@
-// Code generated by protoc-gen-go.
-// source: dnss.proto
-// DO NOT EDIT!
-
-/*
-Package dnss is a generated protocol buffer package.
-
-It is generated from these files:
-	dnss.proto
-
-It has these top-level messages:
-	RawMsg
-*/
-package dnss
-
-import proto "github.com/golang/protobuf/proto"
-import fmt "fmt"
-import math "math"
-
-import (
-	context "golang.org/x/net/context"
-	grpc "google.golang.org/grpc"
-)
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ = proto.Marshal
-var _ = fmt.Errorf
-var _ = math.Inf
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the proto package it is being compiled against.
-// A compilation error at this line likely means your copy of the
-// proto package needs to be updated.
-const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
-
-type RawMsg struct {
-	// DNS-encoded message.
-	// A horrible hack, but will do for now.
-	Data []byte `protobuf:"bytes,1,opt,name=data,proto3" json:"data,omitempty"`
-}
-
-func (m *RawMsg) Reset()                    { *m = RawMsg{} }
-func (m *RawMsg) String() string            { return proto.CompactTextString(m) }
-func (*RawMsg) ProtoMessage()               {}
-func (*RawMsg) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
-
-func init() {
-	proto.RegisterType((*RawMsg)(nil), "dnss.RawMsg")
-}
-
-// Reference imports to suppress errors if they are not otherwise used.
-var _ context.Context
-var _ grpc.ClientConn
-
-// This is a compile-time assertion to ensure that this generated file
-// is compatible with the grpc package it is being compiled against.
-const _ = grpc.SupportPackageIsVersion4
-
-// Client API for DNSService service
-
-type DNSServiceClient interface {
-	Query(ctx context.Context, in *RawMsg, opts ...grpc.CallOption) (*RawMsg, error)
-}
-
-type dNSServiceClient struct {
-	cc *grpc.ClientConn
-}
-
-func NewDNSServiceClient(cc *grpc.ClientConn) DNSServiceClient {
-	return &dNSServiceClient{cc}
-}
-
-func (c *dNSServiceClient) Query(ctx context.Context, in *RawMsg, opts ...grpc.CallOption) (*RawMsg, error) {
-	out := new(RawMsg)
-	err := grpc.Invoke(ctx, "/dnss.DNSService/Query", in, out, c.cc, opts...)
-	if err != nil {
-		return nil, err
-	}
-	return out, nil
-}
-
-// Server API for DNSService service
-
-type DNSServiceServer interface {
-	Query(context.Context, *RawMsg) (*RawMsg, error)
-}
-
-func RegisterDNSServiceServer(s *grpc.Server, srv DNSServiceServer) {
-	s.RegisterService(&_DNSService_serviceDesc, srv)
-}
-
-func _DNSService_Query_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
-	in := new(RawMsg)
-	if err := dec(in); err != nil {
-		return nil, err
-	}
-	if interceptor == nil {
-		return srv.(DNSServiceServer).Query(ctx, in)
-	}
-	info := &grpc.UnaryServerInfo{
-		Server:     srv,
-		FullMethod: "/dnss.DNSService/Query",
-	}
-	handler := func(ctx context.Context, req interface{}) (interface{}, error) {
-		return srv.(DNSServiceServer).Query(ctx, req.(*RawMsg))
-	}
-	return interceptor(ctx, in, info, handler)
-}
-
-var _DNSService_serviceDesc = grpc.ServiceDesc{
-	ServiceName: "dnss.DNSService",
-	HandlerType: (*DNSServiceServer)(nil),
-	Methods: []grpc.MethodDesc{
-		{
-			MethodName: "Query",
-			Handler:    _DNSService_Query_Handler,
-		},
-	},
-	Streams:  []grpc.StreamDesc{},
-	Metadata: "dnss.proto",
-}
-
-func init() { proto.RegisterFile("dnss.proto", fileDescriptor0) }
-
-var fileDescriptor0 = []byte{
-	// 105 bytes of a gzipped FileDescriptorProto
-	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x4a, 0xc9, 0x2b, 0x2e,
-	0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x01, 0xb1, 0x95, 0x64, 0xb8, 0xd8, 0x82, 0x12,
-	0xcb, 0x7d, 0x8b, 0xd3, 0x85, 0x84, 0xb8, 0x58, 0x52, 0x12, 0x4b, 0x12, 0x25, 0x18, 0x15, 0x18,
-	0x35, 0x78, 0x82, 0xc0, 0x6c, 0x23, 0x43, 0x2e, 0x2e, 0x17, 0xbf, 0xe0, 0xe0, 0xd4, 0xa2, 0xb2,
-	0xcc, 0xe4, 0x54, 0x21, 0x65, 0x2e, 0xd6, 0xc0, 0xd2, 0xd4, 0xa2, 0x4a, 0x21, 0x1e, 0x3d, 0xb0,
-	0x39, 0x10, 0x8d, 0x52, 0x28, 0xbc, 0x24, 0x36, 0xb0, 0xe9, 0xc6, 0x80, 0x00, 0x00, 0x00, 0xff,
-	0xff, 0xc0, 0xc7, 0x8e, 0xd6, 0x6b, 0x00, 0x00, 0x00,
-}
diff --git a/internal/proto/dnss.proto b/internal/proto/dnss.proto
deleted file mode 100644
index 8f982ea..0000000
--- a/internal/proto/dnss.proto
+++ /dev/null
@@ -1,15 +0,0 @@
-
-syntax = "proto3";
-
-package dnss;
-
-message RawMsg {
-	// DNS-encoded message.
-	// A horrible hack, but will do for now.
-	bytes data = 1;
-}
-
-service DNSService {
-	rpc Query(RawMsg) returns (RawMsg);
-}
-
diff --git a/internal/proto/dummy.go b/internal/proto/dummy.go
deleted file mode 100644
index 5136454..0000000
--- a/internal/proto/dummy.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package dnss
-
-// Generate the protobuf+grpc service.
-//go:generate protoc --go_out=plugins=grpc:. dnss.proto
diff --git a/monitoring_test.go b/monitoring_test.go
index e198e0b..496a8c4 100644
--- a/monitoring_test.go
+++ b/monitoring_test.go
@@ -8,8 +8,6 @@ package main
 import (
 	"net/http"
 	"testing"
-
-	"google.golang.org/grpc"
 )
 
 func TestMonitoringServer(t *testing.T) {
@@ -17,10 +15,6 @@ func TestMonitoringServer(t *testing.T) {
 	const addr = "localhost:19395"
 	launchMonitoringServer(addr)
 
-	if !grpc.EnableTracing {
-		t.Errorf("grpc tracing is disabled")
-	}
-
 	checkGet(t, "http://"+addr+"/")
 	checkGet(t, "http://"+addr+"/debug/requests")
 	checkGet(t, "http://"+addr+"/debug/pprof/goroutine")
diff --git a/testing/grpc/grpc.go b/testing/grpc/grpc.go
deleted file mode 100644
index 268365b..0000000
--- a/testing/grpc/grpc.go
+++ /dev/null
@@ -1,4 +0,0 @@
-package grpc
-
-// Dummy file so "go build ./..." does not complain about the directory not
-// having buildable files.
diff --git a/testing/grpc/grpc_test.go b/testing/grpc/grpc_test.go
deleted file mode 100644
index 0172b9a..0000000
--- a/testing/grpc/grpc_test.go
+++ /dev/null
@@ -1,243 +0,0 @@
-// Tests for dnss in GRPC modes.
-package grpc
-
-import (
-	"crypto/rand"
-	"crypto/rsa"
-	"crypto/x509"
-	"crypto/x509/pkix"
-	"encoding/pem"
-	"flag"
-	"fmt"
-	"io/ioutil"
-	"math/big"
-	"net"
-	"os"
-	"testing"
-	"time"
-
-	"blitiri.com.ar/go/dnss/internal/dnstox"
-	"blitiri.com.ar/go/dnss/internal/grpctodns"
-	"blitiri.com.ar/go/dnss/testing/util"
-
-	"github.com/golang/glog"
-	"github.com/miekg/dns"
-)
-
-// Addresses to use for testing. These will be picked at initialization time,
-// see init().
-var dnsToGrpcAddr, grpcToDnsAddr, dnsSrvAddr string
-
-func init() {
-	dnsToGrpcAddr = util.GetFreePort()
-	grpcToDnsAddr = util.GetFreePort()
-	dnsSrvAddr = util.GetFreePort()
-}
-
-//
-// === Tests ===
-//
-
-func dnsQuery(conn *dns.Conn) error {
-	m := &dns.Msg{}
-	m.SetQuestion("ca.chai.", dns.TypeMX)
-
-	conn.WriteMsg(m)
-	_, err := conn.ReadMsg()
-	return err
-}
-
-func TestSimple(t *testing.T) {
-	conn, err := dns.DialTimeout("udp", dnsToGrpcAddr, 1*time.Second)
-	if err != nil {
-		t.Fatalf("dns.Dial error: %v", err)
-	}
-	defer conn.Close()
-
-	err = dnsQuery(conn)
-	if err != nil {
-		t.Errorf("dns query returned error: %v", err)
-	}
-}
-
-//
-// === Benchmarks ===
-//
-
-func manyDNSQueries(b *testing.B, addr string) {
-	conn, err := dns.DialTimeout("udp", addr, 1*time.Second)
-	if err != nil {
-		b.Fatalf("dns.Dial error: %v", err)
-	}
-	defer conn.Close()
-
-	for i := 0; i < b.N; i++ {
-		err = dnsQuery(conn)
-		if err != nil {
-			b.Errorf("dns query returned error: %v", err)
-		}
-	}
-}
-
-func BenchmarkGRPCDirect(b *testing.B) {
-	manyDNSQueries(b, dnsSrvAddr)
-}
-
-func BenchmarkGRPCWithProxy(b *testing.B) {
-	manyDNSQueries(b, dnsToGrpcAddr)
-}
-
-//
-// === Test environment ===
-//
-
-// dnsServer implements a DNS server for testing.
-// It always gives the same reply, regardless of the query.
-type dnsServer struct {
-	Addr     string
-	srv      *dns.Server
-	answerRR dns.RR
-}
-
-func (s *dnsServer) Handler(w dns.ResponseWriter, r *dns.Msg) {
-	// Building the reply (and setting the corresponding id) is cheaper than
-	// copying a "master" message.
-	m := &dns.Msg{}
-	m.Id = r.Id
-	m.Response = true
-	m.Authoritative = true
-	m.Rcode = dns.RcodeSuccess
-	m.Answer = append(m.Answer, s.answerRR)
-	w.WriteMsg(m)
-}
-
-func (s *dnsServer) ListenAndServe() {
-	var err error
-
-	s.answerRR, err = dns.NewRR("test.blah A 1.2.3.4")
-	if err != nil {
-		panic(err)
-	}
-
-	s.srv = &dns.Server{
-		Addr:    s.Addr,
-		Net:     "udp",
-		Handler: dns.HandlerFunc(s.Handler),
-	}
-	err = s.srv.ListenAndServe()
-	if err != nil {
-		panic(err)
-	}
-}
-
-// generateCert generates a new, INSECURE self-signed certificate and writes
-// it to a pair of (cert.pem, key.pem) files to the given path.
-// Note the certificate is only useful for testing purposes.
-func generateCert(path string) error {
-	tmpl := x509.Certificate{
-		SerialNumber: big.NewInt(1234),
-		Subject: pkix.Name{
-			Organization: []string{"dnss testing"},
-		},
-
-		IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
-
-		NotBefore: time.Now(),
-		NotAfter:  time.Now().Add(30 * time.Minute),
-
-		KeyUsage: x509.KeyUsageKeyEncipherment |
-			x509.KeyUsageDigitalSignature |
-			x509.KeyUsageCertSign,
-
-		BasicConstraintsValid: true,
-		IsCA: true,
-	}
-
-	priv, err := rsa.GenerateKey(rand.Reader, 1024)
-	if err != nil {
-		return err
-	}
-
-	derBytes, err := x509.CreateCertificate(
-		rand.Reader, &tmpl, &tmpl, &priv.PublicKey, priv)
-	if err != nil {
-		return err
-	}
-
-	certOut, err := os.Create(path + "/cert.pem")
-	if err != nil {
-		return err
-	}
-	defer certOut.Close()
-	pem.Encode(certOut, &pem.Block{Type: "CERTIFICATE", Bytes: derBytes})
-
-	keyOut, err := os.OpenFile(
-		path+"/key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
-	if err != nil {
-		return err
-	}
-	defer keyOut.Close()
-
-	block := &pem.Block{
-		Type:  "RSA PRIVATE KEY",
-		Bytes: x509.MarshalPKCS1PrivateKey(priv),
-	}
-	pem.Encode(keyOut, block)
-	return nil
-}
-
-// realMain is the real main function, which returns the value to pass to
-// os.Exit(). We have to do this so we can use defer.
-func realMain(m *testing.M) int {
-	flag.Parse()
-	defer glog.Flush()
-
-	// Generate certificates in a temporary directory.
-	tmpDir, err := ioutil.TempDir("", "dnss_test:")
-	if err != nil {
-		fmt.Printf("Failed to create temp dir: %v\n", tmpDir)
-		return 1
-	}
-	defer os.RemoveAll(tmpDir)
-
-	err = generateCert(tmpDir)
-	if err != nil {
-		fmt.Printf("Failed to generate cert for testing: %v\n", err)
-		return 1
-	}
-
-	// DNS to GRPC server.
-	gr := dnstox.NewGRPCResolver(grpcToDnsAddr, tmpDir+"/cert.pem")
-	cr := dnstox.NewCachingResolver(gr)
-	dtg := dnstox.New(dnsToGrpcAddr, cr, "")
-	go dtg.ListenAndServe()
-
-	// GRPC to DNS server.
-	gtd := &grpctodns.Server{
-		Addr:     grpcToDnsAddr,
-		Upstream: dnsSrvAddr,
-		CertFile: tmpDir + "/cert.pem",
-		KeyFile:  tmpDir + "/key.pem",
-	}
-	go gtd.ListenAndServe()
-
-	// DNS test server.
-	dnsSrv := dnsServer{
-		Addr: dnsSrvAddr,
-	}
-	go dnsSrv.ListenAndServe()
-
-	// Wait for the servers to start up.
-	err = util.WaitForDNSServer(dnsToGrpcAddr)
-	if err != nil {
-		fmt.Printf("Error waiting for the test servers to start: %v\n", err)
-		fmt.Printf("Check the INFO logs for more details\n")
-		return 1
-	}
-
-	return m.Run()
-}
-
-func TestMain(m *testing.M) {
-	os.Exit(realMain(m))
-}
diff --git a/testing/https/https_test.go b/testing/https/https_test.go
index b984ea2..3b5d31c 100644
--- a/testing/https/https_test.go
+++ b/testing/https/https_test.go
@@ -9,7 +9,7 @@ import (
 	"os"
 	"testing"
 
-	"blitiri.com.ar/go/dnss/internal/dnstox"
+	"blitiri.com.ar/go/dnss/internal/dnstohttps"
 	"blitiri.com.ar/go/dnss/testing/util"
 
 	"github.com/golang/glog"
@@ -143,8 +143,8 @@ func realMain(m *testing.M) int {
 	httpsrv := httptest.NewServer(http.HandlerFunc(DNSHandler))
 
 	// DNS to HTTPS server.
-	r := dnstox.NewHTTPSResolver(httpsrv.URL, "")
-	dth := dnstox.New(DNSAddr, r, "")
+	r := dnstohttps.NewHTTPSResolver(httpsrv.URL, "")
+	dth := dnstohttps.New(DNSAddr, r, "")
 	go dth.ListenAndServe()
 
 	// Wait for the servers to start up.