| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | package proxy | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2018-04-22 08:34:35 +01:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	"crypto/tls" | 
					
						
							| 
									
										
										
										
											2018-02-14 14:20:27 -05:00
										 |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 	"github.com/coredns/coredns/pb" | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin/pkg/trace" | 
					
						
							| 
									
										
										
										
											2017-02-21 22:51:47 -08:00
										 |  |  | 	"github.com/coredns/coredns/request" | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-13 20:24:37 +00:00
										 |  |  | 	"github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc" | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	"github.com/miekg/dns" | 
					
						
							| 
									
										
										
										
											2017-03-01 10:41:54 -05:00
										 |  |  | 	opentracing "github.com/opentracing/opentracing-go" | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	"google.golang.org/grpc" | 
					
						
							|  |  |  | 	"google.golang.org/grpc/credentials" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type grpcClient struct { | 
					
						
							| 
									
										
										
										
											2017-03-01 10:41:54 -05:00
										 |  |  | 	dialOpts []grpc.DialOption | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	clients  map[string]pb.DnsServiceClient | 
					
						
							|  |  |  | 	conns    []*grpc.ClientConn | 
					
						
							|  |  |  | 	upstream *staticUpstream | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func newGrpcClient(tls *tls.Config, u *staticUpstream) *grpcClient { | 
					
						
							|  |  |  | 	g := &grpcClient{upstream: u} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if tls == nil { | 
					
						
							| 
									
										
										
										
											2017-03-01 10:41:54 -05:00
										 |  |  | 		g.dialOpts = append(g.dialOpts, grpc.WithInsecure()) | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-03-01 10:41:54 -05:00
										 |  |  | 		g.dialOpts = append(g.dialOpts, grpc.WithTransportCredentials(credentials.NewTLS(tls))) | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	g.clients = map[string]pb.DnsServiceClient{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return g | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (g *grpcClient) Exchange(ctx context.Context, addr string, state request.Request) (*dns.Msg, error) { | 
					
						
							|  |  |  | 	msg, err := state.Req.Pack() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-14 14:20:27 -05:00
										 |  |  | 	if cl, ok := g.clients[addr]; ok { | 
					
						
							|  |  |  | 		reply, err := cl.Query(ctx, &pb.DnsPacket{Msg: msg}) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		d := new(dns.Msg) | 
					
						
							|  |  |  | 		err = d.Unpack(reply.Msg) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return d, nil | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-14 14:20:27 -05:00
										 |  |  | 	return nil, fmt.Errorf("grpc exchange - no connection available for host: %s ", addr) | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-01 12:41:41 +02:00
										 |  |  | func (g *grpcClient) Transport() string { return "tcp" } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | func (g *grpcClient) Protocol() string { return "grpc" } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (g *grpcClient) OnShutdown(p *Proxy) error { | 
					
						
							| 
									
										
										
										
											2017-03-01 10:41:54 -05:00
										 |  |  | 	g.clients = map[string]pb.DnsServiceClient{} | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	for i, conn := range g.conns { | 
					
						
							|  |  |  | 		err := conn.Close() | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2018-04-19 07:41:56 +01:00
										 |  |  | 			log.Warningf("Error closing connection %d: %s\n", i, err) | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-03-01 10:41:54 -05:00
										 |  |  | 	g.conns = []*grpc.ClientConn{} | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (g *grpcClient) OnStartup(p *Proxy) error { | 
					
						
							| 
									
										
										
										
											2017-03-01 10:41:54 -05:00
										 |  |  | 	dialOpts := g.dialOpts | 
					
						
							|  |  |  | 	if p.Trace != nil { | 
					
						
							|  |  |  | 		if t, ok := p.Trace.(trace.Trace); ok { | 
					
						
							|  |  |  | 			onlyIfParent := func(parentSpanCtx opentracing.SpanContext, method string, req, resp interface{}) bool { | 
					
						
							|  |  |  | 				return parentSpanCtx != nil | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			intercept := otgrpc.OpenTracingClientInterceptor(t.Tracer(), otgrpc.IncludingSpans(onlyIfParent)) | 
					
						
							|  |  |  | 			dialOpts = append(dialOpts, grpc.WithUnaryInterceptor(intercept)) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2018-04-19 07:41:56 +01:00
										 |  |  | 			log.Warningf("Wrong type for trace plugin reference: %s", p.Trace) | 
					
						
							| 
									
										
										
										
											2017-03-01 10:41:54 -05:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 	for _, host := range g.upstream.Hosts { | 
					
						
							| 
									
										
										
										
											2017-03-01 10:41:54 -05:00
										 |  |  | 		conn, err := grpc.Dial(host.Name, dialOpts...) | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 		if err != nil { | 
					
						
							| 
									
										
										
										
											2018-04-19 07:41:56 +01:00
										 |  |  | 			log.Warningf("Skipping gRPC host '%s' due to Dial error: %s\n", host.Name, err) | 
					
						
							| 
									
										
										
										
											2017-02-14 22:20:20 -05:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			g.clients[host.Name] = pb.NewDnsServiceClient(conn) | 
					
						
							|  |  |  | 			g.conns = append(g.conns, conn) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |