add support unix socket for GRPC (#5943)
This commit is contained in:
parent
31ff926ea1
commit
917489e71c
7 changed files with 91 additions and 1 deletions
|
@ -129,7 +129,15 @@ Or with multiple upstreams from the same provider
|
|||
}
|
||||
~~~
|
||||
|
||||
Forward requests to a local upstream listening on a Unix domain socket.
|
||||
|
||||
~~~ corefile
|
||||
. {
|
||||
grpc . unix:///path/to/grpc.sock
|
||||
}
|
||||
~~~
|
||||
|
||||
## Bugs
|
||||
|
||||
The TLS config is global for the whole grpc proxy if you need a different `tls_servername` for
|
||||
different upstreams you're out of luck.
|
||||
different upstreams you're out of luck.
|
|
@ -3,9 +3,15 @@ package grpc
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/coredns/caddy"
|
||||
"github.com/coredns/coredns/pb"
|
||||
"github.com/coredns/coredns/plugin/pkg/dnstest"
|
||||
"github.com/coredns/coredns/plugin/test"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"google.golang.org/grpc"
|
||||
|
@ -64,3 +70,56 @@ type testServiceClient struct {
|
|||
func (m testServiceClient) Query(ctx context.Context, in *pb.DnsPacket, opts ...grpc.CallOption) (*pb.DnsPacket, error) {
|
||||
return m.dnsPacket, m.err
|
||||
}
|
||||
|
||||
func TestProxyUnix(t *testing.T) {
|
||||
tdir, err := os.MkdirTemp("", "tmp*")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(tdir)
|
||||
|
||||
fd := path.Join(tdir, "test.grpc")
|
||||
listener, err := net.Listen("unix", fd)
|
||||
if err != nil {
|
||||
t.Fatal("Failed to listen: ", err)
|
||||
}
|
||||
defer listener.Close()
|
||||
|
||||
server := grpc.NewServer()
|
||||
pb.RegisterDnsServiceServer(server, &grpcDnsServiceServer{})
|
||||
|
||||
go server.Serve(listener)
|
||||
defer server.Stop()
|
||||
|
||||
c := caddy.NewTestController("dns", "grpc . unix://"+fd)
|
||||
g, err := parseGRPC(c)
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create forwarder: %s", err)
|
||||
}
|
||||
|
||||
m := new(dns.Msg)
|
||||
m.SetQuestion("example.org.", dns.TypeA)
|
||||
rec := dnstest.NewRecorder(&test.ResponseWriter{})
|
||||
|
||||
if _, err := g.ServeDNS(context.TODO(), rec, m); err != nil {
|
||||
t.Fatal("Expected to receive reply, but didn't")
|
||||
}
|
||||
if x := rec.Msg.Answer[0].Header().Name; x != "example.org." {
|
||||
t.Errorf("Expected %s, got %s", "example.org.", x)
|
||||
}
|
||||
}
|
||||
|
||||
type grpcDnsServiceServer struct {
|
||||
pb.UnimplementedDnsServiceServer
|
||||
}
|
||||
|
||||
func (*grpcDnsServiceServer) Query(ctx context.Context, in *pb.DnsPacket) (*pb.DnsPacket, error) {
|
||||
msg := &dns.Msg{}
|
||||
msg.Unpack(in.GetMsg())
|
||||
answer := new(dns.Msg)
|
||||
answer.Answer = append(answer.Answer, test.A("example.org. IN A 127.0.0.1"))
|
||||
answer.SetRcode(msg, dns.RcodeSuccess)
|
||||
buf, _ := answer.Pack()
|
||||
return &pb.DnsPacket{Msg: buf}, nil
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ func TestSetup(t *testing.T) {
|
|||
{"grpc . 127.0.0.1:8080", false, ".", nil, ""},
|
||||
{"grpc . [::1]:53", false, ".", nil, ""},
|
||||
{"grpc . [2003::1]:53", false, ".", nil, ""},
|
||||
{"grpc . unix:///var/run/g.sock", false, ".", nil, ""},
|
||||
// negative
|
||||
{"grpc . a27.0.0.1", true, "", nil, "not an IP"},
|
||||
{"grpc . 127.0.0.1 {\nblaatl\n}\n", true, "", nil, "unknown property"},
|
||||
|
|
|
@ -33,6 +33,14 @@ func HostPortOrFile(s ...string) ([]string, error) {
|
|||
var servers []string
|
||||
for _, h := range s {
|
||||
trans, host := Transport(h)
|
||||
if len(host) == 0 {
|
||||
return servers, fmt.Errorf("invalid address: %q", h)
|
||||
}
|
||||
|
||||
if trans == transport.UNIX {
|
||||
servers = append(servers, trans+"://"+host)
|
||||
continue
|
||||
}
|
||||
|
||||
addr, _, err := net.SplitHostPort(host)
|
||||
|
||||
|
|
|
@ -58,6 +58,16 @@ func TestHostPortOrFile(t *testing.T) {
|
|||
"",
|
||||
true,
|
||||
},
|
||||
{
|
||||
"unix:///var/run/g.sock",
|
||||
"unix:///var/run/g.sock",
|
||||
false,
|
||||
},
|
||||
{
|
||||
"unix://",
|
||||
"",
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
err := os.WriteFile("resolv.conf", []byte("nameserver 127.0.0.1\n"), 0600)
|
||||
|
|
|
@ -27,6 +27,9 @@ func Transport(s string) (trans string, addr string) {
|
|||
s = s[len(transport.HTTPS+"://"):]
|
||||
|
||||
return transport.HTTPS, s
|
||||
case strings.HasPrefix(s, transport.UNIX+"://"):
|
||||
s = s[len(transport.UNIX+"://"):]
|
||||
return transport.UNIX, s
|
||||
}
|
||||
|
||||
return transport.DNS, s
|
||||
|
|
|
@ -6,6 +6,7 @@ const (
|
|||
TLS = "tls"
|
||||
GRPC = "grpc"
|
||||
HTTPS = "https"
|
||||
UNIX = "unix"
|
||||
)
|
||||
|
||||
// Port numbers for the various transports.
|
||||
|
|
Loading…
Add table
Reference in a new issue