diff --git a/config.go b/config.go index 87e5c6a8..4f34f1c9 100644 --- a/config.go +++ b/config.go @@ -61,6 +61,7 @@ type dnsConfig struct { } var defaultDNS = []string{"tls://1.1.1.1", "tls://1.0.0.1"} +var defaultBootstrap = []string{"1.1.1.1"} type tlsConfigSettings struct { Enabled bool `yaml:"enabled" json:"enabled"` // Enabled is the encryption (DOT/DOH/HTTPS) status @@ -114,7 +115,7 @@ var config = configuration{ QueryLogEnabled: true, Ratelimit: 20, RefuseAny: true, - BootstrapDNS: "8.8.8.8:53", + BootstrapDNS: defaultBootstrap, }, UpstreamDNS: defaultDNS, }, diff --git a/control.go b/control.go index fd1759e3..480f9fdc 100644 --- a/control.go +++ b/control.go @@ -437,6 +437,45 @@ func checkDNS(input string) error { return nil } +func handleSetBootstrapDNS(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, http.StatusBadRequest) + return + } + // if empty body -- user is asking for default servers + hosts := strings.Fields(string(body)) + + if len(hosts) == 0 { + config.DNS.BootstrapDNS = defaultBootstrap + } else { + config.DNS.BootstrapDNS = hosts + } + + err = writeAllConfigs() + if err != nil { + errorText := fmt.Sprintf("Couldn't write config file: %s", err) + log.Println(errorText) + http.Error(w, errorText, http.StatusInternalServerError) + return + } + err = reconfigureDNSServer() + if err != nil { + errorText := fmt.Sprintf("Couldn't reconfigure the DNS server: %s", err) + log.Println(errorText) + http.Error(w, errorText, http.StatusInternalServerError) + return + } + _, err = fmt.Fprintf(w, "OK %d bootsrap servers\n", len(hosts)) + if err != nil { + errorText := fmt.Sprintf("Couldn't write body: %s", err) + log.Println(errorText) + http.Error(w, errorText, http.StatusInternalServerError) + } +} + func handleGetVersionJSON(w http.ResponseWriter, r *http.Request) { now := time.Now() if now.Sub(versionCheckLastTime) <= versionCheckPeriod && len(versionCheckJSON) != 0 { @@ -1317,6 +1356,7 @@ func registerControlHandlers() { http.HandleFunc("/control/querylog_disable", postInstall(optionalAuth(ensurePOST(handleQueryLogDisable)))) http.HandleFunc("/control/set_upstream_dns", postInstall(optionalAuth(ensurePOST(handleSetUpstreamDNS)))) http.HandleFunc("/control/test_upstream_dns", postInstall(optionalAuth(ensurePOST(handleTestUpstreamDNS)))) + http.HandleFunc("/control/set_bootstrap_dns", postInstall(optionalAuth(ensurePOST(handleSetBootstrapDNS)))) http.HandleFunc("/control/i18n/change_language", postInstall(optionalAuth(ensurePOST(handleI18nChangeLanguage)))) http.HandleFunc("/control/i18n/current_language", postInstall(optionalAuth(ensureGET(handleI18nCurrentLanguage)))) http.HandleFunc("/control/stats_top", postInstall(optionalAuth(ensureGET(handleStatsTop)))) diff --git a/dns.go b/dns.go index b7f0d130..c70a4300 100644 --- a/dns.go +++ b/dns.go @@ -61,7 +61,7 @@ func generateServerConfig() dnsforward.ServerConfig { for _, u := range config.DNS.UpstreamDNS { opts := upstream.Options{ Timeout: dnsforward.DefaultTimeout, - Bootstrap: []string{config.DNS.BootstrapDNS}, + Bootstrap: config.DNS.BootstrapDNS, } dnsUpstream, err := upstream.AddressToUpstream(u, opts) if err != nil { diff --git a/dnsforward/dnsforward.go b/dnsforward/dnsforward.go index 99f09e6d..30dd5449 100644 --- a/dnsforward/dnsforward.go +++ b/dnsforward/dnsforward.go @@ -66,7 +66,7 @@ type FilteringConfig struct { Ratelimit int `yaml:"ratelimit"` RatelimitWhitelist []string `yaml:"ratelimit_whitelist"` RefuseAny bool `yaml:"refuse_any"` - BootstrapDNS string `yaml:"bootstrap_dns"` + BootstrapDNS []string `yaml:"bootstrap_dns"` dnsfilter.Config `yaml:",inline"` } diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index f1e23f86..067def2a 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -142,6 +142,30 @@ paths: 8.8.4.4: OK "192.168.1.104:53535": "Couldn't communicate with DNS server" + /set_bootstrap_dns: + post: + tags: + - global + operationId: setBootstrapDNS + summary: 'Set bootstrap DNS for DNS-over-HTTPS and DNS-over-TLS upstreams, empty value will reset it to default values' + consumes: + - text/plain + parameters: + - in: body + name: upstream + description: 'Bootstrap servers, separated by newline or space, port is optional after colon' + schema: + # TODO: use JSON + 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: OK + /version.json: get: tags: