summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2022-04-12 01:31:37 +0700
committerShulhan <ms@kilabit.info>2022-04-12 01:31:37 +0700
commit8422dd7cdee8fbe31ef8b31e8e54c03ba330fadb (patch)
treea47c0eeeb6c13e3b46bd24a99c92a7602063fec9
parent429a9d9205bad2be34cdfe7fb5b1a9a6f127f541 (diff)
downloadpakakeh.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.go70
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
+}