+ DNS: add fastest_addr setting

* API: /dns_info, /dns_config: add "parallel_requests" instead of "all_servers" from /set_upstreams_config
* API: /status: removed fields

#715

Squashed commit of the following:

commit 7dd913bd336ecbaa7419b998d0bf913d89702fe6
Merge: 43706970 8170955a
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Wed Apr 22 19:09:36 2020 +0300

    Merge remote-tracking branch 'origin/master' into 715-fastest-addr

commit 437069702a3e91e0b066e4b22b08cdc02ff19eaf
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Wed Apr 22 19:08:55 2020 +0300

    minor

commit 9e713df80c5bf113c98794c0a20915c756a76938
Merge: e3bf4037 9b7c1181
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Tue Apr 21 16:02:03 2020 +0300

    Merge remote-tracking branch 'origin/master' into 715-fastest-addr

commit e3bf4037f49198e42bde55305d6f9077341b556a
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Tue Apr 21 15:40:49 2020 +0300

    minor

commit d6e6a823c5e51acc061b2850d362772efcb827e1
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Fri Apr 17 17:56:24 2020 +0300

    * API changes

    . removed POST /set_upstreams_config
    . removed fields from GET /status: bootstrap_dns, upstream_dns, all_servers
    . added new fields to /dns_config and /dns_info

commit 237a452d09cc48ff8f00e81c7fd35e7828bea835
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Fri Apr 17 16:43:13 2020 +0300

    * API: /dns_info, /dns_config: add "parallel_requests" instead of "all_servers" from /set_upstreams_config

commit 9976723b9725ed19e0cce152d1d1198b13c4acc1
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Mon Mar 23 10:28:25 2020 +0300

    openapi

commit 6f8ea16c6332606f29095b0094d71e8a91798f82
Merge: 36e4d4e8 c8285c41
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Fri Mar 20 19:18:48 2020 +0300

    Merge remote-tracking branch 'origin/master' into 715-fastest-addr

commit 36e4d4e82cadeaba5a11313f0d69d66a0924c342
Author: Simon Zolin <s.zolin@adguard.com>
Date:   Fri Mar 20 18:13:43 2020 +0300

    + DNS: add fastest_addr setting
This commit is contained in:
Simon Zolin 2020-04-22 19:14:04 +03:00
parent 8170955a07
commit e2ddc82d70
6 changed files with 148 additions and 83 deletions

View File

@ -882,6 +882,9 @@ Response:
200 OK
{
"upstream_dns": ["tls://...", ...],
"bootstrap_dns": ["1.2.3.4", ...],
"protection_enabled": true | false,
"ratelimit": 1234,
"blocking_mode": "default" | "nxdomain" | "null_ip" | "custom_ip",
@ -890,6 +893,8 @@ Response:
"edns_cs_enabled": true | false,
"dnssec_enabled": true | false
"disable_ipv6": true | false,
"fastest_addr": true | false, // use Fastest Address algorithm
"parallel_requests": true | false, // send DNS requests to all upstream servers at once
}
@ -900,6 +905,9 @@ Request:
POST /control/dns_config
{
"upstream_dns": ["tls://...", ...],
"bootstrap_dns": ["1.2.3.4", ...],
"protection_enabled": true | false,
"ratelimit": 1234,
"blocking_mode": "default" | "nxdomain" | "null_ip" | "custom_ip",
@ -908,6 +916,8 @@ Request:
"edns_cs_enabled": true | false,
"dnssec_enabled": true | false
"disable_ipv6": true | false,
"fastest_addr": true | false, // use Fastest Address algorithm
"parallel_requests": true | false, // send DNS requests to all upstream servers at once
}
Response:

View File

@ -141,6 +141,8 @@ type FilteringConfig struct {
// Respond with an empty answer to all AAAA requests
AAAADisabled bool `yaml:"aaaa_disabled"`
FastestAddrAlgo bool `yaml:"fastest_addr"` // use Fastest Address algorithm
AllowedClients []string `yaml:"allowed_clients"` // IP addresses of whitelist clients
DisallowedClients []string `yaml:"disallowed_clients"` // IP addresses of clients that should be blocked
BlockedHosts []string `yaml:"blocked_hosts"` // hosts that should be blocked
@ -305,6 +307,7 @@ func (s *Server) Prepare(config *ServerConfig) error {
RequestHandler: s.handleDNSRequest,
AllServers: s.conf.AllServers,
EnableEDNSClientSubnet: s.conf.EnableEDNSClientSubnet,
FindFastestAddr: s.conf.FastestAddrAlgo,
}
intlProxyConfig := proxy.Config{

View File

@ -22,6 +22,9 @@ func httpError(r *http.Request, w http.ResponseWriter, code int, format string,
}
type dnsConfigJSON struct {
Upstreams []string `json:"upstream_dns"`
Bootstraps []string `json:"bootstrap_dns"`
ProtectionEnabled bool `json:"protection_enabled"`
RateLimit uint32 `json:"ratelimit"`
BlockingMode string `json:"blocking_mode"`
@ -30,11 +33,16 @@ type dnsConfigJSON struct {
EDNSCSEnabled bool `json:"edns_cs_enabled"`
DNSSECEnabled bool `json:"dnssec_enabled"`
DisableIPv6 bool `json:"disable_ipv6"`
FastestAddr bool `json:"fastest_addr"`
ParallelRequests bool `json:"parallel_requests"`
}
func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) {
resp := dnsConfigJSON{}
s.RLock()
resp.Upstreams = stringArrayDup(s.conf.UpstreamDNS)
resp.Bootstraps = stringArrayDup(s.conf.BootstrapDNS)
resp.ProtectionEnabled = s.conf.ProtectionEnabled
resp.BlockingMode = s.conf.BlockingMode
resp.BlockingIPv4 = s.conf.BlockingIPv4
@ -43,6 +51,8 @@ func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) {
resp.EDNSCSEnabled = s.conf.EnableEDNSClientSubnet
resp.DNSSECEnabled = s.conf.EnableDNSSEC
resp.DisableIPv6 = s.conf.AAAADisabled
resp.FastestAddr = s.conf.FastestAddrAlgo
resp.ParallelRequests = s.conf.AllServers
s.RUnlock()
js, err := json.Marshal(resp)
@ -75,6 +85,7 @@ func checkBlockingMode(req dnsConfigJSON) bool {
return true
}
// nolint(gocyclo) - we need to check each JSON field separately
func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
req := dnsConfigJSON{}
js, err := jsonutil.DecodeObject(&req, r.Body)
@ -83,6 +94,25 @@ func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
return
}
if js.Exists("upstream_dns") {
if len(req.Upstreams) != 0 {
err = ValidateUpstreams(req.Upstreams)
if err != nil {
httpError(r, w, http.StatusBadRequest, "wrong upstreams specification: %s", err)
return
}
}
}
if js.Exists("bootstrap_dns") {
for _, host := range req.Bootstraps {
if err := checkPlainDNS(host); err != nil {
httpError(r, w, http.StatusBadRequest, "%s can not be used as bootstrap dns cause: %s", host, err)
return
}
}
}
if js.Exists("blocking_mode") && !checkBlockingMode(req) {
httpError(r, w, http.StatusBadRequest, "blocking_mode: incorrect value")
return
@ -91,6 +121,16 @@ func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
restart := false
s.Lock()
if js.Exists("upstream_dns") {
s.conf.UpstreamDNS = req.Upstreams
restart = true
}
if js.Exists("bootstrap_dns") {
s.conf.BootstrapDNS = req.Bootstraps
restart = true
}
if js.Exists("protection_enabled") {
s.conf.ProtectionEnabled = req.ProtectionEnabled
}
@ -129,6 +169,14 @@ func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
s.conf.AAAADisabled = req.DisableIPv6
}
if js.Exists("fastest_addr") {
s.conf.FastestAddrAlgo = req.FastestAddr
}
if js.Exists("parallel_requests") {
s.conf.AllServers = req.ParallelRequests
}
s.Unlock()
s.conf.ConfigModified()
@ -144,51 +192,6 @@ func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) {
type upstreamJSON struct {
Upstreams []string `json:"upstream_dns"` // Upstreams
BootstrapDNS []string `json:"bootstrap_dns"` // Bootstrap DNS
AllServers bool `json:"all_servers"` // --all-servers param for dnsproxy
}
func (s *Server) handleSetUpstreamConfig(w http.ResponseWriter, r *http.Request) {
req := upstreamJSON{}
err := json.NewDecoder(r.Body).Decode(&req)
if err != nil {
httpError(r, w, http.StatusBadRequest, "Failed to parse new upstreams config json: %s", err)
return
}
if len(req.Upstreams) != 0 {
err = ValidateUpstreams(req.Upstreams)
if err != nil {
httpError(r, w, http.StatusBadRequest, "wrong upstreams specification: %s", err)
return
}
}
newconf := FilteringConfig{}
newconf.UpstreamDNS = req.Upstreams
// bootstrap servers are plain DNS only
for _, host := range req.BootstrapDNS {
if err := checkPlainDNS(host); err != nil {
httpError(r, w, http.StatusBadRequest, "%s can not be used as bootstrap dns cause: %s", host, err)
return
}
}
newconf.BootstrapDNS = req.BootstrapDNS
newconf.AllServers = req.AllServers
s.Lock()
s.conf.UpstreamDNS = newconf.UpstreamDNS
s.conf.BootstrapDNS = newconf.BootstrapDNS
s.conf.AllServers = newconf.AllServers
s.Unlock()
s.conf.ConfigModified()
err = s.Reconfigure(nil)
if err != nil {
httpError(r, w, http.StatusInternalServerError, "%s", err)
return
}
}
// ValidateUpstreams validates each upstream and returns an error if any upstream is invalid or if there are no default upstreams specified
@ -399,7 +402,6 @@ func (s *Server) handleDOH(w http.ResponseWriter, r *http.Request) {
func (s *Server) registerHandlers() {
s.conf.HTTPRegister("GET", "/control/dns_info", s.handleGetConfig)
s.conf.HTTPRegister("POST", "/control/dns_config", s.handleSetConfig)
s.conf.HTTPRegister("POST", "/control/set_upstreams_config", s.handleSetUpstreamConfig)
s.conf.HTTPRegister("POST", "/control/test_upstream_dns", s.handleTestUpstreamDNS)
s.conf.HTTPRegister("GET", "/control/access/list", s.handleAccessList)

View File

@ -55,9 +55,6 @@ func handleStatus(w http.ResponseWriter, r *http.Request) {
"language": config.Language,
"protection_enabled": c.ProtectionEnabled,
"bootstrap_dns": c.BootstrapDNS,
"upstream_dns": c.UpstreamDNS,
"all_servers": c.AllServers,
}
jsonVal, err := json.Marshal(data)

View File

@ -1,6 +1,70 @@
# AdGuard Home API Change Log
## v0.102: API changes
### API: Get general status: GET /control/status
* Removed "upstream_dns", "bootstrap_dns", "all_servers" parameters
### API: Get DNS general settings: GET /control/dns_info
* Added "parallel_requests", "upstream_dns", "bootstrap_dns" parameters
Request:
GET /control/dns_info
Response:
200 OK
{
"upstream_dns": ["tls://...", ...],
"bootstrap_dns": ["1.2.3.4", ...],
"protection_enabled": true | false,
"ratelimit": 1234,
"blocking_mode": "default" | "nxdomain" | "null_ip" | "custom_ip",
"blocking_ipv4": "1.2.3.4",
"blocking_ipv6": "1:2:3::4",
"edns_cs_enabled": true | false,
"dnssec_enabled": true | false
"disable_ipv6": true | false,
"fastest_addr": true | false, // use Fastest Address algorithm
"parallel_requests": true | false, // send DNS requests to all upstream servers at once
}
### API: Set DNS general settings: POST /control/dns_config
* Added "parallel_requests", "upstream_dns", "bootstrap_dns" parameters
* removed /control/set_upstreams_config method
Request:
POST /control/dns_config
{
"upstream_dns": ["tls://...", ...],
"bootstrap_dns": ["1.2.3.4", ...],
"protection_enabled": true | false,
"ratelimit": 1234,
"blocking_mode": "default" | "nxdomain" | "null_ip" | "custom_ip",
"blocking_ipv4": "1.2.3.4",
"blocking_ipv6": "1:2:3::4",
"edns_cs_enabled": true | false,
"dnssec_enabled": true | false
"disable_ipv6": true | false,
"fastest_addr": true | false, // use Fastest Address algorithm
"parallel_requests": true | false, // send DNS requests to all upstream servers at once
}
Response:
200 OK
## v0.101: API changes
### API: Refresh filters: POST /control/filtering/refresh

View File

@ -2,7 +2,7 @@ swagger: '2.0'
info:
title: 'AdGuard Home'
description: 'AdGuard Home REST API. Admin web interface is built on top of this REST API.'
version: '0.101'
version: '0.102'
schemes:
- http
basePath: /control
@ -99,25 +99,6 @@ paths:
200:
description: OK
/set_upstreams_config:
post:
tags:
- global
operationId: setUpstreamsConfig
summary: "Updates the current upstreams configuration"
consumes:
- application/json
parameters:
- in: "body"
name: "body"
description: "Upstreams configuration JSON"
required: true
schema:
$ref: "#/definitions/UpstreamsConfig"
responses:
200:
description: OK
/test_upstream_dns:
post:
tags:
@ -1072,16 +1053,6 @@ definitions:
type: "boolean"
running:
type: "boolean"
bootstrap_dns:
type: "string"
example: "8.8.8.8:53"
upstream_dns:
type: "array"
items:
type: "string"
example:
- "tls://1.1.1.1"
- "tls://1.0.0.1"
version:
type: "string"
example: "0.1"
@ -1093,6 +1064,22 @@ definitions:
type: "object"
description: "Query log configuration"
properties:
bootstrap_dns:
type: "array"
description: 'Bootstrap servers, port is optional after colon. Empty value will reset it to default values'
items:
type: "string"
example:
- "8.8.8.8:53"
- "1.1.1.1:53"
upstream_dns:
type: "array"
description: 'Upstream servers, port is optional after colon. Empty value will reset it to default values'
items:
type: "string"
example:
- "tls://1.1.1.1"
- "tls://1.0.0.1"
protection_enabled:
type: "boolean"
ratelimit:
@ -1112,6 +1099,11 @@ definitions:
type: "boolean"
dnssec_enabled:
type: "boolean"
fastest_addr:
type: "boolean"
parallel_requests:
type: "boolean"
description: "If true, parallel queries to all configured upstream servers are enabled"
UpstreamsConfig:
type: "object"
@ -1119,7 +1111,6 @@ definitions:
required:
- "bootstrap_dns"
- "upstream_dns"
- "all_servers"
properties:
bootstrap_dns:
type: "array"
@ -1137,9 +1128,7 @@ definitions:
example:
- "tls://1.1.1.1"
- "tls://1.0.0.1"
all_servers:
type: "boolean"
description: "If true, parallel queries to all configured upstream servers are enabled"
Filter:
type: "object"
description: "Filter subscription info"