diff --git a/cmd/dig.go b/cmd/dig.go index 5a610c9..024d889 100644 --- a/cmd/dig.go +++ b/cmd/dig.go @@ -54,7 +54,7 @@ func ParseDig(arg string, opts *util.Options) error { opts.Display.ShowClass = isNo // EDNS queries - case "dnssec": + case "do", "dnssec": opts.EDNS.DNSSEC = isNo case "expire": opts.EDNS.Expire = isNo @@ -79,8 +79,6 @@ func ParseDig(arg string, opts *util.Options) error { opts.TLS = isNo case "dnscrypt": opts.DNSCrypt = isNo - case "https": - opts.HTTPS = isNo case "quic": opts.QUIC = isNo // End DNS-over-X @@ -206,6 +204,18 @@ func parseDigEq(startNo bool, arg string, opts *util.Options) error { opts.EDNS.Version = 0 } + case "https", "https-get", "https-post": + opts.HTTPS = startNo + if isSplit && val != "" { + opts.HTTPSOptions.Endpoint = val + } else { + opts.HTTPSOptions.Endpoint = "/dns-query" + } + + if strings.HasSuffix(arg, "get") { + opts.HTTPSOptions.Get = true + } + case "subnet": if isSplit && val != "" { err := util.ParseSubnet(val, opts) diff --git a/cmd/dig_test.go b/cmd/dig_test.go index 6ba9cf5..02ee7a0 100644 --- a/cmd/dig_test.go +++ b/cmd/dig_test.go @@ -25,7 +25,7 @@ func FuzzDig(f *testing.F) { "qr", "noqr", "ttlunits", "nottlunits", "ttlid", "nottlid", - "dnssec", "nodnssec", + "do", "dnssec", "nodo", "nodnssec", "edns", "edns=a", "edns=0", "noedns", "expire", "noexpire", "ednsflags", "ednsflags=\"", "ednsflags=1", "noednsflags", @@ -43,7 +43,7 @@ func FuzzDig(f *testing.F) { "badcookie", "nobadcookie", "tls", "notls", "dnscrypt", "nodnscrypt", - "https", "nohttps", + "https", "https=/dns", "https-get", "https-get=/", "nohttps", "quic", "noquic", "short", "noshort", "identify", "noidentify", diff --git a/completions/zsh.zsh b/completions/zsh.zsh index 346cbf9..269bd12 100644 --- a/completions/zsh.zsh +++ b/completions/zsh.zsh @@ -8,7 +8,7 @@ local -a alts args '*+'{no,}'ignore[ignore truncation in UDP responses]' '*+'{no,}'tls[use DNS-over-TLS for queries]' '*+'{no,}'dnscrypt[use DNSCrypt for queries]' - '*+'{no,}'https[use DNS-over-HTTPS for queries]' + '*+'{no,}'https=[use DNS-over-HTTPS for queries]:endpoint [/dns-query]' '*+'{no,}'quic[use DNS-over-QUIC for queries]' '*+'{no,}'aaonly[set aa flag in the query]' '*+'{no,}'additional[print additional section of a reply]' @@ -50,7 +50,7 @@ local -a alts args # '*+'{no,}'rrcomments[set display of per-record comments]' # '*+ndots=[specify number of dots to be considered absolute]:dots' '*+bufsize=[specify UDP buffer size]:size (bytes)' - '*+'{no,}'dnssec[enable DNSSEC]' + '*+'{no,}''{dnssec,do}'[enable DNSSEC]' '*+'{no,}'nsid[include EDNS name server ID request in query]' '*+'{no,}'class[display the class whening printing the answer]' '*+'{no,}'ttlid[display the TTL whening printing the record]' diff --git a/doc/awl.1.scd b/doc/awl.1.scd index de88719..e43d93d 100644 --- a/doc/awl.1.scd +++ b/doc/awl.1.scd @@ -25,13 +25,14 @@ some more recent RFCs and output options. When no arguments are given, *awl* will perform an _NS_ query on the root ('_._'). When a nameserver is not given, *awl* will query a random system nameserver. -If one cannot be found, *awl* will query localhost. +If one cannot be found, *awl* will query the localhost. # OPTIONS Anything in [brackets] is optional. +Many options are inherited from *dig*(1). -*-D*, *--dnssec*, *+dnssec* +*-D*, *--dnssec*, *+dnssec*, *+do* Enable DNSSEC. This needs to be manually enabled. *-v*[=_int_] @@ -83,13 +84,13 @@ Anything in [brackets] is optional. *--no-bad-cookie*, *+[no]badcookie* \[Do not\] ignore BADCOOKIE responses -*--tcp*, *+tcp*, *+vc* +*--tcp*, *+[no]tcp*, *+[no]vc* Use TCP for the query (see RFC 7766). -*--dnscrypt*, *+dnscrypt* +*--dnscrypt*, *+[no]dnscrypt* Use DNSCrypt. -*-T*, *--tls*, *+tls* +*-T*, *--tls*, *+[no]tls* Use DNS-over-TLS, implies *--tcp* (see RFC 7858) *--tls-host* _string_ @@ -99,10 +100,10 @@ Anything in [brackets] is optional. *--tls-no-verify* Ignore TLS validation when performing a DNS query. -*-H*. *--https*, *+https* +*-H*. *--https*, *+[no]https* Use DNS-over-HTTPS (see RFC 8484). -*-Q*. *--quic*, *+quic* +*-Q*. *--quic*, *+[no]quic* Use DNS-over-QUIC (see RFC 9250). *-x*, *--reverse* @@ -204,16 +205,16 @@ All of these options except disabling EDNS imply *+edns*. ## Output Formats -*-j*, *--json*, *+json* +*-j*, *--json*, *+[no]json* Print the query results as JSON. -*-X*, *--xml*, *+xml* +*-X*, *--xml*, *+[no]xml* Print the query results as XML. -*-y*, *--yaml*, *+yaml* +*-y*, *--yaml*, *+[no]yaml* Print the query results as YAML. -*-s*, *--short*, *+short* +*-s*, *--short*, *+[no]short* Print just the address of the answer. # EXIT STATUS @@ -254,8 +255,6 @@ Probably more, _https://www.statdns.com/rfc_ # BUGS -OPT records are only printed when using a standard output, not JSON/XML/YAML. - Full parity with *dig*(1) is not complete. This man page is probably not complete. diff --git a/pkg/resolvers/HTTPS.go b/pkg/resolvers/HTTPS.go index d10ea06..9cfa691 100644 --- a/pkg/resolvers/HTTPS.go +++ b/pkg/resolvers/HTTPS.go @@ -48,7 +48,14 @@ func (resolver *HTTPSResolver) LookUp(msg *dns.Msg) (util.Response, error) { resolver.opts.Logger.Debug("https: sending HTTPS request") - req, err := http.NewRequest("POST", resolver.opts.Request.Server, bytes.NewBuffer(buf)) + var method string + if resolver.opts.HTTPSOptions.Get { + method = "GET" + } else { + method = "POST" + } + + req, err := http.NewRequest(method, resolver.opts.Request.Server, bytes.NewBuffer(buf)) if err != nil { return util.Response{}, fmt.Errorf("doh: request creation: %w", err) } diff --git a/pkg/resolvers/resolver.go b/pkg/resolvers/resolver.go index 28a8998..3840c92 100644 --- a/pkg/resolvers/resolver.go +++ b/pkg/resolvers/resolver.go @@ -31,6 +31,8 @@ func LoadResolver(opts *util.Options) (Resolver, error) { opts.Request.Server = "https://" + opts.Request.Server } + opts.Request.Server += opts.HTTPSOptions.Endpoint + return &HTTPSResolver{ opts: opts, }, nil diff --git a/pkg/util/options.go b/pkg/util/options.go index 0dbc1b0..b462a18 100644 --- a/pkg/util/options.go +++ b/pkg/util/options.go @@ -18,8 +18,12 @@ type Options struct { TLSHost string `json:"tlsHost" example:""` // EDNS Options EDNS + + // HTTPS options :) + HTTPSOptions + // DNS request :) - Request Request + Request // Verbosity levels, see [logawl.AllLevels] Verbosity int `json:"-" example:"0"` @@ -65,6 +69,16 @@ type Options struct { IPv6 bool `json:"forceIPv6" example:"false"` } +// HTTPSOptions are options exclusively for DNS-over-HTTPS queries. +type HTTPSOptions struct { + // URL endpoint + Endpoint string `json:"endpoint" example:"/dns-query"` + + // True, make GET request. + // False, make POST request. + Get bool `json:"get" example:"false"` +} + // HeaderFlags are the flags that are in DNS headers. type HeaderFlags struct { // Authoritative Answer DNS query flag