mirror of
https://github.com/cunnie/sslip.io.git
synced 2025-10-17 05:00:42 +08:00

- located in Warsaw, Poland - IPv4: 51.75.53.19 - IPv6: 2001:41d0:602:2313::1 The crux of this is to take the load off ns-aws, which jumped from $12.66 → $20.63 → $38.51 → $62.30 in the last four months due to bandwidth charges exceeding 10 TB. The real fix is to randomize the order in which the nameservers are returned.
471 lines
20 KiB
Go
471 lines
20 KiB
Go
package xip_test
|
|
|
|
import (
|
|
"math/rand"
|
|
"net"
|
|
"strings"
|
|
"xip/testhelper"
|
|
"xip/xip"
|
|
|
|
. "github.com/onsi/ginkgo/v2"
|
|
. "github.com/onsi/gomega"
|
|
"golang.org/x/net/dns/dnsmessage"
|
|
)
|
|
|
|
var _ = Describe("Xip", func() {
|
|
var (
|
|
err error
|
|
)
|
|
rand.Seed(GinkgoRandomSeed()) // Set to ginkgo's seed so that it's different each test & we can reproduce failures if necessary
|
|
|
|
Describe("CNAMEResources()", func() {
|
|
It("returns nil by default", func() {
|
|
randomDomain := testhelper.Random8ByteString() + ".com."
|
|
cname := xip.CNAMEResource(randomDomain)
|
|
Expect(cname).To(BeNil())
|
|
})
|
|
When("querying one of sslip.io's DKIM CNAME's", func() {
|
|
It("returns the CNAME", func() {
|
|
cname := xip.CNAMEResource("protonmail._domainkey.SSlip.Io.")
|
|
Expect(cname.CNAME.String()).To(MatchRegexp("^protonmail\\.domainkey.*.domains\\.proton\\.ch\\.$"))
|
|
})
|
|
})
|
|
When("a domain has been customized but has no CNAMEs", func() {
|
|
It("returns nil", func() {
|
|
customizedDomain := testhelper.Random8ByteString() + ".com."
|
|
xip.Customizations[customizedDomain] = xip.DomainCustomization{}
|
|
cname := xip.CNAMEResource(customizedDomain)
|
|
Expect(cname).To(BeNil())
|
|
delete(xip.Customizations, customizedDomain)
|
|
})
|
|
})
|
|
When("a domain has been customized with CNAMES", func() {
|
|
It("returns CNAME resources", func() {
|
|
customizedDomain := testhelper.Random8ByteString() + ".com."
|
|
xip.Customizations[strings.ToLower(customizedDomain)] = xip.DomainCustomization{
|
|
CNAME: dnsmessage.CNAMEResource{
|
|
CNAME: dnsmessage.Name{
|
|
// google.com.
|
|
Length: 11,
|
|
Data: [255]byte{
|
|
103, 111, 111, 103, 108, 101, 46, 99, 111, 109, 46,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
cname := xip.CNAMEResource(customizedDomain)
|
|
Expect(cname.CNAME.String()).To(Equal("google.com."))
|
|
delete(xip.Customizations, customizedDomain) // clean-up
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("MXResources()", func() {
|
|
It("returns the MX resource", func() {
|
|
randomDomain := testhelper.Random8ByteString() + ".com."
|
|
mx := xip.MXResources(randomDomain)
|
|
mxHostName := dnsmessage.MustNewName(randomDomain)
|
|
Expect(len(mx)).To(Equal(1))
|
|
Expect(mx[0].MX).To(Equal(mxHostName))
|
|
})
|
|
When("sslip.io is the domain being queried", func() {
|
|
It("returns sslip.io's custom MX records", func() {
|
|
mx := xip.MXResources("sslIP.iO.")
|
|
Expect(len(mx)).To(Equal(2))
|
|
Expect(mx[0].MX.Data).To(Equal(xip.Customizations["sslip.io."].MX[0].MX.Data))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("NSResources()", func() {
|
|
When("we use the default nameservers", func() {
|
|
var x, _ = xip.NewXip("file:///", []string{"ns-aws.sslip.io.", "ns-azure.sslip.io.", "ns-gce.sslip.io.", "ns-ovh.sslip.io."}, []string{}, []string{})
|
|
It("returns the name servers", func() {
|
|
randomDomain := testhelper.Random8ByteString() + ".com."
|
|
ns := x.NSResources(randomDomain)
|
|
Expect(len(ns)).To(Equal(4))
|
|
Expect(ns[0].NS.String()).To(Equal("ns-aws.sslip.io."))
|
|
Expect(ns[1].NS.String()).To(Equal("ns-azure.sslip.io."))
|
|
Expect(ns[2].NS.String()).To(Equal("ns-gce.sslip.io."))
|
|
Expect(ns[3].NS.String()).To(Equal("ns-ovh.sslip.io."))
|
|
})
|
|
When(`the domain name contains "_acme-challenge."`, func() {
|
|
When("the domain name has an embedded IP", func() {
|
|
It(`returns an array of one NS record pointing to the domain name _sans_ "acme-challenge."`, func() {
|
|
randomDomain := "192.168.0.1." + testhelper.Random8ByteString() + ".com."
|
|
ns := x.NSResources("_acme-challenge." + randomDomain)
|
|
Expect(len(ns)).To(Equal(1))
|
|
Expect(ns[0].NS.String()).To(Equal(strings.ToLower(randomDomain)))
|
|
aResources := xip.NameToA(randomDomain, true)
|
|
Expect(len(aResources)).To(Equal(1))
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(aResources[0].A).To(Equal([4]byte{192, 168, 0, 1}))
|
|
})
|
|
})
|
|
When("the domain name does not have an embedded IP", func() {
|
|
It("returns the default trinity of nameservers", func() {
|
|
randomDomain := "_acme-challenge." + testhelper.Random8ByteString() + ".com."
|
|
ns := x.NSResources(randomDomain)
|
|
Expect(len(ns)).To(Equal(4))
|
|
})
|
|
})
|
|
})
|
|
When("we delegate domains to other nameservers", func() {
|
|
When(`we don't use the "=" in the arguments`, func() {
|
|
It("returns an informative log message", func() {
|
|
var _, logs = xip.NewXip("file://etc/blocklist-test.txt", []string{"ns-aws.sslip.io.", "ns-azure.sslip.io.", "ns-gce.sslip.io.", "ns-ovh.sslip.io."}, []string{}, []string{"noEquals"})
|
|
Expect(strings.Join(logs, "")).To(MatchRegexp(`"-delegates: arguments should be in the format "delegatedDomain=nameserver", not "noEquals"`))
|
|
})
|
|
})
|
|
When(`there's no "." at the end of the delegated domain or nameserver`, func() {
|
|
It(`helpfully adds the "."`, func() {
|
|
var x, logs = xip.NewXip("file://etc/blocklist-test.txt", []string{"ns-aws.sslip.io.", "ns-azure.sslip.io.", "ns-gce.sslip.io.", "ns-ovh.sslip.io."}, []string{}, []string{"a=b"})
|
|
Expect(strings.Join(logs, "")).To(MatchRegexp(`Adding delegated NS record "a\.=b\."`))
|
|
ns := x.NSResources("a.")
|
|
Expect(len(ns)).To(Equal(1))
|
|
})
|
|
})
|
|
})
|
|
})
|
|
When("we override the default nameservers", func() {
|
|
var x, _ = xip.NewXip("file:///", []string{"mickey", "minn.ie.", "goo.fy"}, []string{}, []string{})
|
|
It("returns the configured servers", func() {
|
|
randomDomain := testhelper.Random8ByteString() + ".com."
|
|
ns := x.NSResources(randomDomain)
|
|
Expect(len(ns)).To(Equal(3))
|
|
Expect(ns[0].NS.String()).To(Equal("mickey."))
|
|
Expect(ns[1].NS.String()).To(Equal("minn.ie."))
|
|
Expect(ns[2].NS.String()).To(Equal("goo.fy."))
|
|
})
|
|
|
|
})
|
|
})
|
|
|
|
Describe("SOAResource()", func() {
|
|
It("returns the SOA resource for the domain in question", func() {
|
|
randomDomain := testhelper.Random8ByteString() + ".com."
|
|
randomDomainName := dnsmessage.MustNewName(randomDomain)
|
|
soa := xip.SOAResource(randomDomainName)
|
|
Expect(soa.NS.Data).To(Equal(randomDomainName.Data))
|
|
})
|
|
})
|
|
|
|
Describe("TXTResources()", func() {
|
|
var x xip.Xip
|
|
It("returns an empty array for a random domain", func() {
|
|
randomDomain := testhelper.Random8ByteString() + ".com."
|
|
txts, err := x.TXTResources(randomDomain, nil)
|
|
Expect(err).To(Not(HaveOccurred()))
|
|
Expect(len(txts)).To(Equal(0))
|
|
})
|
|
When("queried for the sslip.io domain", func() {
|
|
It("returns mail-related TXT resources for the sslip.io domain", func() {
|
|
domain := "ssLip.iO."
|
|
txts, err := x.TXTResources(domain, nil)
|
|
Expect(err).To(Not(HaveOccurred()))
|
|
Expect(len(txts)).To(Equal(2))
|
|
Expect(txts[0].TXT[0]).To(MatchRegexp("protonmail-verification="))
|
|
Expect(txts[1].TXT[0]).To(MatchRegexp("v=spf1"))
|
|
})
|
|
})
|
|
When("a random domain has been customized w/out any TXT defaults", func() { // Unnecessary, but confirms Golang's behavior for me, a doubting Thomas
|
|
customizedDomain := testhelper.Random8ByteString() + ".com."
|
|
xip.Customizations[customizedDomain] = xip.DomainCustomization{}
|
|
It("returns no TXT resources", func() {
|
|
txts, err := x.TXTResources(customizedDomain, nil)
|
|
Expect(err).To(Not(HaveOccurred()))
|
|
Expect(len(txts)).To(Equal(0))
|
|
})
|
|
delete(xip.Customizations, customizedDomain) // clean-up
|
|
})
|
|
When(`the domain "ip.sslip.io" is queried`, func() {
|
|
It("returns the IP address of the querier", func() {
|
|
txts, err := x.TXTResources("ip.sslip.io.", net.IP{1, 1, 1, 1})
|
|
Expect(err).To(Not(HaveOccurred()))
|
|
Expect(len(txts)).To(Equal(1))
|
|
Expect(txts[0].TXT[0]).To(MatchRegexp("^1.1.1.1$"))
|
|
})
|
|
})
|
|
When(`a customized domain without a TXT entry is queried`, func() {
|
|
It("returns no records (and doesn't panic, either)", func() {
|
|
txts, err := x.TXTResources("ns.sslip.io.", nil)
|
|
Expect(err).To(Not(HaveOccurred()))
|
|
Expect(len(txts)).To(Equal(0))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("NameToA()", func() {
|
|
xip.Customizations["custom.record."] = xip.DomainCustomization{A: []dnsmessage.AResource{
|
|
{A: [4]byte{78, 46, 204, 247}},
|
|
}}
|
|
DescribeTable("when it succeeds",
|
|
func(fqdn string, expectedA dnsmessage.AResource) {
|
|
ipv4Answers := xip.NameToA(fqdn, true)
|
|
Expect(len(ipv4Answers)).To(Equal(1))
|
|
Expect(ipv4Answers[0]).To(Equal(expectedA))
|
|
},
|
|
Entry("custom record", "CusTom.RecOrd.", dnsmessage.AResource{A: [4]byte{78, 46, 204, 247}}),
|
|
// dots
|
|
Entry("loopback", "127.0.0.1", dnsmessage.AResource{A: [4]byte{127, 0, 0, 1}}),
|
|
Entry("255 with domain", "255.254.253.252.com", dnsmessage.AResource{A: [4]byte{255, 254, 253, 252}}),
|
|
Entry(`"This" network, pre-and-post`, "nono.io.0.1.2.3.ssLIp.IO", dnsmessage.AResource{A: [4]byte{0, 1, 2, 3}}),
|
|
Entry("private network, two IPs, grabs the leftmost", "nono.io.172.16.0.30.172.31.255.255.sslip.io", dnsmessage.AResource{A: [4]byte{172, 16, 0, 30}}),
|
|
// dashes
|
|
Entry("shared address with dashes", "100-64-1-2", dnsmessage.AResource{A: [4]byte{100, 64, 1, 2}}),
|
|
Entry("link-local with domain", "169-254-168-253-com", dnsmessage.AResource{A: [4]byte{169, 254, 168, 253}}),
|
|
Entry("IETF protocol assignments with domain and www", "www-192-0-0-1-com", dnsmessage.AResource{A: [4]byte{192, 0, 0, 1}}),
|
|
// dots-and-dashes, mix-and-matches
|
|
Entry("Pandaxin's paradox", "minio-01.192-168-1-100.sslip.io", dnsmessage.AResource{A: [4]byte{192, 168, 1, 100}}),
|
|
)
|
|
DescribeTable("when it does NOT match an IP address",
|
|
func(fqdn string) {
|
|
ipv4Answers := xip.NameToA(fqdn, true)
|
|
Expect(len(ipv4Answers)).To(Equal(0))
|
|
},
|
|
Entry("empty string", ""),
|
|
Entry("bare domain", "nono.io"),
|
|
Entry("canonical domain", "sslip.io"),
|
|
Entry("www", "www.sslip.io"),
|
|
Entry("a lone number", "538.sslip.io"),
|
|
Entry("too big", "256.254.253.252"),
|
|
Entry("NS but no dot", "ns-aws.sslip.io"),
|
|
Entry("NS + cruft at beginning", "p-ns-aws.sslip.io"),
|
|
Entry("test-net address with dots-and-dashes mixed", "www-192.0-2.3.example-me.com"),
|
|
)
|
|
When("There is more than one A record", func() {
|
|
It("returns them all", func() {
|
|
fqdn := testhelper.Random8ByteString()
|
|
xip.Customizations[strings.ToLower(fqdn)] = xip.DomainCustomization{
|
|
A: []dnsmessage.AResource{
|
|
{A: [4]byte{1}},
|
|
{A: [4]byte{2}},
|
|
},
|
|
}
|
|
ipv4Answers := xip.NameToA(fqdn, true)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(len(ipv4Answers)).To(Equal(2))
|
|
Expect(ipv4Answers[0].A).To(Equal([4]byte{1}))
|
|
Expect(ipv4Answers[1].A).To(Equal([4]byte{2}))
|
|
delete(xip.Customizations, fqdn)
|
|
})
|
|
})
|
|
When("There are multiple matches", func() {
|
|
It("returns the leftmost one", func() {
|
|
ipv4Answers := xip.NameToA("nono.io.127.0.0.1.192.168.0.1.sslip.io", true)
|
|
Expect(len(ipv4Answers)).To(Equal(1))
|
|
Expect(ipv4Answers[0]).
|
|
To(Equal(dnsmessage.AResource{A: [4]byte{127, 0, 0, 1}}))
|
|
})
|
|
})
|
|
When("There are matches with dashes and dots", func() {
|
|
It("returns the one with dashes", func() {
|
|
ipv4Answers := xip.NameToA("nono.io.127.0.0.1.192-168-0-1.sslip.io", true)
|
|
Expect(len(ipv4Answers)).To(Equal(1))
|
|
Expect(ipv4Answers[0]).
|
|
To(Equal(dnsmessage.AResource{A: [4]byte{192, 168, 0, 1}}))
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("IsAcmeChallenge()", func() {
|
|
When("the domain doesn't have '_acme-challenge.' in it", func() {
|
|
It("returns false", func() {
|
|
randomDomain := testhelper.Random8ByteString() + ".com."
|
|
Expect(xip.IsAcmeChallenge(randomDomain)).To(BeFalse())
|
|
})
|
|
It("returns false even when there are embedded IPs", func() {
|
|
randomDomain := "127.0.0.1." + testhelper.Random8ByteString() + ".com."
|
|
Expect(xip.IsAcmeChallenge(randomDomain)).To(BeFalse())
|
|
})
|
|
})
|
|
When("it has '_acme-challenge.' in it", func() {
|
|
When("it does NOT have any embedded IPs", func() {
|
|
It("returns false", func() {
|
|
randomDomain := "_acme-challenge." + testhelper.Random8ByteString() + ".com."
|
|
Expect(xip.IsAcmeChallenge(randomDomain)).To(BeFalse())
|
|
})
|
|
})
|
|
When("it has embedded IPs", func() {
|
|
It("returns true", func() {
|
|
randomDomain := "_acme-challenge.127.0.0.1." + testhelper.Random8ByteString() + ".com."
|
|
Expect(xip.IsAcmeChallenge(randomDomain)).To(BeTrue())
|
|
randomDomain = "_acme-challenge.fe80--1." + testhelper.Random8ByteString() + ".com."
|
|
Expect(xip.IsAcmeChallenge(randomDomain)).To(BeTrue())
|
|
})
|
|
When("it has random capitalization", func() {
|
|
It("returns true", func() {
|
|
randomDomain := "_AcMe-ChAlLeNgE.127.0.0.1." + testhelper.Random8ByteString() + ".com."
|
|
Expect(xip.IsAcmeChallenge(randomDomain)).To(BeTrue())
|
|
randomDomain = "_aCMe-cHAllENge.fe80--1." + testhelper.Random8ByteString() + ".com."
|
|
Expect(xip.IsAcmeChallenge(randomDomain)).To(BeTrue())
|
|
})
|
|
})
|
|
})
|
|
})
|
|
})
|
|
Describe("IsDelegated()", func() {
|
|
var nsName dnsmessage.Name
|
|
nsName, err = dnsmessage.NewName("1.com")
|
|
Expect(err).ToNot(HaveOccurred())
|
|
xip.Customizations["a.com"] = xip.DomainCustomization{NS: []dnsmessage.NSResource{dnsmessage.NSResource{NS: nsName}}}
|
|
xip.Customizations["b.com"] = xip.DomainCustomization{}
|
|
|
|
When("the domain is delegated", func() {
|
|
When("the fqdn exactly matches the domain", func() {
|
|
It("returns true", func() {
|
|
Expect(xip.IsDelegated("A.com")).To(BeTrue())
|
|
})
|
|
})
|
|
When("the fqdn is a subdomain of the domain", func() {
|
|
It("returns true", func() {
|
|
Expect(xip.IsDelegated("b.a.COM")).To(BeTrue())
|
|
})
|
|
})
|
|
When("the fqdn doesn't match the domain", func() {
|
|
It("returns false", func() {
|
|
Expect(xip.IsDelegated("Aa.com")).To(BeFalse())
|
|
})
|
|
})
|
|
})
|
|
When("the domain is customized but not delegated", func() {
|
|
It("returns false", func() {
|
|
Expect(xip.IsDelegated("b.COM")).To(BeFalse())
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("NameToAAAA()", func() {
|
|
DescribeTable("when it succeeds",
|
|
func(fqdn string, expectedAAAA dnsmessage.AAAAResource) {
|
|
ipv6Answers := xip.NameToAAAA(fqdn, true)
|
|
Expect(len(ipv6Answers)).To(Equal(1))
|
|
Expect(ipv6Answers[0]).To(Equal(expectedAAAA))
|
|
},
|
|
// dashes only
|
|
Entry("loopback", "--1", dnsmessage.AAAAResource{AAAA: [16]byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}}),
|
|
Entry("ff with domain", "fffe-fdfc-fbfa-f9f8-f7f6-f5f4-f3f2-f1f0.com", dnsmessage.AAAAResource{AAAA: [16]byte{255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240}}),
|
|
Entry("ff with domain and pre", "www.fffe-fdfc-fbfa-f9f8-f7f6-f5f4-f3f2-f1f0.com", dnsmessage.AAAAResource{AAAA: [16]byte{255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240}}),
|
|
Entry("ff with domain dashes", "1.www-fffe-fdfc-fbfa-f9f8-f7f6-f5f4-f3f2-f1f0-1.com", dnsmessage.AAAAResource{AAAA: [16]byte{255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240}}),
|
|
Entry("Browsing the logs", "2006-41d0-2-e01e--56dB-3598.sSLIP.io.", dnsmessage.AAAAResource{AAAA: [16]byte{32, 6, 65, 208, 0, 2, 224, 30, 0, 0, 0, 0, 86, 219, 53, 152}}),
|
|
Entry("Browsing the logs", "1-2-3--4-5-6.sSLIP.io.", dnsmessage.AAAAResource{AAAA: [16]byte{0, 1, 0, 2, 0, 3, 0, 0, 0, 0, 0, 4, 0, 5, 0, 6}}),
|
|
Entry("Browsing the logs", "1--2-3-4-5-6.sSLIP.io.", dnsmessage.AAAAResource{AAAA: [16]byte{0, 1, 0, 0, 0, 0, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6}}),
|
|
)
|
|
DescribeTable("when it does not match an IP address",
|
|
func(fqdn string) {
|
|
ipv6Answers := xip.NameToAAAA(fqdn, true)
|
|
Expect(len(ipv6Answers)).To(Equal(0))
|
|
},
|
|
Entry("empty string", ""),
|
|
Entry("bare domain", "nono.io"),
|
|
Entry("canonical domain", "sslip.io"),
|
|
Entry("www", "www.sslip.io"),
|
|
Entry("a 1 without double-dash", "-1"),
|
|
Entry("too big", "--g"),
|
|
)
|
|
When("using randomly generated IPv6 addresses (fuzz testing)", func() {
|
|
It("should succeed every time", func() {
|
|
for i := 0; i < 10000; i++ {
|
|
addr := testhelper.RandomIPv6Address()
|
|
ipv6Answers := xip.NameToAAAA(strings.ReplaceAll(addr.String(), ":", "-"), true)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(ipv6Answers[0].AAAA[:]).To(Equal([]uint8(addr)))
|
|
}
|
|
})
|
|
})
|
|
When("There is more than one AAAA record", func() {
|
|
It("returns them all", func() {
|
|
fqdn := testhelper.Random8ByteString()
|
|
xip.Customizations[strings.ToLower(fqdn)] = xip.DomainCustomization{
|
|
AAAA: []dnsmessage.AAAAResource{
|
|
{AAAA: [16]byte{1}},
|
|
{AAAA: [16]byte{2}},
|
|
},
|
|
}
|
|
ipv6Addrs := xip.NameToAAAA(fqdn, true)
|
|
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)
|
|
})
|
|
})
|
|
})
|
|
|
|
Describe("ReadBlocklist()", func() {
|
|
It("strips comments", func() {
|
|
input := strings.NewReader("# a comment\n#another comment\nno-comments\n")
|
|
bls, blIPs, err := xip.ReadBlocklist(input)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(bls).To(Equal([]string{"no-comments"}))
|
|
Expect(blIPs).To(BeNil())
|
|
})
|
|
It("strips blank lines", func() {
|
|
input := strings.NewReader("\n\n\nno-blank-lines")
|
|
bls, blIPs, err := xip.ReadBlocklist(input)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(bls).To(Equal([]string{"no-blank-lines"}))
|
|
Expect(blIPs).To(BeNil())
|
|
})
|
|
It("lowercases names for comparison", func() {
|
|
input := strings.NewReader("NO-YELLING")
|
|
bls, blIPs, err := xip.ReadBlocklist(input)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(bls).To(Equal([]string{"no-yelling"}))
|
|
Expect(blIPs).To(BeNil())
|
|
})
|
|
It("removes all non-allowable characters", func() {
|
|
input := strings.NewReader("\nalpha #comment # comment\nåß∂ # comment # comment\ndelta∆\n ... GAMMA∑µ®† ...#asdfasdf#asdfasdf")
|
|
bls, blIPs, err := xip.ReadBlocklist(input)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(bls).To(Equal([]string{"alpha", "delta", "gamma"}))
|
|
Expect(blIPs).To(BeNil())
|
|
})
|
|
It("reads in IPv4 CIDRs", func() {
|
|
input := strings.NewReader("\n43.134.66.67/24 #asdfasdf")
|
|
bls, blIPs, err := xip.ReadBlocklist(input)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(bls).To(BeNil())
|
|
Expect(blIPs).To(Equal([]net.IPNet{{IP: net.IP{43, 134, 66, 0}, Mask: net.IPMask{255, 255, 255, 0}}}))
|
|
})
|
|
It("reads in IPv6 CIDRs", func() {
|
|
input := strings.NewReader("\n 2600::/64 #asdfasdf")
|
|
bls, blIPs, err := xip.ReadBlocklist(input)
|
|
Expect(err).ToNot(HaveOccurred())
|
|
Expect(bls).To(BeNil())
|
|
Expect(blIPs).To(Equal([]net.IPNet{
|
|
{IP: net.IP{38, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
Mask: net.IPMask{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}}}))
|
|
})
|
|
})
|
|
|
|
Describe("IsPublic()", func() {
|
|
DescribeTable("when determining whether an IP is public or private",
|
|
func(ip net.IP, expectedPublic bool) {
|
|
Expect(xip.IsPublic(ip)).To(Equal(expectedPublic))
|
|
},
|
|
Entry("Google Nameserver IPv4", net.ParseIP("8.8.8.8"), true),
|
|
Entry("Google Nameserver IPv6", net.ParseIP("2001:4860:4860::8888"), true),
|
|
Entry("Apple Studio morgoth.nono.io", net.ParseIP("2601:646:100:69f0:7d:9069:ea74:e3a"), true),
|
|
Entry("External interface home.nono.io", net.ParseIP("2001:558:6045:109:892f:2df3:15e3:3184"), true),
|
|
Entry("RFC 1918 Section 3 10/8", net.ParseIP("10.9.9.30"), false),
|
|
Entry("RFC 1918 Section 3 172.16/12", net.ParseIP("172.31.255.255"), false),
|
|
Entry("RFC 1918 Section 3 192.168/16", net.ParseIP("192.168.0.1"), false),
|
|
Entry("RFC 4193 Section 8 fc00::/7", net.ParseIP("fdff::"), false),
|
|
Entry("CG-NAT 100.64/10", net.ParseIP("100.127.255.255"), false),
|
|
Entry("CG-NAT 100.64/10", net.ParseIP("100.128.0.0"), true),
|
|
Entry("link-local IPv4", net.ParseIP("169.254.169.254"), false),
|
|
Entry("not link-local IPv4", net.ParseIP("169.255.255.255"), true),
|
|
Entry("link-local IPv6", net.ParseIP("fe80::"), false),
|
|
Entry("loopback IPv4 127/8", net.ParseIP("127.127.127.127"), false),
|
|
Entry("loopback IPv6 ::1/128", net.ParseIP("::1"), false),
|
|
Entry("IPv4/IPv6 Translation internet", net.ParseIP("64:ff9b::"), true),
|
|
Entry("IPv4/IPv6 Translation private internet", net.ParseIP("64:ff9b:1::"), false),
|
|
Entry("IPv4/IPv6 Translation internet", net.ParseIP("64:ff9b::"), true),
|
|
Entry("Teredo Tunneling", net.ParseIP("2001::"), true),
|
|
Entry("ORCHIDv2 (?)", net.ParseIP("2001:20::"), false),
|
|
Entry("Documentation", net.ParseIP("2001:db8::"), false),
|
|
Entry("Private internets", net.ParseIP("fc00::"), false),
|
|
)
|
|
})
|
|
})
|