Allow overriding the provider preset with an explicit HTTPS DoH URL, including validation that custom endpoints apply only to DoH queries.
71 lines
2.1 KiB
Go
71 lines
2.1 KiB
Go
package edns
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/url"
|
|
)
|
|
|
|
func Query(ctx context.Context, options QueryOptions) Result {
|
|
wire, query, transactionID, err := BuildQuery(options.Name, options.RecordType)
|
|
result := Result{
|
|
SchemaVersion: 1,
|
|
Operation: "query",
|
|
Query: query,
|
|
Transport: TransportInfo{
|
|
Protocol: options.Protocol,
|
|
Encrypted: true,
|
|
Bootstrap: "system_resolver",
|
|
},
|
|
DNS: DNSInfo{Answers: []AnswerRecord{}},
|
|
}
|
|
if err != nil {
|
|
result.Query = QueryInfo{Name: options.Name, Type: options.RecordType}
|
|
result.Error = &ErrorInfo{Class: "input", Message: err.Error()}
|
|
return result
|
|
}
|
|
|
|
provider, err := FindProvider(options.Provider)
|
|
if err != nil {
|
|
result.Error = &ErrorInfo{Class: "input", Message: err.Error()}
|
|
return result
|
|
}
|
|
if options.EndpointURL != "" {
|
|
if options.Protocol != "doh" {
|
|
result.Error = &ErrorInfo{Class: "input", Message: "custom --url applies only to DoH"}
|
|
return result
|
|
}
|
|
parsed, err := url.Parse(options.EndpointURL)
|
|
if err != nil || parsed.Scheme != "https" || parsed.Hostname() == "" {
|
|
result.Error = &ErrorInfo{Class: "input", Message: fmt.Sprintf("invalid DoH endpoint URL %q", options.EndpointURL)}
|
|
return result
|
|
}
|
|
provider = Provider{ID: "custom", Profile: "custom", DoHURL: options.EndpointURL}
|
|
}
|
|
result.Resolver = ResolverInfo{Provider: provider.ID, Profile: provider.Profile}
|
|
|
|
var response []byte
|
|
switch options.Protocol {
|
|
case "doh":
|
|
result.Resolver.Endpoint = provider.DoHURL
|
|
response, result.Transport, err = exchangeDoH(ctx, provider, wire, options.Method)
|
|
case "dot":
|
|
result.Resolver.Endpoint = provider.DoTAddr
|
|
response, result.Transport, err = exchangeDoT(ctx, provider, wire)
|
|
default:
|
|
err = fmt.Errorf("protocol %q is not available; run ednsdiag capabilities", options.Protocol)
|
|
}
|
|
if err != nil {
|
|
result.Error = &ErrorInfo{Class: "transport", Message: err.Error()}
|
|
return result
|
|
}
|
|
|
|
result.DNS, err = ParseResponse(response, transactionID, query)
|
|
if err != nil {
|
|
result.Error = &ErrorInfo{Class: "protocol", Message: err.Error()}
|
|
return result
|
|
}
|
|
result.Completed = true
|
|
return result
|
|
}
|