/
dnsclient.go
85 lines (78 loc) · 2.07 KB
/
dnsclient.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
// Package dnsclient provides a minimal DNS client library. It provides native support for
// - Dns Over UDP
// - DNS Over TCP
// - DNS Over HTTPS (DoH)
// - DNS Over TLS (DoT)
// - DNS Over QUIC (DoQ)
package dnsclient
import (
"context"
"fmt"
"net"
"net/url"
"time"
"github.com/miekg/dns"
)
/*
Client Provides a unified interface for DNS queries
func main() {
msg := dns.Msg{}
msg.RecursionDesired = true
msg.Question = []dns.Question{{
Name: "example.com.",
Qtype: dns.StringToType["A"],
Qclass: dns.ClassINET,
}}
addr := &net.UDPAddr{
IP: net.IPv4(1, 1, 1, 1),
Port: 53,
}
c, _ := dnsclient.NewClassicDNS(addr, false, false, false)
response, ttr, err := c.Query(context.Background(), &msg)
fmt.Printf("Query: %v, Response: %v, Time to Respond: %s, Error: %v", msg, response, ttr, err)
}
*/
type Client interface {
Query(context.Context, *dns.Msg) ([]dns.RR, time.Duration, error)
Close() error
Reconnect() error
}
/*
New creates a DNS Client by parsing a URI and returning the appropriate client for it
URI string could look like below:
- udp://1.1.1.1:53
- udp6://[2606:4700:4700::1111]:53
- tcp://9.9.9.9:5353
- https://dns.adguard.com
- quic://dns.adguard.com:8853
- tls://dns.adguard.com:853
*/
func New(uri string, skipVerify bool, proxy string) (Client, error) {
parsedURL, err := url.Parse(uri)
if err != nil {
return nil, err
}
switch parsedURL.Scheme {
case "udp", "udp6":
addr, err := net.ResolveUDPAddr(parsedURL.Scheme, parsedURL.Host)
if err != nil {
return nil, err
}
return NewClassicDNS(addr, false, false, skipVerify, proxy)
case "tcp", "tcp6", "tls", "tls6":
useTLS := false
if parsedURL.Scheme == "tls" || parsedURL.Scheme == "tls6" {
useTLS = true
}
addr, err := net.ResolveTCPAddr("tcp", parsedURL.Host)
if err != nil {
return nil, err
}
return NewClassicDNS(addr, true, useTLS, skipVerify, proxy)
case "https":
return NewDoHClient(*parsedURL, skipVerify, proxy)
case "quic":
return NewDoQClient(parsedURL.Host, skipVerify)
}
return nil, fmt.Errorf("Can't understand the URL")
}