Pull request 1979: AG-25263 filtering config
Squashed commit of the following: commit a5607f811ab4642a0e34d3042240e3a9aafc3d84 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Aug 30 15:44:26 2023 +0300 home: upgrade yaml commit 0593e4da17613b8770c4567fdd5fbfde31631e6f Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Aug 30 15:01:14 2023 +0300 home: upgrade yaml commit 59ec4ba0bbe59fb2e95290f4f8101891ce4ff959 Merge: 6555941f5a325c9b6b
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Aug 30 14:57:41 2023 +0300 Merge remote-tracking branch 'origin/master' into AG-25263-filtering-config # Conflicts: # internal/dnsforward/http.go # internal/dnsforward/http_test.go # internal/dnsforward/process.go # internal/dnsforward/process_internal_test.go commit 6555941f57e99aa8bc2473b8be9e4f096ce665e0 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Aug 30 14:38:01 2023 +0300 docs: changelog commit c66d14cecbb1f08869a90c46e58d08ec03e29de5 Merge: a50ff1622aac36a2d2
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Aug 30 12:58:41 2023 +0300 Merge remote-tracking branch 'origin/master' into AG-25263-filtering-config commit a50ff162291f7953912c1bb195bd7b5d802d0ab3 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Aug 30 11:22:12 2023 +0300 home: imp code commit ef40d073e00d6acb164c0d680ed9971c4e75fbb7 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Aug 29 16:19:14 2023 +0300 home: imp code commit 5fa09a95e901a72dc5d2a90ba47c96842152587b Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Aug 29 14:47:48 2023 +0300 home: imp code commit 52bb295120f468faf94c953d0e795d1d58696ef1 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Aug 29 13:33:01 2023 +0300 home: imp code commit 24cfccf071385d660aeba4ced744ebbacc819686 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Aug 29 12:24:20 2023 +0300 filtering: imp code commit 758242b69ee5f351b25407340f989ec6b90d3607 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Tue Aug 29 10:32:51 2023 +0300 home: imp code commit 906deaa3bf86af5038fb05a54c34cc9511500ac9 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Aug 28 14:46:01 2023 +0300 dnsforward: imp code commit 978bb508349cd0b6a1a0bd3df5b879b6a4dd9e29 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Aug 28 14:40:31 2023 +0300 home: imp code commit d5b8dd5c930b0ccbe612f320a9908f2849370fd4 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Aug 28 12:34:32 2023 +0300 filtering: imp code commit d3e5726df6bc93112329ec81bc83932ccf64b8de Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Aug 28 11:57:33 2023 +0300 home: upgrade yaml commit 75d701553595786d5695540c001e6d46153351a9 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Aug 28 11:46:55 2023 +0300 home: upgrade yaml commit cd8cb623b0e6eb00fd05fb62b7445ca4315b94e0 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Aug 28 11:29:16 2023 +0300 docs: changelog commit 31c098d6f8d68a4afa30246c8d067a1ef4586de9 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Aug 28 11:08:48 2023 +0300 docs: changelog commit 24c88dd5d42b0168a13ea11b3f760eae1e804558 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Sun Aug 27 19:12:55 2023 +0300 home: imp code commit 94f2d386c9c1b6be5df06525078c90a3d068641f Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Sun Aug 27 16:15:05 2023 +0300 home: upgrade yaml ... and 10 more commits
This commit is contained in:
parent
a325c9b6bb
commit
a2ca8b5b4a
72
CHANGELOG.md
72
CHANGELOG.md
|
@ -46,7 +46,77 @@ NOTE: Add new changes BELOW THIS COMMENT.
|
||||||
|
|
||||||
#### Configuration Changes
|
#### Configuration Changes
|
||||||
|
|
||||||
In this release, the schema version has changed from 24 to 25.
|
In this release, the schema version has changed from 24 to 26.
|
||||||
|
|
||||||
|
- Filtering-related settings have been moved from `dns` section of the YAML
|
||||||
|
configuration file to the new section `filtering`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# BEFORE:
|
||||||
|
'dns':
|
||||||
|
'filtering_enabled': true
|
||||||
|
'filters_update_interval': 24
|
||||||
|
'parental_enabled': false
|
||||||
|
'safebrowsing_enabled': false
|
||||||
|
'safebrowsing_cache_size': 1048576
|
||||||
|
'safesearch_cache_size': 1048576
|
||||||
|
'parental_cache_size': 1048576
|
||||||
|
'safe_search':
|
||||||
|
'enabled': false
|
||||||
|
'bing': true
|
||||||
|
'duckduckgo': true
|
||||||
|
'google': true
|
||||||
|
'pixabay': true
|
||||||
|
'yandex': true
|
||||||
|
'youtube': true
|
||||||
|
'rewrites': []
|
||||||
|
'blocked_services':
|
||||||
|
'schedule':
|
||||||
|
'time_zone': 'Local'
|
||||||
|
'ids': []
|
||||||
|
'protection_enabled': true,
|
||||||
|
'blocking_mode': 'custom_ip',
|
||||||
|
'blocking_ipv4': '1.2.3.4',
|
||||||
|
'blocking_ipv6': '1:2:3::4',
|
||||||
|
'blocked_response_ttl': 10,
|
||||||
|
'protection_disabled_until': 'null',
|
||||||
|
'parental_block_host': 'p.dns.adguard.com',
|
||||||
|
'safebrowsing_block_host': 's.dns.adguard.com'
|
||||||
|
|
||||||
|
# AFTER:
|
||||||
|
'filtering':
|
||||||
|
'filtering_enabled': true
|
||||||
|
'filters_update_interval': 24
|
||||||
|
'parental_enabled': false
|
||||||
|
'safebrowsing_enabled': false
|
||||||
|
'safebrowsing_cache_size': 1048576
|
||||||
|
'safesearch_cache_size': 1048576
|
||||||
|
'parental_cache_size': 1048576
|
||||||
|
'safe_search':
|
||||||
|
'enabled': false
|
||||||
|
'bing': true
|
||||||
|
'duckduckgo': true
|
||||||
|
'google': true
|
||||||
|
'pixabay': true
|
||||||
|
'yandex': true
|
||||||
|
'youtube': true
|
||||||
|
'rewrites': []
|
||||||
|
'blocked_services':
|
||||||
|
'schedule':
|
||||||
|
'time_zone': 'Local'
|
||||||
|
'ids': []
|
||||||
|
'protection_enabled': true,
|
||||||
|
'blocking_mode': 'custom_ip',
|
||||||
|
'blocking_ipv4': '1.2.3.4',
|
||||||
|
'blocking_ipv6': '1:2:3::4',
|
||||||
|
'blocked_response_ttl': 10,
|
||||||
|
'protection_disabled_until': 'null',
|
||||||
|
'parental_block_host': 'p.dns.adguard.com',
|
||||||
|
'safebrowsing_block_host': 's.dns.adguard.com',
|
||||||
|
```
|
||||||
|
|
||||||
|
To rollback this change, remove the new object `filtering`, set back filtering
|
||||||
|
properties in `dns` section, and change the `schema_version` back to `25`.
|
||||||
|
|
||||||
- Property `debug_pprof` which used to setup profiling HTTP handler, is now
|
- Property `debug_pprof` which used to setup profiling HTTP handler, is now
|
||||||
moved to the new `pprof` object under `http` section. The new object contains
|
moved to the new `pprof` object under `http` section. The new object contains
|
||||||
|
|
|
@ -25,33 +25,9 @@ import (
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
)
|
)
|
||||||
|
|
||||||
// BlockingMode is an enum of all allowed blocking modes.
|
// Config represents the DNS filtering configuration of AdGuard Home. The zero
|
||||||
type BlockingMode string
|
// Config is empty and ready for use.
|
||||||
|
type Config struct {
|
||||||
// Allowed blocking modes.
|
|
||||||
const (
|
|
||||||
// BlockingModeCustomIP means respond with a custom IP address.
|
|
||||||
BlockingModeCustomIP BlockingMode = "custom_ip"
|
|
||||||
|
|
||||||
// BlockingModeDefault is the same as BlockingModeNullIP for
|
|
||||||
// Adblock-style rules, but responds with the IP address specified in
|
|
||||||
// the rule when blocked by an `/etc/hosts`-style rule.
|
|
||||||
BlockingModeDefault BlockingMode = "default"
|
|
||||||
|
|
||||||
// BlockingModeNullIP means respond with a zero IP address: "0.0.0.0"
|
|
||||||
// for A requests and "::" for AAAA ones.
|
|
||||||
BlockingModeNullIP BlockingMode = "null_ip"
|
|
||||||
|
|
||||||
// BlockingModeNXDOMAIN means respond with the NXDOMAIN code.
|
|
||||||
BlockingModeNXDOMAIN BlockingMode = "nxdomain"
|
|
||||||
|
|
||||||
// BlockingModeREFUSED means respond with the REFUSED code.
|
|
||||||
BlockingModeREFUSED BlockingMode = "refused"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FilteringConfig represents the DNS filtering configuration of AdGuard Home
|
|
||||||
// The zero FilteringConfig is empty and ready for use.
|
|
||||||
type FilteringConfig struct {
|
|
||||||
// Callbacks for other modules
|
// Callbacks for other modules
|
||||||
|
|
||||||
// FilterHandler is an optional additional filtering callback.
|
// FilterHandler is an optional additional filtering callback.
|
||||||
|
@ -62,37 +38,6 @@ type FilteringConfig struct {
|
||||||
// nil if there are no custom upstreams for the client.
|
// nil if there are no custom upstreams for the client.
|
||||||
GetCustomUpstreamByClient func(id string) (conf *proxy.UpstreamConfig, err error) `yaml:"-"`
|
GetCustomUpstreamByClient func(id string) (conf *proxy.UpstreamConfig, err error) `yaml:"-"`
|
||||||
|
|
||||||
// Protection configuration
|
|
||||||
|
|
||||||
// ProtectionEnabled defines whether or not use any of filtering features.
|
|
||||||
ProtectionEnabled bool `yaml:"protection_enabled"`
|
|
||||||
|
|
||||||
// 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 netip.Addr `yaml:"blocking_ipv4"`
|
|
||||||
|
|
||||||
// BlockingIPv6 is the IP address to be returned for a blocked AAAA
|
|
||||||
// request.
|
|
||||||
BlockingIPv6 netip.Addr `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"`
|
|
||||||
|
|
||||||
// ProtectionDisabledUntil is the timestamp until when the protection is
|
|
||||||
// disabled.
|
|
||||||
ProtectionDisabledUntil *time.Time `yaml:"protection_disabled_until"`
|
|
||||||
|
|
||||||
// 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
|
// Anti-DNS amplification
|
||||||
|
|
||||||
// Ratelimit is the maximum number of requests per second from a given IP
|
// Ratelimit is the maximum number of requests per second from a given IP
|
||||||
|
@ -137,7 +82,7 @@ type FilteringConfig struct {
|
||||||
|
|
||||||
// AllowedClients is the slice of IP addresses, CIDR networks, and
|
// AllowedClients is the slice of IP addresses, CIDR networks, and
|
||||||
// ClientIDs of allowed clients. If not empty, only these clients are
|
// ClientIDs of allowed clients. If not empty, only these clients are
|
||||||
// allowed, and [FilteringConfig.DisallowedClients] are ignored.
|
// allowed, and [Config.DisallowedClients] are ignored.
|
||||||
AllowedClients []string `yaml:"allowed_clients"`
|
AllowedClients []string `yaml:"allowed_clients"`
|
||||||
|
|
||||||
// DisallowedClients is the slice of IP addresses, CIDR networks, and
|
// DisallowedClients is the slice of IP addresses, CIDR networks, and
|
||||||
|
@ -283,7 +228,7 @@ type ServerConfig struct {
|
||||||
// Remove that.
|
// Remove that.
|
||||||
AddrProcConf *client.DefaultAddrProcConfig
|
AddrProcConf *client.DefaultAddrProcConfig
|
||||||
|
|
||||||
FilteringConfig
|
Config
|
||||||
TLSConfig
|
TLSConfig
|
||||||
DNSCryptConfig
|
DNSCryptConfig
|
||||||
TLSAllowUnencryptedDoH bool
|
TLSAllowUnencryptedDoH bool
|
||||||
|
@ -324,13 +269,6 @@ type ServerConfig struct {
|
||||||
UseHTTP3Upstreams bool
|
UseHTTP3Upstreams bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// if any of ServerConfig values are zero, then default values from below are used
|
|
||||||
var defaultValues = ServerConfig{
|
|
||||||
UDPListenAddrs: []*net.UDPAddr{{Port: 53}},
|
|
||||||
TCPListenAddrs: []*net.TCPAddr{{Port: 53}},
|
|
||||||
FilteringConfig: FilteringConfig{BlockedResponseTTL: 3600},
|
|
||||||
}
|
|
||||||
|
|
||||||
// createProxyConfig creates and validates configuration for the main proxy.
|
// createProxyConfig creates and validates configuration for the main proxy.
|
||||||
func (s *Server) createProxyConfig() (conf proxy.Config, err error) {
|
func (s *Server) createProxyConfig() (conf proxy.Config, err error) {
|
||||||
srvConf := s.conf
|
srvConf := s.conf
|
||||||
|
@ -403,10 +341,7 @@ func (s *Server) createProxyConfig() (conf proxy.Config, err error) {
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const defaultBlockedResponseTTL = 3600
|
||||||
defaultSafeBrowsingBlockHost = "standard-block.dns.adguard.com"
|
|
||||||
defaultParentalBlockHost = "family-block.dns.adguard.com"
|
|
||||||
)
|
|
||||||
|
|
||||||
// initDefaultSettings initializes default settings if nothing
|
// initDefaultSettings initializes default settings if nothing
|
||||||
// is configured
|
// is configured
|
||||||
|
@ -419,20 +354,12 @@ func (s *Server) initDefaultSettings() {
|
||||||
s.conf.BootstrapDNS = defaultBootstrap
|
s.conf.BootstrapDNS = defaultBootstrap
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.conf.ParentalBlockHost == "" {
|
|
||||||
s.conf.ParentalBlockHost = defaultParentalBlockHost
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.conf.SafeBrowsingBlockHost == "" {
|
|
||||||
s.conf.SafeBrowsingBlockHost = defaultSafeBrowsingBlockHost
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.conf.UDPListenAddrs == nil {
|
if s.conf.UDPListenAddrs == nil {
|
||||||
s.conf.UDPListenAddrs = defaultValues.UDPListenAddrs
|
s.conf.UDPListenAddrs = defaultUDPListenAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.conf.TCPListenAddrs == nil {
|
if s.conf.TCPListenAddrs == nil {
|
||||||
s.conf.TCPListenAddrs = defaultValues.TCPListenAddrs
|
s.conf.TCPListenAddrs = defaultTCPListenAddrs
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.conf.BlockedHosts) == 0 {
|
if len(s.conf.BlockedHosts) == 0 {
|
||||||
|
@ -565,9 +492,9 @@ func (s *Server) UpdatedProtectionStatus() (enabled bool, disabledUntil *time.Ti
|
||||||
s.serverLock.RLock()
|
s.serverLock.RLock()
|
||||||
defer s.serverLock.RUnlock()
|
defer s.serverLock.RUnlock()
|
||||||
|
|
||||||
disabledUntil = s.conf.ProtectionDisabledUntil
|
disabledUntil = s.dnsFilter.ProtectionDisabledUntil
|
||||||
if disabledUntil == nil {
|
if disabledUntil == nil {
|
||||||
return s.conf.ProtectionEnabled, nil
|
return s.dnsFilter.ProtectionEnabled, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if time.Now().Before(*disabledUntil) {
|
if time.Now().Before(*disabledUntil) {
|
||||||
|
@ -599,8 +526,8 @@ func (s *Server) enableProtectionAfterPause() {
|
||||||
s.serverLock.Lock()
|
s.serverLock.Lock()
|
||||||
defer s.serverLock.Unlock()
|
defer s.serverLock.Unlock()
|
||||||
|
|
||||||
s.conf.ProtectionEnabled = true
|
s.dnsFilter.ProtectionEnabled = true
|
||||||
s.conf.ProtectionDisabledUntil = nil
|
s.dnsFilter.ProtectionDisabledUntil = nil
|
||||||
|
|
||||||
log.Info("dns: protection is restarted after pause")
|
log.Info("dns: protection is restarted after pause")
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,11 +283,13 @@ func TestServer_HandleDNSRequest_dns64(t *testing.T) {
|
||||||
// right after stop, due to a data race in [proxy.Proxy.Init] method
|
// right after stop, due to a data race in [proxy.Proxy.Init] method
|
||||||
// when setting an OOB size. As a temporary workaround, recreate the
|
// when setting an OOB size. As a temporary workaround, recreate the
|
||||||
// whole server for each test case.
|
// whole server for each test case.
|
||||||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
UseDNS64: true,
|
UseDNS64: true,
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
}, localUps)
|
}, localUps)
|
||||||
|
|
|
@ -45,6 +45,14 @@ var defaultBootstrap = []string{"9.9.9.10", "149.112.112.10", "2620:fe::10", "26
|
||||||
// Often requested by all kinds of DNS probes
|
// Often requested by all kinds of DNS probes
|
||||||
var defaultBlockedHosts = []string{"version.bind", "id.server", "hostname.bind"}
|
var defaultBlockedHosts = []string{"version.bind", "id.server", "hostname.bind"}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// defaultUDPListenAddrs are the default UDP addresses for the server.
|
||||||
|
defaultUDPListenAddrs = []*net.UDPAddr{{Port: 53}}
|
||||||
|
|
||||||
|
// defaultTCPListenAddrs are the default TCP addresses for the server.
|
||||||
|
defaultTCPListenAddrs = []*net.TCPAddr{{Port: 53}}
|
||||||
|
)
|
||||||
|
|
||||||
var webRegistered bool
|
var webRegistered bool
|
||||||
|
|
||||||
// DHCP is an interface for accesing DHCP lease data needed in this package.
|
// DHCP is an interface for accesing DHCP lease data needed in this package.
|
||||||
|
@ -255,11 +263,11 @@ func (s *Server) Close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteDiskConfig - write configuration
|
// WriteDiskConfig - write configuration
|
||||||
func (s *Server) WriteDiskConfig(c *FilteringConfig) {
|
func (s *Server) WriteDiskConfig(c *Config) {
|
||||||
s.serverLock.RLock()
|
s.serverLock.RLock()
|
||||||
defer s.serverLock.RUnlock()
|
defer s.serverLock.RUnlock()
|
||||||
|
|
||||||
sc := s.conf.FilteringConfig
|
sc := s.conf.Config
|
||||||
*c = sc
|
*c = sc
|
||||||
c.RatelimitWhitelist = stringutil.CloneSlice(sc.RatelimitWhitelist)
|
c.RatelimitWhitelist = stringutil.CloneSlice(sc.RatelimitWhitelist)
|
||||||
c.BootstrapDNS = stringutil.CloneSlice(sc.BootstrapDNS)
|
c.BootstrapDNS = stringutil.CloneSlice(sc.BootstrapDNS)
|
||||||
|
@ -534,7 +542,11 @@ func (s *Server) setupLocalResolvers() (err error) {
|
||||||
func (s *Server) Prepare(conf *ServerConfig) (err error) {
|
func (s *Server) Prepare(conf *ServerConfig) (err error) {
|
||||||
s.conf = *conf
|
s.conf = *conf
|
||||||
|
|
||||||
err = validateBlockingMode(s.conf.BlockingMode, s.conf.BlockingIPv4, s.conf.BlockingIPv6)
|
err = validateBlockingMode(
|
||||||
|
s.dnsFilter.BlockingMode,
|
||||||
|
s.dnsFilter.BlockingIPv4,
|
||||||
|
s.dnsFilter.BlockingIPv6,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("checking blocking mode: %w", err)
|
return fmt.Errorf("checking blocking mode: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -645,15 +657,18 @@ func (s *Server) setupAddrProc() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateBlockingMode returns an error if the blocking mode data aren't valid.
|
// validateBlockingMode returns an error if the blocking mode data aren't valid.
|
||||||
func validateBlockingMode(mode BlockingMode, blockingIPv4, blockingIPv6 netip.Addr) (err error) {
|
func validateBlockingMode(
|
||||||
|
mode filtering.BlockingMode,
|
||||||
|
blockingIPv4, blockingIPv6 netip.Addr,
|
||||||
|
) (err error) {
|
||||||
switch mode {
|
switch mode {
|
||||||
case
|
case
|
||||||
BlockingModeDefault,
|
filtering.BlockingModeDefault,
|
||||||
BlockingModeNXDOMAIN,
|
filtering.BlockingModeNXDOMAIN,
|
||||||
BlockingModeREFUSED,
|
filtering.BlockingModeREFUSED,
|
||||||
BlockingModeNullIP:
|
filtering.BlockingModeNullIP:
|
||||||
return nil
|
return nil
|
||||||
case BlockingModeCustomIP:
|
case filtering.BlockingModeCustomIP:
|
||||||
if !blockingIPv4.Is4() {
|
if !blockingIPv4.Is4() {
|
||||||
return fmt.Errorf("blocking_ipv4 must be valid ipv4 on custom_ip blocking_mode")
|
return fmt.Errorf("blocking_ipv4 must be valid ipv4 on custom_ip blocking_mode")
|
||||||
} else if !blockingIPv6.Is6() {
|
} else if !blockingIPv6.Is6() {
|
||||||
|
|
|
@ -105,8 +105,8 @@ func createTestServer(
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
if forwardConf.BlockingMode == "" {
|
if s.dnsFilter.BlockingMode == "" {
|
||||||
forwardConf.BlockingMode = BlockingModeDefault
|
s.dnsFilter.BlockingMode = filtering.BlockingModeDefault
|
||||||
}
|
}
|
||||||
|
|
||||||
err = s.Prepare(&forwardConf)
|
err = s.Prepare(&forwardConf)
|
||||||
|
@ -181,7 +181,7 @@ func createTestTLS(t *testing.T, tlsConf TLSConfig) (s *Server, certPem []byte)
|
||||||
s = createTestServer(t, &filtering.Config{}, ServerConfig{
|
s = createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
|
@ -303,10 +303,12 @@ func sendTestMessages(t *testing.T, conn *dns.Conn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServer(t *testing.T) {
|
func TestServer(t *testing.T) {
|
||||||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
|
@ -344,14 +346,14 @@ func TestServer_timeout(t *testing.T) {
|
||||||
t.Run("custom", func(t *testing.T) {
|
t.Run("custom", func(t *testing.T) {
|
||||||
srvConf := &ServerConfig{
|
srvConf := &ServerConfig{
|
||||||
UpstreamTimeout: testTimeout,
|
UpstreamTimeout: testTimeout,
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
BlockingMode: BlockingModeDefault,
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := NewServer(DNSCreateParams{DNSFilter: &filtering.DNSFilter{}})
|
s, err := NewServer(DNSCreateParams{DNSFilter: &filtering.DNSFilter{}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
s.dnsFilter.BlockingMode = filtering.BlockingModeDefault
|
||||||
|
|
||||||
err = s.Prepare(srvConf)
|
err = s.Prepare(srvConf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -363,8 +365,8 @@ func TestServer_timeout(t *testing.T) {
|
||||||
s, err := NewServer(DNSCreateParams{DNSFilter: &filtering.DNSFilter{}})
|
s, err := NewServer(DNSCreateParams{DNSFilter: &filtering.DNSFilter{}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
s.conf.FilteringConfig.BlockingMode = BlockingModeDefault
|
s.dnsFilter.BlockingMode = filtering.BlockingModeDefault
|
||||||
s.conf.FilteringConfig.EDNSClientSubnet = &EDNSClientSubnet{
|
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
}
|
}
|
||||||
err = s.Prepare(&s.conf)
|
err = s.Prepare(&s.conf)
|
||||||
|
@ -378,7 +380,7 @@ func TestServerWithProtectionDisabled(t *testing.T) {
|
||||||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
|
@ -454,9 +456,8 @@ func TestServerRace(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
|
||||||
},
|
},
|
||||||
ConfigModified: func() {},
|
ConfigModified: func() {},
|
||||||
}
|
}
|
||||||
|
@ -489,6 +490,7 @@ func TestSafeSearch(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
filterConf := &filtering.Config{
|
filterConf := &filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
SafeSearchConf: safeSearchConf,
|
SafeSearchConf: safeSearchConf,
|
||||||
SafeSearchCacheSize: 1000,
|
SafeSearchCacheSize: 1000,
|
||||||
CacheTime: 30,
|
CacheTime: 30,
|
||||||
|
@ -505,8 +507,7 @@ func TestSafeSearch(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
|
@ -566,7 +567,7 @@ func TestInvalidRequest(t *testing.T) {
|
||||||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
|
@ -594,15 +595,16 @@ func TestBlockedRequest(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
|
||||||
BlockingMode: BlockingModeDefault,
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, forwardConf, nil)
|
||||||
startDeferStop(t, s)
|
startDeferStop(t, s)
|
||||||
|
|
||||||
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
|
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
|
||||||
|
@ -623,8 +625,7 @@ func TestServerCustomClientUpstream(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
|
@ -676,7 +677,7 @@ func TestBlockCNAMEProtectionEnabled(t *testing.T) {
|
||||||
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
s := createTestServer(t, &filtering.Config{}, ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
|
@ -686,7 +687,7 @@ func TestBlockCNAMEProtectionEnabled(t *testing.T) {
|
||||||
CName: testCNAMEs,
|
CName: testCNAMEs,
|
||||||
IPv4: testIPv4,
|
IPv4: testIPv4,
|
||||||
}
|
}
|
||||||
s.conf.ProtectionEnabled = false
|
|
||||||
s.dnsProxy.UpstreamConfig = &proxy.UpstreamConfig{
|
s.dnsProxy.UpstreamConfig = &proxy.UpstreamConfig{
|
||||||
Upstreams: []upstream.Upstream{testUpstm},
|
Upstreams: []upstream.Upstream{testUpstm},
|
||||||
}
|
}
|
||||||
|
@ -708,15 +709,16 @@ func TestBlockCNAME(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
|
||||||
BlockingMode: BlockingModeDefault,
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, forwardConf, nil)
|
||||||
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
s.conf.UpstreamConfig.Upstreams = []upstream.Upstream{
|
||||||
&aghtest.Upstream{
|
&aghtest.Upstream{
|
||||||
CName: testCNAMEs,
|
CName: testCNAMEs,
|
||||||
|
@ -778,8 +780,7 @@ func TestClientRulesForCNAMEMatching(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
|
||||||
FilterHandler: func(_ netip.Addr, _ string, settings *filtering.Settings) {
|
FilterHandler: func(_ netip.Addr, _ string, settings *filtering.Settings) {
|
||||||
settings.FilteringEnabled = false
|
settings.FilteringEnabled = false
|
||||||
},
|
},
|
||||||
|
@ -824,15 +825,16 @@ func TestNullBlockedRequest(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
|
||||||
BlockingMode: BlockingModeNullIP,
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
|
BlockingMode: filtering.BlockingModeNullIP,
|
||||||
|
}, forwardConf, nil)
|
||||||
startDeferStop(t, s)
|
startDeferStop(t, s)
|
||||||
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
|
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
|
||||||
|
|
||||||
|
@ -864,7 +866,12 @@ func TestBlockedCustomIP(t *testing.T) {
|
||||||
Data: []byte(rules),
|
Data: []byte(rules),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
f, err := filtering.New(&filtering.Config{}, filters)
|
f, err := filtering.New(&filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
|
BlockingMode: filtering.BlockingModeCustomIP,
|
||||||
|
BlockingIPv4: netip.Addr{},
|
||||||
|
BlockingIPv6: netip.Addr{},
|
||||||
|
}, filters)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
dhcp := &testDHCP{
|
dhcp := &testDHCP{
|
||||||
|
@ -882,12 +889,8 @@ func TestBlockedCustomIP(t *testing.T) {
|
||||||
conf := &ServerConfig{
|
conf := &ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||||
BlockingMode: BlockingModeCustomIP,
|
|
||||||
BlockingIPv4: netip.Addr{},
|
|
||||||
BlockingIPv6: netip.Addr{},
|
|
||||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
|
@ -898,8 +901,8 @@ func TestBlockedCustomIP(t *testing.T) {
|
||||||
err = s.Prepare(conf)
|
err = s.Prepare(conf)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
conf.BlockingIPv4 = netip.AddrFrom4([4]byte{0, 0, 0, 1})
|
s.dnsFilter.BlockingIPv4 = netip.AddrFrom4([4]byte{0, 0, 0, 1})
|
||||||
conf.BlockingIPv6 = netip.MustParseAddr("::1")
|
s.dnsFilter.BlockingIPv6 = netip.MustParseAddr("::1")
|
||||||
|
|
||||||
err = s.Prepare(conf)
|
err = s.Prepare(conf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -936,16 +939,17 @@ func TestBlockedByHosts(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
|
||||||
BlockingMode: BlockingModeDefault,
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, forwardConf, nil)
|
||||||
startDeferStop(t, s)
|
startDeferStop(t, s)
|
||||||
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
|
addr := s.dnsProxy.Addr(proxy.ProtoUDP)
|
||||||
|
|
||||||
|
@ -976,15 +980,15 @@ func TestBlockedBySafeBrowsing(t *testing.T) {
|
||||||
ans4, _ := aghtest.HostToIPs(hostname)
|
ans4, _ := aghtest.HostToIPs(hostname)
|
||||||
|
|
||||||
filterConf := &filtering.Config{
|
filterConf := &filtering.Config{
|
||||||
SafeBrowsingEnabled: true,
|
ProtectionEnabled: true,
|
||||||
SafeBrowsingChecker: sbChecker,
|
SafeBrowsingEnabled: true,
|
||||||
|
SafeBrowsingChecker: sbChecker,
|
||||||
|
SafeBrowsingBlockHost: ans4.String(),
|
||||||
}
|
}
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
SafeBrowsingBlockHost: ans4.String(),
|
|
||||||
ProtectionEnabled: true,
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
|
@ -1006,6 +1010,7 @@ func TestBlockedBySafeBrowsing(t *testing.T) {
|
||||||
|
|
||||||
func TestRewrite(t *testing.T) {
|
func TestRewrite(t *testing.T) {
|
||||||
c := &filtering.Config{
|
c := &filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
Rewrites: []*filtering.LegacyRewrite{{
|
Rewrites: []*filtering.LegacyRewrite{{
|
||||||
Domain: "test.com",
|
Domain: "test.com",
|
||||||
Answer: "1.2.3.4",
|
Answer: "1.2.3.4",
|
||||||
|
@ -1040,10 +1045,8 @@ func TestRewrite(t *testing.T) {
|
||||||
assert.NoError(t, s.Prepare(&ServerConfig{
|
assert.NoError(t, s.Prepare(&ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
UpstreamDNS: []string{"8.8.8.8:53"},
|
||||||
BlockingMode: BlockingModeDefault,
|
|
||||||
UpstreamDNS: []string{"8.8.8.8:53"},
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
|
@ -1148,7 +1151,9 @@ func (d *testDHCP) Enabled() (ok bool) { return d.OnEnabled() }
|
||||||
func TestPTRResponseFromDHCPLeases(t *testing.T) {
|
func TestPTRResponseFromDHCPLeases(t *testing.T) {
|
||||||
const localDomain = "lan"
|
const localDomain = "lan"
|
||||||
|
|
||||||
flt, err := filtering.New(&filtering.Config{}, nil)
|
flt, err := filtering.New(&filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
s, err := NewServer(DNSCreateParams{
|
s, err := NewServer(DNSCreateParams{
|
||||||
|
@ -1168,9 +1173,7 @@ func TestPTRResponseFromDHCPLeases(t *testing.T) {
|
||||||
s.conf.UDPListenAddrs = []*net.UDPAddr{{}}
|
s.conf.UDPListenAddrs = []*net.UDPAddr{{}}
|
||||||
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
|
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
|
||||||
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
||||||
s.conf.FilteringConfig.ProtectionEnabled = true
|
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{Enabled: false}
|
||||||
s.conf.FilteringConfig.BlockingMode = BlockingModeDefault
|
|
||||||
s.conf.FilteringConfig.EDNSClientSubnet = &EDNSClientSubnet{Enabled: false}
|
|
||||||
|
|
||||||
err = s.Prepare(&s.conf)
|
err = s.Prepare(&s.conf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -1234,7 +1237,8 @@ func TestPTRResponseFromHosts(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
flt, err := filtering.New(&filtering.Config{
|
flt, err := filtering.New(&filtering.Config{
|
||||||
EtcHosts: hc,
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
EtcHosts: hc,
|
||||||
}, nil)
|
}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -1251,8 +1255,7 @@ func TestPTRResponseFromHosts(t *testing.T) {
|
||||||
s.conf.UDPListenAddrs = []*net.UDPAddr{{}}
|
s.conf.UDPListenAddrs = []*net.UDPAddr{{}}
|
||||||
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
|
s.conf.TCPListenAddrs = []*net.TCPAddr{{}}
|
||||||
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
s.conf.UpstreamDNS = []string{"127.0.0.1:53"}
|
||||||
s.conf.FilteringConfig.BlockingMode = BlockingModeDefault
|
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{Enabled: false}
|
||||||
s.conf.FilteringConfig.EDNSClientSubnet = &EDNSClientSubnet{Enabled: false}
|
|
||||||
|
|
||||||
err = s.Prepare(&s.conf)
|
err = s.Prepare(&s.conf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
@ -34,7 +34,9 @@ func TestServer_FilterDNSRewrite(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions and entities.
|
// Helper functions and entities.
|
||||||
srv := &Server{}
|
srv := &Server{
|
||||||
|
dnsFilter: &filtering.DNSFilter{},
|
||||||
|
}
|
||||||
makeQ := func(qtype rules.RRType) (req *dns.Msg) {
|
makeQ := func(qtype rules.RRType) (req *dns.Msg) {
|
||||||
return &dns.Msg{
|
return &dns.Msg{
|
||||||
Question: []dns.Question{{
|
Question: []dns.Question{{
|
||||||
|
|
|
@ -30,9 +30,7 @@ func TestHandleDNSRequest_handleDNSRequest(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
|
||||||
BlockingMode: BlockingModeDefault,
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{
|
EDNSClientSubnet: &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
|
@ -42,7 +40,10 @@ func TestHandleDNSRequest_handleDNSRequest(t *testing.T) {
|
||||||
ID: 0, Data: []byte(rules),
|
ID: 0, Data: []byte(rules),
|
||||||
}}
|
}}
|
||||||
|
|
||||||
f, err := filtering.New(&filtering.Config{}, filters)
|
f, err := filtering.New(&filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, filters)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
f.SetEnabled(true)
|
f.SetEnabled(true)
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
@ -47,7 +48,7 @@ type jsonDNSConfig struct {
|
||||||
RateLimit *uint32 `json:"ratelimit"`
|
RateLimit *uint32 `json:"ratelimit"`
|
||||||
|
|
||||||
// BlockingMode defines the way blocked responses are constructed.
|
// BlockingMode defines the way blocked responses are constructed.
|
||||||
BlockingMode *BlockingMode `json:"blocking_mode"`
|
BlockingMode *filtering.BlockingMode `json:"blocking_mode"`
|
||||||
|
|
||||||
// EDNSCSEnabled defines if EDNS Client Subnet is enabled.
|
// EDNSCSEnabled defines if EDNS Client Subnet is enabled.
|
||||||
EDNSCSEnabled *bool `json:"edns_cs_enabled"`
|
EDNSCSEnabled *bool `json:"edns_cs_enabled"`
|
||||||
|
@ -113,9 +114,9 @@ func (s *Server) getDNSConfig() (c *jsonDNSConfig) {
|
||||||
upstreamFile := s.conf.UpstreamDNSFileName
|
upstreamFile := s.conf.UpstreamDNSFileName
|
||||||
bootstraps := stringutil.CloneSliceOrEmpty(s.conf.BootstrapDNS)
|
bootstraps := stringutil.CloneSliceOrEmpty(s.conf.BootstrapDNS)
|
||||||
fallbacks := stringutil.CloneSliceOrEmpty(s.conf.FallbackDNS)
|
fallbacks := stringutil.CloneSliceOrEmpty(s.conf.FallbackDNS)
|
||||||
blockingMode := s.conf.BlockingMode
|
blockingMode := s.dnsFilter.BlockingMode
|
||||||
blockingIPv4 := s.conf.BlockingIPv4
|
blockingIPv4 := s.dnsFilter.BlockingIPv4
|
||||||
blockingIPv6 := s.conf.BlockingIPv6
|
blockingIPv6 := s.dnsFilter.BlockingIPv6
|
||||||
ratelimit := s.conf.Ratelimit
|
ratelimit := s.conf.Ratelimit
|
||||||
|
|
||||||
customIP := s.conf.EDNSClientSubnet.CustomIP
|
customIP := s.conf.EDNSClientSubnet.CustomIP
|
||||||
|
@ -319,10 +320,10 @@ func (s *Server) setConfig(dc *jsonDNSConfig) (shouldRestart bool) {
|
||||||
defer s.serverLock.Unlock()
|
defer s.serverLock.Unlock()
|
||||||
|
|
||||||
if dc.BlockingMode != nil {
|
if dc.BlockingMode != nil {
|
||||||
s.conf.BlockingMode = *dc.BlockingMode
|
s.dnsFilter.BlockingMode = *dc.BlockingMode
|
||||||
if *dc.BlockingMode == BlockingModeCustomIP {
|
if *dc.BlockingMode == filtering.BlockingModeCustomIP {
|
||||||
s.conf.BlockingIPv4 = dc.BlockingIPv4
|
s.dnsFilter.BlockingIPv4 = dc.BlockingIPv4
|
||||||
s.conf.BlockingIPv6 = dc.BlockingIPv6
|
s.dnsFilter.BlockingIPv6 = dc.BlockingIPv6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -335,7 +336,7 @@ func (s *Server) setConfig(dc *jsonDNSConfig) (shouldRestart bool) {
|
||||||
s.conf.EDNSClientSubnet.CustomIP = dc.EDNSCSCustomIP
|
s.conf.EDNSClientSubnet.CustomIP = dc.EDNSCSCustomIP
|
||||||
}
|
}
|
||||||
|
|
||||||
setIfNotNil(&s.conf.ProtectionEnabled, dc.ProtectionEnabled)
|
setIfNotNil(&s.dnsFilter.ProtectionEnabled, dc.ProtectionEnabled)
|
||||||
setIfNotNil(&s.conf.EnableDNSSEC, dc.DNSSECEnabled)
|
setIfNotNil(&s.conf.EnableDNSSEC, dc.DNSSECEnabled)
|
||||||
setIfNotNil(&s.conf.AAAADisabled, dc.DisableIPv6)
|
setIfNotNil(&s.conf.AAAADisabled, dc.DisableIPv6)
|
||||||
|
|
||||||
|
@ -831,8 +832,8 @@ func (s *Server) handleSetProtection(w http.ResponseWriter, r *http.Request) {
|
||||||
s.serverLock.Lock()
|
s.serverLock.Lock()
|
||||||
defer s.serverLock.Unlock()
|
defer s.serverLock.Unlock()
|
||||||
|
|
||||||
s.conf.ProtectionEnabled = protectionReq.Enabled
|
s.dnsFilter.ProtectionEnabled = protectionReq.Enabled
|
||||||
s.conf.ProtectionDisabledUntil = disabledUntil
|
s.dnsFilter.ProtectionDisabledUntil = disabledUntil
|
||||||
}()
|
}()
|
||||||
|
|
||||||
s.conf.ConfigModified()
|
s.conf.ConfigModified()
|
||||||
|
|
|
@ -58,6 +58,8 @@ const jsonExt = ".json"
|
||||||
|
|
||||||
func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
|
func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
|
||||||
filterConf := &filtering.Config{
|
filterConf := &filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
SafeBrowsingEnabled: true,
|
SafeBrowsingEnabled: true,
|
||||||
SafeBrowsingCacheSize: 1000,
|
SafeBrowsingCacheSize: 1000,
|
||||||
SafeSearchConf: filtering.SafeSearchConfig{Enabled: true},
|
SafeSearchConf: filtering.SafeSearchConfig{Enabled: true},
|
||||||
|
@ -68,12 +70,10 @@ func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{},
|
||||||
TCPListenAddrs: []*net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||||
BlockingMode: BlockingModeDefault,
|
FallbackDNS: []string{"9.9.9.10"},
|
||||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
FallbackDNS: []string{"9.9.9.10"},
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
|
||||||
},
|
},
|
||||||
ConfigModified: func() {},
|
ConfigModified: func() {},
|
||||||
}
|
}
|
||||||
|
@ -135,6 +135,8 @@ func TestDNSForwardHTTP_handleGetConfig(t *testing.T) {
|
||||||
|
|
||||||
func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
|
func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
|
||||||
filterConf := &filtering.Config{
|
filterConf := &filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
SafeBrowsingEnabled: true,
|
SafeBrowsingEnabled: true,
|
||||||
SafeBrowsingCacheSize: 1000,
|
SafeBrowsingCacheSize: 1000,
|
||||||
SafeSearchConf: filtering.SafeSearchConfig{Enabled: true},
|
SafeSearchConf: filtering.SafeSearchConfig{Enabled: true},
|
||||||
|
@ -145,11 +147,9 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
|
||||||
forwardConf := ServerConfig{
|
forwardConf := ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{},
|
UDPListenAddrs: []*net.UDPAddr{},
|
||||||
TCPListenAddrs: []*net.TCPAddr{},
|
TCPListenAddrs: []*net.TCPAddr{},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
ProtectionEnabled: true,
|
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
||||||
BlockingMode: BlockingModeDefault,
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
UpstreamDNS: []string{"8.8.8.8:53", "8.8.4.4:53"},
|
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
|
||||||
},
|
},
|
||||||
ConfigModified: func() {},
|
ConfigModified: func() {},
|
||||||
}
|
}
|
||||||
|
@ -157,6 +157,7 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
|
||||||
s.sysResolvers = &fakeSystemResolvers{}
|
s.sysResolvers = &fakeSystemResolvers{}
|
||||||
|
|
||||||
defaultConf := s.conf
|
defaultConf := s.conf
|
||||||
|
defaultFilterConf := filterConf
|
||||||
|
|
||||||
err := s.Start()
|
err := s.Start()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -247,8 +248,9 @@ func TestDNSForwardHTTP_handleSetConfig(t *testing.T) {
|
||||||
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
t.Cleanup(func() {
|
t.Cleanup(func() {
|
||||||
|
s.dnsFilter.Config = *defaultFilterConf
|
||||||
s.conf = defaultConf
|
s.conf = defaultConf
|
||||||
s.conf.FilteringConfig.EDNSClientSubnet = &EDNSClientSubnet{}
|
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{}
|
||||||
})
|
})
|
||||||
|
|
||||||
rBody := io.NopCloser(bytes.NewReader(caseData.Req))
|
rBody := io.NopCloser(bytes.NewReader(caseData.Req))
|
||||||
|
@ -503,7 +505,7 @@ func TestServer_HandleTestUpstreamDNS(t *testing.T) {
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
UpstreamTimeout: upsTimeout,
|
UpstreamTimeout: upsTimeout,
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
|
|
|
@ -50,7 +50,7 @@ func (s *Server) genDNSFilterMessage(
|
||||||
req := dctx.Req
|
req := dctx.Req
|
||||||
qt := req.Question[0].Qtype
|
qt := req.Question[0].Qtype
|
||||||
if qt != dns.TypeA && qt != dns.TypeAAAA {
|
if qt != dns.TypeA && qt != dns.TypeAAAA {
|
||||||
if s.conf.BlockingMode == BlockingModeNullIP {
|
if s.dnsFilter.BlockingMode == filtering.BlockingModeNullIP {
|
||||||
return s.makeResponse(req)
|
return s.makeResponse(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +59,9 @@ func (s *Server) genDNSFilterMessage(
|
||||||
|
|
||||||
switch res.Reason {
|
switch res.Reason {
|
||||||
case filtering.FilteredSafeBrowsing:
|
case filtering.FilteredSafeBrowsing:
|
||||||
return s.genBlockedHost(req, s.conf.SafeBrowsingBlockHost, dctx)
|
return s.genBlockedHost(req, s.dnsFilter.SafeBrowsingBlockHost, dctx)
|
||||||
case filtering.FilteredParental:
|
case filtering.FilteredParental:
|
||||||
return s.genBlockedHost(req, s.conf.ParentalBlockHost, dctx)
|
return s.genBlockedHost(req, s.dnsFilter.ParentalBlockHost, dctx)
|
||||||
case filtering.FilteredSafeSearch:
|
case filtering.FilteredSafeSearch:
|
||||||
// If Safe Search generated the necessary IP addresses, use them.
|
// If Safe Search generated the necessary IP addresses, use them.
|
||||||
// Otherwise, if there were no errors, there are no addresses for the
|
// Otherwise, if there were no errors, there are no addresses for the
|
||||||
|
@ -76,13 +76,13 @@ func (s *Server) genDNSFilterMessage(
|
||||||
// blocking mode.
|
// blocking mode.
|
||||||
func (s *Server) genForBlockingMode(req *dns.Msg, ips []netip.Addr) (resp *dns.Msg) {
|
func (s *Server) genForBlockingMode(req *dns.Msg, ips []netip.Addr) (resp *dns.Msg) {
|
||||||
qt := req.Question[0].Qtype
|
qt := req.Question[0].Qtype
|
||||||
switch m := s.conf.BlockingMode; m {
|
switch m := s.dnsFilter.BlockingMode; m {
|
||||||
case BlockingModeCustomIP:
|
case filtering.BlockingModeCustomIP:
|
||||||
switch qt {
|
switch qt {
|
||||||
case dns.TypeA:
|
case dns.TypeA:
|
||||||
return s.genARecord(req, s.conf.BlockingIPv4)
|
return s.genARecord(req, s.dnsFilter.BlockingIPv4)
|
||||||
case dns.TypeAAAA:
|
case dns.TypeAAAA:
|
||||||
return s.genAAAARecord(req, s.conf.BlockingIPv6)
|
return s.genAAAARecord(req, s.dnsFilter.BlockingIPv6)
|
||||||
default:
|
default:
|
||||||
// Generally shouldn't happen, since the types are checked in
|
// Generally shouldn't happen, since the types are checked in
|
||||||
// genDNSFilterMessage.
|
// genDNSFilterMessage.
|
||||||
|
@ -90,20 +90,20 @@ func (s *Server) genForBlockingMode(req *dns.Msg, ips []netip.Addr) (resp *dns.M
|
||||||
|
|
||||||
return s.makeResponse(req)
|
return s.makeResponse(req)
|
||||||
}
|
}
|
||||||
case BlockingModeDefault:
|
case filtering.BlockingModeDefault:
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
return s.genResponseWithIPs(req, ips)
|
return s.genResponseWithIPs(req, ips)
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.makeResponseNullIP(req)
|
return s.makeResponseNullIP(req)
|
||||||
case BlockingModeNullIP:
|
case filtering.BlockingModeNullIP:
|
||||||
return s.makeResponseNullIP(req)
|
return s.makeResponseNullIP(req)
|
||||||
case BlockingModeNXDOMAIN:
|
case filtering.BlockingModeNXDOMAIN:
|
||||||
return s.genNXDomain(req)
|
return s.genNXDomain(req)
|
||||||
case BlockingModeREFUSED:
|
case filtering.BlockingModeREFUSED:
|
||||||
return s.makeResponseREFUSED(req)
|
return s.makeResponseREFUSED(req)
|
||||||
default:
|
default:
|
||||||
log.Error("dns: invalid blocking mode %q", s.conf.BlockingMode)
|
log.Error("dns: invalid blocking mode %q", s.dnsFilter.BlockingMode)
|
||||||
|
|
||||||
return s.makeResponse(req)
|
return s.makeResponse(req)
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ func (s *Server) hdr(req *dns.Msg, rrType rules.RRType) (h dns.RR_Header) {
|
||||||
return dns.RR_Header{
|
return dns.RR_Header{
|
||||||
Name: req.Question[0].Name,
|
Name: req.Question[0].Name,
|
||||||
Rrtype: rrType,
|
Rrtype: rrType,
|
||||||
Ttl: s.conf.BlockedResponseTTL,
|
Ttl: s.dnsFilter.BlockedResponseTTL,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -243,6 +243,12 @@ func (s *Server) makeResponseNullIP(req *dns.Msg) (resp *dns.Msg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) genBlockedHost(request *dns.Msg, newAddr string, d *proxy.DNSContext) *dns.Msg {
|
func (s *Server) genBlockedHost(request *dns.Msg, newAddr string, d *proxy.DNSContext) *dns.Msg {
|
||||||
|
if newAddr == "" {
|
||||||
|
log.Printf("block host is not specified.")
|
||||||
|
|
||||||
|
return s.genServerFailure(request)
|
||||||
|
}
|
||||||
|
|
||||||
ip, err := netip.ParseAddr(newAddr)
|
ip, err := netip.ParseAddr(newAddr)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return s.genResponseWithIPs(request, []netip.Addr{ip})
|
return s.genResponseWithIPs(request, []netip.Addr{ip})
|
||||||
|
@ -346,13 +352,13 @@ func (s *Server) genSOA(request *dns.Msg) []dns.RR {
|
||||||
Hdr: dns.RR_Header{
|
Hdr: dns.RR_Header{
|
||||||
Name: zone,
|
Name: zone,
|
||||||
Rrtype: dns.TypeSOA,
|
Rrtype: dns.TypeSOA,
|
||||||
Ttl: s.conf.BlockedResponseTTL,
|
Ttl: s.dnsFilter.BlockedResponseTTL,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
},
|
},
|
||||||
Mbox: "hostmaster.", // zone will be appended later if it's not empty or "."
|
Mbox: "hostmaster.", // zone will be appended later if it's not empty or "."
|
||||||
}
|
}
|
||||||
if soa.Hdr.Ttl == 0 {
|
if soa.Hdr.Ttl == 0 {
|
||||||
soa.Hdr.Ttl = defaultValues.BlockedResponseTTL
|
soa.Hdr.Ttl = defaultBlockedResponseTTL
|
||||||
}
|
}
|
||||||
if len(zone) > 0 && zone[0] != '.' {
|
if len(zone) > 0 && zone[0] != '.' {
|
||||||
soa.Mbox += zone
|
soa.Mbox += zone
|
||||||
|
|
|
@ -607,7 +607,7 @@ func (s *Server) processDHCPAddrs(dctx *dnsContext) (rc resultCode) {
|
||||||
Rrtype: dns.TypePTR,
|
Rrtype: dns.TypePTR,
|
||||||
// TODO(e.burkov): Use [dhcpsvc.Lease.Expiry]. See
|
// TODO(e.burkov): Use [dhcpsvc.Lease.Expiry]. See
|
||||||
// https://github.com/AdguardTeam/AdGuardHome/issues/3932.
|
// https://github.com/AdguardTeam/AdGuardHome/issues/3932.
|
||||||
Ttl: s.conf.BlockedResponseTTL,
|
Ttl: s.dnsFilter.BlockedResponseTTL,
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
},
|
},
|
||||||
Ptr: dns.Fqdn(strings.Join([]string{host, s.localDomainSuffix}, ".")),
|
Ptr: dns.Fqdn(strings.Join([]string{host, s.localDomainSuffix}, ".")),
|
||||||
|
|
|
@ -77,7 +77,7 @@ func TestServer_ProcessInitial(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
c := ServerConfig{
|
c := ServerConfig{
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
AAAADisabled: tc.aaaaDisabled,
|
AAAADisabled: tc.aaaaDisabled,
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
|
@ -174,7 +174,7 @@ func TestServer_ProcessFilteringAfterResponse(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
c := ServerConfig{
|
c := ServerConfig{
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
AAAADisabled: tc.aaaaDisabled,
|
AAAADisabled: tc.aaaaDisabled,
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
|
@ -342,11 +342,12 @@ func prepareTestServer(t *testing.T, portDoH, portDoT, portDoQ int, ddrEnabled b
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
s = &Server{
|
s = &Server{
|
||||||
|
dnsFilter: &filtering.DNSFilter{},
|
||||||
dnsProxy: &proxy.Proxy{
|
dnsProxy: &proxy.Proxy{
|
||||||
Config: proxy.Config{},
|
Config: proxy.Config{},
|
||||||
},
|
},
|
||||||
conf: ServerConfig{
|
conf: ServerConfig{
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
HandleDDR: ddrEnabled,
|
HandleDDR: ddrEnabled,
|
||||||
},
|
},
|
||||||
TLSConfig: TLSConfig{
|
TLSConfig: TLSConfig{
|
||||||
|
@ -466,6 +467,7 @@ func TestServer_ProcessDHCPHosts_localRestriction(t *testing.T) {
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
s := &Server{
|
s := &Server{
|
||||||
|
dnsFilter: &filtering.DNSFilter{},
|
||||||
dhcpServer: dhcp,
|
dhcpServer: dhcp,
|
||||||
localDomainSuffix: localDomainSuffix,
|
localDomainSuffix: localDomainSuffix,
|
||||||
}
|
}
|
||||||
|
@ -600,6 +602,7 @@ func TestServer_ProcessDHCPHosts(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
|
dnsFilter: &filtering.DNSFilter{},
|
||||||
dhcpServer: testDHCP,
|
dhcpServer: testDHCP,
|
||||||
localDomainSuffix: tc.suffix,
|
localDomainSuffix: tc.suffix,
|
||||||
}
|
}
|
||||||
|
@ -674,8 +677,8 @@ func TestServer_ProcessRestrictLocal(t *testing.T) {
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
// TODO(s.chzhen): Add tests where EDNSClientSubnet.Enabled is true.
|
// TODO(s.chzhen): Add tests where EDNSClientSubnet.Enabled is true.
|
||||||
// Improve FilteringConfig declaration for tests.
|
// Improve Config declaration for tests.
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
}, ups)
|
}, ups)
|
||||||
|
@ -750,7 +753,7 @@ func TestServer_ProcessLocalPTR_usingResolvers(t *testing.T) {
|
||||||
ServerConfig{
|
ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
FilteringConfig: FilteringConfig{
|
Config: Config{
|
||||||
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||||
"github.com/AdguardTeam/urlfilter/rules"
|
"github.com/AdguardTeam/urlfilter/rules"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
@ -13,11 +14,7 @@ func TestGenAnswerHTTPS_andSVCB(t *testing.T) {
|
||||||
// Preconditions.
|
// Preconditions.
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
conf: ServerConfig{
|
dnsFilter: &filtering.DNSFilter{},
|
||||||
FilteringConfig: FilteringConfig{
|
|
||||||
BlockedResponseTTL: 3600,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
req := &dns.Msg{
|
req := &dns.Msg{
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||||
|
@ -76,35 +77,19 @@ type Resolver interface {
|
||||||
|
|
||||||
// Config allows you to configure DNS filtering with New() or just change variables directly.
|
// Config allows you to configure DNS filtering with New() or just change variables directly.
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
// BlockingIPv4 is the IP address to be returned for a blocked A request.
|
||||||
|
BlockingIPv4 netip.Addr `yaml:"blocking_ipv4"`
|
||||||
|
|
||||||
|
// BlockingIPv6 is the IP address to be returned for a blocked AAAA request.
|
||||||
|
BlockingIPv6 netip.Addr `yaml:"blocking_ipv6"`
|
||||||
|
|
||||||
// SafeBrowsingChecker is the safe browsing hash-prefix checker.
|
// SafeBrowsingChecker is the safe browsing hash-prefix checker.
|
||||||
SafeBrowsingChecker Checker `yaml:"-"`
|
SafeBrowsingChecker Checker `yaml:"-"`
|
||||||
|
|
||||||
// ParentControl is the parental control hash-prefix checker.
|
// ParentControl is the parental control hash-prefix checker.
|
||||||
ParentalControlChecker Checker `yaml:"-"`
|
ParentalControlChecker Checker `yaml:"-"`
|
||||||
|
|
||||||
// enabled is used to be returned within Settings.
|
SafeSearch SafeSearch `yaml:"-"`
|
||||||
//
|
|
||||||
// It is of type uint32 to be accessed by atomic.
|
|
||||||
//
|
|
||||||
// TODO(e.burkov): Use atomic.Bool in Go 1.19.
|
|
||||||
enabled uint32
|
|
||||||
|
|
||||||
FilteringEnabled bool `yaml:"filtering_enabled"` // whether or not use filter lists
|
|
||||||
FiltersUpdateIntervalHours uint32 `yaml:"filters_update_interval"` // time period to update filters (in hours)
|
|
||||||
|
|
||||||
ParentalEnabled bool `yaml:"parental_enabled"`
|
|
||||||
SafeBrowsingEnabled bool `yaml:"safebrowsing_enabled"`
|
|
||||||
|
|
||||||
SafeBrowsingCacheSize uint `yaml:"safebrowsing_cache_size"` // (in bytes)
|
|
||||||
SafeSearchCacheSize uint `yaml:"safesearch_cache_size"` // (in bytes)
|
|
||||||
ParentalCacheSize uint `yaml:"parental_cache_size"` // (in bytes)
|
|
||||||
// TODO(a.garipov): Use timeutil.Duration
|
|
||||||
CacheTime uint `yaml:"cache_time"` // Element's TTL (in minutes)
|
|
||||||
|
|
||||||
SafeSearchConf SafeSearchConfig `yaml:"safe_search"`
|
|
||||||
SafeSearch SafeSearch `yaml:"-"`
|
|
||||||
|
|
||||||
Rewrites []*LegacyRewrite `yaml:"rewrites"`
|
|
||||||
|
|
||||||
// BlockedServices is the configuration of blocked services.
|
// BlockedServices is the configuration of blocked services.
|
||||||
// Per-client settings can override this configuration.
|
// Per-client settings can override this configuration.
|
||||||
|
@ -123,11 +108,30 @@ type Config struct {
|
||||||
// HTTPClient is the client to use for updating the remote filters.
|
// HTTPClient is the client to use for updating the remote filters.
|
||||||
HTTPClient *http.Client `yaml:"-"`
|
HTTPClient *http.Client `yaml:"-"`
|
||||||
|
|
||||||
|
// filtersMu protects filter lists.
|
||||||
|
filtersMu *sync.RWMutex
|
||||||
|
|
||||||
|
// ProtectionDisabledUntil is the timestamp until when the protection is
|
||||||
|
// disabled.
|
||||||
|
ProtectionDisabledUntil *time.Time `yaml:"protection_disabled_until"`
|
||||||
|
|
||||||
|
SafeSearchConf SafeSearchConfig `yaml:"safe_search"`
|
||||||
|
|
||||||
// DataDir is used to store filters' contents.
|
// DataDir is used to store filters' contents.
|
||||||
DataDir string `yaml:"-"`
|
DataDir string `yaml:"-"`
|
||||||
|
|
||||||
// filtersMu protects filter lists.
|
// BlockingMode defines the way how blocked responses are constructed.
|
||||||
filtersMu *sync.RWMutex
|
BlockingMode BlockingMode `yaml:"blocking_mode"`
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
|
||||||
|
Rewrites []*LegacyRewrite `yaml:"rewrites"`
|
||||||
|
|
||||||
// Filters are the blocking filter lists.
|
// Filters are the blocking filter lists.
|
||||||
Filters []FilterYAML `yaml:"-"`
|
Filters []FilterYAML `yaml:"-"`
|
||||||
|
@ -137,8 +141,62 @@ type Config struct {
|
||||||
|
|
||||||
// UserRules is the global list of custom rules.
|
// UserRules is the global list of custom rules.
|
||||||
UserRules []string `yaml:"-"`
|
UserRules []string `yaml:"-"`
|
||||||
|
|
||||||
|
SafeBrowsingCacheSize uint `yaml:"safebrowsing_cache_size"` // (in bytes)
|
||||||
|
SafeSearchCacheSize uint `yaml:"safesearch_cache_size"` // (in bytes)
|
||||||
|
ParentalCacheSize uint `yaml:"parental_cache_size"` // (in bytes)
|
||||||
|
// TODO(a.garipov): Use timeutil.Duration
|
||||||
|
CacheTime uint `yaml:"cache_time"` // Element's TTL (in minutes)
|
||||||
|
|
||||||
|
// enabled is used to be returned within Settings.
|
||||||
|
//
|
||||||
|
// It is of type uint32 to be accessed by atomic.
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): Use atomic.Bool in Go 1.19.
|
||||||
|
enabled uint32
|
||||||
|
|
||||||
|
// FiltersUpdateIntervalHours is the time period to update filters
|
||||||
|
// (in hours).
|
||||||
|
FiltersUpdateIntervalHours uint32 `yaml:"filters_update_interval"`
|
||||||
|
|
||||||
|
// BlockedResponseTTL is the time-to-live value for blocked responses. If
|
||||||
|
// 0, then default value is used (3600).
|
||||||
|
BlockedResponseTTL uint32 `yaml:"blocked_response_ttl"`
|
||||||
|
|
||||||
|
// FilteringEnabled indicates whether or not use filter lists.
|
||||||
|
FilteringEnabled bool `yaml:"filtering_enabled"`
|
||||||
|
|
||||||
|
ParentalEnabled bool `yaml:"parental_enabled"`
|
||||||
|
SafeBrowsingEnabled bool `yaml:"safebrowsing_enabled"`
|
||||||
|
|
||||||
|
// ProtectionEnabled defines whether or not use any of filtering features.
|
||||||
|
ProtectionEnabled bool `yaml:"protection_enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BlockingMode is an enum of all allowed blocking modes.
|
||||||
|
type BlockingMode string
|
||||||
|
|
||||||
|
// Allowed blocking modes.
|
||||||
|
const (
|
||||||
|
// BlockingModeCustomIP means respond with a custom IP address.
|
||||||
|
BlockingModeCustomIP BlockingMode = "custom_ip"
|
||||||
|
|
||||||
|
// BlockingModeDefault is the same as BlockingModeNullIP for
|
||||||
|
// Adblock-style rules, but responds with the IP address specified in
|
||||||
|
// the rule when blocked by an `/etc/hosts`-style rule.
|
||||||
|
BlockingModeDefault BlockingMode = "default"
|
||||||
|
|
||||||
|
// BlockingModeNullIP means respond with a zero IP address: "0.0.0.0"
|
||||||
|
// for A requests and "::" for AAAA ones.
|
||||||
|
BlockingModeNullIP BlockingMode = "null_ip"
|
||||||
|
|
||||||
|
// BlockingModeNXDOMAIN means respond with the NXDOMAIN code.
|
||||||
|
BlockingModeNXDOMAIN BlockingMode = "nxdomain"
|
||||||
|
|
||||||
|
// BlockingModeREFUSED means respond with the REFUSED code.
|
||||||
|
BlockingModeREFUSED BlockingMode = "refused"
|
||||||
|
)
|
||||||
|
|
||||||
// LookupStats store stats collected during safebrowsing or parental checks
|
// LookupStats store stats collected during safebrowsing or parental checks
|
||||||
type LookupStats struct {
|
type LookupStats struct {
|
||||||
Requests uint64 // number of HTTP requests that were sent
|
Requests uint64 // number of HTTP requests that were sent
|
||||||
|
@ -182,6 +240,15 @@ type DNSFilter struct {
|
||||||
rulesStorageAllow *filterlist.RuleStorage
|
rulesStorageAllow *filterlist.RuleStorage
|
||||||
filteringEngineAllow *urlfilter.DNSEngine
|
filteringEngineAllow *urlfilter.DNSEngine
|
||||||
|
|
||||||
|
// Config contains filtering parameters. For direct access by library
|
||||||
|
// users, even a = assignment.
|
||||||
|
//
|
||||||
|
// TODO(d.kolyshev): Remove this embed.
|
||||||
|
Config
|
||||||
|
|
||||||
|
// confLock protects Config.
|
||||||
|
confLock sync.RWMutex
|
||||||
|
|
||||||
safeSearch SafeSearch
|
safeSearch SafeSearch
|
||||||
|
|
||||||
// safeBrowsingChecker is the safe browsing hash-prefix checker.
|
// safeBrowsingChecker is the safe browsing hash-prefix checker.
|
||||||
|
@ -192,10 +259,6 @@ type DNSFilter struct {
|
||||||
|
|
||||||
engineLock sync.RWMutex
|
engineLock sync.RWMutex
|
||||||
|
|
||||||
Config // for direct access by library users, even a = assignment
|
|
||||||
// confLock protects Config.
|
|
||||||
confLock sync.RWMutex
|
|
||||||
|
|
||||||
// Channel for passing data to filters-initializer goroutine
|
// Channel for passing data to filters-initializer goroutine
|
||||||
filtersInitializerChan chan filtersInitializerParams
|
filtersInitializerChan chan filtersInitializerParams
|
||||||
filtersInitializerLock sync.Mutex
|
filtersInitializerLock sync.Mutex
|
||||||
|
|
|
@ -131,7 +131,8 @@ type configuration struct {
|
||||||
WhitelistFilters []filtering.FilterYAML `yaml:"whitelist_filters"`
|
WhitelistFilters []filtering.FilterYAML `yaml:"whitelist_filters"`
|
||||||
UserRules []string `yaml:"user_rules"`
|
UserRules []string `yaml:"user_rules"`
|
||||||
|
|
||||||
DHCP *dhcpd.ServerConfig `yaml:"dhcp"`
|
DHCP *dhcpd.ServerConfig `yaml:"dhcp"`
|
||||||
|
Filtering *filtering.Config `yaml:"filtering"`
|
||||||
|
|
||||||
// Clients contains the YAML representations of the persistent clients.
|
// Clients contains the YAML representations of the persistent clients.
|
||||||
// This field is only used for reading and writing persistent client data.
|
// This field is only used for reading and writing persistent client data.
|
||||||
|
@ -185,9 +186,10 @@ type dnsConfig struct {
|
||||||
// in query log and statistics.
|
// in query log and statistics.
|
||||||
AnonymizeClientIP bool `yaml:"anonymize_client_ip"`
|
AnonymizeClientIP bool `yaml:"anonymize_client_ip"`
|
||||||
|
|
||||||
dnsforward.FilteringConfig `yaml:",inline"`
|
// Config is the embed configuration with DNS params.
|
||||||
|
//
|
||||||
DnsfilterConf *filtering.Config `yaml:",inline"`
|
// TODO(a.garipov): Remove embed.
|
||||||
|
dnsforward.Config `yaml:",inline"`
|
||||||
|
|
||||||
// UpstreamTimeout is the timeout for querying upstream servers.
|
// UpstreamTimeout is the timeout for querying upstream servers.
|
||||||
UpstreamTimeout timeutil.Duration `yaml:"upstream_timeout"`
|
UpstreamTimeout timeutil.Duration `yaml:"upstream_timeout"`
|
||||||
|
@ -295,14 +297,11 @@ var config = &configuration{
|
||||||
DNS: dnsConfig{
|
DNS: dnsConfig{
|
||||||
BindHosts: []netip.Addr{netip.IPv4Unspecified()},
|
BindHosts: []netip.Addr{netip.IPv4Unspecified()},
|
||||||
Port: defaultPortDNS,
|
Port: defaultPortDNS,
|
||||||
FilteringConfig: dnsforward.FilteringConfig{
|
Config: dnsforward.Config{
|
||||||
ProtectionEnabled: true, // whether or not use any of filtering features
|
Ratelimit: 20,
|
||||||
BlockingMode: dnsforward.BlockingModeDefault,
|
RefuseAny: true,
|
||||||
BlockedResponseTTL: 10, // in seconds
|
AllServers: false,
|
||||||
Ratelimit: 20,
|
HandleDDR: true,
|
||||||
RefuseAny: true,
|
|
||||||
AllServers: false,
|
|
||||||
HandleDDR: true,
|
|
||||||
FastestTimeout: timeutil.Duration{
|
FastestTimeout: timeutil.Duration{
|
||||||
Duration: fastip.DefaultPingWaitTimeout,
|
Duration: fastip.DefaultPingWaitTimeout,
|
||||||
},
|
},
|
||||||
|
@ -322,33 +321,6 @@ var config = &configuration{
|
||||||
// was later increased to 300 due to https://github.com/AdguardTeam/AdGuardHome/issues/2257
|
// was later increased to 300 due to https://github.com/AdguardTeam/AdGuardHome/issues/2257
|
||||||
MaxGoroutines: 300,
|
MaxGoroutines: 300,
|
||||||
},
|
},
|
||||||
DnsfilterConf: &filtering.Config{
|
|
||||||
FilteringEnabled: true,
|
|
||||||
FiltersUpdateIntervalHours: 24,
|
|
||||||
|
|
||||||
ParentalEnabled: false,
|
|
||||||
SafeBrowsingEnabled: false,
|
|
||||||
|
|
||||||
SafeBrowsingCacheSize: 1 * 1024 * 1024,
|
|
||||||
SafeSearchCacheSize: 1 * 1024 * 1024,
|
|
||||||
ParentalCacheSize: 1 * 1024 * 1024,
|
|
||||||
CacheTime: 30,
|
|
||||||
|
|
||||||
SafeSearchConf: filtering.SafeSearchConfig{
|
|
||||||
Enabled: false,
|
|
||||||
Bing: true,
|
|
||||||
DuckDuckGo: true,
|
|
||||||
Google: true,
|
|
||||||
Pixabay: true,
|
|
||||||
Yandex: true,
|
|
||||||
YouTube: true,
|
|
||||||
},
|
|
||||||
|
|
||||||
BlockedServices: &filtering.BlockedServices{
|
|
||||||
Schedule: schedule.EmptyWeekly(),
|
|
||||||
IDs: []string{},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
UpstreamTimeout: timeutil.Duration{Duration: dnsforward.DefaultTimeout},
|
UpstreamTimeout: timeutil.Duration{Duration: dnsforward.DefaultTimeout},
|
||||||
UsePrivateRDNS: true,
|
UsePrivateRDNS: true,
|
||||||
},
|
},
|
||||||
|
@ -385,6 +357,37 @@ var config = &configuration{
|
||||||
URL: "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt",
|
URL: "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt",
|
||||||
Name: "AdAway Default Blocklist",
|
Name: "AdAway Default Blocklist",
|
||||||
}},
|
}},
|
||||||
|
Filtering: &filtering.Config{
|
||||||
|
ProtectionEnabled: true,
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
BlockedResponseTTL: 10, // in seconds
|
||||||
|
|
||||||
|
FilteringEnabled: true,
|
||||||
|
FiltersUpdateIntervalHours: 24,
|
||||||
|
|
||||||
|
ParentalEnabled: false,
|
||||||
|
SafeBrowsingEnabled: false,
|
||||||
|
|
||||||
|
SafeBrowsingCacheSize: 1 * 1024 * 1024,
|
||||||
|
SafeSearchCacheSize: 1 * 1024 * 1024,
|
||||||
|
ParentalCacheSize: 1 * 1024 * 1024,
|
||||||
|
CacheTime: 30,
|
||||||
|
|
||||||
|
SafeSearchConf: filtering.SafeSearchConfig{
|
||||||
|
Enabled: false,
|
||||||
|
Bing: true,
|
||||||
|
DuckDuckGo: true,
|
||||||
|
Google: true,
|
||||||
|
Pixabay: true,
|
||||||
|
Yandex: true,
|
||||||
|
YouTube: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
BlockedServices: &filtering.BlockedServices{
|
||||||
|
Schedule: schedule.EmptyWeekly(),
|
||||||
|
IDs: []string{},
|
||||||
|
},
|
||||||
|
},
|
||||||
DHCP: &dhcpd.ServerConfig{
|
DHCP: &dhcpd.ServerConfig{
|
||||||
LocalDomainName: "lan",
|
LocalDomainName: "lan",
|
||||||
Conf4: dhcpd.V4ServerConf{
|
Conf4: dhcpd.V4ServerConf{
|
||||||
|
@ -493,8 +496,8 @@ func parseConfig() (err error) {
|
||||||
return fmt.Errorf("validating udp ports: %w", err)
|
return fmt.Errorf("validating udp ports: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !filtering.ValidateUpdateIvl(config.DNS.DnsfilterConf.FiltersUpdateIntervalHours) {
|
if !filtering.ValidateUpdateIvl(config.Filtering.FiltersUpdateIntervalHours) {
|
||||||
config.DNS.DnsfilterConf.FiltersUpdateIntervalHours = 24
|
config.Filtering.FiltersUpdateIntervalHours = 24
|
||||||
}
|
}
|
||||||
|
|
||||||
if config.DNS.UpstreamTimeout.Duration == 0 {
|
if config.DNS.UpstreamTimeout.Duration == 0 {
|
||||||
|
@ -574,17 +577,17 @@ func (c *configuration) write() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if Context.filters != nil {
|
if Context.filters != nil {
|
||||||
Context.filters.WriteDiskConfig(config.DNS.DnsfilterConf)
|
Context.filters.WriteDiskConfig(config.Filtering)
|
||||||
config.Filters = config.DNS.DnsfilterConf.Filters
|
config.Filters = config.Filtering.Filters
|
||||||
config.WhitelistFilters = config.DNS.DnsfilterConf.WhitelistFilters
|
config.WhitelistFilters = config.Filtering.WhitelistFilters
|
||||||
config.UserRules = config.DNS.DnsfilterConf.UserRules
|
config.UserRules = config.Filtering.UserRules
|
||||||
}
|
}
|
||||||
|
|
||||||
if s := Context.dnsServer; s != nil {
|
if s := Context.dnsServer; s != nil {
|
||||||
c := dnsforward.FilteringConfig{}
|
c := dnsforward.Config{}
|
||||||
s.WriteDiskConfig(&c)
|
s.WriteDiskConfig(&c)
|
||||||
dns := &config.DNS
|
dns := &config.DNS
|
||||||
dns.FilteringConfig = c
|
dns.Config = c
|
||||||
|
|
||||||
dns.LocalPTRResolvers = s.LocalPTRResolvers()
|
dns.LocalPTRResolvers = s.LocalPTRResolvers()
|
||||||
|
|
||||||
|
|
|
@ -127,12 +127,12 @@ func handleStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
fltConf *dnsforward.FilteringConfig
|
fltConf *dnsforward.Config
|
||||||
protectionDisabledUntil *time.Time
|
protectionDisabledUntil *time.Time
|
||||||
protectionEnabled bool
|
protectionEnabled bool
|
||||||
)
|
)
|
||||||
if Context.dnsServer != nil {
|
if Context.dnsServer != nil {
|
||||||
fltConf = &dnsforward.FilteringConfig{}
|
fltConf = &dnsforward.Config{}
|
||||||
Context.dnsServer.WriteDiskConfig(fltConf)
|
Context.dnsServer.WriteDiskConfig(fltConf)
|
||||||
protectionEnabled, protectionDisabledUntil = Context.dnsServer.UpdatedProtectionStatus()
|
protectionEnabled, protectionDisabledUntil = Context.dnsServer.UpdatedProtectionStatus()
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ func initDNS() (err error) {
|
||||||
return fmt.Errorf("init querylog: %w", err)
|
return fmt.Errorf("init querylog: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
Context.filters, err = filtering.New(config.DNS.DnsfilterConf, nil)
|
Context.filters, err = filtering.New(config.Filtering, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap the error, since it's informative enough as is.
|
// Don't wrap the error, since it's informative enough as is.
|
||||||
return err
|
return err
|
||||||
|
@ -230,13 +230,13 @@ func newServerConfig(
|
||||||
hosts := aghalg.CoalesceSlice(dnsConf.BindHosts, []netip.Addr{netutil.IPv4Localhost()})
|
hosts := aghalg.CoalesceSlice(dnsConf.BindHosts, []netip.Addr{netutil.IPv4Localhost()})
|
||||||
|
|
||||||
newConf = &dnsforward.ServerConfig{
|
newConf = &dnsforward.ServerConfig{
|
||||||
UDPListenAddrs: ipsToUDPAddrs(hosts, dnsConf.Port),
|
UDPListenAddrs: ipsToUDPAddrs(hosts, dnsConf.Port),
|
||||||
TCPListenAddrs: ipsToTCPAddrs(hosts, dnsConf.Port),
|
TCPListenAddrs: ipsToTCPAddrs(hosts, dnsConf.Port),
|
||||||
FilteringConfig: dnsConf.FilteringConfig,
|
Config: dnsConf.Config,
|
||||||
ConfigModified: onConfigModified,
|
ConfigModified: onConfigModified,
|
||||||
HTTPRegister: httpReg,
|
HTTPRegister: httpReg,
|
||||||
UseDNS64: config.DNS.UseDNS64,
|
UseDNS64: config.DNS.UseDNS64,
|
||||||
DNS64Prefixes: config.DNS.DNS64Prefixes,
|
DNS64Prefixes: config.DNS.DNS64Prefixes,
|
||||||
}
|
}
|
||||||
|
|
||||||
var initialAddresses []netip.Addr
|
var initialAddresses []netip.Addr
|
||||||
|
|
|
@ -272,7 +272,7 @@ func setupOpts(opts options) (err error) {
|
||||||
|
|
||||||
// initContextClients initializes Context clients and related fields.
|
// initContextClients initializes Context clients and related fields.
|
||||||
func initContextClients() (err error) {
|
func initContextClients() (err error) {
|
||||||
err = setupDNSFilteringConf(config.DNS.DnsfilterConf)
|
err = setupDNSFilteringConf(config.Filtering)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap the error, because it's informative enough as is.
|
// Don't wrap the error, because it's informative enough as is.
|
||||||
return err
|
return err
|
||||||
|
@ -303,7 +303,7 @@ func initContextClients() (err error) {
|
||||||
Context.dhcpServer,
|
Context.dhcpServer,
|
||||||
Context.etcHosts,
|
Context.etcHosts,
|
||||||
arpDB,
|
arpDB,
|
||||||
config.DNS.DnsfilterConf,
|
config.Filtering,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't wrap the error, because it's informative enough as is.
|
// Don't wrap the error, because it's informative enough as is.
|
||||||
|
@ -365,6 +365,9 @@ func setupDNSFilteringConf(conf *filtering.Config) (err error) {
|
||||||
pcService = "parental control"
|
pcService = "parental control"
|
||||||
defaultParentalServer = `https://family.adguard-dns.com/dns-query`
|
defaultParentalServer = `https://family.adguard-dns.com/dns-query`
|
||||||
pcTXTSuffix = `pc.dns.adguard.com.`
|
pcTXTSuffix = `pc.dns.adguard.com.`
|
||||||
|
|
||||||
|
defaultSafeBrowsingBlockHost = "standard-block.dns.adguard.com"
|
||||||
|
defaultParentalBlockHost = "family-block.dns.adguard.com"
|
||||||
)
|
)
|
||||||
|
|
||||||
conf.EtcHosts = Context.etcHosts
|
conf.EtcHosts = Context.etcHosts
|
||||||
|
@ -401,6 +404,10 @@ func setupDNSFilteringConf(conf *filtering.Config) (err error) {
|
||||||
CacheSize: conf.SafeBrowsingCacheSize,
|
CacheSize: conf.SafeBrowsingCacheSize,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if conf.SafeBrowsingBlockHost != "" {
|
||||||
|
conf.SafeBrowsingBlockHost = defaultSafeBrowsingBlockHost
|
||||||
|
}
|
||||||
|
|
||||||
parUps, err := upstream.AddressToUpstream(defaultParentalServer, upsOpts)
|
parUps, err := upstream.AddressToUpstream(defaultParentalServer, upsOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("converting parental server: %w", err)
|
return fmt.Errorf("converting parental server: %w", err)
|
||||||
|
@ -414,6 +421,10 @@ func setupDNSFilteringConf(conf *filtering.Config) (err error) {
|
||||||
CacheSize: conf.ParentalCacheSize,
|
CacheSize: conf.ParentalCacheSize,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if conf.ParentalBlockHost != "" {
|
||||||
|
conf.ParentalBlockHost = defaultParentalBlockHost
|
||||||
|
}
|
||||||
|
|
||||||
conf.SafeSearchConf.CustomResolver = safeSearchResolver{}
|
conf.SafeSearchConf.CustomResolver = safeSearchResolver{}
|
||||||
conf.SafeSearch, err = safesearch.NewDefault(
|
conf.SafeSearch, err = safesearch.NewDefault(
|
||||||
conf.SafeSearchConf,
|
conf.SafeSearchConf,
|
||||||
|
@ -544,7 +555,7 @@ func run(opts options, clientBuildFS fs.FS, done chan struct{}) {
|
||||||
fatalOnError(err)
|
fatalOnError(err)
|
||||||
|
|
||||||
upd := updater.NewUpdater(&updater.Config{
|
upd := updater.NewUpdater(&updater.Config{
|
||||||
Client: config.DNS.DnsfilterConf.HTTPClient,
|
Client: config.Filtering.HTTPClient,
|
||||||
Version: version.Version(),
|
Version: version.Version(),
|
||||||
Channel: version.Channel(),
|
Channel: version.Channel(),
|
||||||
GOARCH: runtime.GOARCH,
|
GOARCH: runtime.GOARCH,
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// currentSchemaVersion is the current schema version.
|
// currentSchemaVersion is the current schema version.
|
||||||
const currentSchemaVersion = 25
|
const currentSchemaVersion = 26
|
||||||
|
|
||||||
// These aliases are provided for convenience.
|
// These aliases are provided for convenience.
|
||||||
type (
|
type (
|
||||||
|
@ -100,6 +100,7 @@ func upgradeConfigSchema(oldVersion int, diskConf yobj) (err error) {
|
||||||
upgradeSchema22to23,
|
upgradeSchema22to23,
|
||||||
upgradeSchema23to24,
|
upgradeSchema23to24,
|
||||||
upgradeSchema24to25,
|
upgradeSchema24to25,
|
||||||
|
upgradeSchema25to26,
|
||||||
}
|
}
|
||||||
|
|
||||||
n := 0
|
n := 0
|
||||||
|
@ -1425,34 +1426,172 @@ func upgradeSchema24to25(diskConf yobj) (err error) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// moveField gets field value for key from diskConf, and then set this value
|
// upgradeSchema25to26 performs the following changes:
|
||||||
// in newConf for newKey.
|
//
|
||||||
func moveField[T any](diskConf, newConf yobj, key, newKey string) (err error) {
|
// # BEFORE:
|
||||||
ok, newVal, err := fieldValue[T](diskConf, key)
|
// 'dns':
|
||||||
|
// 'filtering_enabled': true
|
||||||
|
// 'filters_update_interval': 24
|
||||||
|
// 'parental_enabled': false
|
||||||
|
// 'safebrowsing_enabled': false
|
||||||
|
// 'safebrowsing_cache_size': 1048576
|
||||||
|
// 'safesearch_cache_size': 1048576
|
||||||
|
// 'parental_cache_size': 1048576
|
||||||
|
// 'safe_search':
|
||||||
|
// 'enabled': false
|
||||||
|
// 'bing': true
|
||||||
|
// 'duckduckgo': true
|
||||||
|
// 'google': true
|
||||||
|
// 'pixabay': true
|
||||||
|
// 'yandex': true
|
||||||
|
// 'youtube': true
|
||||||
|
// 'rewrites': []
|
||||||
|
// 'blocked_services':
|
||||||
|
// 'schedule':
|
||||||
|
// 'time_zone': 'Local'
|
||||||
|
// 'ids': []
|
||||||
|
// 'protection_enabled': true,
|
||||||
|
// 'blocking_mode': 'custom_ip',
|
||||||
|
// 'blocking_ipv4': '1.2.3.4',
|
||||||
|
// 'blocking_ipv6': '1:2:3::4',
|
||||||
|
// 'blocked_response_ttl': 10,
|
||||||
|
// 'protection_disabled_until': 'null',
|
||||||
|
// 'parental_block_host': 'p.dns.adguard.com',
|
||||||
|
// 'safebrowsing_block_host': 's.dns.adguard.com',
|
||||||
|
// ...
|
||||||
|
//
|
||||||
|
// # AFTER:
|
||||||
|
// 'filtering':
|
||||||
|
// 'filtering_enabled': true
|
||||||
|
// 'filters_update_interval': 24
|
||||||
|
// 'parental_enabled': false
|
||||||
|
// 'safebrowsing_enabled': false
|
||||||
|
// 'safebrowsing_cache_size': 1048576
|
||||||
|
// 'safesearch_cache_size': 1048576
|
||||||
|
// 'parental_cache_size': 1048576
|
||||||
|
// 'safe_search':
|
||||||
|
// 'enabled': false
|
||||||
|
// 'bing': true
|
||||||
|
// 'duckduckgo': true
|
||||||
|
// 'google': true
|
||||||
|
// 'pixabay': true
|
||||||
|
// 'yandex': true
|
||||||
|
// 'youtube': true
|
||||||
|
// 'rewrites': []
|
||||||
|
// 'blocked_services':
|
||||||
|
// 'schedule':
|
||||||
|
// 'time_zone': 'Local'
|
||||||
|
// 'ids': []
|
||||||
|
// 'protection_enabled': true,
|
||||||
|
// 'blocking_mode': 'custom_ip',
|
||||||
|
// 'blocking_ipv4': '1.2.3.4',
|
||||||
|
// 'blocking_ipv6': '1:2:3::4',
|
||||||
|
// 'blocked_response_ttl': 10,
|
||||||
|
// 'protection_disabled_until': 'null',
|
||||||
|
// 'parental_block_host': 'p.dns.adguard.com',
|
||||||
|
// 'safebrowsing_block_host': 's.dns.adguard.com',
|
||||||
|
// 'dns'
|
||||||
|
// ...
|
||||||
|
func upgradeSchema25to26(diskConf yobj) (err error) {
|
||||||
|
log.Printf("Upgrade yaml: 25 to 26")
|
||||||
|
diskConf["schema_version"] = 26
|
||||||
|
|
||||||
|
dnsVal, ok := diskConf["dns"]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
dnsObj, ok := dnsVal.(yobj)
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("unexpected type of dns: %T", dnsVal)
|
||||||
|
}
|
||||||
|
|
||||||
|
filteringObj := yobj{}
|
||||||
|
err = coalesceError(
|
||||||
|
moveFieldValue[bool](dnsObj, filteringObj, "filtering_enabled"),
|
||||||
|
moveFieldValue[int](dnsObj, filteringObj, "filters_update_interval"),
|
||||||
|
moveFieldValue[bool](dnsObj, filteringObj, "parental_enabled"),
|
||||||
|
moveFieldValue[bool](dnsObj, filteringObj, "safebrowsing_enabled"),
|
||||||
|
moveFieldValue[int](dnsObj, filteringObj, "safebrowsing_cache_size"),
|
||||||
|
moveFieldValue[int](dnsObj, filteringObj, "safesearch_cache_size"),
|
||||||
|
moveFieldValue[int](dnsObj, filteringObj, "parental_cache_size"),
|
||||||
|
moveFieldValue[yobj](dnsObj, filteringObj, "safe_search"),
|
||||||
|
moveFieldValue[yarr](dnsObj, filteringObj, "rewrites"),
|
||||||
|
moveFieldValue[yobj](dnsObj, filteringObj, "blocked_services"),
|
||||||
|
moveFieldValue[bool](dnsObj, filteringObj, "protection_enabled"),
|
||||||
|
moveFieldValue[string](dnsObj, filteringObj, "blocking_mode"),
|
||||||
|
moveFieldValue[string](dnsObj, filteringObj, "blocking_ipv4"),
|
||||||
|
moveFieldValue[string](dnsObj, filteringObj, "blocking_ipv6"),
|
||||||
|
moveFieldValue[int](dnsObj, filteringObj, "blocked_response_ttl"),
|
||||||
|
moveFieldValue[any](dnsObj, filteringObj, "protection_disabled_until"),
|
||||||
|
moveFieldValue[string](dnsObj, filteringObj, "parental_block_host"),
|
||||||
|
moveFieldValue[string](dnsObj, filteringObj, "safebrowsing_block_host"),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
// Don't wrap the error, because it's informative enough as is.
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
switch v := newVal.(type) {
|
if len(filteringObj) != 0 {
|
||||||
case int, bool, string:
|
diskConf["filtering"] = filteringObj
|
||||||
newConf[newKey] = v
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("invalid type of %s: %T", key, newVal)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete(dnsObj, "filtering_enabled")
|
||||||
|
delete(dnsObj, "filters_update_interval")
|
||||||
|
delete(dnsObj, "parental_enabled")
|
||||||
|
delete(dnsObj, "safebrowsing_enabled")
|
||||||
|
delete(dnsObj, "safebrowsing_cache_size")
|
||||||
|
delete(dnsObj, "safesearch_cache_size")
|
||||||
|
delete(dnsObj, "parental_cache_size")
|
||||||
|
delete(dnsObj, "safe_search")
|
||||||
|
delete(dnsObj, "rewrites")
|
||||||
|
delete(dnsObj, "blocked_services")
|
||||||
|
delete(dnsObj, "protection_enabled")
|
||||||
|
delete(dnsObj, "blocking_mode")
|
||||||
|
delete(dnsObj, "blocking_ipv4")
|
||||||
|
delete(dnsObj, "blocking_ipv6")
|
||||||
|
delete(dnsObj, "blocked_response_ttl")
|
||||||
|
delete(dnsObj, "protection_disabled_until")
|
||||||
|
delete(dnsObj, "parental_block_host")
|
||||||
|
delete(dnsObj, "safebrowsing_block_host")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// fieldValue returns the value of type T for key in diskConf object.
|
// moveField gets field value for key from fromObj, and then sets this value in
|
||||||
func fieldValue[T any](diskConf yobj, key string) (ok bool, field any, err error) {
|
// newConf for newKey.
|
||||||
fieldVal, ok := diskConf[key]
|
func moveField[T any](fromObj, newConf yobj, key, newKey string) (err error) {
|
||||||
|
ok, newVal, err := fieldValue[T](fromObj, key)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, new(T), nil
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
newConf[newKey] = newVal
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// moveFieldValue gets field value for key from fromObj, and then sets this
|
||||||
|
// value in newConf with the same key.
|
||||||
|
func moveFieldValue[T any](fromObj, newConf yobj, key string) (err error) {
|
||||||
|
return moveField[T](fromObj, newConf, key, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fieldValue returns the value of type T for key in confObj object. Returns
|
||||||
|
// nil for fields with nil values.
|
||||||
|
func fieldValue[T any](confObj yobj, key string) (ok bool, field T, err error) {
|
||||||
|
fieldVal, ok := confObj[key]
|
||||||
|
if !ok {
|
||||||
|
return false, field, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if fieldVal == nil {
|
||||||
|
return true, field, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
f, ok := fieldVal.(T)
|
f, ok := fieldVal.(T)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false, nil, fmt.Errorf("unexpected type of %s: %T", key, fieldVal)
|
return false, field, fmt.Errorf("unexpected type of %s: %T", key, fieldVal)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true, f, nil
|
return true, f, nil
|
||||||
|
|
|
@ -1466,3 +1466,102 @@ func TestUpgradeSchema24to25(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpgradeSchema25to26(t *testing.T) {
|
||||||
|
const newSchemaVer = 26
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
in yobj
|
||||||
|
want yobj
|
||||||
|
name string
|
||||||
|
}{{
|
||||||
|
name: "empty",
|
||||||
|
in: yobj{},
|
||||||
|
want: yobj{
|
||||||
|
"schema_version": newSchemaVer,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "ok",
|
||||||
|
in: yobj{
|
||||||
|
"dns": yobj{
|
||||||
|
"filtering_enabled": true,
|
||||||
|
"filters_update_interval": 24,
|
||||||
|
"parental_enabled": false,
|
||||||
|
"safebrowsing_enabled": false,
|
||||||
|
"safebrowsing_cache_size": 1048576,
|
||||||
|
"safesearch_cache_size": 1048576,
|
||||||
|
"parental_cache_size": 1048576,
|
||||||
|
"safe_search": yobj{
|
||||||
|
"enabled": false,
|
||||||
|
"bing": true,
|
||||||
|
"duckduckgo": true,
|
||||||
|
"google": true,
|
||||||
|
"pixabay": true,
|
||||||
|
"yandex": true,
|
||||||
|
"youtube": true,
|
||||||
|
},
|
||||||
|
"rewrites": yarr{},
|
||||||
|
"blocked_services": yobj{
|
||||||
|
"schedule": yobj{
|
||||||
|
"time_zone": "Local",
|
||||||
|
},
|
||||||
|
"ids": yarr{},
|
||||||
|
},
|
||||||
|
"protection_enabled": true,
|
||||||
|
"blocking_mode": "custom_ip",
|
||||||
|
"blocking_ipv4": "1.2.3.4",
|
||||||
|
"blocking_ipv6": "1:2:3::4",
|
||||||
|
"blocked_response_ttl": 10,
|
||||||
|
"protection_disabled_until": nil,
|
||||||
|
"parental_block_host": "p.dns.adguard.com",
|
||||||
|
"safebrowsing_block_host": "s.dns.adguard.com",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: yobj{
|
||||||
|
"dns": yobj{},
|
||||||
|
"filtering": yobj{
|
||||||
|
"filtering_enabled": true,
|
||||||
|
"filters_update_interval": 24,
|
||||||
|
"parental_enabled": false,
|
||||||
|
"safebrowsing_enabled": false,
|
||||||
|
"safebrowsing_cache_size": 1048576,
|
||||||
|
"safesearch_cache_size": 1048576,
|
||||||
|
"parental_cache_size": 1048576,
|
||||||
|
"safe_search": yobj{
|
||||||
|
"enabled": false,
|
||||||
|
"bing": true,
|
||||||
|
"duckduckgo": true,
|
||||||
|
"google": true,
|
||||||
|
"pixabay": true,
|
||||||
|
"yandex": true,
|
||||||
|
"youtube": true,
|
||||||
|
},
|
||||||
|
"rewrites": yarr{},
|
||||||
|
"blocked_services": yobj{
|
||||||
|
"schedule": yobj{
|
||||||
|
"time_zone": "Local",
|
||||||
|
},
|
||||||
|
"ids": yarr{},
|
||||||
|
},
|
||||||
|
"protection_enabled": true,
|
||||||
|
"blocking_mode": "custom_ip",
|
||||||
|
"blocking_ipv4": "1.2.3.4",
|
||||||
|
"blocking_ipv6": "1:2:3::4",
|
||||||
|
"blocked_response_ttl": 10,
|
||||||
|
"protection_disabled_until": nil,
|
||||||
|
"parental_block_host": "p.dns.adguard.com",
|
||||||
|
"safebrowsing_block_host": "s.dns.adguard.com",
|
||||||
|
},
|
||||||
|
"schema_version": newSchemaVer,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
err := upgradeSchema25to26(tc.in)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.want, tc.in)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue