diff --git a/agent/dns.go b/agent/dns.go index 937c32d080..c003305a49 100644 --- a/agent/dns.go +++ b/agent/dns.go @@ -1551,13 +1551,14 @@ func findWeight(node structs.CheckServiceNode) int { } } -func (d *DNSServer) encodeIPAsFqdn(dc string, ip net.IP) string { +func (d *DNSServer) encodeIPAsFqdn(questionName string, dc string, ip net.IP) string { ipv4 := ip.To4() + respDomain := d.getResponseDomain(questionName) if ipv4 != nil { ipStr := hex.EncodeToString(ip) - return fmt.Sprintf("%s.addr.%s.%s", ipStr[len(ipStr)-(net.IPv4len*2):], dc, d.domain) + return fmt.Sprintf("%s.addr.%s.%s", ipStr[len(ipStr)-(net.IPv4len*2):], dc, respDomain) } else { - return fmt.Sprintf("%s.addr.%s.%s", hex.EncodeToString(ip), dc, d.domain) + return fmt.Sprintf("%s.addr.%s.%s", hex.EncodeToString(ip), dc, respDomain) } } @@ -1681,7 +1682,7 @@ func (d *DNSServer) makeRecordFromIP(dc string, addr net.IP, serviceNode structs } if q.Qtype == dns.TypeSRV { - ipFQDN := d.encodeIPAsFqdn(dc, addr) + ipFQDN := d.encodeIPAsFqdn(q.Name, dc, addr) answers := []dns.RR{ &dns.SRV{ Hdr: dns.RR_Header{ diff --git a/agent/dns_test.go b/agent/dns_test.go index 7bcab1ceab..e658c58f45 100644 --- a/agent/dns_test.go +++ b/agent/dns_test.go @@ -2502,6 +2502,110 @@ func TestDNS_ServiceLookup_ServiceAddress_A(t *testing.T) { } } +func TestDNS_AltDomain_ServiceLookup_ServiceAddress_A(t *testing.T) { + if testing.Short() { + t.Skip("too slow for testing.Short") + } + + t.Parallel() + a := NewTestAgent(t, ` + alt_domain = "test-domain" + `) + defer a.Shutdown() + testrpc.WaitForLeader(t, a.RPC, "dc1") + + // Register a node with a service. + { + args := &structs.RegisterRequest{ + Datacenter: "dc1", + Node: "foo", + Address: "127.0.0.1", + Service: &structs.NodeService{ + Service: "db", + Tags: []string{"primary"}, + Address: "127.0.0.2", + Port: 12345, + }, + } + + var out struct{} + if err := a.RPC("Catalog.Register", args, &out); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Register an equivalent prepared query. + var id string + { + args := &structs.PreparedQueryRequest{ + Datacenter: "dc1", + Op: structs.PreparedQueryCreate, + Query: &structs.PreparedQuery{ + Name: "test", + Service: structs.ServiceQuery{ + Service: "db", + }, + }, + } + if err := a.RPC("PreparedQuery.Apply", args, &id); err != nil { + t.Fatalf("err: %v", err) + } + } + + // Look up the service directly and via prepared query. + questions := []struct { + ask string + wantDomain string + }{ + {"db.service.consul.", "consul."}, + {id + ".query.consul.", "consul."}, + {"db.service.test-domain.", "test-domain."}, + {id + ".query.test-domain.", "test-domain."}, + } + for _, question := range questions { + m := new(dns.Msg) + m.SetQuestion(question.ask, dns.TypeSRV) + + c := new(dns.Client) + in, _, err := c.Exchange(m, a.DNSAddr()) + if err != nil { + t.Fatalf("err: %v", err) + } + + if len(in.Answer) != 1 { + t.Fatalf("Bad: %#v", in) + } + + srvRec, ok := in.Answer[0].(*dns.SRV) + if !ok { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + if srvRec.Port != 12345 { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Target != "7f000002.addr.dc1."+question.wantDomain { + t.Fatalf("Bad: %#v", srvRec) + } + if srvRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Answer[0]) + } + + aRec, ok := in.Extra[0].(*dns.A) + if !ok { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Name != "7f000002.addr.dc1."+question.wantDomain { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.A.String() != "127.0.0.2" { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + if aRec.Hdr.Ttl != 0 { + t.Fatalf("Bad: %#v", in.Extra[0]) + } + } +} + func TestDNS_ServiceLookup_ServiceAddress_SRV(t *testing.T) { if testing.Short() { t.Skip("too slow for testing.Short")