Skip to content

Commit

Permalink
Pull request 1744: 1472-edns-custom-ip
Browse files Browse the repository at this point in the history
Merge in DNS/adguard-home from 1472-edns-custom-ip to master

Updates #1472.

Squashed commit of the following:

commit 07460c3
Merge: 6545543 ae653f1
Author: Stanislav Chzhen <[email protected]>
Date:   Wed Mar 1 15:38:46 2023 +0300

    Merge branch 'master' into 1472-edns-custom-ip

commit 6545543
Author: Stanislav Chzhen <[email protected]>
Date:   Wed Mar 1 15:37:17 2023 +0300

    dnsforward: add todo

commit e1978ad
Merge: 6cd98f4 bb22643
Author: Stanislav Chzhen <[email protected]>
Date:   Wed Mar 1 11:32:23 2023 +0300

    Merge branch 'master' into 1472-edns-custom-ip

commit 6cd98f4
Author: Stanislav Chzhen <[email protected]>
Date:   Wed Mar 1 11:31:16 2023 +0300

    all: fix chlog; fix field alignment

commit defdec6
Merge: 1130ebd a772212
Author: Stanislav Chzhen <[email protected]>
Date:   Tue Feb 28 12:17:23 2023 +0300

    Merge branch 'master' into 1472-edns-custom-ip

commit 1130ebd
Author: Stanislav Chzhen <[email protected]>
Date:   Tue Feb 28 12:13:30 2023 +0300

    all: add use_custom field

commit ec0cdc7
Author: Stanislav Chzhen <[email protected]>
Date:   Mon Feb 27 13:59:13 2023 +0300

    all: fix chlog; imp code

commit f8450cf
Author: Stanislav Chzhen <[email protected]>
Date:   Mon Feb 27 11:28:16 2023 +0300

    dnsforward: fix fmt

commit 54a344e
Author: Stanislav Chzhen <[email protected]>
Date:   Mon Feb 27 11:11:52 2023 +0300

    all: fix chlog; add test case

commit 47b5476
Merge: 8724f37 304f2ba
Author: Stanislav Chzhen <[email protected]>
Date:   Wed Feb 22 16:33:07 2023 +0300

    Merge branch 'master' into 1472-edns-custom-ip

commit 8724f37
Author: Stanislav Chzhen <[email protected]>
Date:   Wed Feb 22 16:31:40 2023 +0300

    all: fix comments

commit d2b1528
Merge: 7898c23 76a513c
Author: Stanislav Chzhen <[email protected]>
Date:   Wed Feb 22 11:53:25 2023 +0300

    Merge branch 'master' into 1472-edns-custom-ip

commit 7898c23
Author: Stanislav Chzhen <[email protected]>
Date:   Wed Feb 22 11:52:37 2023 +0300

    all: upd chlog

commit 8763261
Merge: d28394b ff9b24a
Author: Stanislav Chzhen <[email protected]>
Date:   Tue Feb 21 17:12:03 2023 +0300

    Merge branch 'master' into 1472-edns-custom-ip

commit d28394b
Author: Stanislav Chzhen <[email protected]>
Date:   Tue Feb 21 17:11:29 2023 +0300

    home: fix default value

commit 1a5da3f
Author: Stanislav Chzhen <[email protected]>
Date:   Tue Feb 21 13:37:04 2023 +0300

    all: add custom ip for edns
  • Loading branch information
schzhn committed Mar 1, 2023
1 parent ae653f1 commit 012e5be
Show file tree
Hide file tree
Showing 10 changed files with 333 additions and 46 deletions.
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,43 @@ NOTE: Add new changes BELOW THIS COMMENT.

### Added

- The ability to set custom IP for EDNS Client Subnet by using the new
`dns.edns_client_subnet.use_custom` and `dns.edns_client_subnet.custom_ip`
fields ([#1472]). The UI changes are coming in the upcoming releases.
- The ability to use `dnstype` rules in the disallowed domains list ([#5468]).
This allows dropping requests based on their question types.

### Changed

#### Configuration Changes

In this release, the schema version has changed from 16 to 17.

- Property `edns_client_subnet`, which in schema versions 16 and earlier used
to be a part of the `dns` object, is now part of the `dns.edns_client_subnet`
object:

```yaml
# BEFORE:
'dns':
#
'edns_client_subnet': false

# AFTER:
'dns':
#
'edns_client_subnet':
'enabled': false
'use_custom': false
'custom_ip': ''
```
To rollback this change, move the value of `dns.edns_client_subnet.enabled`
into the `dns.edns_client_subnet`, remove the fields
`dns.edns_client_subnet.enabled`, `dns.edns_client_subnet.use_custom`,
`dns.edns_client_subnet.custom_ip`, and change the `schema_version` back to
`16`.

### Fixed

- Various dark theme bugs ([#5439], [#5441], [#5442], [#5515]).
Expand All @@ -37,6 +71,7 @@ NOTE: Add new changes BELOW THIS COMMENT.
been relaxed to meet those from [RFC 3696][rfc3696] ([#4884]).
- Failing service installation via script on FreeBSD ([#5431]).

[#1472]: https://github.com/AdguardTeam/AdGuardHome/issues/1472
[#4884]: https://github.com/AdguardTeam/AdGuardHome/issues/4884
[#5270]: https://github.com/AdguardTeam/AdGuardHome/issues/5270
[#5373]: https://github.com/AdguardTeam/AdGuardHome/issues/5373
Expand Down Expand Up @@ -129,6 +164,7 @@ In this release, the schema version has changed from 14 to 16.
'file_enabled': true
'interval': '2160h'
'size_memory': 1000
'ignored': []
```

To rollback this change, rename and move properties back into the `dns`
Expand Down
151 changes: 113 additions & 38 deletions internal/dnsforward/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ const (
// The zero FilteringConfig is empty and ready for use.
type FilteringConfig struct {
// Callbacks for other modules
// --

// FilterHandler is an optional additional filtering callback.
FilterHandler func(clientAddr net.IP, clientID string, settings *filtering.Settings) `yaml:"-"`
Expand All @@ -64,77 +63,129 @@ type FilteringConfig struct {
GetCustomUpstreamByClient func(id string) (conf *proxy.UpstreamConfig, err error) `yaml:"-"`

// Protection configuration
// --

ProtectionEnabled bool `yaml:"protection_enabled"` // whether or not use any of filtering features
BlockingMode BlockingMode `yaml:"blocking_mode"` // mode how to answer filtered requests
BlockingIPv4 net.IP `yaml:"blocking_ipv4"` // IP address to be returned for a blocked A request
BlockingIPv6 net.IP `yaml:"blocking_ipv6"` // IP address to be returned for a blocked AAAA request
BlockedResponseTTL uint32 `yaml:"blocked_response_ttl"` // if 0, then default is used (3600)
// ProtectionEnabled defines whether or not use any of filtering features.
ProtectionEnabled bool `yaml:"protection_enabled"`

// IP (or domain name) which is used to respond to DNS requests blocked by parental control or safe-browsing
ParentalBlockHost string `yaml:"parental_block_host"`
// BlockingMode defines the way how blocked responses are constructed.
BlockingMode BlockingMode `yaml:"blocking_mode"`

// BlockingIPv4 is the IP address to be returned for a blocked A request.
BlockingIPv4 net.IP `yaml:"blocking_ipv4"`

// BlockingIPv6 is the IP address to be returned for a blocked AAAA
// request.
BlockingIPv6 net.IP `yaml:"blocking_ipv6"`

// BlockedResponseTTL is the time-to-live value for blocked responses. If
// 0, then default value is used (3600).
BlockedResponseTTL uint32 `yaml:"blocked_response_ttl"`

// ParentalBlockHost is the IP (or domain name) which is used to respond to
// DNS requests blocked by parental control.
ParentalBlockHost string `yaml:"parental_block_host"`

// SafeBrowsingBlockHost is the IP (or domain name) which is used to
// respond to DNS requests blocked by safe-browsing.
SafeBrowsingBlockHost string `yaml:"safebrowsing_block_host"`

// Anti-DNS amplification
// --

Ratelimit uint32 `yaml:"ratelimit"` // max number of requests per second from a given IP (0 to disable)
RatelimitWhitelist []string `yaml:"ratelimit_whitelist"` // a list of whitelisted client IP addresses
RefuseAny bool `yaml:"refuse_any"` // if true, refuse ANY requests
// Ratelimit is the maximum number of requests per second from a given IP
// (0 to disable).
Ratelimit uint32 `yaml:"ratelimit"`

// RatelimitWhitelist is the list of whitelisted client IP addresses.
RatelimitWhitelist []string `yaml:"ratelimit_whitelist"`

// RefuseAny, if true, refuse ANY requests.
RefuseAny bool `yaml:"refuse_any"`

// Upstream DNS servers configuration
// --

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
// UpstreamDNS is the list of upstream DNS servers.
UpstreamDNS []string `yaml:"upstream_dns"`

// UpstreamDNSFileName, if set, points to the file which contains upstream
// DNS servers.
UpstreamDNSFileName string `yaml:"upstream_dns_file"`

// BootstrapDNS is the list of bootstrap DNS servers for DoH and DoT
// resolvers (plain DNS only).
BootstrapDNS []string `yaml:"bootstrap_dns"`

// AllServers, if true, parallel queries to all configured upstream servers
// are enabled.
AllServers bool `yaml:"all_servers"`

// FastestAddr, if true, use Fastest Address algorithm.
FastestAddr bool `yaml:"fastest_addr"`

// FastestTimeout replaces the default timeout for dialing IP addresses
// when FastestAddr is true.
FastestTimeout timeutil.Duration `yaml:"fastest_timeout"`

// Access settings
// --

// AllowedClients is the slice of IP addresses, CIDR networks, and ClientIDs
// of allowed clients. If not empty, only these clients are allowed, and
// [FilteringConfig.DisallowedClients] are ignored.
// AllowedClients is the slice of IP addresses, CIDR networks, and
// ClientIDs of allowed clients. If not empty, only these clients are
// allowed, and [FilteringConfig.DisallowedClients] are ignored.
AllowedClients []string `yaml:"allowed_clients"`

// DisallowedClients is the slice of IP addresses, CIDR networks, and
// ClientIDs of disallowed clients.
DisallowedClients []string `yaml:"disallowed_clients"`

BlockedHosts []string `yaml:"blocked_hosts"` // hosts that should be blocked
// BlockedHosts is the list of hosts that should be blocked.
BlockedHosts []string `yaml:"blocked_hosts"`

// TrustedProxies is the list of IP addresses and CIDR networks to detect
// proxy servers addresses the DoH requests from which should be handled.
// The value of nil or an empty slice for this field makes Proxy not trust
// any address.
TrustedProxies []string `yaml:"trusted_proxies"`

// DNS cache settings
// --

CacheSize uint32 `yaml:"cache_size"` // DNS cache size (in bytes)
CacheMinTTL uint32 `yaml:"cache_ttl_min"` // override TTL value (minimum) received from upstream server
CacheMaxTTL uint32 `yaml:"cache_ttl_max"` // override TTL value (maximum) received from upstream server
// CacheSize is the DNS cache size (in bytes).
CacheSize uint32 `yaml:"cache_size"`

// CacheMinTTL is the override TTL value (minimum) received from upstream
// server.
CacheMinTTL uint32 `yaml:"cache_ttl_min"`

// CacheMaxTTL is the override TTL value (maximum) received from upstream
// server.
CacheMaxTTL uint32 `yaml:"cache_ttl_max"`

// CacheOptimistic defines if optimistic cache mechanism should be used.
CacheOptimistic bool `yaml:"cache_optimistic"`

// Other settings
// --

BogusNXDomain []string `yaml:"bogus_nxdomain"` // transform responses with these IP addresses to NXDOMAIN
AAAADisabled bool `yaml:"aaaa_disabled"` // Respond with an empty answer to all AAAA requests
EnableDNSSEC bool `yaml:"enable_dnssec"` // Set AD flag in outcoming DNS request
EnableEDNSClientSubnet bool `yaml:"edns_client_subnet"` // Enable EDNS Client Subnet option
MaxGoroutines uint32 `yaml:"max_goroutines"` // Max. number of parallel goroutines for processing incoming requests
HandleDDR bool `yaml:"handle_ddr"` // Handle DDR requests
// BogusNXDomain is the list of IP addresses, responses with them will be
// transformed to NXDOMAIN.
BogusNXDomain []string `yaml:"bogus_nxdomain"`

// AAAADisabled, if true, respond with an empty answer to all AAAA
// requests.
AAAADisabled bool `yaml:"aaaa_disabled"`

// EnableDNSSEC, if true, set AD flag in outcoming DNS request.
EnableDNSSEC bool `yaml:"enable_dnssec"`

// EDNSClientSubnet is the settings list for EDNS Client Subnet.
EDNSClientSubnet *EDNSClientSubnet `yaml:"edns_client_subnet"`

// IpsetList is the ipset configuration that allows AdGuard Home to add
// IP addresses of the specified domain names to an ipset list. Syntax:
// MaxGoroutines is the max number of parallel goroutines for processing
// incoming requests.
MaxGoroutines uint32 `yaml:"max_goroutines"`

// HandleDDR, if true, handle DDR requests
HandleDDR bool `yaml:"handle_ddr"`

// IpsetList is the ipset configuration that allows AdGuard Home to add IP
// addresses of the specified domain names to an ipset list. Syntax:
//
// DOMAIN[,DOMAIN].../IPSET_NAME
//
Expand All @@ -146,6 +197,18 @@ type FilteringConfig struct {
IpsetListFileName string `yaml:"ipset_file"`
}

// EDNSClientSubnet is the settings list for EDNS Client Subnet.
type EDNSClientSubnet struct {
// CustomIP for EDNS Client Subnet.
CustomIP string `yaml:"custom_ip"`

// Enabled defines if EDNS Client Subnet is enabled.
Enabled bool `yaml:"enabled"`

// UseCustom defines if CustomIP should be used.
UseCustom bool `yaml:"use_custom"`
}

// TLSConfig is the TLS configuration for HTTPS, DNS-over-HTTPS, and DNS-over-TLS
type TLSConfig struct {
cert tls.Certificate
Expand Down Expand Up @@ -270,12 +333,24 @@ func (s *Server) createProxyConfig() (conf proxy.Config, err error) {
UpstreamConfig: srvConf.UpstreamConfig,
BeforeRequestHandler: s.beforeRequestHandler,
RequestHandler: s.handleDNSRequest,
EnableEDNSClientSubnet: srvConf.EnableEDNSClientSubnet,
EnableEDNSClientSubnet: srvConf.EDNSClientSubnet.Enabled,
MaxGoroutines: int(srvConf.MaxGoroutines),
UseDNS64: srvConf.UseDNS64,
DNS64Prefs: srvConf.DNS64Prefixes,
}

if srvConf.EDNSClientSubnet.UseCustom {
// TODO(s.chzhen): Add wrapper around netip.Addr.
var ip net.IP
ip, err = netutil.ParseIP(srvConf.EDNSClientSubnet.CustomIP)
if err != nil {
return conf, fmt.Errorf("edns: %w", err)
}

// TODO(s.chzhen): Use netip.Addr instead of net.IP inside dnsproxy.
conf.EDNSAddr = ip
}

if srvConf.CacheSize != 0 {
conf.CacheEnabled = true
conf.CacheSizeBytes = int(srvConf.CacheSize)
Expand Down
3 changes: 3 additions & 0 deletions internal/dnsforward/dns64_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,9 @@ func TestServer_HandleDNSRequest_dns64(t *testing.T) {
UDPListenAddrs: []*net.UDPAddr{{}},
TCPListenAddrs: []*net.TCPAddr{{}},
UseDNS64: true,
FilteringConfig: FilteringConfig{
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
},
}, localUps)

t.Run(tc.name, func(t *testing.T) {
Expand Down
8 changes: 8 additions & 0 deletions internal/dnsforward/dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,11 @@ func TestServer_ProcessRestrictLocal(t *testing.T) {
s := createTestServer(t, &filtering.Config{}, ServerConfig{
UDPListenAddrs: []*net.UDPAddr{{}},
TCPListenAddrs: []*net.TCPAddr{{}},
// TODO(s.chzhen): Add tests where EDNSClientSubnet.Enabled is true.
// Improve FilteringConfig declaration for tests.
FilteringConfig: FilteringConfig{
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
},
}, ups)
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{ups}
startDeferStop(t, s)
Expand Down Expand Up @@ -539,6 +544,9 @@ func TestServer_ProcessLocalPTR_usingResolvers(t *testing.T) {
ServerConfig{
UDPListenAddrs: []*net.UDPAddr{{}},
TCPListenAddrs: []*net.TCPAddr{{}},
FilteringConfig: FilteringConfig{
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
},
},
aghtest.NewUpstreamMock(func(req *dns.Msg) (resp *dns.Msg, err error) {
return aghalg.Coalesce(
Expand Down
Loading

0 comments on commit 012e5be

Please sign in to comment.