Home

Awesome

<p align="center"> <img src="https://github.com/semihalev/sdns/blob/master/logo.png?raw=true" width="200"> </p> <h1 align="center">SDNS :rocket:</h1> <p align="center"> A high-performance, recursive DNS resolver server with DNSSEC support, focused on preserving privacy. </p> <p align="center"> <a href="https://github.com/semihalev/sdns/actions"><img src="https://img.shields.io/github/actions/workflow/status/semihalev/sdns/go.yml?style=flat-square"></a> <a href="https://goreportcard.com/report/github.com/semihalev/sdns"><img src="https://goreportcard.com/badge/github.com/semihalev/sdns?style=flat-square"></a> <a href="http://godoc.org/github.com/semihalev/sdns"><img src="https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square"></a> <a href="https://codecov.io/gh/semihalev/sdns"><img src="https://img.shields.io/codecov/c/github/semihalev/sdns?style=flat-square"></a> <a href="https://github.com/semihalev/sdns/releases"><img src="https://img.shields.io/github/v/release/semihalev/sdns?style=flat-square"></a> <a href="https://github.com/semihalev/sdns/blob/master/LICENSE"><img src="https://img.shields.io/github/license/semihalev/sdns?style=flat-square"></a> </p>

Installation

Use the go get command to install sdns:

go get github.com/semihalev/sdns

Pre-build Binaries

You can download the latest release from the Github Repo.

Docker

$ docker run -d --name sdns -p 53:53 -p 53:53/udp sdns

Docker Compose

Install docker-compose and run from the root directory:

$ sudo apt install docker-compose
$ docker-compose up -d

Homebrew for macOS

Install and run as a service:

$ brew install sdns
$ brew install semihalev/tap/sdns (updated every release)
$ brew services start sdns

Snapcraft

$ snap install sdns

AUR for ArchLinux

$ yay -S sdns-git

Note: Pre-built binaries, Docker packages, brew taps, and snaps are automatically created by Github workflows.

Building from Source

$ go build

Testing

$ make test

Flags

FlagDesc
-c, --config PATHLocation of the config file. If it doesn't exist, a new one will be generated.
-v, --versionShow the version of the sdns.
-h, --helpShow this help and exit.

Debugging Environment

To debug your environment, execute the following command:

$ export SDNS_DEBUGNS=true && export SDNS_PPROF=true && ./sdns

The SDNS_DEBUGNS environment variable is beneficial for verifying the RTT (Round Trip Time) of authoritative servers. To use it, send an HINFO query for zones with chaos class.

Here's an example of the output you might receive:

$ dig chaos hinfo example.com

; <<>> DiG 9.17.1 <<>> chaos hinfo example.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 29636
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 4, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: f27dbb995df5ac79e4fa37c07d131b5bd03aa1c5f802047a7c02fb228a886cb281ecc319323dea81 (good)
;; QUESTION SECTION:
;example.com.			CH	HINFO

;; AUTHORITY SECTION:
example.com.		0	CH	HINFO	"Host" "IPv4:199.43.135.53:53 rtt:142ms health:[GOOD]"
example.com.		0	CH	HINFO	"Host" "IPv4:199.43.133.53:53 rtt:145ms health:[GOOD]"
example.com.		0	CH	HINFO	"Host" "IPv6:[2001:500:8f::53]:53 rtt:147ms health:[GOOD]"
example.com.		0	CH	HINFO	"Host" "IPv6:[2001:500:8d::53]:53 rtt:148ms health:[GOOD]"

Configuration (v1.3.7)

KeyDescription
versionConfiguration version
directorysdns working directory (must grant write access to sdns user)
bindDNS server binding address Default: :53
bindtlsDNS-over-TLS server binding address Default: :853
binddohDNS-over-HTTPS server binding address Default: :8053
binddoqDNS-over-QUIC server binding address Default: :853
tlscertificatePath to the TLS certificate file
tlsprivatekeyPath to the TLS private key file
outboundipsOutbound IPv4 addresses (randomly chosen if multiple entries provided)
outboundip6sOutbound IPv6 addresses (randomly chosen if multiple entries provided)
rootserversDNS Root IPv4 servers
root6serversDNS Root IPv6 servers
dnssecDNSSEC validation on signed zones, off for disabled.
rootkeysTrusted DNSSEC anchors
fallbackserversFailover resolver IPv4 or IPv6 addresses with port (leave blank to disable) Example: "8.8.8.8:53"
forwarderserversForwarder resolver IPv4 or IPv6 addresses with port (leave blank to disable) Example: "8.8.8.8:53"
apiHTTP API server binding address (leave blank to disable)
bearertokenAPI bearer token for authorization. If the token set, Authorization header should be send on API requests
blocklistsRemote blocklist address list (downloaded to the blocklist folder)
blocklistdir[DEPRECATED] Directory creation is automated in the working directory
loglevelLog verbosity level (crit, error, warn, info, debug)
accesslogLocation of the access log file (leave blank to disable) Default: Common Log Format
nullrouteIPv4 address for forwarding blocked queries
nullroutev6IPv6 address for forwarding blocked queries
accesslistClient whitelist for query permissions
querytimeoutMaximum wait duration for DNS query response Default: 10s
timeoutNetwork timeout duration for each DNS lookup Default: 2s
hostsfileEnable serving zone data from a hosts file (leave blank to disable)
expireDefault error cache TTL (in seconds) Default: 600
cachesizeCache size (total records in cache) Default: 256000
prefetchCache prefetch before expiry (threshold: 10%-90%, 0 to disable)
maxdepthMaximum iteration depth per query Default: 30
ratelimitQuery-based rate limit per second (0 to disable) Default: 0
clientratelimitClient IP address-based rate limit per minute (no limit if client supports EDNS cookie) Default: 0
blocklistManual blocklist entries
whitelistManual whitelist entries
cookiesecretDNS cookie secret (RFC 7873) - auto-generated if not set
nsidDNS server identifier (RFC 5001) - useful for operating multiple sdns instances (leave blank to disable)
chaosEnable responses to version.server, version.bind, hostname.bind and id.server chaos txt queries
qname_min_levelQname minimize level (0 to disable - higher values increase complexity and impact response performance)
emptyzonesEnable response to RFC 1918 zone queries. For details, see http://as112.net/

Plugin Configuration

In sdns, you have the ability to add custom plugins. The sequence of the plugins and the middlewares has a mutual impact on their execution. Config keys must be strings, and values can be of any type. Plugins are loaded before the cache middleware in the specified order.

The plugin interface is straightforward. For additional information, please refer to the example plugin.

Example Configuration

[plugins]
     [plugins.example]
     path = "/path/to/exampleplugin.so"
     config = {key_1 = "value_1", intkey = 2, boolkey = true, keyN = "nnn"}
     [plugins.another]
     path = "/path/to/anotherplugin.so"

Server Configuration Checklist

Features

TODO

Performance

Benchmark Environment

Benchmarking Tool

Benchmark Comparisons

Benchmarks were performed on the following DNS resolvers: sdns-1.3.3, pdns-recursor-4.8.4, bind-9.19.12, unbound-1.17.1.

Benchmark Results

ResolverRESPONSELOSTNOERRORSERVFAILNXDOMAINRun TimeQPS
SDNS100%135,16486613,96987s47ms571/s
PowerDNS99.99%635,14089313,96188s83ms563/s
Bind99.74%13235,02488513,959127s64ms390/s
Unbound99.49%25335,15262413,971174s64ms284/s

Contributing

We welcome pull requests. If you're considering significant changes, please start a discussion by opening an issue first.

Before submitting patches, please review our CONTRIBUTING guidelines.

:hearts: Made With

Inspired by

License

MIT