Skip to content

Commit

Permalink
Pull request: 2704 local addresses vol.3
Browse files Browse the repository at this point in the history
Merge in DNS/adguard-home from 2704-local-addresses-vol.3 to master

Updates AdguardTeam#2704.
Updates AdguardTeam#2829.
Updates AdguardTeam#2928.

Squashed commit of the following:

commit 8c42355
Author: Eugene Burkov <[email protected]>
Date:   Wed Apr 7 18:07:41 2021 +0300

    dnsforward: rm errors pkg

commit 7594a21
Merge: 830b083 908452f
Author: Eugene Burkov <[email protected]>
Date:   Wed Apr 7 18:00:03 2021 +0300

    Merge branch 'master' into 2704-local-addresses-vol.3

commit 830b083
Author: Eugene Burkov <[email protected]>
Date:   Wed Apr 7 17:47:51 2021 +0300

    dnsforward: reduce local upstream timeout

commit 493e81d
Author: Ildar Kamalov <[email protected]>
Date:   Tue Apr 6 19:11:00 2021 +0300

    client: private_upstream test

commit a0194ac
Author: Eugene Burkov <[email protected]>
Date:   Tue Apr 6 18:36:23 2021 +0300

    all: expand api, fix conflicts

commit 0f4e068
Merge: 89cf93a 8746005
Author: Eugene Burkov <[email protected]>
Date:   Tue Apr 6 18:35:04 2021 +0300

    Merge branch 'master' into 2704-local-addresses-vol.3

commit 89cf93a
Author: Ildar Kamalov <[email protected]>
Date:   Tue Apr 6 18:02:40 2021 +0300

    client: add local ptr upstreams to upstream test

commit e6dd869
Author: Ildar Kamalov <[email protected]>
Date:   Tue Apr 6 15:24:22 2021 +0300

    client: add private DNS form

commit b858057
Author: Eugene Burkov <[email protected]>
Date:   Tue Apr 6 13:05:28 2021 +0300

    aghstrings: mk cloning correct

commit 8009ba6
Author: Eugene Burkov <[email protected]>
Date:   Tue Apr 6 12:37:46 2021 +0300

    aghstrings: fix lil bug

commit 0dd19f2
Author: Eugene Burkov <[email protected]>
Date:   Mon Apr 5 20:45:01 2021 +0300

    all: log changes

commit eb5558d
Author: Eugene Burkov <[email protected]>
Date:   Mon Apr 5 20:18:53 2021 +0300

    dnsforward: keep the style

commit d6d5fcb
Author: Eugene Burkov <[email protected]>
Date:   Mon Apr 5 20:02:52 2021 +0300

    dnsforward: disable redundant filtering for local ptr

commit 4f864c3
Author: Eugene Burkov <[email protected]>
Date:   Mon Apr 5 17:53:17 2021 +0300

    dnsforward: imp tests

commit 7848e6f
Author: Eugene Burkov <[email protected]>
Date:   Mon Apr 5 14:52:12 2021 +0300

    all: imp code

commit 19ac306
Author: Eugene Burkov <[email protected]>
Date:   Sun Apr 4 16:28:05 2021 +0300

    all: mv more logic to aghstrings

commit fac892e
Author: Eugene Burkov <[email protected]>
Date:   Fri Apr 2 20:23:23 2021 +0300

    dnsforward: use filepath

commit 05a3aee
Author: Eugene Burkov <[email protected]>
Date:   Fri Apr 2 20:17:54 2021 +0300

    aghstrings: introduce the pkg

commit f24e1b6
Author: Eugene Burkov <[email protected]>
Date:   Fri Apr 2 20:01:23 2021 +0300

    all: imp code

commit 0217a0e
Author: Eugene Burkov <[email protected]>
Date:   Fri Apr 2 18:04:13 2021 +0300

    openapi: log changes

... and 3 more commits
  • Loading branch information
EugeneOne1 authored and heyxkhoa committed Mar 17, 2023
1 parent c2e12ec commit 8a1f181
Show file tree
Hide file tree
Showing 40 changed files with 1,619 additions and 587 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ and this project adheres to

### Added

- The ability to set up custom upstreams to resolve PTR queries for local
addresses and to disable the automatic resolving of clients' addresses
([#2704]).
- Logging of the client's IP address after failed login attempts ([#2824]).
- Search by clients' names in the query log ([#1273]).
- Verbose version output with `-v --version` ([#2416]).
Expand Down
5 changes: 5 additions & 0 deletions client/src/__locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
"load_balancing_desc": "Query one upstream server at a time. AdGuard Home will use the weighted random algorithm to pick the server so that the fastest server is used more often.",
"bootstrap_dns": "Bootstrap DNS servers",
"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 DNS servers",
"local_ptr_desc": "The DNS server or servers that AdGuard Home will use for queries for locally served resources. For instance, this server will be used for resolving clients' hostnames for the clients with private IP addresses. If not set, AdGuard Home will automatically use your default DNS resolver.",
"local_ptr_placeholder": "Enter one server address per line",
"resolve_clients_title": "Enable clients' hostnames resolution",
"resolve_clients_desc": "If enabled, AdGuard Home will attempt to automatically resolve clients' hostnames from their IP addresses by sending a PTR query to a corresponding resolver (private DNS server for local clients, upstream server for clients with public IP).",
"check_dhcp_servers": "Check for DHCP servers",
"save_config": "Save configuration",
"enabled_dhcp": "DHCP server enabled",
Expand Down
4 changes: 4 additions & 0 deletions client/src/actions/dnsConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ export const setDnsConfig = (config) => async (dispatch) => {
data.bootstrap_dns = splitByNewLine(config.bootstrap_dns);
hasDnsSettings = true;
}
if (Object.prototype.hasOwnProperty.call(data, 'local_ptr_upstreams')) {
data.local_ptr_upstreams = splitByNewLine(config.local_ptr_upstreams);
hasDnsSettings = true;
}
if (Object.prototype.hasOwnProperty.call(data, 'upstream_dns')) {
data.upstream_dns = splitByNewLine(config.upstream_dns);
hasDnsSettings = true;
Expand Down
16 changes: 13 additions & 3 deletions client/src/actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -296,14 +296,15 @@ export const testUpstreamFailure = createAction('TEST_UPSTREAM_FAILURE');
export const testUpstreamSuccess = createAction('TEST_UPSTREAM_SUCCESS');

export const testUpstream = (
{ bootstrap_dns, upstream_dns }, upstream_dns_file,
{ bootstrap_dns, upstream_dns, local_ptr_upstreams }, upstream_dns_file,
) => async (dispatch) => {
dispatch(testUpstreamRequest());
try {
const removeComments = compose(filterOutComments, splitByNewLine);

const config = {
bootstrap_dns: splitByNewLine(bootstrap_dns),
private_upstream: splitByNewLine(local_ptr_upstreams),
...(upstream_dns_file ? null : {
upstream_dns: removeComments(upstream_dns),
}),
Expand Down Expand Up @@ -332,8 +333,17 @@ export const testUpstream = (

export const testUpstreamWithFormValues = () => async (dispatch, getState) => {
const { upstream_dns_file } = getState().dnsConfig;
const { bootstrap_dns, upstream_dns } = getState().form[FORM_NAME.UPSTREAM].values;
return dispatch(testUpstream({ bootstrap_dns, upstream_dns }, upstream_dns_file));
const {
bootstrap_dns,
upstream_dns,
local_ptr_upstreams,
} = getState().form[FORM_NAME.UPSTREAM].values;

return dispatch(testUpstream({
bootstrap_dns,
upstream_dns,
local_ptr_upstreams,
}, upstream_dns_file));
};

export const changeLanguageRequest = createAction('CHANGE_LANGUAGE_REQUEST');
Expand Down
56 changes: 46 additions & 10 deletions client/src/components/Settings/Dns/Upstream/Form.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Field, reduxForm } from 'redux-form';
import { Trans, useTranslation } from 'react-i18next';
import classnames from 'classnames';
import Examples from './Examples';
import { renderRadioField, renderTextareaField } from '../../../../helpers/form';
import { renderRadioField, renderTextareaField, CheckboxField } from '../../../../helpers/form';
import {
DNS_REQUEST_OPTIONS,
FORM_NAME,
Expand All @@ -28,11 +28,12 @@ const renderField = ({
const processingTestUpstream = useSelector((state) => state.settings.processingTestUpstream);
const processingSetConfig = useSelector((state) => state.dnsConfig.processingSetConfig);

return <div
return (
<div
key={placeholder}
className={classnames('col-12 mb-4', containerClass)}
>
<Field
>
<Field
id={name}
value={value}
name={name}
Expand All @@ -44,8 +45,9 @@ const renderField = ({
disabled={processingSetConfig || processingTestUpstream}
normalizeOnBlur={normalizeOnBlur}
onScroll={onScroll}
/>
</div>;
/>
</div>
);
};

renderField.propTypes = {
Expand Down Expand Up @@ -160,10 +162,10 @@ const Form = ({
{' '}
<Trans components={[
<a
href="https://kb.adguard.com/general/dns-providers"
target="_blank"
rel="noopener noreferrer"
key="0"
href="https://kb.adguard.com/general/dns-providers"
target="_blank"
rel="noopener noreferrer"
key="0"
>
DNS providers
</a>,
Expand Down Expand Up @@ -197,6 +199,40 @@ const Form = ({
normalizeOnBlur={removeEmptyLines}
/>
</div>
<div className="col-12">
<hr />
</div>
<div className="col-12 mb-4">
<label
className="form__label form__label--with-desc"
htmlFor="local_ptr"
>
<Trans>local_ptr_title</Trans>
</label>
<div className="form__desc form__desc--top">
<Trans>local_ptr_desc</Trans>
</div>
<Field
id="local_ptr_upstreams"
name="local_ptr_upstreams"
component={renderTextareaField}
type="text"
className="form-control form-control--textarea form-control--textarea-small font-monospace"
placeholder={t('local_ptr_placeholder')}
disabled={processingSetConfig}
normalizeOnBlur={removeEmptyLines}
/>
</div>
<div className="col-12 mb-4">
<Field
name="resolve_clients"
type="checkbox"
component={CheckboxField}
placeholder={t('resolve_clients_title')}
subtitle={t('resolve_clients_desc')}
disabled={processingSetConfig}
/>
</div>
</div>
<div className="card-actions">
<div className="btn-list">
Expand Down
8 changes: 8 additions & 0 deletions client/src/components/Settings/Dns/Upstream/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ const Upstream = () => {
upstream_dns,
bootstrap_dns,
upstream_mode,
resolve_clients,
local_ptr_upstreams,
} = useSelector((state) => state.dnsConfig, shallowEqual);

const upstream_dns_file = useSelector((state) => state.dnsConfig.upstream_dns_file);
Expand All @@ -21,11 +23,15 @@ const Upstream = () => {
bootstrap_dns,
upstream_dns,
upstream_mode,
resolve_clients,
local_ptr_upstreams,
} = values;

const dnsConfig = {
bootstrap_dns,
upstream_mode,
resolve_clients,
local_ptr_upstreams,
...(upstream_dns_file ? null : { upstream_dns }),
};

Expand All @@ -45,6 +51,8 @@ const Upstream = () => {
upstream_dns: upstreamDns,
bootstrap_dns,
upstream_mode,
resolve_clients,
local_ptr_upstreams,
}}
onSubmit={handleSubmit}
/>
Expand Down
2 changes: 2 additions & 0 deletions client/src/reducers/dnsConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const dnsConfig = handleActions(
blocking_ipv6,
upstream_dns,
bootstrap_dns,
local_ptr_upstreams,
...values
} = payload;

Expand All @@ -26,6 +27,7 @@ const dnsConfig = handleActions(
blocking_ipv6: blocking_ipv6 || DEFAULT_BLOCKING_IPV6,
upstream_dns: (upstream_dns && upstream_dns.join('\n')) || '',
bootstrap_dns: (bootstrap_dns && bootstrap_dns.join('\n')) || '',
local_ptr_upstreams: (local_ptr_upstreams && local_ptr_upstreams.join('\n')) || '',
processingGetConfig: false,
};
},
Expand Down
3 changes: 2 additions & 1 deletion internal/agherr/agherr.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ func (e *manyError) Error() (msg string) {
b := &strings.Builder{}

// Ignore errors, since strings.(*Buffer).Write never returns
// errors.
// errors. We don't use aghstrings.WriteToBuilder here since
// this package should be importable for any other.
_, _ = fmt.Fprintf(b, "%s: %s (hidden: %s", e.message, e.underlying[0], e.underlying[1])
for _, u := range e.underlying[2:] {
// See comment above.
Expand Down
11 changes: 9 additions & 2 deletions internal/aghnet/exchanger.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ type multiAddrExchanger struct {

// NewMultiAddrExchanger creates an Exchanger instance from passed addresses.
// It returns an error if any of addrs failed to become an upstream.
func NewMultiAddrExchanger(addrs []string, timeout time.Duration) (e Exchanger, err error) {
func NewMultiAddrExchanger(
addrs []string,
bootstraps []string,
timeout time.Duration,
) (e Exchanger, err error) {
defer agherr.Annotate("exchanger: %w", &err)

if len(addrs) == 0 {
Expand All @@ -41,7 +45,10 @@ func NewMultiAddrExchanger(addrs []string, timeout time.Duration) (e Exchanger,
var ups []upstream.Upstream = make([]upstream.Upstream, 0, len(addrs))
for _, addr := range addrs {
var u upstream.Upstream
u, err = upstream.AddressToUpstream(addr, upstream.Options{Timeout: timeout})
u, err = upstream.AddressToUpstream(addr, upstream.Options{
Bootstrap: bootstraps,
Timeout: timeout,
})
if err != nil {
return nil, err
}
Expand Down
6 changes: 3 additions & 3 deletions internal/aghnet/exchanger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,19 @@ func TestNewMultiAddrExchanger(t *testing.T) {
var err error

t.Run("empty", func(t *testing.T) {
e, err = NewMultiAddrExchanger([]string{}, 0)
e, err = NewMultiAddrExchanger([]string{}, nil, 0)
require.NoError(t, err)
assert.NotNil(t, e)
})

t.Run("successful", func(t *testing.T) {
e, err = NewMultiAddrExchanger([]string{"www.example.com"}, 0)
e, err = NewMultiAddrExchanger([]string{"www.example.com"}, nil, 0)
require.NoError(t, err)
assert.NotNil(t, e)
})

t.Run("unsuccessful", func(t *testing.T) {
e, err = NewMultiAddrExchanger([]string{"invalid-proto://www.example.com"}, 0)
e, err = NewMultiAddrExchanger([]string{"invalid-proto://www.example.com"}, nil, 0)
require.Error(t, err)
assert.Nil(t, e)
})
Expand Down
54 changes: 43 additions & 11 deletions internal/aghnet/net.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"time"

"github.com/AdguardTeam/AdGuardHome/internal/agherr"
"github.com/AdguardTeam/AdGuardHome/internal/aghstrings"
"github.com/AdguardTeam/golibs/log"
)

Expand Down Expand Up @@ -355,30 +356,30 @@ const (
// (PTR) record lookups. This is the modified version of ReverseAddr from
// github.com/miekg/dns package with no error among returned values.
func ReverseAddr(ip net.IP) (arpa string) {
const dot = "."

var strLen int
var suffix string
// Don't handle errors in implementations since strings.WriteString
// never returns non-nil errors.
var writeByte func(val byte)
b := &strings.Builder{}
if ip4 := ip.To4(); ip4 != nil {
strLen, suffix = arpaV4MaxLen, arpaV4Suffix[1:]
ip = ip4
writeByte = func(val byte) {
_, _ = b.WriteString(strconv.Itoa(int(val)))
_, _ = b.WriteRune('.')
aghstrings.WriteToBuilder(b, strconv.Itoa(int(val)), dot)
}

} else if ip6 := ip.To16(); ip6 != nil {
strLen, suffix = arpaV6MaxLen, arpaV6Suffix[1:]
ip = ip6
writeByte = func(val byte) {
lByte, rByte := val&0xF, val>>4

_, _ = b.WriteString(strconv.FormatUint(uint64(lByte), 16))
_, _ = b.WriteRune('.')
_, _ = b.WriteString(strconv.FormatUint(uint64(rByte), 16))
_, _ = b.WriteRune('.')
aghstrings.WriteToBuilder(
b,
strconv.FormatUint(uint64(val&0xF), 16),
dot,
strconv.FormatUint(uint64(val>>4), 16),
dot,
)
}

} else {
Expand All @@ -389,7 +390,38 @@ func ReverseAddr(ip net.IP) (arpa string) {
for i := len(ip) - 1; i >= 0; i-- {
writeByte(ip[i])
}
_, _ = b.WriteString(suffix)
aghstrings.WriteToBuilder(b, suffix)

return b.String()
}

// CollectAllIfacesAddrs returns the slice of all network interfaces IP
// addresses without port number.
func CollectAllIfacesAddrs() (addrs []string, err error) {
var ifaces []net.Interface
ifaces, err = net.Interfaces()
if err != nil {
return nil, fmt.Errorf("getting network interfaces: %w", err)
}

for _, iface := range ifaces {
var ifaceAddrs []net.Addr
ifaceAddrs, err = iface.Addrs()
if err != nil {
return nil, fmt.Errorf("getting addresses for %q: %w", iface.Name, err)
}

for _, addr := range ifaceAddrs {
cidr := addr.String()
var ip net.IP
ip, _, err = net.ParseCIDR(cidr)
if err != nil {
return nil, fmt.Errorf("parsing cidr: %w", err)
}

addrs = append(addrs, ip.String())
}
}

return addrs, nil
}
Loading

0 comments on commit 8a1f181

Please sign in to comment.