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 4144333..1d39041 100644 --- a/bosh-release/src/sslip.io-dns-server/integration_test.go +++ b/bosh-release/src/sslip.io-dns-server/integration_test.go @@ -121,26 +121,26 @@ var _ = Describe("sslip.io-dns-server", func() { "@127.0.0.1 example.com txt +short", `\A\z`, `TypeTXT example.com. \? nil, SOA example.com. briancunnie.gmail.com. 2021080200 900 900 1800 300\n$`), - Entry(`getting a non-existent value: TXT for my-key.kv.sslip.io"`, - "@127.0.0.1 my-key.kv.sslip.io txt +short", + Entry(`getting a non-existent value: TXT for my-key.k-v.io"`, + "@127.0.0.1 my-key.k-v.io txt +short", `\A\z`, - `TypeTXT my-key.kv.sslip.io. \? nil, SOA my-key.kv.sslip.io. briancunnie.gmail.com. 2021080200 900 900 1800 300\n$`), - Entry(`putting a value: TXT for put.MyValue.MY-KEY.kv.sslip.io"`, - "@127.0.0.1 put.MyValue.MY-KEY.kv.sslip.io txt +short", + `TypeTXT my-key.k-v.io. \? nil, SOA my-key.k-v.io. briancunnie.gmail.com. 2021080200 900 900 1800 300\n$`), + Entry(`putting a value: TXT for put.MyValue.MY-KEY.k-v.io"`, + "@127.0.0.1 put.MyValue.MY-KEY.k-v.io txt +short", `"MyValue"`, - `TypeTXT put.MyValue.MY-KEY.kv.sslip.io. \? \["MyValue"\]`), - Entry(`getting a value: TXT for my-key.kv.sslip.io"`, - "@127.0.0.1 my-key.kv.sslip.io txt +short", + `TypeTXT put.MyValue.MY-KEY.k-v.io. \? \["MyValue"\]`), + Entry(`getting a value: TXT for my-key.k-v.io"`, + "@127.0.0.1 my-key.k-v.io txt +short", `"MyValue"`, - `TypeTXT my-key.kv.sslip.io. \? \["MyValue"\]`), - Entry(`deleting a value: TXT for delete.my-key.kv.sslip.io"`, - "@127.0.0.1 delete.my-key.kv.sslip.io txt +short", + `TypeTXT my-key.k-v.io. \? \["MyValue"\]`), + Entry(`deleting a value: TXT for delete.my-key.k-v.io"`, + "@127.0.0.1 delete.my-key.k-v.io txt +short", `"MyValue"`, - `TypeTXT delete.my-key.kv.sslip.io. \? \["MyValue"\]`), - Entry(`getting a non-existent value: TXT for my-key.kv.sslip.io"`, - "@127.0.0.1 my-key.kv.sslip.io txt +short", + `TypeTXT delete.my-key.k-v.io. \? \["MyValue"\]`), + Entry(`getting a non-existent value: TXT for my-key.k-v.io"`, + "@127.0.0.1 my-key.k-v.io txt +short", `\A\z`, - `TypeTXT my-key.kv.sslip.io. \? nil, SOA my-key.kv.sslip.io. briancunnie.gmail.com. 2021080200 900 900 1800 300\n$`), + `TypeTXT my-key.k-v.io. \? nil, SOA my-key.k-v.io. briancunnie.gmail.com. 2021080200 900 900 1800 300\n$`), ) }) Describe("for more complex assertions", func() { @@ -225,33 +225,33 @@ var _ = Describe("sslip.io-dns-server", func() { Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT sslip.io. \? \["protonmail-verification=ce0ca3f5010aa7a2cf8bcc693778338ffde73e26"\], \["v=spf1 include:_spf.protonmail.ch mx ~all"\]\n`)) }) }) - When(`a TXT record for a host under the "kv.sslip.io" domain is queried`, func() { + When(`a TXT record for a host under the "k-v.io" domain is queried`, func() { It(`the PUT has a three-minute TTL`, func() { - digArgs = "@localhost put.a.b.kv.sslip.io txt" + digArgs = "@localhost put.a.b.k-v.io txt" digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) Expect(err).ToNot(HaveOccurred()) - Eventually(digSession).Should(Say(`put.a.b.kv.sslip.io. 180 IN TXT "a"`)) + Eventually(digSession).Should(Say(`put.a.b.k-v.io. 180 IN TXT "a"`)) Eventually(digSession, 1).Should(Exit(0)) - Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT put.a.b.kv.sslip.io. \? \["a"\]`)) + Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT put.a.b.k-v.io. \? \["a"\]`)) }) It(`the GET has a three-minute TTL`, func() { - digArgs = "@localhost b.kv.sslip.io txt" + digArgs = "@localhost b.k-v.io txt" digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) Expect(err).ToNot(HaveOccurred()) - Eventually(digSession).Should(Say(`b.kv.sslip.io. 180 IN TXT "a"`)) + Eventually(digSession).Should(Say(`b.k-v.io. 180 IN TXT "a"`)) Eventually(digSession, 1).Should(Exit(0)) - Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT b.kv.sslip.io. \? \["a"\]`)) + Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT b.k-v.io. \? \["a"\]`)) }) It(`the DELETE has a three-minute TTL`, func() { - digArgs = "@localhost delete.b.kv.sslip.io txt" + digArgs = "@localhost delete.b.k-v.io txt" digCmd = exec.Command("dig", strings.Split(digArgs, " ")...) digSession, err = Start(digCmd, GinkgoWriter, GinkgoWriter) Expect(err).ToNot(HaveOccurred()) - Eventually(digSession).Should(Say(`delete.b.kv.sslip.io. 180 IN TXT "a"`)) + Eventually(digSession).Should(Say(`delete.b.k-v.io. 180 IN TXT "a"`)) Eventually(digSession, 1).Should(Exit(0)) - Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT delete.b.kv.sslip.io. \? \["a"\]`)) + Eventually(string(serverSession.Err.Contents())).Should(MatchRegexp(`TypeTXT delete.b.k-v.io. \? \["a"\]`)) }) }) When(`a record for an "_acme-challenge" domain is queried`, 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 b92a478..7fc5824 100644 --- a/bosh-release/src/sslip.io-dns-server/xip/xip.go +++ b/bosh-release/src/sslip.io-dns-server/xip/xip.go @@ -20,7 +20,7 @@ import ( // Xip contains info that the routines need to answer a query that I don't want to plumb // through the call hierarchy -// (the source address for `ip.sslip.io`, and the etcd client for `kv.sslip.io`) +// (the source address for `ip.sslip.io`, and the etcd client for `k-v.io`) type Xip struct { SrcAddr net.IP Etcd *v3client.Client @@ -53,7 +53,7 @@ type DomainCustomizations map[string]DomainCustomization // KvCustomizations is a lookup table for custom TXT records // e.g. KvCustomizations["my-key"] = []dnsmessage.TXTResource{ TXT: { "my-value" } } -// The key should NOT include ".kv.sslip.io." +// The key should NOT include ".k-v.io." type KvCustomizations map[string][]dnsmessage.TXTResource // There's nothing like global variables to make my heart pound with joy. @@ -66,7 +66,7 @@ var ( // https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses ipv6RE = regexp.MustCompile(`(^|[.-])(([0-9a-fA-F]{1,4}-){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}-){1,7}-|([0-9a-fA-F]{1,4}-){1,6}-[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}-){1,5}(-[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}-){1,4}(-[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}-){1,3}(-[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}-){1,2}(-[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}-((-[0-9a-fA-F]{1,4}){1,6})|-((-[0-9a-fA-F]{1,4}){1,7}|-)|fe80-(-[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]+|--(ffff(-0{1,4})?-)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])|([0-9a-fA-F]{1,4}-){1,4}-((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))($|[.-])`) dns01ChallengeRE = regexp.MustCompile(`(?i)_acme-challenge\.`) - kvRE = regexp.MustCompile(`\.kv\.sslip\.io\.$`) + kvRE = regexp.MustCompile(`\.k-v\.io\.$`) nsAwsSslip, _ = dnsmessage.NewName("ns-aws.sslip.io.") nsAzureSslip, _ = dnsmessage.NewName("ns-azure.sslip.io.") nsGceSslip, _ = dnsmessage.NewName("ns-gce.sslip.io.") @@ -745,27 +745,27 @@ func ipSslipIo(sourceIP string) ([]dnsmessage.TXTResource, error) { return []dnsmessage.TXTResource{{TXT: []string{sourceIP}}}, nil } -// when TXT for "kv.sslip.io" is queried, return the key-value pair +// when TXT for "k-v.io" is queried, return the key-value pair func (x Xip) kvTXTResources(fqdn string) ([]dnsmessage.TXTResource, error) { // "labels" => official RFC 1035 term - // kv.sslip.io. => ["kv", "sslip", "io"] are labels + // k-v.io. => ["k-v", "io"] are labels var ( verb string // i.e. "get", "put", "delete" - key string // e.g. "my-key" as in "my-key.kv.sslip.io" - value string // e.g. "my-value" as in "put.my-value.my-key.kv.sslip.io" + key string // e.g. "my-key" as in "my-key.k-v.io" + value string // e.g. "my-value" as in "put.my-value.my-key.k-v.io" ) labels := strings.Split(fqdn, ".") - labels = labels[:len(labels)-4] // strip ".kv.sslip.io" - key = strings.ToLower(labels[len(labels)-1]) // key is always present, always first subdomain of "kv.sslip.io" + labels = labels[:len(labels)-3] // strip ".k-v.io" + key = strings.ToLower(labels[len(labels)-1]) // key is always present, always first subdomain of "k-v.io" switch { case len(labels) == 1: verb = "get" // default action if only key, not verb, is not present case len(labels) == 2: - verb = strings.ToLower(labels[0]) // verb, if present, is leftmost, "put.value.key.kv.sslip.io" + verb = strings.ToLower(labels[0]) // verb, if present, is leftmost, "put.value.key.k-v.io" case len(labels) > 2: verb = strings.ToLower(labels[0]) // concatenate multiple labels to create value, especially useful for version numbers - value = strings.Join(labels[1:len(labels)-1], ".") // e.g. "put.94.0.2.firefox-version.kv.sslip.io" + value = strings.Join(labels[1:len(labels)-1], ".") // e.g. "put.94.0.2.firefox-version.k-v.io" } // prepare to query etcd: ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*500) diff --git a/bosh-release/src/sslip.io-dns-server/xip/xip_test.go b/bosh-release/src/sslip.io-dns-server/xip/xip_test.go index c86d81e..732ed2b 100644 --- a/bosh-release/src/sslip.io-dns-server/xip/xip_test.go +++ b/bosh-release/src/sslip.io-dns-server/xip/xip_test.go @@ -172,7 +172,7 @@ var _ = Describe("Xip", func() { AfterEach(func() { x.Etcd.Close() }) - DescribeTable(`the domain "kv.sslip.io" is queried`, + DescribeTable(`the domain "k-v.io" is queried`, func(fqdn string, txts []string) { txtResources, err := x.TXTResources(fqdn) Expect(err).ToNot(HaveOccurred()) @@ -183,25 +183,25 @@ var _ = Describe("Xip", func() { } }, // simple tests: get, put, delete with single label value - Entry("no arguments → empty array", "kv.sslip.io.", []string{}), - Entry("putting a value → that value", "PUT.MyValue.my-key.kv.sslip.io.", []string{"MyValue"}), - Entry("getting that value → that value", "my-key.kv.sslip.io.", []string{"MyValue"}), - Entry("getting that value with an UPPERCASE key → that value", "MY-KEY.kv.sslip.io.", []string{"MyValue"}), - Entry("explicitly getting that value → that value", "GeT.my-key.kv.sslip.io.", []string{"MyValue"}), - Entry("deleting that value → the deleted value", "DelETe.my-key.kv.sslip.io.", []string{"MyValue"}), - Entry("getting that deleted value → empty array", "my-key.kv.sslip.io.", []string{}), + Entry("no arguments → empty array", "k-v.io.", []string{}), + Entry("putting a value → that value", "PUT.MyValue.my-key.k-v.io.", []string{"MyValue"}), + Entry("getting that value → that value", "my-key.k-v.io.", []string{"MyValue"}), + Entry("getting that value with an UPPERCASE key → that value", "MY-KEY.k-v.io.", []string{"MyValue"}), + Entry("explicitly getting that value → that value", "GeT.my-key.k-v.io.", []string{"MyValue"}), + Entry("deleting that value → the deleted value", "DelETe.my-key.k-v.io.", []string{"MyValue"}), + Entry("getting that deleted value → empty array", "my-key.k-v.io.", []string{}), // errors - Entry("getting a non-existent key → empty array", "nonexistent.kv.sslip.io.", []string{}), - Entry("putting but skipping the value → error txt", "put.my-key.kv.sslip.io.", []string{"422: no value provided"}), - Entry("deleting a non-existent key → silently succeeds", "delete.non-existent.kv.sslip.io.", []string{}), - Entry("using a garbage verb → error txt", "post.my-key.kv.sslip.io.", []string{"422: valid verbs are get, put, delete"}), + Entry("getting a non-existent key → empty array", "nonexistent.k-v.io.", []string{}), + Entry("putting but skipping the value → error txt", "put.my-key.k-v.io.", []string{"422: no value provided"}), + Entry("deleting a non-existent key → silently succeeds", "delete.non-existent.k-v.io.", []string{}), + Entry("using a garbage verb → error txt", "post.my-key.k-v.io.", []string{"422: valid verbs are get, put, delete"}), // others - Entry("putting a multi-label value", "put.96.0.4664.55.chrome-version.kv.sslip.io.", []string{"96.0.4664.55"}), + Entry("putting a multi-label value", "put.96.0.4664.55.chrome-version.k-v.io.", []string{"96.0.4664.55"}), Entry("putting a super-long multi-label value to use in a DNS amplification attack gets truncated to 63 characters", "put"+ ".IReturnedAndSawUnderTheSunThatTheRaceIsNotToTheSwiftNotThe"+ ".BattleToTheStrongNeitherYetBreadToTheWiseNorYetRichesToMenOf"+ - ".amplify.kv.sslip.io.", + ".amplify.k-v.io.", []string{"IReturnedAndSawUnderTheSunThatTheRaceIsNotToTheSwiftNotThe.Batt"}, ), ) diff --git a/k8s/document_root/index.html b/k8s/document_root/index.html index 588fd22..3be9336 100644 --- a/k8s/document_root/index.html +++ b/k8s/document_root/index.html @@ -227,45 +227,32 @@ dig @ns.sslip.io txt ip.sslip.io +short -6 # forces IPv6 lookup; sample reply "2 "https://icanhazip.com/">https://icanhazip.com/ requires 8692 bytes spread out over 34 packets—over 14 times as much! Admittedly bandwidth usage is a bigger concern for the one hosting the service than the one using the service.
-kv.sslip.io
: (key-value) read/write/delete TXTsWe enable special behavior under the kv.sslip.io
subdomain: it can be treated as a key-value
- store, the sub-subdomain being the key, and the TXT record being the value.
k-v.io
: (key-value) read/write/delete TXTsWe enable special behavior under the k-v.io
domain: it can be treated as a key-value store, the
+ subdomain being the key, and the TXT record being the value.
For example, to write ("put") the value "12.0.1" to the key "macos-version" on the
ns-gce.sslip.io.
nameserver, you'd use the following dig
command:
dig @ns-gce.sslip.io. txt put.12.0.1.macos-version.kv.sslip.io.
-
+ dig @ns-gce.sslip.io. txt put.12.0.1.macos-version.k-v.io
.
+
To read ("get") the value back, you'd write the following dig
command:
dig @ns-gce.sslip.io. txt get.macos-version.kv.sslip.io.
-
+ dig @ns-gce.sslip.io. txt get.macos-version.k-v.io.
+
Since "get" is the default behavior, you don't need to include it in the domain name:
-dig @ns-gce.sslip.io. txt macos-version.kv.sslip.io.
-
+ dig @ns-gce.sslip.io. txt macos-version.k-v.io.
+
Finally, when you're done with the key-value, you can "delete" it:
-dig @ns-gce.sslip.io. txt delete.macos-version.kv.sslip.io.
+ dig @ns-gce.sslip.io. txt delete.macos-version.k-v.io.
- Notes:
+ Notes:
- - Keys are case-insensitive (to accommodate DNS convention). In other words,
KEY.kv.sslip.io
and
- key.kv.sslip.io
return the same TXT record.
- - Values are case-sensitive.
put.CamelCase.style.kv.sslip.io
sets the TXT record to
- "CamelCase".
- put
requests will return the TXT record being put; i.e.
- put.hello.world.kv.sslip.io
returns one TXT record of one string, hello
.
+ - Keys are case-insensitive (to accommodate DNS convention). In other words,
+
KEY.k-v.io
and key.k-v.io
return the same TXT record.
+
put.CamelCase.style.k-v.io
sets the TXT record to "CamelCase".put
requests will return the TXT record being put; i.e. put.hello.world.k-v.io
+ returns one TXT record of one string, hello
.delete
requests will return the TXT record being deleted; i.e.
- delete.world.kv.sslip.io
returns one TXT record of one string, hello
. If the TXT
- record does not exist, no TXT records will be returned.delete.world.k-v.io
returns one TXT record of one string, hello
. If the TXT record
+ does not exist, no TXT records will be returned.