-
-
Notifications
You must be signed in to change notification settings - Fork 7
/
dns_server.go
98 lines (80 loc) · 2.17 KB
/
dns_server.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
package main
import (
"fmt"
"github.com/miekg/dns"
"strings"
)
const DNSDefaultTTL = 1
type dnsRequestHandler struct{}
func newDNSReplyMsg() *dns.Msg {
msg := dns.Msg{}
msg.Compress = true
// this is an authoritative DNS server
msg.Authoritative = true
msg.RecursionAvailable = false
// DNSSEC disabled for now
// TODO: fix DNSSEC
msg.AuthenticatedData = false
msg.CheckingDisabled = true
return &msg
}
// send out the generated answer, and if the answer is not correct, send out a SERVFAIL
func finishAnswer(w *dns.ResponseWriter, r *dns.Msg) {
err := (*w).WriteMsg(r)
if err != nil {
softFailIf(err)
// if answer sanity check (miekg/dns automatically does this) fails, reply with SERVFAIL
msg := newDNSReplyMsg()
msg.SetReply(r)
msg.Rcode = dns.RcodeServerFailure
err = (*w).WriteMsg(msg)
softFailIf(err)
}
// access log to stdout
fmt.Printf("[DNS] C=%d Q=%d R=%d DOMAIN=%s %s => %s\n", r.Question[0].Qclass, r.Question[0].Qtype, r.Rcode, r.Question[0].Name, (*w).RemoteAddr(), (*w).LocalAddr())
}
// TODO: force TCP for 1) clients which requests too fast; 2) non-existent answers
// See: https://labs.apnic.net/?p=382
func (this *dnsRequestHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
msg := newDNSReplyMsg()
msg.SetReply(r)
// on function return, we send out the current answer
defer finishAnswer(&w, msg)
// sanity check
if len(r.Question) != 1 {
msg.Rcode = dns.RcodeRefused
return
}
switch r.Question[0].Qclass {
case dns.ClassINET:
switch r.Question[0].Qtype {
case dns.TypeA:
handleA(this, r, msg)
return
case dns.TypeAAAA:
handleAAAA(this, r, msg)
return
case dns.TypeSOA:
handleSOA(this, r, msg)
return
default:
handleDefault(this, r, msg)
return
}
case dns.ClassCHAOS:
switch r.Question[0].Qtype {
case dns.TypeTXT:
if strings.EqualFold(r.Question[0].Name, "version.bind.") {
// we need to reply our software version
// https://serverfault.com/questions/517087/dns-how-to-find-out-which-software-a-remote-dns-server-is-running
handleTXTVersionRequest(this, r, msg)
} else {
handleDefault(this, r, msg)
}
return
default:
handleDefault(this, r, msg)
return
}
}
}