From dfab6597cd0d3f92381cb2240cdc4fe5195bd74c Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 1 Sep 2020 14:33:35 +0300 Subject: [PATCH 1/5] + DNS: "dns.upstream_dns_file" setting --- AGHTechDoc.md | 2 ++ dnsforward/config.go | 28 +++++++++++++++++++++++----- dnsforward/dnsforward_http.go | 11 +++++++++-- openapi/openapi.yaml | 2 ++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index e5e582ec..50ad9d90 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -986,6 +986,7 @@ Response: { "upstream_dns": ["tls://...", ...], + "upstream_dns_file": "", "bootstrap_dns": ["1.2.3.4", ...], "protection_enabled": true | false, @@ -1011,6 +1012,7 @@ Request: { "upstream_dns": ["tls://...", ...], + "upstream_dns_file": "", "bootstrap_dns": ["1.2.3.4", ...], "protection_enabled": true | false, diff --git a/dnsforward/config.go b/dnsforward/config.go index 69af11eb..db224ea2 100644 --- a/dnsforward/config.go +++ b/dnsforward/config.go @@ -5,6 +5,7 @@ import ( "crypto/x509" "errors" "fmt" + "io/ioutil" "net" "net/http" "sort" @@ -13,6 +14,7 @@ import ( "github.com/joomcode/errorx" "github.com/AdguardTeam/AdGuardHome/dnsfilter" + "github.com/AdguardTeam/AdGuardHome/util" "github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/dnsproxy/upstream" ) @@ -55,10 +57,11 @@ type FilteringConfig struct { // Upstream DNS servers configuration // -- - UpstreamDNS []string `yaml:"upstream_dns"` - BootstrapDNS []string `yaml:"bootstrap_dns"` // a list of bootstrap DNS for DoH and DoT (plain DNS only) - AllServers bool `yaml:"all_servers"` // if true, parallel queries to all configured upstream servers are enabled - FastestAddr bool `yaml:"fastest_addr"` // use Fastest Address algorithm + UpstreamDNS []string `yaml:"upstream_dns"` + UpstreamDNSFileName string `yaml:"upstream_dns_file"` + BootstrapDNS []string `yaml:"bootstrap_dns"` // a list of bootstrap DNS for DoH and DoT (plain DNS only) + AllServers bool `yaml:"all_servers"` // if true, parallel queries to all configured upstream servers are enabled + FastestAddr bool `yaml:"fastest_addr"` // use Fastest Address algorithm // Access settings // -- @@ -215,7 +218,22 @@ func (s *Server) initDefaultSettings() { // prepareUpstreamSettings - prepares upstream DNS server settings func (s *Server) prepareUpstreamSettings() error { - upstreamConfig, err := proxy.ParseUpstreamsConfig(s.conf.UpstreamDNS, s.conf.BootstrapDNS, DefaultTimeout) + var upstreams []string + if s.conf.UpstreamDNSFileName != "" { + data, err := ioutil.ReadFile(s.conf.UpstreamDNSFileName) + if err != nil { + return err + } + d := string(data) + for len(d) != 0 { + s := util.SplitNext(&d, '\n') + upstreams = append(upstreams, s) + } + log.Debug("DNS: using %d upstream servers from file %s", len(upstreams), s.conf.UpstreamDNSFileName) + } else { + upstreams = s.conf.UpstreamDNS + } + upstreamConfig, err := proxy.ParseUpstreamsConfig(upstreams, s.conf.BootstrapDNS, DefaultTimeout) if err != nil { return fmt.Errorf("DNS: proxy.ParseUpstreamsConfig: %s", err) } diff --git a/dnsforward/dnsforward_http.go b/dnsforward/dnsforward_http.go index 63e82d95..286e9b81 100644 --- a/dnsforward/dnsforward_http.go +++ b/dnsforward/dnsforward_http.go @@ -22,8 +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"` + Upstreams []string `json:"upstream_dns"` + UpstreamsFile string `json:"upstream_dns_file"` + Bootstraps []string `json:"bootstrap_dns"` ProtectionEnabled bool `json:"protection_enabled"` RateLimit uint32 `json:"ratelimit"` @@ -43,6 +44,7 @@ func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) { resp := dnsConfigJSON{} s.RLock() resp.Upstreams = stringArrayDup(s.conf.UpstreamDNS) + resp.UpstreamsFile = s.conf.UpstreamDNSFileName resp.Bootstraps = stringArrayDup(s.conf.BootstrapDNS) resp.ProtectionEnabled = s.conf.ProtectionEnabled @@ -157,6 +159,11 @@ func (s *Server) handleSetConfig(w http.ResponseWriter, r *http.Request) { restart = true } + if js.Exists("upstream_dns_file") { + s.conf.UpstreamDNSFileName = req.UpstreamsFile + restart = true + } + if js.Exists("bootstrap_dns") { s.conf.BootstrapDNS = req.Bootstraps restart = true diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 57d63c70..4b5da50e 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -997,6 +997,8 @@ components: example: - tls://1.1.1.1 - tls://1.0.0.1 + upstream_dns_file: + type: string protection_enabled: type: boolean dhcp_available: From b04e12e189b5949cdc8f60aede950dedf574d839 Mon Sep 17 00:00:00 2001 From: Artem Baskal Date: Tue, 8 Sep 2020 14:06:19 +0300 Subject: [PATCH 2/5] + client: Display upstreams list loaded from a file Squashed commit of the following: commit b5abc9115806f345c8d0dd5ea00b8552d27813f9 Merge: 92708411 c1c8abdd Author: ArtemBaskal Date: Mon Sep 7 14:38:06 2020 +0300 Merge branch '1680-upstreams-file' into feature/1680 commit 92708411f07638c037e049ee8012d15bdeda77e4 Author: ArtemBaskal Date: Fri Sep 4 13:54:24 2020 +0300 + client: Display upstreams list loaded from a file --- client/src/__locales/en.json | 4 +- .../components/Settings/Dns/Upstream/Form.js | 93 +++++++++++-------- .../components/Settings/Dns/Upstream/index.js | 23 +++-- client/src/helpers/constants.js | 1 + client/src/reducers/dnsConfig.js | 1 + 5 files changed, 74 insertions(+), 48 deletions(-) diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 6cce0d91..674332d7 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -574,5 +574,7 @@ "original_response": "Original response", "click_to_view_queries": "Click to view queries", "port_53_faq_link": "Port 53 is often occupied by \"DNSStubListener\" or \"systemd-resolved\" services. Please read <0>this instruction on how to resolve this.", - "adg_will_drop_dns_queries": "AdGuard Home will be dropping all DNS queries from this client." + "adg_will_drop_dns_queries": "AdGuard Home will be dropping all DNS queries from this client.", + "configured_in": "Configured in {{path}}", + "please_read_wiki": "Please read the wiki" } diff --git a/client/src/components/Settings/Dns/Upstream/Form.js b/client/src/components/Settings/Dns/Upstream/Form.js index 2678edac..65a41c9f 100644 --- a/client/src/components/Settings/Dns/Upstream/Form.js +++ b/client/src/components/Settings/Dns/Upstream/Form.js @@ -5,51 +5,61 @@ import { Field, reduxForm } from 'redux-form'; import { Trans, useTranslation } from 'react-i18next'; import classnames from 'classnames'; +import i18next from 'i18next'; import Examples from './Examples'; import { renderRadioField, renderTextareaField } from '../../../../helpers/form'; -import { DNS_REQUEST_OPTIONS, FORM_NAME } from '../../../../helpers/constants'; +import { DNS_REQUEST_OPTIONS, FORM_NAME, UPSTREAM_CONFIGURATION_WIKI_LINK } from '../../../../helpers/constants'; import { testUpstream } from '../../../../actions'; import { removeEmptyLines } from '../../../../helpers/helpers'; -const getInputFields = () => [{ - // eslint-disable-next-line react/display-name - getTitle: () => , - name: 'upstream_dns', - type: 'text', - component: renderTextareaField, - className: 'form-control form-control--textarea font-monospace', - placeholder: 'upstream_dns', - normalizeOnBlur: removeEmptyLines, -}, -{ - name: 'upstream_mode', - type: 'radio', - value: DNS_REQUEST_OPTIONS.LOAD_BALANCING, - component: renderRadioField, - subtitle: 'load_balancing_desc', - placeholder: 'load_balancing', -}, -{ - name: 'upstream_mode', - type: 'radio', - value: DNS_REQUEST_OPTIONS.PARALLEL, - component: renderRadioField, - subtitle: 'upstream_parallel', - placeholder: 'parallel_requests', -}, -{ - name: 'upstream_mode', - type: 'radio', - value: DNS_REQUEST_OPTIONS.FASTEST_ADDR, - component: renderRadioField, - subtitle: 'fastest_addr_desc', - placeholder: 'fastest_addr', -}]; +const Title = () => ; + +const getInputFields = (upstream_dns_file) => [ + { + getTitle: Title, + name: 'upstream_dns', + type: 'text', + value: 'test', + component: renderTextareaField, + className: 'form-control form-control--textarea font-monospace', + placeholder: 'upstream_dns', + normalizeOnBlur: removeEmptyLines, + disabled: !!upstream_dns_file, + }, + { + name: 'upstream_mode', + type: 'radio', + value: DNS_REQUEST_OPTIONS.LOAD_BALANCING, + component: renderRadioField, + subtitle: 'load_balancing_desc', + placeholder: 'load_balancing', + }, + { + name: 'upstream_mode', + type: 'radio', + value: DNS_REQUEST_OPTIONS.PARALLEL, + component: renderRadioField, + subtitle: 'upstream_parallel', + placeholder: 'parallel_requests', + }, + { + name: 'upstream_mode', + type: 'radio', + value: DNS_REQUEST_OPTIONS.FASTEST_ADDR, + component: renderRadioField, + subtitle: 'fastest_addr_desc', + placeholder: 'fastest_addr', + }, +]; const Form = ({ - submitting, invalid, processingSetConfig, processingTestUpstream, handleSubmit, + submitting, invalid, handleSubmit, }) => { const dispatch = useDispatch(); const { t } = useTranslation(); @@ -57,6 +67,9 @@ const Form = ({ const bootstrap_dns = useSelector( (store) => store.form[FORM_NAME.UPSTREAM].values.bootstrap_dns, ); + const upstream_dns_file = useSelector((state) => state.dnsConfig.upstream_dns_file); + const processingTestUpstream = useSelector((state) => state.settings.processingTestUpstream); + const processingSetConfig = useSelector((state) => state.dnsConfig.processingSetConfig); const handleUpstreamTest = () => dispatch(testUpstream({ upstream_dns, @@ -67,7 +80,7 @@ const Form = ({ 'btn-loading': processingTestUpstream, }); - const INPUT_FIELDS = getInputFields(); + const INPUT_FIELDS = getInputFields(upstream_dns_file); return
@@ -146,8 +159,6 @@ Form.propTypes = { initialValues: PropTypes.object, upstream_dns: PropTypes.string, bootstrap_dns: PropTypes.string, - processingTestUpstream: PropTypes.bool, - processingSetConfig: PropTypes.bool, }; export default reduxForm({ form: FORM_NAME.UPSTREAM })(Form); diff --git a/client/src/components/Settings/Dns/Upstream/index.js b/client/src/components/Settings/Dns/Upstream/index.js index a0a26c00..4092638c 100644 --- a/client/src/components/Settings/Dns/Upstream/index.js +++ b/client/src/components/Settings/Dns/Upstream/index.js @@ -12,15 +12,28 @@ const Upstream = () => { upstream_dns, bootstrap_dns, upstream_mode, - processingSetConfig, } = useSelector((state) => state.dnsConfig, shallowEqual); - const { processingTestUpstream } = useSelector((state) => state.settings, shallowEqual); + const upstream_dns_file = useSelector((state) => state.dnsConfig.upstream_dns_file); const handleSubmit = (values) => { - dispatch(setDnsConfig(values)); + const { + bootstrap_dns, + upstream_dns, + upstream_mode, + } = values; + + const dnsConfig = { + bootstrap_dns, + upstream_mode, + ...(upstream_dns_file ? null : { upstream_dns }), + }; + + dispatch(setDnsConfig(dnsConfig)); }; + const upstreamDns = upstream_dns_file ? t('configured_in', { path: upstream_dns_file }) : upstream_dns; + return {
diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js index e0075a25..7f63d324 100644 --- a/client/src/helpers/constants.js +++ b/client/src/helpers/constants.js @@ -52,6 +52,7 @@ export const REPOSITORY = { export const PRIVACY_POLICY_LINK = 'https://adguard.com/privacy/home.html'; export const PORT_53_FAQ_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/FAQ#bindinuse'; +export const UPSTREAM_CONFIGURATION_WIKI_LINK = 'https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration#upstreams'; export const ADDRESS_IN_USE_TEXT = 'address already in use'; diff --git a/client/src/reducers/dnsConfig.js b/client/src/reducers/dnsConfig.js index 91e95818..bbe4ad2f 100644 --- a/client/src/reducers/dnsConfig.js +++ b/client/src/reducers/dnsConfig.js @@ -48,6 +48,7 @@ const dnsConfig = handleActions( edns_cs_enabled: false, disable_ipv6: false, dnssec_enabled: false, + upstream_dns_file: '', }, ); From 90e4316cfc152323257f092c7002b29252a2339b Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Wed, 9 Sep 2020 14:50:21 +0300 Subject: [PATCH 3/5] * (ui): fix strings --- client/src/__locales/en.json | 3 +-- client/src/components/Settings/Dns/Upstream/Form.js | 9 +++------ client/src/components/Settings/Dns/Upstream/index.js | 1 - 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 2fe1e760..001b7a09 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -132,7 +132,7 @@ "encryption_settings": "Encryption settings", "dhcp_settings": "DHCP settings", "upstream_dns": "Upstream DNS servers", - "upstream_dns_hint": "If you keep this field empty, AdGuard Home will use Quad9 as an upstream.", + "upstream_dns_help": "Enter servers addresses one per line. <0>Learn more about configuring upstream DNS servers.", "upstream_dns_configured_in_file": "Configured in {{path}}", "test_upstream_btn": "Test upstreams", "upstreams": "Upstreams", @@ -579,6 +579,5 @@ "click_to_view_queries": "Click to view queries", "port_53_faq_link": "Port 53 is often occupied by \"DNSStubListener\" or \"systemd-resolved\" services. Please read <0>this instruction on how to resolve this.", "adg_will_drop_dns_queries": "AdGuard Home will be dropping all DNS queries from this client.", - "please_read_wiki": "Please read the wiki", "experimental": "Experimental" } diff --git a/client/src/components/Settings/Dns/Upstream/Form.js b/client/src/components/Settings/Dns/Upstream/Form.js index 65a41c9f..0ebb6605 100644 --- a/client/src/components/Settings/Dns/Upstream/Form.js +++ b/client/src/components/Settings/Dns/Upstream/Form.js @@ -5,7 +5,6 @@ import { Field, reduxForm } from 'redux-form'; import { Trans, useTranslation } from 'react-i18next'; import classnames from 'classnames'; -import i18next from 'i18next'; import Examples from './Examples'; import { renderRadioField, renderTextareaField } from '../../../../helpers/form'; import { DNS_REQUEST_OPTIONS, FORM_NAME, UPSTREAM_CONFIGURATION_WIKI_LINK } from '../../../../helpers/constants'; @@ -13,11 +12,9 @@ import { testUpstream } from '../../../../actions'; import { removeEmptyLines } from '../../../../helpers/helpers'; const Title = () => ; const getInputFields = (upstream_dns_file) => [ diff --git a/client/src/components/Settings/Dns/Upstream/index.js b/client/src/components/Settings/Dns/Upstream/index.js index 315a8aea..0342713e 100644 --- a/client/src/components/Settings/Dns/Upstream/index.js +++ b/client/src/components/Settings/Dns/Upstream/index.js @@ -36,7 +36,6 @@ const Upstream = () => { return
From f8010902ce7428210948207c4e59b8f2dc8a540b Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Wed, 9 Sep 2020 17:50:39 +0300 Subject: [PATCH 4/5] * (dnsforward): upgrade dnsproxy to v0.32.1 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 476a496f..e1d1dfb7 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome go 1.14 require ( - github.com/AdguardTeam/dnsproxy v0.32.0 + github.com/AdguardTeam/dnsproxy v0.32.1 github.com/AdguardTeam/golibs v0.4.2 github.com/AdguardTeam/urlfilter v0.12.2 github.com/NYTimes/gziphandler v1.1.1 diff --git a/go.sum b/go.sum index 60b7eda0..10b294c7 100644 --- a/go.sum +++ b/go.sum @@ -7,8 +7,8 @@ dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBr dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= -github.com/AdguardTeam/dnsproxy v0.32.0 h1:taULDOMubiQSvRLynn8GlfMunhKaVryCBd/OkM++YFU= -github.com/AdguardTeam/dnsproxy v0.32.0/go.mod h1:ZLDrKIypYxBDz2N9FQHgeehuHrwTbuhZXdGwNySshbw= +github.com/AdguardTeam/dnsproxy v0.32.1 h1:UoiFt/aT8YCBFUGe7hG8ehLRXyvoIf22mOQqeIQxhWI= +github.com/AdguardTeam/dnsproxy v0.32.1/go.mod h1:ZLDrKIypYxBDz2N9FQHgeehuHrwTbuhZXdGwNySshbw= github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.4.2 h1:7M28oTZFoFwNmp8eGPb3ImmYbxGaJLyQXeIFVHjME0o= github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= From 88c67764b9515902514b0a8e4f00af29a353c584 Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Wed, 9 Sep 2020 18:12:11 +0300 Subject: [PATCH 5/5] * (dnsforward): don't fail when default upstream is not set --- dnsforward/config.go | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/dnsforward/config.go b/dnsforward/config.go index c66406ac..5e4fe170 100644 --- a/dnsforward/config.go +++ b/dnsforward/config.go @@ -187,7 +187,7 @@ func (s *Server) createProxyConfig() (proxy.Config, error) { // Validate proxy config if proxyConfig.UpstreamConfig == nil || len(proxyConfig.UpstreamConfig.Upstreams) == 0 { - return proxyConfig, errors.New("no upstream servers configured") + return proxyConfig, errors.New("no default upstream servers configured") } return proxyConfig, nil @@ -250,6 +250,16 @@ func (s *Server) prepareUpstreamSettings() error { if err != nil { return fmt.Errorf("DNS: proxy.ParseUpstreamsConfig: %s", err) } + + if len(upstreamConfig.Upstreams) == 0 { + log.Info("Warning: no default upstream servers specified, using %v", defaultDNS) + uc, err := proxy.ParseUpstreamsConfig(defaultDNS, s.conf.BootstrapDNS, DefaultTimeout) + if err != nil { + return fmt.Errorf("DNS: failed to parse default upstreams: %v", err) + } + upstreamConfig.Upstreams = uc.Upstreams + } + s.conf.UpstreamConfig = &upstreamConfig return nil }