Pull request: 3136 show default resolvers
Merge in DNS/adguard-home from 3136-show-default to master
Closes #3136.
Squashed commit of the following:
commit add09a772dddcccd404056e7649c2d3350a79fec
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Tue Jun 1 11:11:24 2021 +0300
openapi: fix typo
commit 69e402c49318d53a0d03b81207644d9fb04a139a
Merge: 76e8492c e17e1f20
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Tue Jun 1 11:09:51 2021 +0300
Merge branch 'master' into 3136-show-default
commit 76e8492c8da679e204ceb7a77f1c6f73a2488040
Author: Ildar Kamalov <ik@adguard.com>
Date: Tue Jun 1 10:55:09 2021 +0300
client: check upstreams
commit 05fe6ea196a1ed9386eec25dbfbe22779fe7bcfd
Author: Vlad <v.abdulmyanov@adguard.com>
Date: Mon May 31 19:23:35 2021 +0300
add defaul resolvers line
commit 8d63c7df9947c9588478d1173834b42569fd8951
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Mon May 31 11:56:08 2021 +0300
all: imp changelog
commit e3912e3b20eca9dcf90ddddaa5edb54d1e0cfe6e
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Fri May 28 20:23:05 2021 +0300
all: add local ptr resolvers addresses output
This commit is contained in:
parent
e17e1f20fb
commit
1e55db408f
|
@ -15,6 +15,8 @@ and this project adheres to
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- Output of the default addresses of the upstreams used for resolving PTRs for
|
||||||
|
private addresses ([#3136]).
|
||||||
- Detection and handling of recurrent PTR requests for locally-served addresses
|
- Detection and handling of recurrent PTR requests for locally-served addresses
|
||||||
([#3185]).
|
([#3185]).
|
||||||
- The ability to completely disable reverse DNS resolving of IPs from
|
- The ability to completely disable reverse DNS resolving of IPs from
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
"bootstrap_dns_desc": "Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams.",
|
"bootstrap_dns_desc": "Bootstrap DNS servers are used to resolve IP addresses of the DoH/DoT resolvers you specify as upstreams.",
|
||||||
"local_ptr_title": "Private reverse DNS servers",
|
"local_ptr_title": "Private reverse DNS servers",
|
||||||
"local_ptr_desc": "The DNS servers that AdGuard Home uses for local PTR queries. These servers are used to resolve the hostnames of clients with private IP addresses, for example \"192.168.12.34\", using rDNS. If not set, AdGuard Home uses the default DNS resolvers of your OS.",
|
"local_ptr_desc": "The DNS servers that AdGuard Home uses for local PTR queries. These servers are used to resolve the hostnames of clients with private IP addresses, for example \"192.168.12.34\", using rDNS. If not set, AdGuard Home uses the default DNS resolvers of your OS.",
|
||||||
|
"local_ptr_default_resolver": "By default, AdGuard Home will use the following DNS resolvers: {{ip}}",
|
||||||
|
"local_ptr_no_default_resolver": "AdGuard Home could not determine suitable private rDNS resolvers for this system.",
|
||||||
"local_ptr_placeholder": "Enter one server address per line",
|
"local_ptr_placeholder": "Enter one server address per line",
|
||||||
"resolve_clients_title": "Enable reverse resolving of clients' IP addresses",
|
"resolve_clients_title": "Enable reverse resolving of clients' IP addresses",
|
||||||
"resolve_clients_desc": "If enabled, AdGuard Home will attempt to reversely resolve clients' IP addresses into their hostnames by sending PTR queries to corresponding resolvers (private DNS servers for local clients, upstream servers for clients with public IP addresses).",
|
"resolve_clients_desc": "If enabled, AdGuard Home will attempt to reversely resolve clients' IP addresses into their hostnames by sending PTR queries to corresponding resolvers (private DNS servers for local clients, upstream servers for clients with public IP addresses).",
|
||||||
|
|
|
@ -143,6 +143,9 @@ const Form = ({
|
||||||
const upstream_dns = useSelector((store) => store.form[FORM_NAME.UPSTREAM].values.upstream_dns);
|
const upstream_dns = useSelector((store) => store.form[FORM_NAME.UPSTREAM].values.upstream_dns);
|
||||||
const processingTestUpstream = useSelector((state) => state.settings.processingTestUpstream);
|
const processingTestUpstream = useSelector((state) => state.settings.processingTestUpstream);
|
||||||
const processingSetConfig = useSelector((state) => state.dnsConfig.processingSetConfig);
|
const processingSetConfig = useSelector((state) => state.dnsConfig.processingSetConfig);
|
||||||
|
const defaultLocalPtrUpstreams = useSelector(
|
||||||
|
(state) => state.dnsConfig.default_local_ptr_upstreams,
|
||||||
|
);
|
||||||
|
|
||||||
const handleUpstreamTest = () => dispatch(testUpstreamWithFormValues());
|
const handleUpstreamTest = () => dispatch(testUpstreamWithFormValues());
|
||||||
|
|
||||||
|
@ -212,6 +215,14 @@ const Form = ({
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">
|
||||||
<Trans>local_ptr_desc</Trans>
|
<Trans>local_ptr_desc</Trans>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="form__desc form__desc--top">
|
||||||
|
{/** TODO: Add internazionalization for "" */}
|
||||||
|
{defaultLocalPtrUpstreams?.length > 0 ? (
|
||||||
|
<Trans values={{ ip: defaultLocalPtrUpstreams.map((s) => `"${s}"`).join(', ') }}>local_ptr_default_resolver</Trans>
|
||||||
|
) : (
|
||||||
|
<Trans>local_ptr_no_default_resolver</Trans>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
<Field
|
<Field
|
||||||
id="local_ptr_upstreams"
|
id="local_ptr_upstreams"
|
||||||
name="local_ptr_upstreams"
|
name="local_ptr_upstreams"
|
||||||
|
|
|
@ -16,8 +16,8 @@ type HostGenFunc func() (host string)
|
||||||
|
|
||||||
// SystemResolvers helps to work with local resolvers' addresses provided by OS.
|
// SystemResolvers helps to work with local resolvers' addresses provided by OS.
|
||||||
type SystemResolvers interface {
|
type SystemResolvers interface {
|
||||||
// Get returns the slice of local resolvers' addresses.
|
// Get returns the slice of local resolvers' addresses. It should be
|
||||||
// It should be safe for concurrent use.
|
// safe for concurrent use.
|
||||||
Get() (rs []string)
|
Get() (rs []string)
|
||||||
// refresh refreshes the local resolvers' addresses cache. It should be
|
// refresh refreshes the local resolvers' addresses cache. It should be
|
||||||
// safe for concurrent use.
|
// safe for concurrent use.
|
||||||
|
|
|
@ -76,6 +76,7 @@ type Server struct {
|
||||||
ipset ipsetCtx
|
ipset ipsetCtx
|
||||||
subnetDetector *aghnet.SubnetDetector
|
subnetDetector *aghnet.SubnetDetector
|
||||||
localResolvers *proxy.Proxy
|
localResolvers *proxy.Proxy
|
||||||
|
sysResolvers aghnet.SystemResolvers
|
||||||
recDetector *recursionDetector
|
recDetector *recursionDetector
|
||||||
|
|
||||||
tableHostToIP hostToIPTable
|
tableHostToIP hostToIPTable
|
||||||
|
@ -154,6 +155,13 @@ func NewServer(p DNSCreateParams) (s *Server, err error) {
|
||||||
recDetector: newRecursionDetector(recursionTTL, cachedRecurrentReqNum),
|
recDetector: newRecursionDetector(recursionTTL, cachedRecurrentReqNum),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(e.burkov): Enable the refresher after the actual implementation
|
||||||
|
// passes the public testing.
|
||||||
|
s.sysResolvers, err = aghnet.NewSystemResolvers(0, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("initializing system resolvers: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
if p.DHCPServer != nil {
|
if p.DHCPServer != nil {
|
||||||
s.dhcpServer = p.DHCPServer
|
s.dhcpServer = p.DHCPServer
|
||||||
s.dhcpServer.SetOnLeaseChanged(s.onDHCPLeaseChanged)
|
s.dhcpServer.SetOnLeaseChanged(s.onDHCPLeaseChanged)
|
||||||
|
@ -375,28 +383,11 @@ func (s *Server) collectDNSIPAddrs() (addrs []string, err error) {
|
||||||
return addrs[:i], nil
|
return addrs[:i], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// setupResolvers initializes the resolvers for local addresses. For internal
|
func (s *Server) filterOurDNSAddrs(addrs []string) (filtered []string, err error) {
|
||||||
// use only.
|
|
||||||
func (s *Server) setupResolvers(localAddrs []string) (err error) {
|
|
||||||
bootstraps := s.conf.BootstrapDNS
|
|
||||||
if len(localAddrs) == 0 {
|
|
||||||
var sysRes aghnet.SystemResolvers
|
|
||||||
// TODO(e.burkov): Enable the refresher after the actual
|
|
||||||
// implementation passes the public testing.
|
|
||||||
sysRes, err = aghnet.NewSystemResolvers(0, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
localAddrs = sysRes.Get()
|
|
||||||
bootstraps = nil
|
|
||||||
}
|
|
||||||
log.Debug("upstreams to resolve PTR for local addresses: %v", localAddrs)
|
|
||||||
|
|
||||||
var ourAddrs []string
|
var ourAddrs []string
|
||||||
ourAddrs, err = s.collectDNSIPAddrs()
|
ourAddrs, err = s.collectDNSIPAddrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ourAddrsSet := aghstrings.NewSet(ourAddrs...)
|
ourAddrsSet := aghstrings.NewSet(ourAddrs...)
|
||||||
|
@ -405,7 +396,24 @@ func (s *Server) setupResolvers(localAddrs []string) (err error) {
|
||||||
// really applicable here since in case of listening on all network
|
// really applicable here since in case of listening on all network
|
||||||
// interfaces we should check the whole interface's network to cut off
|
// interfaces we should check the whole interface's network to cut off
|
||||||
// all the loopback addresses as well.
|
// all the loopback addresses as well.
|
||||||
localAddrs = aghstrings.FilterOut(localAddrs, ourAddrsSet.Has)
|
return aghstrings.FilterOut(addrs, ourAddrsSet.Has), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// setupResolvers initializes the resolvers for local addresses. For internal
|
||||||
|
// use only.
|
||||||
|
func (s *Server) setupResolvers(localAddrs []string) (err error) {
|
||||||
|
bootstraps := s.conf.BootstrapDNS
|
||||||
|
if len(localAddrs) == 0 {
|
||||||
|
localAddrs = s.sysResolvers.Get()
|
||||||
|
bootstraps = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
localAddrs, err = s.filterOurDNSAddrs(localAddrs)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("upstreams to resolve PTR for local addresses: %v", localAddrs)
|
||||||
|
|
||||||
var upsConfig proxy.UpstreamConfig
|
var upsConfig proxy.UpstreamConfig
|
||||||
upsConfig, err = proxy.ParseUpstreamsConfig(localAddrs, upstream.Options{
|
upsConfig, err = proxy.ParseUpstreamsConfig(localAddrs, upstream.Options{
|
||||||
|
|
|
@ -96,12 +96,25 @@ func (s *Server) getDNSConfig() dnsConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) handleGetConfig(w http.ResponseWriter, r *http.Request) {
|
||||||
resp := s.getDNSConfig()
|
defLocalPTRUps, err := s.filterOurDNSAddrs(s.sysResolvers.Get())
|
||||||
|
if err != nil {
|
||||||
|
log.Debug("getting dns configuration: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := struct {
|
||||||
|
dnsConfig
|
||||||
|
// DefautLocalPTRUpstreams is used to pass the addresses from
|
||||||
|
// systemResolvers to the front-end. It's not a pointer to the slice
|
||||||
|
// since there is no need to omit it while decoding from JSON.
|
||||||
|
DefautLocalPTRUpstreams []string `json:"default_local_ptr_upstreams,omitempty"`
|
||||||
|
}{
|
||||||
|
dnsConfig: s.getDNSConfig(),
|
||||||
|
DefautLocalPTRUpstreams: defLocalPTRUps,
|
||||||
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
|
||||||
enc := json.NewEncoder(w)
|
if err = json.NewEncoder(w).Encode(resp); err != nil {
|
||||||
if err := enc.Encode(resp); err != nil {
|
|
||||||
httpError(r, w, http.StatusInternalServerError, "json.Encoder: %s", err)
|
httpError(r, w, http.StatusInternalServerError, "json.Encoder: %s", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,25 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// fakeSystemResolvers is a mock aghnet.SystemResolvers implementation for tests.
|
||||||
|
type fakeSystemResolvers struct {
|
||||||
|
// SystemResolvers is embedded here simply to make *fakeSystemResolvers
|
||||||
|
// an aghnet.SystemResolvers without actually implementing all methods.
|
||||||
|
aghnet.SystemResolvers
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get implements the aghnet.SystemResolvers interface for *fakeSystemResolvers.
|
||||||
|
// It always returns nil.
|
||||||
|
func (fsr *fakeSystemResolvers) Get() (rs []string) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func loadTestData(t *testing.T, casesFileName string, cases interface{}) {
|
func loadTestData(t *testing.T, casesFileName string, cases interface{}) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
|
@ -52,6 +66,8 @@ func TestDNSForwardHTTTP_handleGetConfig(t *testing.T) {
|
||||||
ConfigModified: func() {},
|
ConfigModified: func() {},
|
||||||
}
|
}
|
||||||
s := createTestServer(t, filterConf, forwardConf, nil)
|
s := createTestServer(t, filterConf, forwardConf, nil)
|
||||||
|
s.sysResolvers = &fakeSystemResolvers{}
|
||||||
|
|
||||||
require.Nil(t, s.Start())
|
require.Nil(t, s.Start())
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
require.Nil(t, s.Stop())
|
require.Nil(t, s.Stop())
|
||||||
|
@ -125,6 +141,7 @@ func TestDNSForwardHTTTP_handleSetConfig(t *testing.T) {
|
||||||
ConfigModified: func() {},
|
ConfigModified: func() {},
|
||||||
}
|
}
|
||||||
s := createTestServer(t, filterConf, forwardConf, nil)
|
s := createTestServer(t, filterConf, forwardConf, nil)
|
||||||
|
s.sysResolvers = &fakeSystemResolvers{}
|
||||||
|
|
||||||
defaultConf := s.conf
|
defaultConf := s.conf
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,12 @@
|
||||||
|
|
||||||
## v0.107: API changes
|
## v0.107: API changes
|
||||||
|
|
||||||
|
### The new field `"default_local_ptr_upstreams"` in `GET /control/dns_info`
|
||||||
|
|
||||||
|
* The new optional field `"default_local_ptr_upstreams"` is the list of IP
|
||||||
|
addresses AdGuard Home would use by default to resolve PTR request for
|
||||||
|
addresses from locally-served networks.
|
||||||
|
|
||||||
### The field `"use_private_ptr_resolvers"` in DNS configuration
|
### The field `"use_private_ptr_resolvers"` in DNS configuration
|
||||||
|
|
||||||
* The new optional field `"use_private_ptr_resolvers"` of `"DNSConfig"`
|
* The new optional field `"use_private_ptr_resolvers"` of `"DNSConfig"`
|
||||||
|
|
|
@ -69,7 +69,17 @@
|
||||||
'content':
|
'content':
|
||||||
'application/json':
|
'application/json':
|
||||||
'schema':
|
'schema':
|
||||||
'$ref': '#/components/schemas/DNSConfig'
|
'allOf':
|
||||||
|
- '$ref': '#/components/schemas/DNSConfig'
|
||||||
|
- 'type': 'object'
|
||||||
|
'properties':
|
||||||
|
'default_local_ptr_upstreams':
|
||||||
|
'type': 'array'
|
||||||
|
'items':
|
||||||
|
'type': 'string'
|
||||||
|
'example':
|
||||||
|
- '192.168.168.192'
|
||||||
|
- '10.0.0.10'
|
||||||
'/dns_config':
|
'/dns_config':
|
||||||
'post':
|
'post':
|
||||||
'tags':
|
'tags':
|
||||||
|
|
Loading…
Reference in New Issue