Do not recurse when the service address is a local cname

Fixes #2795
This commit is contained in:
Frank Schroeder 2017-05-29 16:08:54 +02:00 committed by Frank Schröder
parent 9956bc9b47
commit 375825f34c
2 changed files with 67 additions and 0 deletions

View File

@ -767,6 +767,12 @@ func (d *DNSServer) serviceNodeRecords(dc string, nodes structs.CheckServiceNode
addr = node.Service.Address addr = node.Service.Address
} }
// If the service address is a CNAME for the service we are looking
// for then use the node address.
if qName == strings.TrimSuffix(addr, ".")+"." {
addr = node.Node.Address
}
// Avoid duplicate entries, possible if a node has // Avoid duplicate entries, possible if a node has
// the same service on multiple ports, etc. // the same service on multiple ports, etc.
if _, ok := handled[addr]; ok { if _, ok := handled[addr]; ok {

View File

@ -14,6 +14,7 @@ import (
"github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/lib"
"github.com/hashicorp/consul/testutil/retry" "github.com/hashicorp/consul/testutil/retry"
"github.com/miekg/dns" "github.com/miekg/dns"
"github.com/pascaldekloe/goe/verify"
) )
const ( const (
@ -609,6 +610,66 @@ func TestDNS_ServiceLookup(t *testing.T) {
} }
} }
func TestDNS_ServiceLookupWithInternalServiceAddress(t *testing.T) {
t.Parallel()
a := NewTestAgent(t.Name(), nil)
defer a.Shutdown()
// Register a node with a service.
// The service is using the consul DNS name as service address
// which triggers a lookup loop and a subsequent stack overflow
// crash.
args := &structs.RegisterRequest{
Datacenter: "dc1",
Node: "foo",
Address: "127.0.0.1",
Service: &structs.NodeService{
Service: "db",
Address: "db.service.consul",
Port: 12345,
},
}
var out struct{}
if err := a.RPC("Catalog.Register", args, &out); err != nil {
t.Fatalf("err: %v", err)
}
// Looking up the service should not trigger a loop
m := new(dns.Msg)
m.SetQuestion("db.service.consul.", dns.TypeSRV)
c := new(dns.Client)
addr, _ := a.Config.ClientListener("", a.Config.Ports.DNS)
in, _, err := c.Exchange(m, addr.String())
if err != nil {
t.Fatalf("err: %v", err)
}
wantAnswer := []dns.RR{
&dns.SRV{
Hdr: dns.RR_Header{Name: "db.service.consul.", Rrtype: 0x21, Class: 0x1, Rdlength: 0x15},
Priority: 0x1,
Weight: 0x1,
Port: 12345,
Target: "foo.node.dc1.consul.",
},
}
verify.Values(t, "answer", in.Answer, wantAnswer)
wantExtra := []dns.RR{
&dns.CNAME{
Hdr: dns.RR_Header{Name: "foo.node.dc1.consul.", Rrtype: 0x5, Class: 0x1, Rdlength: 0x2},
Target: "db.service.consul.",
},
&dns.A{
Hdr: dns.RR_Header{Name: "db.service.consul.", Rrtype: 0x1, Class: 0x1, Rdlength: 0x4},
A: []byte{0x7f, 0x0, 0x0, 0x1}, // 127.0.0.1
},
}
verify.Values(t, "extra", in.Extra, wantExtra)
}
func TestDNS_ExternalServiceLookup(t *testing.T) { func TestDNS_ExternalServiceLookup(t *testing.T) {
t.Parallel() t.Parallel()
a := NewTestAgent(t.Name(), nil) a := NewTestAgent(t.Name(), nil)