-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathresolver.go
155 lines (126 loc) · 3 KB
/
resolver.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package spf
import (
"log"
"net"
"strings"
"time"
"github.com/miekg/dns"
)
// DNSServer global var to use for resolver in format <ip>:<port>
// By default it uses Google's 8.8.8.8:53
// Misconfigured DNSServer will cause SPF checks to return TEMPERROR.
var DNSServer = "8.8.8.8:53"
// LookupSPF returns spf txt record.
// if no records found or more than one record found, r value will be set accordingly to None or PermError.
// If dns lookup faild, r will be set to TempError.
func LookupSPF(domain string) (spf string, r Result) {
txts, err := lookupTXT(domain)
if err != nil {
return "", TempError
}
var spfs []string
for _, txt := range txts {
txt = strings.ToLower(txt)
if txt == "v=spf1" || strings.HasPrefix(txt, "v=spf1 ") {
spfs = append(spfs, txt)
}
}
switch len(spfs) {
case 0:
return "", None
case 1:
return spfs[0], Result("")
default:
return "", PermError
}
}
// lookupTXT using miekg DNS since net.LookupTXT returns error if no TXT records
// returns slice of TXT records and error
func lookupTXT(d string) ([]string, error) {
var txt []string
r, _, err := dnsQuest(d, dns.TypeTXT)
if err != nil {
return txt, err
}
for _, answ := range r.Answer {
if t, ok := answ.(*dns.TXT); ok {
txt = append(txt, strings.Join(t.Txt, ""))
}
}
return txt, nil
}
func lookupA(d string) ([]net.IP, error) {
var ips []net.IP
r, _, err := dnsQuest(d, dns.TypeA)
if err != nil {
return ips, err
}
for _, answ := range r.Answer {
switch answ := answ.(type) {
case *dns.A:
ips = append(ips, answ.A)
case *dns.CNAME:
cnameIP, err := lookupA(answ.Target)
log.Println("Warning: CNAMEs are not allowed in MX records, according to RFC974, RFC1034 3.6.2, RFC1912 2.4, and RFC2181 10.3.")
if err != nil {
return nil, err
}
ips = append(ips, cnameIP...)
}
}
return ips, nil
}
func lookupAAAA(d string) ([]net.IP, error) {
var ips []net.IP
r, _, err := dnsQuest(d, dns.TypeAAAA)
if err != nil {
return ips, err
}
for _, answ := range r.Answer {
a := answ.(*dns.AAAA)
ips = append(ips, a.AAAA)
}
return ips, nil
}
func lookupMX(d string) ([]string, error) {
var mxs []string
r, _, err := dnsQuest(d, dns.TypeMX)
if err != nil {
return mxs, err
}
for _, answ := range r.Answer {
mx := answ.(*dns.MX)
mxs = append(mxs, mx.Mx)
}
return mxs, nil
}
func lookupPTR(ip net.IP) ([]string, error) {
var hosts []string
ipstr := ip.String()
if ip.To4() != nil {
ipstr += ".in-addr.arpa."
} else {
ipstr += "ip6.arpa."
}
r, _, err := dnsQuest(ipstr, dns.TypePTR)
if err != nil {
return hosts, err
}
for _, answ := range r.Answer {
p := answ.(*dns.PTR)
hosts = append(hosts, p.Ptr)
}
return hosts, nil
}
func dnsQuest(d string, t uint16) (r *dns.Msg, rtt time.Duration, err error) {
m := new(dns.Msg)
m.Id = dns.Id()
m.SetQuestion(dns.Fqdn(d), t)
m.RecursionDesired = true
m.SetEdns0(4096, false)
c := new(dns.Client)
return c.Exchange(m, DNSServer)
}
func init() {
//config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
}