/
dns_handler.go
103 lines (90 loc) · 2.03 KB
/
dns_handler.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package main
import (
"fmt"
"log"
"strings"
"github.com/miekg/dns"
"golang.org/x/net/publicsuffix"
)
type DNSHandler struct {
ListenAddr string
db *Database
}
func (d *DNSHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
m := new(dns.Msg)
m.SetReply(r)
m.Compress = false
if r.Opcode != dns.OpcodeQuery {
log.Println("bad opcode: ", r)
w.WriteMsg(m)
return
}
if len(r.Question) == 0 {
// send null
log.Println("no questions: ", r)
w.WriteMsg(m)
return
}
q := r.Question[0]
query := q.Name
query = strings.TrimSuffix(query, ".")
fld, err := publicsuffix.EffectiveTLDPlusOne(query)
if err != nil {
log.Println("error: ", err)
w.WriteMsg(m)
return
}
zone := d.db.GetMemoryZone(fld)
if zone == nil {
log.Println("no zone found for: ", r)
w.WriteMsg(m)
return
}
ind := strings.LastIndex(query, fld)
var subdomain string
if ind > 0 {
subdomain = query[:ind-1]
} else {
subdomain = "@"
}
switch q.Qtype {
case dns.TypeSOA:
ns := d.db.FindMemoryRecord(zone, dns.TypeNS, "")
email := strings.Replace(strings.ToLower(zone.Owner), "@", ".", 1)
if len(ns) > 0 {
v := ns[0]
rr, err := dns.NewRR(fmt.Sprintf("%s 60 IN SOA %s %s 1 7200 3600 1209600 60", q.Name, v.Value, email))
if err == nil {
m.Answer = append(m.Answer, rr)
} else {
log.Println(err)
}
}
case dns.TypeA, dns.TypeAAAA, dns.TypeCNAME, dns.TypeNS, dns.TypeTXT:
// fmt.Println(zone, dnsType, subdomain)
reList := d.db.FindMemoryRecord(zone, q.Qtype, subdomain)
for _, v := range reList {
rr, err := dns.NewRR(fmt.Sprintf("%s %d IN %s %s", q.Name, v.TTL, GetDnsTypeString(q.Qtype), v.Value))
if err == nil {
m.Answer = append(m.Answer, rr)
}
}
}
w.WriteMsg(m)
}
func NewDNSHandler(addr string, db *Database) *DNSHandler {
return &DNSHandler{
ListenAddr: addr,
db: db,
}
}
func (d *DNSHandler) ListenAndServe() error {
server := &dns.Server{
Addr: d.ListenAddr,
Net: "udp",
Handler: d,
}
err := server.ListenAndServe()
defer server.Shutdown()
return err
}