Skip to content

Golang-based DNS server which maps DNS records with embedded IP addresses to those addresses.

License

Notifications You must be signed in to change notification settings

cunnie/sslip.io

Folders and files

NameName
Last commit message
Last commit date
Jan 25, 2025
Jan 20, 2025
Jan 4, 2025
Jan 4, 2025
Mar 6, 2025
Jan 20, 2025
Aug 25, 2016
Jan 4, 2025
May 11, 2024
May 11, 2024
Jan 25, 2025
Dec 2, 2020
Aug 30, 2015
Jun 17, 2024
Dec 28, 2024
Dec 1, 2020
Jan 19, 2025
Jan 20, 2025
Jan 20, 2025
Nov 4, 2024
Dec 5, 2024
Jan 4, 2025
May 11, 2024
Jan 4, 2025
Jan 4, 2025
May 11, 2024

Repository files navigation

sslip.io

Production Nameservers CI Tests

sslip.io is a DNS server that maps specially-crafted DNS A records to IP addresses (e.g. "127-0-0-1.sslip.io" maps to 127.0.0.1). It is similar to, and inspired by, xip.io.

If you'd like to use sslip.io as a service, refer to the website (sslip.io) for more information. This README targets developers; the website targets users.

Quick Start

git clone https://github.com/cunnie/sslip.io.git
cd sslip.io
go mod tidy
sudo go run main.go
 # sudo is required on Linux, but not on macOS, to bind to privileged port 53

In another window:

dig @localhost 192.168.0.1.sslip.io +short
 # should return "192.168.0.1"

Quick Start Tests

go mod tidy
go generate
ginkgo -r -p .

Running Your Own Nameservers

We can customize our nameserver and address records (NS, A, and AAAA), which can be particularly useful in an internetless (air-gapped) environment. This can be done with a combination of the -nameservers flag and the -addresses flag.

For example, let's say we're the DNS admin for pivotal.io, and we'd like to have a subdomain, "xip.pivotal.io", that does sslip.io-style lookups (e.g. "127.0.0.1.xip.pivotal.io" would resolve to "127.0.0.1"). Let's say we have two servers that we've set aside for this purpose:

  • ns-sslip-0.pivotal.io, 10.8.8.8 (IPv4)
  • ns-sslip-1.pivotal.io, fc88:: (IPv6)

First, we delegate the subdomain "xip.pivotal.io" to our two nameservers, and then we run the following command run on each of the two servers:

# after we've cloned our repo & cd'ed into it
go run main.go \
  -nameservers=ns-sslip-0.pivotal.io,ns-sslip-1.pivotal.io \
  -addresses ns-sslip-0.pivotal.io=10.8.8.8,ns-sslip-1.pivotal.io=fc88::

Note: These nameservers are not general-purpose nameservers; for example, they won't look up google.com. They are not recursive. Don't ever configure a machine to point to these nameservers.

Running with Docker

Probably the easiest way to run the nameserver is with the official Docker image, cunnie/sslip.io-dns-server:

docker run \
  -it \
  --rm \
  -p 53:53/udp \
  cunnie/sslip.io-dns-server

If we see the error, "Error starting userland proxy: listen udp4 0.0.0.0:53: bind: address already in use.", we turn off the systemd resolver: sudo systemctl stop systemd-resolved

Let's try a more complicated setup: we're on our workstation, jammy.nono.io, whose IP addresses are 10.9.9.114 and 2601:646:0100:69f0:0:ff:fe00:72. We'd like our workstation to be the DNS server:

docker run \
  -it \
  --rm \
  -p 53:53/udp \
  cunnie/sslip.io-dns-server \
    -nameservers jammy.nono.io \
    -addresses jammy.nono.io=10.9.9.114,jammy.nono.io=2601:646:100:69f0:0:ff:fe00:72

From another machine, we look up the DNS NS record for "127.0.0.1.com", and we see the expected reply:

dig ns 127.0.0.1.com @jammy.nono.io +short
...
  ;; ANSWER SECTION:
  127.0.0.1.com.		604800	IN	NS	jammy.nono.io.

  ;; ADDITIONAL SECTION:
  jammy.nono.io.		604800	IN	A	10.9.9.114
  jammy.nono.io.		604800	IN	AAAA	2601:646:100:69f0:0:ff:fe00:72

The Docker image is multi-platform, supporting both x86_64 architecture as well as ARM64 (AWS Graviton, Apple M1/M2).

Command-line Flags

  • -port overrides the default port, 53, which the server binds to. This can be especially useful when running as a non-privileged user, unable to bind to privileged ports (<1024) ("listen udp :53: bind: permission denied"). For example, to run the server on port 9553: go run main.go -port 9553. To query, dig @localhost 127.0.0.1.sslip.io -p 9553
  • -nameservers overrides the default NS records ns-gce.sslip.io, ns-hetzner.sslip.io, and ns-ovh.sslip.io; flag, e.g. go run main.go -nameservers ns1.example.com,ns2.example.com). If you're running your own nameservers, you probably want to set this. Don't forget to set address records for the new name servers with the -addresses flag (see below). Exception: _acme-challenge records are handled differently to accommodate the procurement of Let's Encrypt wildcard certificates; you can read more about that procedure here
  • -addresses overrides the default A/AAAA (IPv4/IPv6) address records. For example, here's how we set the IPv4 record & IPv6 record for our nameserver (in the -nameservers example above), ns1.example.com: -addresses ns1.example.com=10.8.8.8,ns1.example.com=fc::8888. Note that you can set many addresses for a single host, e.g. ns1.example.com=1.1.1.1,ns1.example.com=8.8.8.8,ns1.example.com=9.9.9.9
  • -blocklistURL overrides the default block list, (https://raw.githubusercontent.com/cunnie/sslip.io/main/etc/blocklist.txt). It's not necessary to override this if you're in an internetless environment: if the DNS server can't download the blocklist, it prints out a message and continues to serve DNS queries

DNS Server Miscellany

  • it binds to both UDP and TCP.
  • The SOA record is hard-coded except the MNAME (primary master name server) record, which is set to the queried hostname (e.g. dig big.apple.com @ns-ovh.nono.io would return an SOA with an MNAME record of big.apple.com.
  • The MX records are hard-coded to the queried hostname with a preference of 0, except sslip.io itself, which has custom MX records to enable email delivery to ProtonMail
  • There are no SRV records

Directory Structure

  • ci/ contains the Concourse continuous integration (CI) pipeline and task
  • spec/ contains the tests for the production nameservers. To run the tests locally:
    DOMAIN=sslip.io rspec --format documentation --color spec/
  • k8s/document_root_sslip.io/ contains the HTML content of the sslip.io website. Please run tidy -im -w 120 k8s/document_root_sslip.io/index.html before submitting pull requests

Acknowledgements

  • Sam Stephenson (xip.io), Roopinder Singh (nip.io), and the other DNS developers out there
  • The contributors (@normanr, @jpambrun come to mind) who improved sslip.io
  • Jenessa Petersen of Let's Encrypt who bumped the rate limits
  • JetBrains who provided a free license for open source development

About

Golang-based DNS server which maps DNS records with embedded IP addresses to those addresses.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published