The Golang DNS server is no longer experimental; the sslip.io
nameservers run the Golang DNS server.
- Include a placeholder for the `ginkgo` tests to run in CI.
- Include `src/` and `bosh-release/` in the list of directories.
- Mark the PowerDNS-related assets as deprecated; we no longer use
PowerDNS.
Previously I had nested `if` statements to test if a key existed and if
there were any records under that key. I squashed it so that it was no
longer nested.
Some may complain it's now harder to read, but for me it's easier to
read, and more logical, too, for the `if` statement says, "if there's an
override, then return the override."
...and everyone else's are themselves, e.g. `127.0.0.1.sslip.io`'s MX
record is `127.0.0.1.sslip.io` with a preference of 0. This allows me to
get email for sslip.io without worrying about email for every sslip.io
subdomain.
- Refactor: the global variable `NameServers` no longer holds the IP
addresses of the nameservers, merely their names. The addresses are now
held in the `Customizations` variable, the more appropriate place. We
only want one source of truth wherever possible.
- 🐞 The original Go Playground for creating `dnsmessage.Name`s was
wrong: it said to NOT put a dot at the end. You need the dot at the end.
The MX records for `sslip.io` now have dots at the end.
- The above bug caused `processQuestion()` to return an unexpected
error, but without the underlying error message. Now, when
`processQuestion()` errors in an unexpected manner, it logs the
underlying error message, which makes debugging much easier.
- Richer logging for MX queries: we now return the servers and
preferences rather than the terse `MX`.
- We use specific `fqdnString` rather than the generic `domain`
as a variable for consistency, which is the hobgoblin of small minds.
I wanted to add SPF and DKIM records (TXT records) to sslip.io, but I
couldn't because I'd have to add those records to _every_ query, and I
didn't want that.
This refactor now allows overrides for specific records for specific
domains. It's a more elegant solution.
sslip.io has the following custom records:
- A (which points to the Hetzner server)
- AAAA (same Hetzner server, but via IPv6)
- MX records (protonmail)
We describe how to run our pre-built executable within a docker
container. They can figure out the rest from there.
If they don't understand those instructions, they shouldn't be running
their own DNS server.
Now that I've worked on the other side of LGPL licensing, and the pain
of providing build instructions for a binary we download from Maven, I'm
a big fan of Apache 2.0 licensing.
The new webserver didn't have A and AAAA records for `sslip.io`, which
meant there was no website. We need a website. This commit fixes that.
The code is somewhat inflexible in that it assumes that there's exactly
oneA record and exactly one AAAA record.
I took the opportunity to bump SOA's serial and set the Hostmaster email
address to my primary email (brian.cunnie@gmail.com).
fixes:
```
curl: (6) Could not resolve host: sslip.io
```
- The impetus? I deployed a custom webserver but forgot to add the
A & AAAA records for sslip.io, so the website disappeared.
- I now check for the A & AAAA records (to be present, but not of any
particular value because that gives me the latitude to migrate to
other machines).
- I also check that the website is responsive.
- drive by: removed hard-coding of `sslip.io` in many tests; instead we
now query the domain that the env var `DOMAIN` is set to.
On macOS, `whois` returns _two_ results for the domain `sslip.io` from
two different whois servers:
- whois.nic.io
- whois.namecheap.com
This means that every nameservers is double-counted. To fix, we remove
the duplicates.
fixes:
```
Failure/Error: expect(dig_nameservers.sort).to eq(whois_nameservers.sort)
expected: ["ns-aws.nono.io.", "ns-aws.nono.io.", "ns-azure.nono.io.", "ns-azure.nono.io.", "ns-gce.nono.io.", "ns-gce.nono.io."]
got: ["ns-aws.nono.io.", "ns-azure.nono.io.", "ns-gce.nono.io."]
(compared using ==)
# ./spec/check-dns_spec.rb:44:in `block (3 levels) in <top (required)>'
```
DiG 9.10.6 no longer has the `+noidn` option, and `dig` will error if we
try to use it.
fixes:
```
dig +short +noidnin ns sslip.io @ns-azure.nono.io.
Invalid option: +noidnin
```
And this previously-invalid dig query now works, so we don't need the
option anyway:
```
dig +short AAAA api.--.sslip.io
::
```
This reverts commit a2564c12d3.
- Modified SOA:
- We're setting the SOA serial _backwards_; yes, even though there's no
impact, it feels gross. But the alternative, modifying the Golang code
and re-releasing, was too much work.
- I changed the SOA's refresh/retry/expire to match google.com's.
- I changed the mname (primary master) from `ns-he.nono.io` to
`sslip.io`. The change is cosmetic; those are the same machine.
- We emptied out the `pdns_named_conf`; we're not using the bind backend
anymore, so the bind configuration can be empty.
fixes <https://ci.nono.io/teams/main/pipelines/sslip.io/jobs/check-dns/builds/3813>:
```
expected: "ns-he.nono.io. briancunnie.gmail.com. 2020112800 300 300 300 300\n"
got: "sslip.io. yoyo.nono.io. 2020090400 900 900 1800 300\n"
```
fixes:
```
+ go build -o /var/vcap/packages/sslip.io-dns-server/bin/sslip.io-dns-server
main.go:7:2: package xip/xip is not in GOROOT (/var/vcap/data/packages/golang-1-linux/da1e0a99a1246edab92d9ffd0c4a2e7c3d5df83a/src/xip/xip)
```
Some clients query us for the A records of our nameservers even though
our nameservers aren't in our domain; the nameservers are in the
`nono.io` domain, not in the `sslip.io` domain.
Our new code returns the A records of our nameservers:
previously:
```
2020/11/28 21:57:38 190.113.222.130.55236 TypeA ns-aws.nono.io. ? nil, SOA
2020/11/28 21:57:38 190.113.222.130.49919 TypeA ns-azure.nono.io. ? nil, SOA
2020/11/28 21:57:38 190.113.222.130.8090 TypeA ns-gce.nono.io. ? nil, SOA
```
now:
```
2020/11/30 13:20:10 127.0.0.1.58410 TypeA ns-aws.nono.io. ? 52.0.56.137
2020/11/30 13:20:20 127.0.0.1.54717 TypeA ns-azure.nono.io. ? 52.187.42.158
2020/11/30 13:20:28 127.0.0.1.62487 TypeA ns-gce.nono.io. ? 104.155.144.4
```
I learned about Golang maps while implementing this feature.
The nameservers only use the pipe backend because they are no longer
acting as secondaries for the "regular" domains.
They are now exclusively serving sslip.io domain (and whitelabels).
I had accidentally swapped the SOA & hostmaster. This didn't break
anything, but it's very embarrassing.
fixes <http://www.webdnstools.com/dnstools/domain_check>:
> Checking DNS contact email address is valid. ns-he@nono.io is not valid. Mail server returned 'no such user'.
> Your SOA record lists briancunnie.gmail.com as the Primary nameserver. This server is not listed as a valid nameserver at the parent servers.
The packaging script is a bit of a hack: we create the `src/` directory
and move our source into it. 🤮
The source should have been in the proper directory to begin with, but
I'm too tired to fight with directory structures right now.
fixes:
```
main.go:7:2: module github.com/cunnie/sslip.io@latest found (v0.0.0-20201126193932-8400f99e37d2), but does not contain package github.com/cunnie/sslip.io/src/xip
```
This is a bittersweet moment—it's likely the last BOSH release I'll ever
write, and in some ways is closing a chapter of my life that I found
incredibly fun, exciting, and educational.
Why write a BOSH Release? Because the sslip.io infrastructure, or at
least three of the four nameservers, are BOSH-deployed.
Why write a DNS server? Why not continue with the existing PowerDNS
server + BASH backend? Because I'm stuck at the 4.2.2 PowerDNS release,
and I was unable to get 4.3+ to compile in the BOSH way. Let's be
honest: converting an application to a BOSH package is like doing a
port, a difficult port, and it was easier to write my own DNS server
than port PowerDNS 4.3+ to BOSH.
There's only one job in this commit (`sslip.io-dns-server`), which is
clearly named to avoid confusing with the at least 3 other DNS servers
(BOSH's DNS, BIND, and PowerDNS) that have BOSH releases. The BOSH
package will be in an upcoming commit.
I used a shorthand logging which extracts the info I'm interested in:
- IP of the asker (e.g. 10.0.9.30)
- Port of the asker (e.g. 59036)
- Type of the question (e.g. TypeA)
- Name of the question (e.g. 127.0.0.1.nono.io)
- Question mark (a delimiter)
- one of the following
- answer (e.g. 127.0.0.1, MX, NS, SOA)
- or no answer, but an authority section (e.g. nil, SOA)
We want to log queries (mostly because I'd like some metric of how many
queries people are making, what those queries are, and what my answers
are).
I also put a guard against one of the error conditions (I had assumed
only one type of error would ever be returned; I believe that assumption
is naïve)
- Unlike MX and SOA records, NS records are an array.
- Moved the variables into a block `var ( ... )`, reads more easily.
- `processQuestion()` answers MX & SOA records (and of course NS
records)