mirror of
https://github.com/cunnie/sslip.io.git
synced 2025-10-26 17:10:28 +08:00
DNS server: allow returning _multiple_ AAAA records
Previously the DNS server only returned the first AAAA record of a customized domain; now it will return all the AAAA records.
This commit is contained in:
@@ -204,13 +204,10 @@ func processQuestion(q dnsmessage.Question, b *dnsmessage.Builder) (logMessage s
|
||||
}
|
||||
case dnsmessage.TypeAAAA:
|
||||
{
|
||||
var nameToAAAA *dnsmessage.AAAAResource
|
||||
nameToAAAA, err = NameToAAAA(q.Name.String())
|
||||
var nameToAAAAs []dnsmessage.AAAAResource
|
||||
nameToAAAAs, err = NameToAAAA(q.Name.String())
|
||||
if err != nil {
|
||||
// There's only one possible error this can be: ErrNotFound. note that
|
||||
// this could be written more efficiently; however, I wrote it to
|
||||
// accommodate 'if err != nil' convention. My first version was 'if
|
||||
// err == nil', and it flummoxed me.
|
||||
// There's only one possible error this can be: ErrNotFound
|
||||
err = noAnswersOnlyAuthorities(q, b, &logMessage)
|
||||
return
|
||||
} else {
|
||||
@@ -218,18 +215,22 @@ func processQuestion(q dnsmessage.Question, b *dnsmessage.Builder) (logMessage s
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
err = b.AAAAResource(dnsmessage.ResourceHeader{
|
||||
Name: q.Name,
|
||||
Type: dnsmessage.TypeAAAA,
|
||||
Class: dnsmessage.ClassINET,
|
||||
TTL: 604800, // 60 * 60 * 24 * 7 == 1 week; long TTL, these IP addrs don't change
|
||||
Length: 0,
|
||||
}, *nameToAAAA)
|
||||
if err != nil {
|
||||
return
|
||||
var logMessages []string
|
||||
for _, nameToAAAA := range nameToAAAAs {
|
||||
err = b.AAAAResource(dnsmessage.ResourceHeader{
|
||||
Name: q.Name,
|
||||
Type: dnsmessage.TypeAAAA,
|
||||
Class: dnsmessage.ClassINET,
|
||||
TTL: 604800, // 60 * 60 * 24 * 7 == 1 week; long TTL, these IP addrs don't change
|
||||
Length: 0,
|
||||
}, nameToAAAA)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
ip := net.IP(nameToAAAA.AAAA[:])
|
||||
logMessages = append(logMessages, ip.String())
|
||||
}
|
||||
ip := net.IP(nameToAAAA.AAAA[:])
|
||||
logMessage += ip.String()
|
||||
logMessage += strings.Join(logMessages, ", ")
|
||||
}
|
||||
}
|
||||
case dnsmessage.TypeALL:
|
||||
@@ -383,14 +384,14 @@ func NameToA(fqdnString string) (*dnsmessage.AResource, error) {
|
||||
|
||||
// NameToAAAA NameToA returns either an AAAAResource that matched the hostname
|
||||
// or ErrNotFound
|
||||
func NameToAAAA(fqdnString string) (*dnsmessage.AAAAResource, error) {
|
||||
func NameToAAAA(fqdnString string) ([]dnsmessage.AAAAResource, error) {
|
||||
fqdn := []byte(fqdnString)
|
||||
// is it a customized AAAA record? If so, return early
|
||||
if domain, ok := Customizations[fqdnString]; ok && len(domain.AAAA) > 0 {
|
||||
return &domain.AAAA[0], nil // TODO: handle multiple AAAA records
|
||||
return domain.AAAA, nil
|
||||
}
|
||||
if !ipv6RE.Match(fqdn) {
|
||||
return &dnsmessage.AAAAResource{}, ErrNotFound
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
|
||||
ipv6RE.Longest()
|
||||
@@ -402,7 +403,7 @@ func NameToAAAA(fqdnString string) (*dnsmessage.AAAAResource, error) {
|
||||
for i := range ipv16address {
|
||||
AAAAR.AAAA[i] = ipv16address[i]
|
||||
}
|
||||
return &AAAAR, nil
|
||||
return []dnsmessage.AAAAResource{AAAAR}, nil
|
||||
}
|
||||
|
||||
func NSResources() map[string]dnsmessage.NSResource {
|
||||
|
||||
@@ -406,9 +406,10 @@ var _ = Describe("Xip", func() {
|
||||
Describe("NameToAAAA()", func() {
|
||||
DescribeTable("when it succeeds",
|
||||
func(fqdn string, expectedAAAA dnsmessage.AAAAResource) {
|
||||
ipv6Answer, err := xip.NameToAAAA(fqdn)
|
||||
ipv6Answers, err := xip.NameToAAAA(fqdn)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(*ipv6Answer).To(Equal(expectedAAAA))
|
||||
Expect(len(ipv6Answers)).To(Equal(1))
|
||||
Expect(ipv6Answers[0]).To(Equal(expectedAAAA))
|
||||
},
|
||||
// sslip.io website
|
||||
Entry("sslip.io", "sslip.io.", xip.Customizations["sslip.io."].AAAA[0]),
|
||||
@@ -439,12 +440,30 @@ var _ = Describe("Xip", func() {
|
||||
It("should succeed every time", func() {
|
||||
for i := 0; i < 1000; i++ {
|
||||
addr := randomIPv6Address()
|
||||
ipv6Answer, err := xip.NameToAAAA(strings.ReplaceAll(addr.String(), ":", "-"))
|
||||
ipv6Answers, err := xip.NameToAAAA(strings.ReplaceAll(addr.String(), ":", "-"))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(ipv6Answer.AAAA[:]).To(Equal([]uint8(addr)))
|
||||
Expect(ipv6Answers[0].AAAA[:]).To(Equal([]uint8(addr)))
|
||||
}
|
||||
})
|
||||
})
|
||||
When("There is more than one AAAA record", func() {
|
||||
It("returns them all", func() {
|
||||
fqdn := random8ByteString()
|
||||
xip.Customizations[fqdn] = xip.DomainCustomization{
|
||||
//copy(xip.Customizations[fqdn].AAAA, dnsmessage.AAAAResource)
|
||||
AAAA: []dnsmessage.AAAAResource{
|
||||
{AAAA: [16]byte{1}},
|
||||
{AAAA: [16]byte{2}},
|
||||
},
|
||||
}
|
||||
ipv6Addrs, err := xip.NameToAAAA(fqdn)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(len(ipv6Addrs)).To(Equal(2))
|
||||
Expect(ipv6Addrs[0].AAAA).To(Equal([16]byte{1}))
|
||||
Expect(ipv6Addrs[1].AAAA).To(Equal([16]byte{2}))
|
||||
delete(xip.Customizations, fqdn)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -465,3 +484,13 @@ func randomIPv6Address() net.IP {
|
||||
}
|
||||
return ipv6
|
||||
}
|
||||
|
||||
// random8ByteString() returns an 8-char string consisting solely of the letters a-z.
|
||||
func random8ByteString() string {
|
||||
var randomString []byte
|
||||
for i := 0; i < 8; i++ {
|
||||
// 97 == ascii 'a', and there are 26 letters in the alphabet
|
||||
randomString = append(randomString, byte(97+rand.Intn(26)))
|
||||
}
|
||||
return string(randomString)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user