diff options
| author | Shulhan <ms@kilabit.info> | 2022-04-12 01:31:37 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2022-04-12 01:31:37 +0700 |
| commit | 8422dd7cdee8fbe31ef8b31e8e54c03ba330fadb (patch) | |
| tree | a47c0eeeb6c13e3b46bd24a99c92a7602063fec9 | |
| parent | 429a9d9205bad2be34cdfe7fb5b1a9a6f127f541 (diff) | |
| download | pakakeh.go-8422dd7cdee8fbe31ef8b31e8e54c03ba330fadb.tar.xz | |
lib/dns: add function to create new client using name server URL
The NewClient create new DNS client using the name server URL.
The name server URL is defined in the same format as ServerOptions's
NameServer.
The function also accept second parameter: isInsecure, which is only
usable for DNS over TLS and DNS over HTTPS.
| -rw-r--r-- | lib/dns/client.go | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/lib/dns/client.go b/lib/dns/client.go index 47fc0220..ee8dbbdb 100644 --- a/lib/dns/client.go +++ b/lib/dns/client.go @@ -5,6 +5,10 @@ package dns import ( + "fmt" + "net" + "net/url" + "strings" "time" ) @@ -19,3 +23,69 @@ type Client interface { SetRemoteAddr(addr string) error SetTimeout(t time.Duration) } + +// +// NewClient create new DNS client using the name server URL. +// The name server URL is defined in the same format as +// ServerOptions.NameServers. +// The isInsecure parameter only usable for DNS over TLS (DoT) and DNS over +// HTTPS (DoH). +// +// For example, +// +// - "udp://127.0.0.1:53" for UDP client. +// - "tcp://127.0.0.1:53" for TCP client. +// - "https://127.0.0.1:853" (HTTPS with IP address) for DoT. +// - "https://localhost/dns-query" (HTTPS with domain name) for DoH. +// +func NewClient(nsUrl string, isInsecure bool) (cl Client, err error) { + var ( + logp = "NewClient" + + urlNS *url.URL + ip net.IP + iphost string + port string + ipport []string + ) + + urlNS, err = url.Parse(nsUrl) + if err != nil { + return nil, fmt.Errorf("%s: invalid name server URL: %q", logp, nsUrl) + } + + ipport = strings.Split(urlNS.Host, ":") + switch len(ipport) { + case 1: + iphost = ipport[0] + case 2: + iphost = ipport[0] + port = ipport[1] + default: + return nil, fmt.Errorf("%s: invalid name server URL: %q", logp, nsUrl) + } + + switch urlNS.Scheme { + case "udp": + cl, err = NewUDPClient(urlNS.Host) + case "tcp": + cl, err = NewTCPClient(urlNS.Host) + case "https": + ip = net.ParseIP(iphost) + if ip == nil { + cl, err = NewDoHClient(nsUrl, isInsecure) + } else { + if len(port) == 0 { + port = "853" + } + cl, err = NewDoTClient(iphost+":"+port, isInsecure) + } + default: + return nil, fmt.Errorf("%s: unknown scheme %q", logp, urlNS.Scheme) + } + if err != nil { + return nil, fmt.Errorf("%s: %w", logp, err) + } + + return cl, nil +} |
