Skip to content

Instantly share code, notes, and snippets.

@walm
Last active May 3, 2024 02:18
Show Gist options
  • Save walm/0d67b4fb2d5daf3edd4fad3e13b162cb to your computer and use it in GitHub Desktop.
Save walm/0d67b4fb2d5daf3edd4fad3e13b162cb to your computer and use it in GitHub Desktop.
Simple Golang DNS Server
package main
import (
"fmt"
"log"
"strconv"
"github.com/miekg/dns"
)
var records = map[string]string{
"test.service.": "192.168.0.2",
}
func parseQuery(m *dns.Msg) {
for _, q := range m.Question {
switch q.Qtype {
case dns.TypeA:
log.Printf("Query for %s\n", q.Name)
ip := records[q.Name]
if ip != "" {
rr, err := dns.NewRR(fmt.Sprintf("%s A %s", q.Name, ip))
if err == nil {
m.Answer = append(m.Answer, rr)
}
}
}
}
}
func handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
m.Compress = false
switch r.Opcode {
case dns.OpcodeQuery:
parseQuery(m)
}
w.WriteMsg(m)
}
func main() {
// attach request handler func
dns.HandleFunc("service.", handleDnsRequest)
// start server
port := 5353
server := &dns.Server{Addr: ":" + strconv.Itoa(port), Net: "udp"}
log.Printf("Starting at %d\n", port)
err := server.ListenAndServe()
defer server.Shutdown()
if err != nil {
log.Fatalf("Failed to start server: %s\n ", err.Error())
}
}
dig @localhost -p 5353 test.service
@vela-security
Copy link

How do I get the client IP address?

@kprc
Copy link

kprc commented Nov 10, 2019

@ MrNsfocus read https://github.com/miekg/dns code, you can extend the MSG type.

@eacp
Copy link

eacp commented Mar 3, 2020

Do you mind if I use this and expand it to use DoT?

I'll give you credit

@walm
Copy link
Author

walm commented Mar 4, 2020

@eacp feel free no need to credit

@ytsarev
Copy link

ytsarev commented Mar 4, 2020

@walm jfyi, reused your code for testing of global load balancing project , see https://github.com/AbsaOSS/ohmyglb/blob/master/pkg/controller/gslb/fakedns.go . Thanks a lot man.

@maxmcd
Copy link

maxmcd commented Apr 11, 2020

@MrNsfocus

func handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) {
	addressOfRequester := w.RemoteAddr()
	...
	w.WriteMsg(m)
}

@briceburg
Copy link

muchos gracias!

@titpetric
Copy link

To respond with NXDOMAIN (non-existant domain), the following should be called:

m.SetRcode(r, dns.RcodeNameError)

@stipx
Copy link

stipx commented Oct 20, 2021

How do I get the client IP address?

It seems you can get it via
dns.Responsewriter.RemoteAddr()

@titpetric
Copy link

titpetric commented Mar 29, 2022 via email

@Ran-Xing
Copy link

Ran-Xing commented Oct 26, 2022

nslookup test.service
;; Got recursion not available from 127.0.0.1, trying next server
Server:		8.8.8.8
Address:	8.8.8.8#53

** server can't find test.service: NXDOMAIN

@NinoM4ster
Copy link

I made a version that supports multiple A records (and also multiple SRV records): https://gist.github.com/NinoM4ster/edaac29339371c6dde7cdb48776d2854

@Ran-Xing
Copy link

@NinoM4ster Are you interested in communicating with dns servers?

@NinoM4ster
Copy link

@NinoM4ster Are you interested in communicating with dns servers?

I'm not sure what you mean.

@Ran-Xing
Copy link

127.0.0.1:53
curl nslookup

@NinoM4ster
Copy link

@Ran-Xing I used the dig command.

@Ran-Xing
Copy link

Ran-Xing commented Nov 13, 2022

oh,no,dig work, but system not work,you can try set 127.0.0.1 on system, then run

get ipaddress

docker run -itd --name nginx --rm nginx
docker run -itd --name ubuntu --rm ubuntu bash
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' nginx
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' ubuntu

records add

	"nginx.service.": {"192.168.0.2"},
	"ubuntu.service.": {"192.168.0.2"},

at last

set word_system dns

127.0.0.1

nslookup nginx.service
curl nginx.service -v

@Ran-Xing
Copy link

Ran-Xing commented Nov 13, 2022

@NinoM4ster I also wrote a dns server according to this writing method, which supports A records, but it does not work on macOS and Linux

dig works fine

@NinoM4ster
Copy link

oh, in my case I'm not using this as a system-wide DNS server, but using a service to query it directly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment