Merge pull request #28 in DNS/adguard-dns from feature/321 to master
* commit 'e733c1950484969c553b92e80ced6e585cc07bea': Implement API to test for upstream DNS servers.
This commit is contained in:
commit
a185161ad4
91
control.go
91
control.go
|
@ -18,6 +18,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdguardDNS/dnsfilter"
|
"github.com/AdguardTeam/AdguardDNS/dnsfilter"
|
||||||
|
"github.com/miekg/dns"
|
||||||
"gopkg.in/asaskevich/govalidator.v4"
|
"gopkg.in/asaskevich/govalidator.v4"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -529,6 +530,95 @@ func handleSetUpstreamDNS(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func handleTestUpstreamDNS(w http.ResponseWriter, r *http.Request) {
|
||||||
|
body, err := ioutil.ReadAll(r.Body)
|
||||||
|
if err != nil {
|
||||||
|
errortext := fmt.Sprintf("Failed to read request body: %s", err)
|
||||||
|
log.Println(errortext)
|
||||||
|
http.Error(w, errortext, 400)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
hosts := strings.Fields(string(body))
|
||||||
|
|
||||||
|
if len(hosts) == 0 {
|
||||||
|
errortext := fmt.Sprintf("No servers specified")
|
||||||
|
log.Println(errortext)
|
||||||
|
http.Error(w, errortext, http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
result := map[string]string{}
|
||||||
|
|
||||||
|
for _, host := range hosts {
|
||||||
|
err := checkDNS(host)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
result[host] = err.Error()
|
||||||
|
} else {
|
||||||
|
result[host] = "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json, err := json.Marshal(result)
|
||||||
|
if err != nil {
|
||||||
|
errortext := fmt.Sprintf("Unable to marshal status json: %s", err)
|
||||||
|
log.Println(errortext)
|
||||||
|
http.Error(w, errortext, http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
_, err = w.Write(json)
|
||||||
|
if err != nil {
|
||||||
|
errortext := fmt.Sprintf("Couldn't write body: %s", err)
|
||||||
|
log.Println(errortext)
|
||||||
|
http.Error(w, errortext, http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkDNS(host string) error {
|
||||||
|
host = appendPortIfMissing(host)
|
||||||
|
{
|
||||||
|
h, _, err := net.SplitHostPort(host)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ip := net.ParseIP(h)
|
||||||
|
if ip == nil {
|
||||||
|
return fmt.Errorf("Invalid DNS server field: %s", h)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req := dns.Msg{}
|
||||||
|
req.Id = dns.Id()
|
||||||
|
req.RecursionDesired = true
|
||||||
|
req.Question = []dns.Question{
|
||||||
|
{"google-public-dns-a.google.com.", dns.TypeA, dns.ClassINET},
|
||||||
|
}
|
||||||
|
resp, err := dns.Exchange(&req, host)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Couldn't communicate with DNS server %s: %s", host, err)
|
||||||
|
}
|
||||||
|
if len(resp.Answer) != 1 {
|
||||||
|
return fmt.Errorf("DNS server %s returned wrong answer", host)
|
||||||
|
}
|
||||||
|
if t, ok := resp.Answer[0].(*dns.A); ok {
|
||||||
|
if !net.IPv4(8, 8, 8, 8).Equal(t.A) {
|
||||||
|
return fmt.Errorf("DNS server %s returned wrong answer: %v", host, t.A)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func appendPortIfMissing(input string) string {
|
||||||
|
_, _, err := net.SplitHostPort(input)
|
||||||
|
if err == nil {
|
||||||
|
return input
|
||||||
|
}
|
||||||
|
return net.JoinHostPort(input, "53")
|
||||||
|
}
|
||||||
|
|
||||||
func parseIPsOptionalPort(input string) []string {
|
func parseIPsOptionalPort(input string) []string {
|
||||||
fields := strings.Fields(input)
|
fields := strings.Fields(input)
|
||||||
hosts := []string{}
|
hosts := []string{}
|
||||||
|
@ -1309,6 +1399,7 @@ func registerControlHandlers() {
|
||||||
http.HandleFunc("/control/querylog_enable", optionalAuth(ensurePOST(handleQueryLogEnable)))
|
http.HandleFunc("/control/querylog_enable", optionalAuth(ensurePOST(handleQueryLogEnable)))
|
||||||
http.HandleFunc("/control/querylog_disable", optionalAuth(ensurePOST(handleQueryLogDisable)))
|
http.HandleFunc("/control/querylog_disable", optionalAuth(ensurePOST(handleQueryLogDisable)))
|
||||||
http.HandleFunc("/control/set_upstream_dns", optionalAuth(ensurePOST(handleSetUpstreamDNS)))
|
http.HandleFunc("/control/set_upstream_dns", optionalAuth(ensurePOST(handleSetUpstreamDNS)))
|
||||||
|
http.HandleFunc("/control/test_upstream_dns", optionalAuth(ensurePOST(handleTestUpstreamDNS)))
|
||||||
http.HandleFunc("/control/filtering/enable", optionalAuth(ensurePOST(handleFilteringEnable)))
|
http.HandleFunc("/control/filtering/enable", optionalAuth(ensurePOST(handleFilteringEnable)))
|
||||||
http.HandleFunc("/control/filtering/disable", optionalAuth(ensurePOST(handleFilteringDisable)))
|
http.HandleFunc("/control/filtering/disable", optionalAuth(ensurePOST(handleFilteringDisable)))
|
||||||
http.HandleFunc("/control/filtering/status", optionalAuth(ensureGET(handleFilteringStatus)))
|
http.HandleFunc("/control/filtering/status", optionalAuth(ensureGET(handleFilteringStatus)))
|
||||||
|
|
29
openapi.yaml
29
openapi.yaml
|
@ -160,6 +160,35 @@ paths:
|
||||||
responses:
|
responses:
|
||||||
200:
|
200:
|
||||||
description: OK
|
description: OK
|
||||||
|
/test_upstream_dns:
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- global
|
||||||
|
operationId: testUpstreamDNS
|
||||||
|
summary: 'Test upstream DNS'
|
||||||
|
consumes:
|
||||||
|
- text/plain
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: upstream
|
||||||
|
description: 'Upstream servers, separated by newline or space, port is optional after colon'
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
example: |
|
||||||
|
1.1.1.1
|
||||||
|
1.0.0.1
|
||||||
|
8.8.8.8 8.8.4.4
|
||||||
|
192.168.1.104:53535
|
||||||
|
responses:
|
||||||
|
200:
|
||||||
|
description: 'Status of testing each requested server, with "OK" meaning that server works, any other text means an error.'
|
||||||
|
examples:
|
||||||
|
application/json:
|
||||||
|
1.1.1.1: OK
|
||||||
|
1.0.0.1: OK
|
||||||
|
8.8.8.8: OK
|
||||||
|
8.8.4.4: OK
|
||||||
|
"192.168.1.104:53535": "Couldn't communicate with DNS server"
|
||||||
/stats_top:
|
/stats_top:
|
||||||
get:
|
get:
|
||||||
tags:
|
tags:
|
||||||
|
|
Loading…
Reference in New Issue