diff --git a/bosh-release/src/sslip.io-dns-server/integration_test.go b/bosh-release/src/sslip.io-dns-server/integration_test.go index 20e3865..348b336 100644 --- a/bosh-release/src/sslip.io-dns-server/integration_test.go +++ b/bosh-release/src/sslip.io-dns-server/integration_test.go @@ -134,30 +134,38 @@ var _ = Describe("sslip.io-dns-server", func() { Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeMX sslip.io. \? 10 mail.protonmail.ch., 20 mailsec.protonmail.ch.\n`)) }) }) - When("there are multiple NS records returned (e.g. almost NS query)", func() { + When("there are multiple NS records returned (e.g. almost any NS query)", func() { It("returns all the records", func() { digArgs = "@localhost example.com ns" digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) Expect(err).ToNot(HaveOccurred()) - Eventually(digSession).Should(Say(`flags: qr aa rd;`)) - Eventually(digSession).Should(Say(`aws.nono.io.`)) - Eventually(digSession).Should(Say(`azure.nono.io.`)) - Eventually(digSession).Should(Say(`gce.nono.io.`)) + Eventually(digSession).Should(Say(`flags: qr aa rd; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 3`)) + Eventually(digSession).Should(Say(`;; ANSWER SECTION:`)) + Eventually(digSession).Should(Say(`ns-aws.nono.io.\n`)) + Eventually(digSession).Should(Say(`ns-azure.nono.io.\n`)) + Eventually(digSession).Should(Say(`ns-gce.nono.io.\n`)) + Eventually(digSession).Should(Say(`;; ADDITIONAL SECTION:`)) + Eventually(digSession).Should(Say(`ns-aws.nono.io..*52.0.56.137\n`)) + Eventually(digSession).Should(Say(`ns-azure.nono.io..*52.187.42.158\n`)) + Eventually(digSession).Should(Say(`ns-gce.nono.io..*104.155.144.4\n`)) Eventually(digSession, 1).Should(Exit(0)) Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeNS example.com. \? ns-aws.nono.io., ns-azure.nono.io., ns-gce.nono.io.\n`)) }) }) When(`the NS record for an "_acme-challenge" domain is queried`, func() { It(`returns the NS record of the query with the "_acme-challenge." stripped`, func() { - digArgs = "@localhost _acme-challenge.127-0-0-1.sslip.io ns" + digArgs = "@localhost _acme-challenge.fe80--.sslip.io ns" digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) Expect(err).ToNot(HaveOccurred()) - Eventually(digSession).Should(Say(`flags: qr aa rd;`)) - Eventually(digSession).Should(Say(`127-0-0-1.sslip.io.`)) + Eventually(digSession).Should(Say(`flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1`)) + Eventually(digSession).Should(Say(`;; ANSWER SECTION:`)) + Eventually(digSession).Should(Say(`fe80--.sslip.io.`)) + Eventually(digSession).Should(Say(`;; ADDITIONAL SECTION:`)) + Eventually(digSession).Should(Say(`fe80--.sslip.io..*fe80::\n`)) Eventually(digSession, 1).Should(Exit(0)) - Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeNS _acme-challenge.127-0-0-1.sslip.io. \? 127-0-0-1.sslip.io.\n`)) + Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeNS _acme-challenge.fe80--.sslip.io. \? fe80--.sslip.io.\n`)) }) }) When(`there are multiple TXT records returned (e.g. SPF for sslip.io)`, func() { diff --git a/bosh-release/src/sslip.io-dns-server/xip/xip.go b/bosh-release/src/sslip.io-dns-server/xip/xip.go index 29e7848..1fdfdbc 100644 --- a/bosh-release/src/sslip.io-dns-server/xip/xip.go +++ b/bosh-release/src/sslip.io-dns-server/xip/xip.go @@ -112,6 +112,7 @@ type Response struct { Header dnsmessage.Header Answers []func(*dnsmessage.Builder) error Authorities []func(*dnsmessage.Builder) error + Additionals []func(*dnsmessage.Builder) error } // QueryResponse takes in a raw (packed) DNS query and returns a raw (packed) @@ -170,6 +171,14 @@ func QueryResponse(queryBytes []byte) (responseBytes []byte, logMessage string, return nil, "", err } } + if err = b.StartAdditionals(); err != nil { + return nil, "", err + } + for _, additionals := range response.Additionals { + if err = additionals(&b); err != nil { + return nil, "", err + } + } if responseBytes, err = b.Finish(); err != nil { return nil, "", err } @@ -338,7 +347,6 @@ func processQuestion(q dnsmessage.Question, response *Response) (string, error) nameServers := NSResources(q.Name.String()) var logMessages []string response.Answers = append(response.Answers, - // 1 or more A records; A records > 1 only available via Customizations func(b *dnsmessage.Builder) error { for _, nameServer := range nameServers { err = b.NSResource(dnsmessage.ResourceHeader{ @@ -354,6 +362,36 @@ func processQuestion(q dnsmessage.Question, response *Response) (string, error) } return nil }) + response.Additionals = append(response.Additionals, + func(b *dnsmessage.Builder) error { + for _, nameServer := range nameServers { + for _, aResource := range NameToA(nameServer.NS.String()) { + err = b.AResource(dnsmessage.ResourceHeader{ + Name: nameServer.NS, + Type: dnsmessage.TypeA, + Class: dnsmessage.ClassINET, + TTL: 604800, // 60 * 60 * 24 * 7 == 1 week; long TTL, these IP addrs don't change + Length: 0, + }, aResource) + if err != nil { + return err + } + } + for _, aaaaResource := range NameToAAAA(nameServer.NS.String()) { + err = b.AAAAResource(dnsmessage.ResourceHeader{ + Name: nameServer.NS, + Type: dnsmessage.TypeAAAA, + Class: dnsmessage.ClassINET, + TTL: 604800, // 60 * 60 * 24 * 7 == 1 week; long TTL, these IP addrs don't change + Length: 0, + }, aaaaResource) + if err != nil { + return err + } + } + } + return nil + }) for _, nameServer := range nameServers { logMessages = append(logMessages, nameServer.NS.String()) } @@ -512,8 +550,7 @@ func NameToA(fqdnString string) []dnsmessage.AResource { return []dnsmessage.AResource{} } -// NameToAAAA returns either []AAAAResource that matched the hostname -// or ErrNotFound +// NameToAAAA returns an []AAAAResource that matched the hostname func NameToAAAA(fqdnString string) []dnsmessage.AAAAResource { fqdn := []byte(fqdnString) // is it a customized AAAA record? If so, return early