-
Notifications
You must be signed in to change notification settings - Fork 0
/
runner.go
73 lines (63 loc) · 1.49 KB
/
runner.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
package main
import (
"errors"
"fmt"
"net"
"os"
"strconv"
"strings"
"time"
"github.com/miekg/dns"
)
type DNSRunner struct {
NameServer string
client *dns.Client
}
func NewDNSRunner(server string, port int, timeout time.Duration, protocol string) (r *DNSRunner) {
r = &DNSRunner{
NameServer: server + ":" + strconv.Itoa(port),
client: &dns.Client{
Timeout: timeout,
Net: protocol,
}}
return
}
func (r *DNSRunner) Query(domain, queryType, subnet string) (resp *dns.Msg, rtt time.Duration, reqSize int, err error) {
// set option
o := new(dns.OPT)
o.Hdr.Name = "."
o.Hdr.Rrtype = dns.TypeOPT
// set client subnet
if len(subnet) != 0 {
err := setSubnet(o, subnet)
if err != nil {
return nil, 0, 0, err
}
}
// set message content
m := new(dns.Msg)
canonicalDomain := dns.Fqdn(domain)
m.SetQuestion(canonicalDomain, dns.StringToType[strings.ToUpper(queryType)])
m.Extra = append(m.Extra, o)
reqSize = m.Len()
resp, rtt, err = r.client.Exchange(m, r.NameServer)
return
}
func setSubnet(o *dns.OPT, subnet string) error {
ext := &dns.EDNS0_SUBNET{
Code: dns.EDNS0SUBNET,
Address: net.ParseIP(subnet),
Family: 1, // IPv4
SourceNetmask: net.IPv4len * 8,
}
if ext.Address == nil {
fmt.Fprintf(os.Stderr, "fail to parse IP address: %s\n", subnet)
return errors.New("invalid subnet address")
}
if ext.Address.To4() == nil {
ext.Family = 2 // IPv6
ext.SourceNetmask = net.IPv6len * 8
}
o.Option = append(o.Option, ext)
return nil
}