Skip to content

Instantly share code, notes, and snippets.

@armon
Created February 14, 2014 20:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save armon/9008541 to your computer and use it in GitHub Desktop.
Save armon/9008541 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"github.com/miekg/dns"
"net"
"time"
)
const domain = "consul."
const MAXREC = 3
func handleQuery(resp dns.ResponseWriter, req *dns.Msg) {
// Setup the message response
m := new(dns.Msg)
m.SetReply(req)
m.Authoritative = true
addSOA(domain, m)
for i := 0; i < MAXREC; i++ {
aRec := &dns.A{
Hdr: dns.RR_Header{
Name: req.Question[0].Name,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 0,
},
A: net.ParseIP(fmt.Sprintf("127.0.0.%d", i+1)),
}
m.Answer = append(m.Answer, aRec)
}
for i := 0; i < MAXREC; i++ {
srvRec := &dns.SRV{
Hdr: dns.RR_Header{
Name: req.Question[0].Name,
Rrtype: dns.TypeSRV,
Class: dns.ClassINET,
Ttl: 0,
},
Priority: 1,
Weight: 1,
Port: 12345,
Target: fmt.Sprintf("foobar%d.node.dc1.consul.", i),
}
m.Answer = append(m.Answer, srvRec)
aRec := &dns.A{
Hdr: dns.RR_Header{
Name: srvRec.Target,
Rrtype: dns.TypeA,
Class: dns.ClassINET,
Ttl: 0,
},
A: net.ParseIP(fmt.Sprintf("127.0.0.%d", i+1)),
}
m.Extra = append(m.Extra, aRec)
}
fmt.Printf("IN: %#v\n\n", m)
// Write out the complete response
if err := resp.WriteMsg(m); err != nil {
panic(err)
}
}
func addSOA(domain string, msg *dns.Msg) {
soa := &dns.SOA{
Hdr: dns.RR_Header{
Name: domain,
Rrtype: dns.TypeSOA,
Class: dns.ClassINET,
Ttl: 0,
},
Ns: "ns." + domain,
Mbox: "postmaster." + domain,
Serial: uint32(time.Now().Unix()),
Refresh: 3600,
Retry: 600,
Expire: 86400,
Minttl: 0,
}
msg.Ns = append(msg.Ns, soa)
}
func main() {
// Start DNS server
mux := dns.NewServeMux()
mux.HandleFunc(domain, handleQuery)
server := &dns.Server{
Addr: "127.0.0.1:10000",
Net: "udp",
Handler: mux,
UDPSize: 65535,
}
go func() {
err := server.ListenAndServe()
panic(err)
}()
time.Sleep(50 * time.Millisecond)
// Create request
m := new(dns.Msg)
m.SetQuestion("web.service.consul.", dns.TypeANY)
c := new(dns.Client)
out, _, err := c.Exchange(m, "127.0.0.1:10000")
if err != nil {
panic(err)
}
fmt.Printf("OUT: %#v\n\n", out)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment