Fast DNS implementation for Go

Overview

Fast DNS implementation for Go

godoc release goreport coverage

Features

  • 0 Dependency
  • Similar Interface with net/http
  • Fast DoH Server Co-create with fasthttp
  • Fast DNS Client with rich features
  • Compatible metrics with coredns
  • High Performance
    • 0-allocs dns request parser
    • 0-allocs dns records marshaller
    • worker pool + message pool
    • prefork + reuse_port + set_affinity

Getting Started

A fastdns server example

package main

import (
	"log"
	"net"
	"os"

	"github.com/phuslu/fastdns"
)

type DNSHandler struct {
	Debug bool
}

func (h *DNSHandler) ServeDNS(rw fastdns.ResponseWriter, req *fastdns.Message) {
	if h.Debug {
		log.Printf("%s: CLASS %s TYPE %s\n", req.Domain, req.Question.Class, req.Question.Type)
	}

	switch req.Question.Type {
	case fastdns.TypeA:
		fastdns.HOST(rw, req, 60, []net.IP{{8, 8, 8, 8}})
	case fastdns.TypeAAAA:
		fastdns.HOST(rw, req, 60, []net.IP{net.ParseIP("2001:4860:4860::8888")})
	case fastdns.TypeCNAME:
		fastdns.CNAME(rw, req, 60, []string{"dns.google"}, []net.IP{{8, 8, 8, 8}, {8, 8, 4, 4}})
	case fastdns.TypeSRV:
		fastdns.SRV(rw, req, 60, []net.SRV{{"www.google.com", 443, 1000, 1000}})
	case fastdns.TypeNS:
		fastdns.NS(rw, req, 60, []net.NS{{"ns1.google.com"}, {"ns2.google.com"}})
	case fastdns.TypeMX:
		fastdns.MX(rw, req, 60, []net.MX{{"mail.gmail.com", 10}, {"smtp.gmail.com", 10}})
	case fastdns.TypeSOA:
		fastdns.SOA(rw, req, 60, net.NS{"ns1.google"}, net.NS{"ns2.google"}, 60, 90, 90, 180, 60)
	case fastdns.TypePTR:
		fastdns.PTR(rw, req, 0, "ptr.google.com")
	case fastdns.TypeTXT:
		fastdns.TXT(rw, req, 60, "greetingfromgoogle")
	default:
		fastdns.Error(rw, req, fastdns.RcodeNXDomain)
	}
}

func main() {
	addr := ":53"

	server := &fastdns.ForkServer{
		Handler: &DNSHandler{
			Debug: os.Getenv("DEBUG") != "",
		},
		Stats: &fastdns.CoreStats{
			Prefix: "coredns_",
			Family: "1",
			Proto:  "udp",
			Server: "dns://" + addr,
			Zone:   ".",
		},
		ErrorLog: log.Default(),
	}

	err := server.ListenAndServe(addr)
	if err != nil {
		log.Fatalf("dnsserver error: %+v", err)
	}
}

DoH Server

see https://github.com/phuslu/fastdns/tree/master/fastdoh

DNS Client

$ go get github.com/phuslu/fastdns/cmd/fastdig
$ fastdig ip.phus.lu @8.8.8.8

; <<>> DiG 0.0.1-Fastdns <<>> ip.phus.lu
;; global options: +cmd +noedns
;; Got answer:
;; ->>HEADER<<- opcode: Query, status: Success, id: 2775
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;ip.phus.lu.            IN      A

;; ANSWER SECTION:
ip.phus.lu.     299     IN      CNAME   phus.lu.
phus.lu.        299     IN      A       101.32.116.118

;; Query time: 15 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Mon Apr 12 22:07:16 +08 2021
;; MSG SIZE  rcvd: 58

High Performance

A Performance result as below, for daily benchmark results see github actions

# go test -v -cpu=1 -run=none -benchmem -bench=.
goos: linux
goarch: amd64
pkg: github.com/phuslu/fastdns
cpu: Intel(R) Xeon(R) Silver 4216 CPU @ 2.10GHz

BenchmarkHOST              	39442191	        30.31 ns/op	       0 B/op	       0 allocs/op
BenchmarkCNAME             	22563691	        53.23 ns/op	       0 B/op	       0 allocs/op
BenchmarkSRV               	20890515	        57.63 ns/op	       0 B/op	       0 allocs/op
BenchmarkNS                	16634973	        71.98 ns/op	       0 B/op	       0 allocs/op
BenchmarkSOA               	14635425	        82.16 ns/op	       0 B/op	       0 allocs/op
BenchmarkPTR               	27980914	        42.96 ns/op	       0 B/op	       0 allocs/op
BenchmarkMX                	24721230	        48.75 ns/op	       0 B/op	       0 allocs/op
BenchmarkTXT               	39824239	        30.14 ns/op	       0 B/op	       0 allocs/op
BenchmarkParseMessage      	50639167	        23.86 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetRequestQustion	26985039	        46.08 ns/op	       0 B/op	       0 allocs/op
BenchmarkSetResponseHeader 	175744434	         6.833 ns/op	       0 B/op	       0 allocs/op
BenchmarkDecodeName        	33319760	        36.07 ns/op	       0 B/op	       0 allocs/op
BenchmarkAppendHOSTRecord  	55649703	        21.56 ns/op	       0 B/op	       0 allocs/op
BenchmarkAppendCNAMERecord 	29943513	        40.04 ns/op	       0 B/op	       0 allocs/op
BenchmarkAppendSRVRecord   	26827544	        45.00 ns/op	       0 B/op	       0 allocs/op
BenchmarkAppendNSRecord    	20113075	        59.70 ns/op	       0 B/op	       0 allocs/op
BenchmarkAppendSOARecord   	17054136	        69.81 ns/op	       0 B/op	       0 allocs/op
BenchmarkAppendPTRRecord   	36748305	        32.60 ns/op	       0 B/op	       0 allocs/op
BenchmarkAppendMXRecord    	34203414	        35.04 ns/op	       0 B/op	       0 allocs/op
BenchmarkAppendTXTRecord   	65836453	        18.22 ns/op	       0 B/op	       0 allocs/op
BenchmarkUpdateStats       	14161730	        84.78 ns/op	       0 B/op	       0 allocs/op
BenchmarkEncodeDomain      	63253357	        19.27 ns/op	       0 B/op	       0 allocs/op

PASS
ok  	github.com/phuslu/fastdns	19.026s

Here is the real-world flamegraph flamegraph when fastdns reaches 1.4M QPS on a single machine with Xeon 4216 and Intel X710.

Acknowledgment

This dns server is inspired by fasthttp, rawdns and miekg/dns.

You might also like...
Resolver (DNS) cache daemon.
Resolver (DNS) cache daemon.

RESCACHED(1) Manual Page NAME rescached - DNS resolver cache daemon. Table of Contents SYNOPSIS OPTIONS DESCRIPTION FEATURES BEHIND THE DNS HOW CACHE

CUP - Cloudflare (DNS) Updater Program

CUP The Cloudflare (DNS) Updater CUP is a tool to turn CloudFlare DNS into a Dynamic DNS service. Documentation Documentation can be found in the docs

🐶 Command-line DNS Client for Humans. Written in Golang
🐶 Command-line DNS Client for Humans. Written in Golang

doggo 🐶 Command-line DNS client for humans doggo is a modern command-line DNS client (like dig) written in Golang. It outputs information in a neat c

CoreDNS is a DNS server that chains plugins
CoreDNS is a DNS server that chains plugins

CoreDNS is a DNS server/forwarder, written in Go, that chains plugins. Each plugin performs a (DNS) function. CoreDNS is a Cloud Native Computing Foun

Are you forwarding DNS traffic to another server for some reason, but want to make sure only queries for certain names are passed? Say no more.

DNSFWD Redirect DNS traffic to an upstream. Get Latest: wget https://github.com/C-Sto/dnsfwd/releases/latest/download/dnsfwd_linux (replace linux with

Gotator is a tool to generate DNS wordlists through permutations.
Gotator is a tool to generate DNS wordlists through permutations.

Gotator is a tool to generate DNS wordlists through permutations.

DNS lookup using Go
DNS lookup using Go

DNS lookup using Go

A tool to solve DNS pollution of GitHub website. Query the real IP address of domain names such as github.com, and refresh the domain name setting of the system hosts file.

githubDNS Target A tool to solve DNS pollution of GitHub website. Query the real IP address of domain names such as github.com, and refresh the domain

forward - facilitates proxying DNS messages to upstream resolvers.

forward Name forward - facilitates proxying DNS messages to upstream resolvers. Description The forward plugin re-uses already opened sockets to the u

Comments
  • Bump github.com/valyala/fasthttp from 1.23.0 to 1.34.0 in /fastdoh

    Bump github.com/valyala/fasthttp from 1.23.0 to 1.34.0 in /fastdoh

    Bumps github.com/valyala/fasthttp from 1.23.0 to 1.34.0.

    Release notes

    Sourced from github.com/valyala/fasthttp's releases.

    v1.34.0

    • 59f94a3 Update github.com/klauspost/compress (#1237) (Mikhail Faraponov)
    • 62c15a5 Don't reset RequestCtx.s (#1234) (Erik Dubbelboer)
    • 7670c6e Fix windows tests (#1235) (Erik Dubbelboer)
    • f54ffa1 feature: Keep the memory usage of the service at a stable level (#1216) (Rennbon)
    • 15262ec Warn about unsafe ServeFile usage (#1228) (Erik Dubbelboer)
    • 1116d03 Fix panic while reading invalid trailers (Erik Dubbelboer)
    • 856ca8e Update dependencies (#1230) (Mikhail Faraponov)
    • 6b5bc7b Add windows support to normalizePath (Erik Dubbelboer)
    • f0b0cfe Don't log ErrBadTrailer by default (Erik Dubbelboer)
    • 6937fee fix: (useless check), skip Response body if http method HEAD (#1224) (Pavel Burak)
    • b85d2a2 Fix http proxy behavior (#1221) (Aoang)
    • ad8a07a RequestHeader support set no default ContentType (#1218) (Jack.Ju)
    • c94581c support configure HostClient (#1214) (lin longhjui)
    • 632e222 Client examples (#1208) (Sergey Ponomarev)
    • 6a3cc23 uri_test.go use example.com for clearness (#1212) (Sergey Ponomarev)
    • 9d665e0 Update dependencies (#1204) (Mikhail Faraponov)
    • 8d7953e Fix scheme check for not yet parsed requests (#1203) (ArminBTVS)

    v1.33.0

    • 61aa8b1 remove redundant code (#1202) (tyltr)
    • 4369776 fix(hijack): reuse RequestCtx (#1201) (Sergio VS)
    • 2aca3e8 fix(hijack): reset userValues after hijack handler execution (#1199) (Sergio VS)
    • 9123060 Updated dependencies (#1194) (Mikhail Faraponov)

    v1.32.0

    • 7eeb00e Make tests less flaky (#1189) (Erik Dubbelboer)
    • d19b872 Update tcpdialer.go (#1188) (Mikhail Faraponov)
    • c727b99 Release UseHostHeader in ReleaseRequest() (#1185) (Tolyar)
    • 6c0518b Fix UseHostHeader for DoTimeout + tests (#1184) (Tolyar)
    • 6b55811 Add MaxIdleWorkerDuration to Server. (#1183) (Kilos Liu)
    • 4517204 Allow to set Host header for Client (#1169) (Tolyar)
    • 258a4c1 fix: reset response after reset user values on keep-alive connections (#1176) (Sergio VS)
    • e9db537 Use %w to wrap errors (#1175) (Erik Dubbelboer)
    • 7db0597 Fix bad request trailer panic (Erik Dubbelboer)
    • 4aadf9a Fix parseTrailer panic (Erik Dubbelboer)
    • da7ff7a Add trailer support (#1165) (ichx)
    • 017f0aa fix: reset request after reset user values on keep-alive connections (#1162) (Sergio VS)
    • 3b117f8 feat: close idle connections when server shutdown (#1155) (ichx)
    • a94a2c3 Remove redundant code (#1154) (ichx)
    • f7c354c Fix race condition in Client.mCleaner (Erik Dubbelboer)
    • c078a9d Add string and bytes buffer convert trick in README (#1151) (ichx)
    • 3ff6aaa uri: isHttps() and isHttp() (#1150) (Sergey Ponomarev)
    • 8febad0 http.go: Request.SetURI() (Fix #1141) (#1148) (Sergey Ponomarev)
    • 2ca01c7 fix: Status Line parsing and writing (#1135) (Shivansh Vij)
    • 931d0a4 Fix lint (Erik Dubbelboer)
    • d613502 use sync.map is better (#1145) (halst)
    • c15e642 Don't run all race tests on windows (#1143) (Erik Dubbelboer)
    • 6006c87 chore (#1137) (tyltr)
    • 6d4db9b Fix race condition in getTCPAddrs (Erik Dubbelboer)

    ... (truncated)

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
Owner
phuslu
Geek
phuslu
dnscrypt-proxy 2 - A flexible DNS proxy, with support for encrypted DNS protocols.

Overview A flexible DNS proxy, with support for modern encrypted DNS protocols such as DNSCrypt v2, DNS-over-HTTPS and Anonymized DNSCrypt. dnscrypt-p

DNSCrypt 9.5k Dec 2, 2022
A smol DNS server (<100 loc) that's configured with a static JSON file. Useful for split-dns.

A smol DNS server (<100 loc) that's configured with a static JSON file. Useful for split-dns.

Arne Bahlo 79 Jul 27, 2022
Fast DNS implementation for Go

Fast DNS implementation for Go Features 0 Dependency Similar Interface with net/http Fast DoH Server Co-create with fasthttp Fast DNS Client with rich

phuslu 104 Nov 23, 2022
Fast and lightweight DNS proxy as ad-blocker for local network with many features

Blocky Blocky is a DNS proxy and ad-blocker for the local network written in Go with following features: Features Blocking - Blocking of DNS queries w

Dimitri Herzog 2.1k Dec 1, 2022
DNSTake — A fast tool to check missing hosted DNS zones that can lead to subdomain takeover

DNSTake — A fast tool to check missing hosted DNS zones that can lead to subdomain takeover

Pwnesia 694 Dec 7, 2022
DNS library in Go

Alternative (more granular) approach to a DNS library Less is more. Complete and usable DNS library. All Resource Records are supported, including the

Miek Gieben 6.6k Dec 4, 2022
DNS over HTTPS [mirror]

dnss dnss is a daemon for using DNS over HTTPS. It can act as a proxy, receiving DNS requests and resolving them using DNS-over-HTTPs (DoH). This can

Alberto Bertogli 100 Nov 30, 2022
DNS server with per-client targeted responses

GeoDNS servers This is the DNS server powering the NTP Pool system and other similar services. Questions or suggestions? For bug reports or feature re

Ask Bjørn Hansen 1.3k Nov 29, 2022
GRONG is a DNS (Domain Name System) authoritative name server.It is more a research project than a production-ready program.

GRONG (Gross and ROugh Nameserver written in Go) is a DNS (Domain Name System) authoritative name server. It is intended as a research project and is

Stéphane Bortzmeyer 57 Oct 17, 2020
Multicast DNS library for Go

Introduction This package allows Go processes to publish multicast DNS style records onto their local network segment. For more information about mDNS

Dave Cheney 192 Oct 23, 2022