Pull request: AG-25263 dns config
Merge in DNS/adguard-home from AG-25263-dns-config to master Squashed commit of the following: commit 478b607526391af65de67d6d7f1d904198610cdf Merge: b944d12fa51340adb3
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Mon Sep 4 18:04:56 2023 +0400 Merge remote-tracking branch 'origin/master' into AG-25263-dns-config commit b944d12fa812b05b9d9f22d2287425ca36630329 Merge: b474f712f0182b9ec1
Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Sep 1 09:13:36 2023 +0400 Merge remote-tracking branch 'origin/master' into AG-25263-dns-config # Conflicts: # internal/dnsforward/dnsforward.go commit b474f712f64daa1a7d7e32d89edc901d2f273c9a Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Fri Sep 1 09:11:17 2023 +0400 all: imp code commit 635a316b8244f13d90a8fe2209f1673c0765aaa9 Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Aug 30 16:18:25 2023 +0300 all: dnsfilter rm config embed commit 5aa6212e89bc38e3d283b8d6b1a78726d10b3f3a Author: Dimitry Kolyshev <dkolyshev@adguard.com> Date: Wed Aug 30 12:45:01 2023 +0300 all: dnsfilter rm config embed
This commit is contained in:
parent
51340adb36
commit
f84ff2bd05
|
@ -492,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.dnsFilter.ProtectionDisabledUntil
|
enabled, disabledUntil = s.dnsFilter.ProtectionStatus()
|
||||||
if disabledUntil == nil {
|
if disabledUntil == nil {
|
||||||
return s.dnsFilter.ProtectionEnabled, nil
|
return enabled, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if time.Now().Before(*disabledUntil) {
|
if time.Now().Before(*disabledUntil) {
|
||||||
|
@ -526,8 +526,7 @@ func (s *Server) enableProtectionAfterPause() {
|
||||||
s.serverLock.Lock()
|
s.serverLock.Lock()
|
||||||
defer s.serverLock.Unlock()
|
defer s.serverLock.Unlock()
|
||||||
|
|
||||||
s.dnsFilter.ProtectionEnabled = true
|
s.dnsFilter.SetProtectionStatus(true, nil)
|
||||||
s.dnsFilter.ProtectionDisabledUntil = nil
|
|
||||||
|
|
||||||
log.Info("dns: protection is restarted after pause")
|
log.Info("dns: protection is restarted after pause")
|
||||||
}
|
}
|
||||||
|
|
|
@ -544,11 +544,8 @@ func (s *Server) Prepare(conf *ServerConfig) (err error) {
|
||||||
|
|
||||||
// dnsFilter can be nil during application update.
|
// dnsFilter can be nil during application update.
|
||||||
if s.dnsFilter != nil {
|
if s.dnsFilter != nil {
|
||||||
err = validateBlockingMode(
|
mode, bIPv4, bIPv6 := s.dnsFilter.BlockingMode()
|
||||||
s.dnsFilter.BlockingMode,
|
err = validateBlockingMode(mode, bIPv4, bIPv6)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -105,10 +105,6 @@ func createTestServer(
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
if s.dnsFilter.BlockingMode == "" {
|
|
||||||
s.dnsFilter.BlockingMode = filtering.BlockingModeDefault
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.Prepare(&forwardConf)
|
err = s.Prepare(&forwardConf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -178,7 +174,9 @@ func createTestTLS(t *testing.T, tlsConf TLSConfig) (s *Server, certPem []byte)
|
||||||
var keyPem []byte
|
var keyPem []byte
|
||||||
_, certPem, keyPem = createServerTLSConfig(t)
|
_, certPem, keyPem = createServerTLSConfig(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{{}},
|
||||||
Config: Config{
|
Config: Config{
|
||||||
|
@ -351,9 +349,8 @@ func TestServer_timeout(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := NewServer(DNSCreateParams{DNSFilter: &filtering.DNSFilter{}})
|
s, err := NewServer(DNSCreateParams{DNSFilter: createTestDNSFilter(t)})
|
||||||
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)
|
||||||
|
@ -362,10 +359,9 @@ func TestServer_timeout(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("default", func(t *testing.T) {
|
t.Run("default", func(t *testing.T) {
|
||||||
s, err := NewServer(DNSCreateParams{DNSFilter: &filtering.DNSFilter{}})
|
s, err := NewServer(DNSCreateParams{DNSFilter: createTestDNSFilter(t)})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
s.dnsFilter.BlockingMode = filtering.BlockingModeDefault
|
|
||||||
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{
|
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
}
|
}
|
||||||
|
@ -377,7 +373,9 @@ func TestServer_timeout(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServerWithProtectionDisabled(t *testing.T) {
|
func TestServerWithProtectionDisabled(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{{}},
|
||||||
Config: Config{
|
Config: Config{
|
||||||
|
@ -490,6 +488,7 @@ func TestSafeSearch(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
filterConf := &filtering.Config{
|
filterConf := &filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
SafeSearchConf: safeSearchConf,
|
SafeSearchConf: safeSearchConf,
|
||||||
SafeSearchCacheSize: 1000,
|
SafeSearchCacheSize: 1000,
|
||||||
|
@ -564,7 +563,9 @@ func TestSafeSearch(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalidRequest(t *testing.T) {
|
func TestInvalidRequest(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{{}},
|
||||||
Config: Config{
|
Config: Config{
|
||||||
|
@ -631,7 +632,9 @@ func TestServerCustomClientUpstream(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, forwardConf, nil)
|
||||||
s.conf.GetCustomUpstreamByClient = func(_ string) (conf *proxy.UpstreamConfig, err error) {
|
s.conf.GetCustomUpstreamByClient = func(_ string) (conf *proxy.UpstreamConfig, err error) {
|
||||||
ups := aghtest.NewUpstreamMock(func(req *dns.Msg) (resp *dns.Msg, err error) {
|
ups := aghtest.NewUpstreamMock(func(req *dns.Msg) (resp *dns.Msg, err error) {
|
||||||
return aghalg.Coalesce(
|
return aghalg.Coalesce(
|
||||||
|
@ -674,7 +677,9 @@ var testIPv4 = map[string][]net.IP{
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockCNAMEProtectionEnabled(t *testing.T) {
|
func TestBlockCNAMEProtectionEnabled(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{{}},
|
||||||
Config: Config{
|
Config: Config{
|
||||||
|
@ -789,7 +794,9 @@ func TestClientRulesForCNAMEMatching(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
s := createTestServer(t, &filtering.Config{}, forwardConf, nil)
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
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,
|
||||||
|
@ -901,8 +908,10 @@ func TestBlockedCustomIP(t *testing.T) {
|
||||||
err = s.Prepare(conf)
|
err = s.Prepare(conf)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
s.dnsFilter.BlockingIPv4 = netip.AddrFrom4([4]byte{0, 0, 0, 1})
|
s.dnsFilter.SetBlockingMode(
|
||||||
s.dnsFilter.BlockingIPv6 = netip.MustParseAddr("::1")
|
filtering.BlockingModeCustomIP,
|
||||||
|
netip.AddrFrom4([4]byte{0, 0, 0, 1}),
|
||||||
|
netip.MustParseAddr("::1"))
|
||||||
|
|
||||||
err = s.Prepare(conf)
|
err = s.Prepare(conf)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
@ -980,6 +989,7 @@ func TestBlockedBySafeBrowsing(t *testing.T) {
|
||||||
ans4, _ := aghtest.HostToIPs(hostname)
|
ans4, _ := aghtest.HostToIPs(hostname)
|
||||||
|
|
||||||
filterConf := &filtering.Config{
|
filterConf := &filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
ProtectionEnabled: true,
|
ProtectionEnabled: true,
|
||||||
SafeBrowsingEnabled: true,
|
SafeBrowsingEnabled: true,
|
||||||
SafeBrowsingChecker: sbChecker,
|
SafeBrowsingChecker: sbChecker,
|
||||||
|
|
|
@ -34,9 +34,14 @@ func TestServer_FilterDNSRewrite(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper functions and entities.
|
// Helper functions and entities.
|
||||||
srv := &Server{
|
srv := createTestServer(t, &filtering.Config{
|
||||||
dnsFilter: &filtering.DNSFilter{},
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
}
|
}, ServerConfig{
|
||||||
|
Config: Config{
|
||||||
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
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{{
|
||||||
|
|
|
@ -114,9 +114,7 @@ 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.dnsFilter.BlockingMode
|
blockingMode, blockingIPv4, blockingIPv6 := s.dnsFilter.BlockingMode()
|
||||||
blockingIPv4 := s.dnsFilter.BlockingIPv4
|
|
||||||
blockingIPv6 := s.dnsFilter.BlockingIPv6
|
|
||||||
ratelimit := s.conf.Ratelimit
|
ratelimit := s.conf.Ratelimit
|
||||||
|
|
||||||
customIP := s.conf.EDNSClientSubnet.CustomIP
|
customIP := s.conf.EDNSClientSubnet.CustomIP
|
||||||
|
@ -320,11 +318,11 @@ 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.dnsFilter.BlockingMode = *dc.BlockingMode
|
s.dnsFilter.SetBlockingMode(*dc.BlockingMode, dc.BlockingIPv4, dc.BlockingIPv6)
|
||||||
if *dc.BlockingMode == filtering.BlockingModeCustomIP {
|
|
||||||
s.dnsFilter.BlockingIPv4 = dc.BlockingIPv4
|
|
||||||
s.dnsFilter.BlockingIPv6 = dc.BlockingIPv6
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if dc.ProtectionEnabled != nil {
|
||||||
|
s.dnsFilter.SetProtectionEnabled(*dc.ProtectionEnabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
if dc.UpstreamMode != nil {
|
if dc.UpstreamMode != nil {
|
||||||
|
@ -336,7 +334,6 @@ func (s *Server) setConfig(dc *jsonDNSConfig) (shouldRestart bool) {
|
||||||
s.conf.EDNSClientSubnet.CustomIP = dc.EDNSCSCustomIP
|
s.conf.EDNSClientSubnet.CustomIP = dc.EDNSCSCustomIP
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
|
@ -690,8 +687,8 @@ func (s *Server) parseUpstreamLine(
|
||||||
}
|
}
|
||||||
|
|
||||||
// dnsFilter can be nil during application update.
|
// dnsFilter can be nil during application update.
|
||||||
if s.dnsFilter != nil && s.dnsFilter.EtcHosts != nil {
|
if s.dnsFilter != nil {
|
||||||
recs := s.dnsFilter.EtcHosts.MatchName(extractUpstreamHost(upstreamAddr))
|
recs := s.dnsFilter.EtcHostsRecords(extractUpstreamHost(upstreamAddr))
|
||||||
for _, rec := range recs {
|
for _, rec := range recs {
|
||||||
opts.ServerIPAddrs = append(opts.ServerIPAddrs, rec.Addr.AsSlice())
|
opts.ServerIPAddrs = append(opts.ServerIPAddrs, rec.Addr.AsSlice())
|
||||||
}
|
}
|
||||||
|
@ -832,8 +829,7 @@ 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.dnsFilter.ProtectionEnabled = protectionReq.Enabled
|
s.dnsFilter.SetProtectionStatus(protectionReq.Enabled, disabledUntil)
|
||||||
s.dnsFilter.ProtectionDisabledUntil = disabledUntil
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
s.conf.ConfigModified()
|
s.conf.ConfigModified()
|
||||||
|
|
|
@ -157,7 +157,6 @@ 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)
|
||||||
|
@ -248,7 +247,7 @@ 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.dnsFilter.SetBlockingMode(filtering.BlockingModeDefault, netip.Addr{}, netip.Addr{})
|
||||||
s.conf = defaultConf
|
s.conf = defaultConf
|
||||||
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{}
|
s.conf.Config.EDNSClientSubnet = &EDNSClientSubnet{}
|
||||||
})
|
})
|
||||||
|
@ -500,6 +499,7 @@ func TestServer_HandleTestUpstreamDNS(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
srv := createTestServer(t, &filtering.Config{
|
srv := createTestServer(t, &filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
EtcHosts: hc,
|
EtcHosts: hc,
|
||||||
}, ServerConfig{
|
}, ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
|
|
|
@ -50,7 +50,8 @@ 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.dnsFilter.BlockingMode == filtering.BlockingModeNullIP {
|
m, _, _ := s.dnsFilter.BlockingMode()
|
||||||
|
if m == filtering.BlockingModeNullIP {
|
||||||
return s.makeResponse(req)
|
return s.makeResponse(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +60,9 @@ func (s *Server) genDNSFilterMessage(
|
||||||
|
|
||||||
switch res.Reason {
|
switch res.Reason {
|
||||||
case filtering.FilteredSafeBrowsing:
|
case filtering.FilteredSafeBrowsing:
|
||||||
return s.genBlockedHost(req, s.dnsFilter.SafeBrowsingBlockHost, dctx)
|
return s.genBlockedHost(req, s.dnsFilter.SafeBrowsingBlockHost(), dctx)
|
||||||
case filtering.FilteredParental:
|
case filtering.FilteredParental:
|
||||||
return s.genBlockedHost(req, s.dnsFilter.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
|
||||||
|
@ -75,21 +76,9 @@ func (s *Server) genDNSFilterMessage(
|
||||||
// genForBlockingMode generates a filtered response to req based on the server's
|
// genForBlockingMode generates a filtered response to req based on the server's
|
||||||
// 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
|
switch mode, bIPv4, bIPv6 := s.dnsFilter.BlockingMode(); mode {
|
||||||
switch m := s.dnsFilter.BlockingMode; m {
|
|
||||||
case filtering.BlockingModeCustomIP:
|
case filtering.BlockingModeCustomIP:
|
||||||
switch qt {
|
return s.makeResponseCustomIP(req, bIPv4, bIPv6)
|
||||||
case dns.TypeA:
|
|
||||||
return s.genARecord(req, s.dnsFilter.BlockingIPv4)
|
|
||||||
case dns.TypeAAAA:
|
|
||||||
return s.genAAAARecord(req, s.dnsFilter.BlockingIPv6)
|
|
||||||
default:
|
|
||||||
// Generally shouldn't happen, since the types are checked in
|
|
||||||
// genDNSFilterMessage.
|
|
||||||
log.Error("dns: invalid msg type %s for blocking mode %s", dns.Type(qt), m)
|
|
||||||
|
|
||||||
return s.makeResponse(req)
|
|
||||||
}
|
|
||||||
case filtering.BlockingModeDefault:
|
case filtering.BlockingModeDefault:
|
||||||
if len(ips) > 0 {
|
if len(ips) > 0 {
|
||||||
return s.genResponseWithIPs(req, ips)
|
return s.genResponseWithIPs(req, ips)
|
||||||
|
@ -103,7 +92,28 @@ func (s *Server) genForBlockingMode(req *dns.Msg, ips []netip.Addr) (resp *dns.M
|
||||||
case filtering.BlockingModeREFUSED:
|
case filtering.BlockingModeREFUSED:
|
||||||
return s.makeResponseREFUSED(req)
|
return s.makeResponseREFUSED(req)
|
||||||
default:
|
default:
|
||||||
log.Error("dns: invalid blocking mode %q", s.dnsFilter.BlockingMode)
|
log.Error("dns: invalid blocking mode %q", mode)
|
||||||
|
|
||||||
|
return s.makeResponse(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeResponseCustomIP generates a DNS response message for Custom IP blocking
|
||||||
|
// mode with the provided IP addresses and an appropriate resource record type.
|
||||||
|
func (s *Server) makeResponseCustomIP(
|
||||||
|
req *dns.Msg,
|
||||||
|
bIPv4 netip.Addr,
|
||||||
|
bIPv6 netip.Addr,
|
||||||
|
) (resp *dns.Msg) {
|
||||||
|
switch qt := req.Question[0].Qtype; qt {
|
||||||
|
case dns.TypeA:
|
||||||
|
return s.genARecord(req, bIPv4)
|
||||||
|
case dns.TypeAAAA:
|
||||||
|
return s.genAAAARecord(req, bIPv6)
|
||||||
|
default:
|
||||||
|
// Generally shouldn't happen, since the types are checked in
|
||||||
|
// genDNSFilterMessage.
|
||||||
|
log.Error("dns: invalid msg type %s for custom IP blocking mode", dns.Type(qt))
|
||||||
|
|
||||||
return s.makeResponse(req)
|
return s.makeResponse(req)
|
||||||
}
|
}
|
||||||
|
@ -132,7 +142,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.dnsFilter.BlockedResponseTTL,
|
Ttl: s.dnsFilter.BlockedResponseTTL(),
|
||||||
Class: dns.ClassINET,
|
Class: dns.ClassINET,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -352,7 +362,7 @@ 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.dnsFilter.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 "."
|
||||||
|
|
|
@ -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.dnsFilter.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}, ".")),
|
||||||
|
|
|
@ -83,7 +83,9 @@ func TestServer_ProcessInitial(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
s := createTestServer(t, &filtering.Config{}, c, nil)
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, c, nil)
|
||||||
|
|
||||||
var gotAddr netip.Addr
|
var gotAddr netip.Addr
|
||||||
s.addrProc = &aghtest.AddressProcessor{
|
s.addrProc = &aghtest.AddressProcessor{
|
||||||
|
@ -180,7 +182,9 @@ func TestServer_ProcessFilteringAfterResponse(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
s := createTestServer(t, &filtering.Config{}, c, nil)
|
s := createTestServer(t, &filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, c, nil)
|
||||||
|
|
||||||
resp := newResp(dns.RcodeSuccess, tc.req, tc.respAns)
|
resp := newResp(dns.RcodeSuccess, tc.req, tc.respAns)
|
||||||
dctx := &dnsContext{
|
dctx := &dnsContext{
|
||||||
|
@ -338,11 +342,23 @@ func TestServer_ProcessDDRQuery(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// createTestDNSFilter returns the minimum valid DNSFilter.
|
||||||
|
func createTestDNSFilter(t *testing.T) (f *filtering.DNSFilter) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
f, err := filtering.New(&filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
}, []filtering.Filter{})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
func prepareTestServer(t *testing.T, portDoH, portDoT, portDoQ int, ddrEnabled bool) (s *Server) {
|
func prepareTestServer(t *testing.T, portDoH, portDoT, portDoQ int, ddrEnabled bool) (s *Server) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
|
|
||||||
s = &Server{
|
s = &Server{
|
||||||
dnsFilter: &filtering.DNSFilter{},
|
dnsFilter: createTestDNSFilter(t),
|
||||||
dnsProxy: &proxy.Proxy{
|
dnsProxy: &proxy.Proxy{
|
||||||
Config: proxy.Config{},
|
Config: proxy.Config{},
|
||||||
},
|
},
|
||||||
|
@ -467,7 +483,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{},
|
dnsFilter: createTestDNSFilter(t),
|
||||||
dhcpServer: dhcp,
|
dhcpServer: dhcp,
|
||||||
localDomainSuffix: localDomainSuffix,
|
localDomainSuffix: localDomainSuffix,
|
||||||
}
|
}
|
||||||
|
@ -602,7 +618,7 @@ func TestServer_ProcessDHCPHosts(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &Server{
|
s := &Server{
|
||||||
dnsFilter: &filtering.DNSFilter{},
|
dnsFilter: createTestDNSFilter(t),
|
||||||
dhcpServer: testDHCP,
|
dhcpServer: testDHCP,
|
||||||
localDomainSuffix: tc.suffix,
|
localDomainSuffix: tc.suffix,
|
||||||
}
|
}
|
||||||
|
@ -673,7 +689,9 @@ func TestServer_ProcessRestrictLocal(t *testing.T) {
|
||||||
), nil
|
), nil
|
||||||
})
|
})
|
||||||
|
|
||||||
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{{}},
|
||||||
// TODO(s.chzhen): Add tests where EDNSClientSubnet.Enabled is true.
|
// TODO(s.chzhen): Add tests where EDNSClientSubnet.Enabled is true.
|
||||||
|
@ -749,7 +767,9 @@ func TestServer_ProcessLocalPTR_usingResolvers(t *testing.T) {
|
||||||
|
|
||||||
s := createTestServer(
|
s := createTestServer(
|
||||||
t,
|
t,
|
||||||
&filtering.Config{},
|
&filtering.Config{
|
||||||
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
|
},
|
||||||
ServerConfig{
|
ServerConfig{
|
||||||
UDPListenAddrs: []*net.UDPAddr{{}},
|
UDPListenAddrs: []*net.UDPAddr{{}},
|
||||||
TCPListenAddrs: []*net.TCPAddr{{}},
|
TCPListenAddrs: []*net.TCPAddr{{}},
|
||||||
|
|
|
@ -13,9 +13,13 @@ import (
|
||||||
func TestGenAnswerHTTPS_andSVCB(t *testing.T) {
|
func TestGenAnswerHTTPS_andSVCB(t *testing.T) {
|
||||||
// Preconditions.
|
// Preconditions.
|
||||||
|
|
||||||
s := &Server{
|
s := createTestServer(t, &filtering.Config{
|
||||||
dnsFilter: &filtering.DNSFilter{},
|
BlockingMode: filtering.BlockingModeDefault,
|
||||||
}
|
}, ServerConfig{
|
||||||
|
Config: Config{
|
||||||
|
EDNSClientSubnet: &EDNSClientSubnet{Enabled: false},
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
req := &dns.Msg{
|
req := &dns.Msg{
|
||||||
Question: []dns.Question{{
|
Question: []dns.Question{{
|
||||||
|
|
|
@ -93,7 +93,7 @@ func (s *Server) prepareUpstreamConfig(
|
||||||
}
|
}
|
||||||
|
|
||||||
// dnsFilter can be nil during application update.
|
// dnsFilter can be nil during application update.
|
||||||
if s.dnsFilter != nil && s.dnsFilter.EtcHosts != nil {
|
if s.dnsFilter != nil {
|
||||||
err = s.replaceUpstreamsWithHosts(uc, opts)
|
err = s.replaceUpstreamsWithHosts(uc, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("resolving upstreams with hosts: %w", err)
|
return nil, fmt.Errorf("resolving upstreams with hosts: %w", err)
|
||||||
|
@ -157,7 +157,7 @@ func (s *Server) resolveUpstreamsWithHosts(
|
||||||
|
|
||||||
withIPs, ok := resolved[host]
|
withIPs, ok := resolved[host]
|
||||||
if !ok {
|
if !ok {
|
||||||
recs := s.dnsFilter.EtcHosts.MatchName(host)
|
recs := s.dnsFilter.EtcHostsRecords(host)
|
||||||
if len(recs) == 0 {
|
if len(recs) == 0 {
|
||||||
resolved[host] = nil
|
resolved[host] = nil
|
||||||
|
|
||||||
|
|
|
@ -83,12 +83,12 @@ func (s *BlockedServices) Validate() (err error) {
|
||||||
|
|
||||||
// ApplyBlockedServices - set blocked services settings for this DNS request
|
// ApplyBlockedServices - set blocked services settings for this DNS request
|
||||||
func (d *DNSFilter) ApplyBlockedServices(setts *Settings) {
|
func (d *DNSFilter) ApplyBlockedServices(setts *Settings) {
|
||||||
d.confLock.RLock()
|
d.confMu.RLock()
|
||||||
defer d.confLock.RUnlock()
|
defer d.confMu.RUnlock()
|
||||||
|
|
||||||
setts.ServicesRules = []ServiceEntry{}
|
setts.ServicesRules = []ServiceEntry{}
|
||||||
|
|
||||||
bsvc := d.BlockedServices
|
bsvc := d.conf.BlockedServices
|
||||||
|
|
||||||
// TODO(s.chzhen): Use startTime from [dnsforward.dnsContext].
|
// TODO(s.chzhen): Use startTime from [dnsforward.dnsContext].
|
||||||
if !bsvc.Schedule.Contains(time.Now()) {
|
if !bsvc.Schedule.Contains(time.Now()) {
|
||||||
|
@ -130,9 +130,13 @@ func (d *DNSFilter) handleBlockedServicesAll(w http.ResponseWriter, r *http.Requ
|
||||||
//
|
//
|
||||||
// Deprecated: Use handleBlockedServicesGet.
|
// Deprecated: Use handleBlockedServicesGet.
|
||||||
func (d *DNSFilter) handleBlockedServicesList(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleBlockedServicesList(w http.ResponseWriter, r *http.Request) {
|
||||||
d.confLock.RLock()
|
var list []string
|
||||||
list := d.Config.BlockedServices.IDs
|
func() {
|
||||||
d.confLock.RUnlock()
|
d.confMu.Lock()
|
||||||
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
|
list = d.conf.BlockedServices.IDs
|
||||||
|
}()
|
||||||
|
|
||||||
aghhttp.WriteJSONResponseOK(w, r, list)
|
aghhttp.WriteJSONResponseOK(w, r, list)
|
||||||
}
|
}
|
||||||
|
@ -150,13 +154,15 @@ func (d *DNSFilter) handleBlockedServicesSet(w http.ResponseWriter, r *http.Requ
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d.confLock.Lock()
|
func() {
|
||||||
d.Config.BlockedServices.IDs = list
|
d.confMu.Lock()
|
||||||
d.confLock.Unlock()
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
|
d.conf.BlockedServices.IDs = list
|
||||||
log.Debug("Updated blocked services list: %d", len(list))
|
log.Debug("Updated blocked services list: %d", len(list))
|
||||||
|
}()
|
||||||
|
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleBlockedServicesGet is the handler for the GET
|
// handleBlockedServicesGet is the handler for the GET
|
||||||
|
@ -164,10 +170,10 @@ func (d *DNSFilter) handleBlockedServicesSet(w http.ResponseWriter, r *http.Requ
|
||||||
func (d *DNSFilter) handleBlockedServicesGet(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleBlockedServicesGet(w http.ResponseWriter, r *http.Request) {
|
||||||
var bsvc *BlockedServices
|
var bsvc *BlockedServices
|
||||||
func() {
|
func() {
|
||||||
d.confLock.RLock()
|
d.confMu.RLock()
|
||||||
defer d.confLock.RUnlock()
|
defer d.confMu.RUnlock()
|
||||||
|
|
||||||
bsvc = d.Config.BlockedServices.Clone()
|
bsvc = d.conf.BlockedServices.Clone()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
aghhttp.WriteJSONResponseOK(w, r, bsvc)
|
aghhttp.WriteJSONResponseOK(w, r, bsvc)
|
||||||
|
@ -196,13 +202,13 @@ func (d *DNSFilter) handleBlockedServicesUpdate(w http.ResponseWriter, r *http.R
|
||||||
}
|
}
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
d.confLock.Lock()
|
d.confMu.Lock()
|
||||||
defer d.confLock.Unlock()
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
d.Config.BlockedServices = bsvc
|
d.conf.BlockedServices = bsvc
|
||||||
}()
|
}()
|
||||||
|
|
||||||
log.Debug("updated blocked services schedule: %d", len(bsvc.IDs))
|
log.Debug("updated blocked services schedule: %d", len(bsvc.IDs))
|
||||||
|
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,12 +91,12 @@ func (d *DNSFilter) filterSetProperties(
|
||||||
newList FilterYAML,
|
newList FilterYAML,
|
||||||
isAllowlist bool,
|
isAllowlist bool,
|
||||||
) (shouldRestart bool, err error) {
|
) (shouldRestart bool, err error) {
|
||||||
d.filtersMu.Lock()
|
d.conf.filtersMu.Lock()
|
||||||
defer d.filtersMu.Unlock()
|
defer d.conf.filtersMu.Unlock()
|
||||||
|
|
||||||
filters := d.Filters
|
filters := d.conf.Filters
|
||||||
if isAllowlist {
|
if isAllowlist {
|
||||||
filters = d.WhitelistFilters
|
filters = d.conf.WhitelistFilters
|
||||||
}
|
}
|
||||||
|
|
||||||
i := slices.IndexFunc(filters, func(flt FilterYAML) bool { return flt.URL == listURL })
|
i := slices.IndexFunc(filters, func(flt FilterYAML) bool { return flt.URL == listURL })
|
||||||
|
@ -162,8 +162,8 @@ func (d *DNSFilter) filterSetProperties(
|
||||||
// filterExists returns true if a filter with the same url exists in d. It's
|
// filterExists returns true if a filter with the same url exists in d. It's
|
||||||
// safe for concurrent use.
|
// safe for concurrent use.
|
||||||
func (d *DNSFilter) filterExists(url string) (ok bool) {
|
func (d *DNSFilter) filterExists(url string) (ok bool) {
|
||||||
d.filtersMu.RLock()
|
d.conf.filtersMu.RLock()
|
||||||
defer d.filtersMu.RUnlock()
|
defer d.conf.filtersMu.RUnlock()
|
||||||
|
|
||||||
r := d.filterExistsLocked(url)
|
r := d.filterExistsLocked(url)
|
||||||
|
|
||||||
|
@ -173,13 +173,13 @@ func (d *DNSFilter) filterExists(url string) (ok bool) {
|
||||||
// filterExistsLocked returns true if d contains the filter with the same url.
|
// filterExistsLocked returns true if d contains the filter with the same url.
|
||||||
// d.filtersMu is expected to be locked.
|
// d.filtersMu is expected to be locked.
|
||||||
func (d *DNSFilter) filterExistsLocked(url string) (ok bool) {
|
func (d *DNSFilter) filterExistsLocked(url string) (ok bool) {
|
||||||
for _, f := range d.Filters {
|
for _, f := range d.conf.Filters {
|
||||||
if f.URL == url {
|
if f.URL == url {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, f := range d.WhitelistFilters {
|
for _, f := range d.conf.WhitelistFilters {
|
||||||
if f.URL == url {
|
if f.URL == url {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -194,8 +194,8 @@ func (d *DNSFilter) filterAdd(flt FilterYAML) (err error) {
|
||||||
// Defer annotating to unlock sooner.
|
// Defer annotating to unlock sooner.
|
||||||
defer func() { err = errors.Annotate(err, "adding filter: %w") }()
|
defer func() { err = errors.Annotate(err, "adding filter: %w") }()
|
||||||
|
|
||||||
d.filtersMu.Lock()
|
d.conf.filtersMu.Lock()
|
||||||
defer d.filtersMu.Unlock()
|
defer d.conf.filtersMu.Unlock()
|
||||||
|
|
||||||
// Check for duplicates.
|
// Check for duplicates.
|
||||||
if d.filterExistsLocked(flt.URL) {
|
if d.filterExistsLocked(flt.URL) {
|
||||||
|
@ -203,9 +203,9 @@ func (d *DNSFilter) filterAdd(flt FilterYAML) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if flt.white {
|
if flt.white {
|
||||||
d.WhitelistFilters = append(d.WhitelistFilters, flt)
|
d.conf.WhitelistFilters = append(d.conf.WhitelistFilters, flt)
|
||||||
} else {
|
} else {
|
||||||
d.Filters = append(d.Filters, flt)
|
d.conf.Filters = append(d.conf.Filters, flt)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -269,7 +269,7 @@ func (d *DNSFilter) periodicallyRefreshFilters() {
|
||||||
ivl := 5 // use a dynamically increasing time interval
|
ivl := 5 // use a dynamically increasing time interval
|
||||||
for {
|
for {
|
||||||
isNetErr, ok := false, false
|
isNetErr, ok := false, false
|
||||||
if d.FiltersUpdateIntervalHours != 0 {
|
if d.conf.FiltersUpdateIntervalHours != 0 {
|
||||||
_, isNetErr, ok = d.tryRefreshFilters(true, true, false)
|
_, isNetErr, ok = d.tryRefreshFilters(true, true, false)
|
||||||
if ok && !isNetErr {
|
if ok && !isNetErr {
|
||||||
ivl = maxInterval
|
ivl = maxInterval
|
||||||
|
@ -307,8 +307,8 @@ func (d *DNSFilter) tryRefreshFilters(block, allow, force bool) (updated int, is
|
||||||
func (d *DNSFilter) listsToUpdate(filters *[]FilterYAML, force bool) (toUpd []FilterYAML) {
|
func (d *DNSFilter) listsToUpdate(filters *[]FilterYAML, force bool) (toUpd []FilterYAML) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
|
|
||||||
d.filtersMu.RLock()
|
d.conf.filtersMu.RLock()
|
||||||
defer d.filtersMu.RUnlock()
|
defer d.conf.filtersMu.RUnlock()
|
||||||
|
|
||||||
for i := range *filters {
|
for i := range *filters {
|
||||||
flt := &(*filters)[i] // otherwise we will be operating on a copy
|
flt := &(*filters)[i] // otherwise we will be operating on a copy
|
||||||
|
@ -318,7 +318,7 @@ func (d *DNSFilter) listsToUpdate(filters *[]FilterYAML, force bool) (toUpd []Fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if !force {
|
if !force {
|
||||||
exp := flt.LastUpdated.Add(time.Duration(d.FiltersUpdateIntervalHours) * time.Hour)
|
exp := flt.LastUpdated.Add(time.Duration(d.conf.FiltersUpdateIntervalHours) * time.Hour)
|
||||||
if now.Before(exp) {
|
if now.Before(exp) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -364,8 +364,8 @@ func (d *DNSFilter) refreshFiltersArray(filters *[]FilterYAML, force bool) (int,
|
||||||
|
|
||||||
updateCount := 0
|
updateCount := 0
|
||||||
|
|
||||||
d.filtersMu.Lock()
|
d.conf.filtersMu.Lock()
|
||||||
defer d.filtersMu.Unlock()
|
defer d.conf.filtersMu.Unlock()
|
||||||
|
|
||||||
for i := range updateFilters {
|
for i := range updateFilters {
|
||||||
uf := &updateFilters[i]
|
uf := &updateFilters[i]
|
||||||
|
@ -427,10 +427,10 @@ func (d *DNSFilter) refreshFiltersIntl(block, allow, force bool) (int, bool) {
|
||||||
isNetErr := false
|
isNetErr := false
|
||||||
|
|
||||||
if block {
|
if block {
|
||||||
updNum, lists, toUpd, isNetErr = d.refreshFiltersArray(&d.Filters, force)
|
updNum, lists, toUpd, isNetErr = d.refreshFiltersArray(&d.conf.Filters, force)
|
||||||
}
|
}
|
||||||
if allow {
|
if allow {
|
||||||
updNumAl, listsAl, toUpdAl, isNetErrAl := d.refreshFiltersArray(&d.WhitelistFilters, force)
|
updNumAl, listsAl, toUpdAl, isNetErrAl := d.refreshFiltersArray(&d.conf.WhitelistFilters, force)
|
||||||
|
|
||||||
updNum += updNumAl
|
updNum += updNumAl
|
||||||
lists = append(lists, listsAl...)
|
lists = append(lists, listsAl...)
|
||||||
|
@ -451,7 +451,7 @@ func (d *DNSFilter) refreshFiltersIntl(block, allow, force bool) (int, bool) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
p := uf.Path(d.DataDir)
|
p := uf.Path(d.conf.DataDir)
|
||||||
err := os.Remove(p + ".old")
|
err := os.Remove(p + ".old")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Debug("filtering: removing old filter file %q: %s", p, err)
|
log.Debug("filtering: removing old filter file %q: %s", p, err)
|
||||||
|
@ -468,7 +468,7 @@ func (d *DNSFilter) update(filter *FilterYAML) (b bool, err error) {
|
||||||
filter.LastUpdated = time.Now()
|
filter.LastUpdated = time.Now()
|
||||||
if !b {
|
if !b {
|
||||||
chErr := os.Chtimes(
|
chErr := os.Chtimes(
|
||||||
filter.Path(d.DataDir),
|
filter.Path(d.conf.DataDir),
|
||||||
filter.LastUpdated,
|
filter.LastUpdated,
|
||||||
filter.LastUpdated,
|
filter.LastUpdated,
|
||||||
)
|
)
|
||||||
|
@ -491,7 +491,7 @@ func (d *DNSFilter) updateIntl(flt *FilterYAML) (ok bool, err error) {
|
||||||
// users.
|
// users.
|
||||||
//
|
//
|
||||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/3198.
|
// See https://github.com/AdguardTeam/AdGuardHome/issues/3198.
|
||||||
tmpFile, err := aghrenameio.NewPendingFile(flt.Path(d.DataDir), 0o644)
|
tmpFile, err := aghrenameio.NewPendingFile(flt.Path(d.conf.DataDir), 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
@ -532,7 +532,7 @@ func (d *DNSFilter) finalizeUpdate(
|
||||||
return errors.WithDeferred(returned, file.Cleanup())
|
return errors.WithDeferred(returned, file.Cleanup())
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info("filtering: saving contents of filter %d into %q", id, flt.Path(d.DataDir))
|
log.Info("filtering: saving contents of filter %d into %q", id, flt.Path(d.conf.DataDir))
|
||||||
|
|
||||||
err = file.CloseReplace()
|
err = file.CloseReplace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -572,7 +572,7 @@ func (d *DNSFilter) reader(fltURL string) (r io.ReadCloser, err error) {
|
||||||
// readerFromURL returns an io.ReadCloser reading filtering-rule list data form
|
// readerFromURL returns an io.ReadCloser reading filtering-rule list data form
|
||||||
// the filter's URL.
|
// the filter's URL.
|
||||||
func (d *DNSFilter) readerFromURL(fltURL string) (r io.ReadCloser, err error) {
|
func (d *DNSFilter) readerFromURL(fltURL string) (r io.ReadCloser, err error) {
|
||||||
resp, err := d.HTTPClient.Get(fltURL)
|
resp, err := d.conf.HTTPClient.Get(fltURL)
|
||||||
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 nil, err
|
return nil, err
|
||||||
|
@ -587,7 +587,7 @@ func (d *DNSFilter) readerFromURL(fltURL string) (r io.ReadCloser, err error) {
|
||||||
|
|
||||||
// loads filter contents from the file in dataDir
|
// loads filter contents from the file in dataDir
|
||||||
func (d *DNSFilter) load(flt *FilterYAML) (err error) {
|
func (d *DNSFilter) load(flt *FilterYAML) (err error) {
|
||||||
fileName := flt.Path(d.DataDir)
|
fileName := flt.Path(d.conf.DataDir)
|
||||||
|
|
||||||
log.Debug("filtering: loading filter %d from %q", flt.ID, fileName)
|
log.Debug("filtering: loading filter %d from %q", flt.ID, fileName)
|
||||||
|
|
||||||
|
@ -623,39 +623,39 @@ func (d *DNSFilter) load(flt *FilterYAML) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSFilter) EnableFilters(async bool) {
|
func (d *DNSFilter) EnableFilters(async bool) {
|
||||||
d.filtersMu.RLock()
|
d.conf.filtersMu.RLock()
|
||||||
defer d.filtersMu.RUnlock()
|
defer d.conf.filtersMu.RUnlock()
|
||||||
|
|
||||||
d.enableFiltersLocked(async)
|
d.enableFiltersLocked(async)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *DNSFilter) enableFiltersLocked(async bool) {
|
func (d *DNSFilter) enableFiltersLocked(async bool) {
|
||||||
filters := make([]Filter, 1, len(d.Filters)+len(d.WhitelistFilters)+1)
|
filters := make([]Filter, 1, len(d.conf.Filters)+len(d.conf.WhitelistFilters)+1)
|
||||||
filters[0] = Filter{
|
filters[0] = Filter{
|
||||||
ID: CustomListID,
|
ID: CustomListID,
|
||||||
Data: []byte(strings.Join(d.UserRules, "\n")),
|
Data: []byte(strings.Join(d.conf.UserRules, "\n")),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, filter := range d.Filters {
|
for _, filter := range d.conf.Filters {
|
||||||
if !filter.Enabled {
|
if !filter.Enabled {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
filters = append(filters, Filter{
|
filters = append(filters, Filter{
|
||||||
ID: filter.ID,
|
ID: filter.ID,
|
||||||
FilePath: filter.Path(d.DataDir),
|
FilePath: filter.Path(d.conf.DataDir),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
var allowFilters []Filter
|
var allowFilters []Filter
|
||||||
for _, filter := range d.WhitelistFilters {
|
for _, filter := range d.conf.WhitelistFilters {
|
||||||
if !filter.Enabled {
|
if !filter.Enabled {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
allowFilters = append(allowFilters, Filter{
|
allowFilters = append(allowFilters, Filter{
|
||||||
ID: filter.ID,
|
ID: filter.ID,
|
||||||
FilePath: filter.Path(d.DataDir),
|
FilePath: filter.Path(d.conf.DataDir),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -664,5 +664,5 @@ func (d *DNSFilter) enableFiltersLocked(async bool) {
|
||||||
log.Error("filtering: enabling filters: %s", err)
|
log.Error("filtering: enabling filters: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.SetEnabled(d.FilteringEnabled)
|
d.SetEnabled(d.conf.FilteringEnabled)
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,9 +69,9 @@ func updateAndAssert(
|
||||||
|
|
||||||
assert.Equal(t, wantRulesCount, f.RulesCount)
|
assert.Equal(t, wantRulesCount, f.RulesCount)
|
||||||
|
|
||||||
dir, err := os.ReadDir(filepath.Join(dnsFilter.DataDir, filterDir))
|
dir, err := os.ReadDir(filepath.Join(dnsFilter.conf.DataDir, filterDir))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.FileExists(t, f.Path(dnsFilter.DataDir))
|
require.FileExists(t, f.Path(dnsFilter.conf.DataDir))
|
||||||
|
|
||||||
assert.Len(t, dir, 1)
|
assert.Len(t, dir, 1)
|
||||||
|
|
||||||
|
|
|
@ -240,15 +240,6 @@ 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.
|
||||||
|
@ -259,6 +250,12 @@ type DNSFilter struct {
|
||||||
|
|
||||||
engineLock sync.RWMutex
|
engineLock sync.RWMutex
|
||||||
|
|
||||||
|
// confMu protects conf.
|
||||||
|
confMu *sync.RWMutex
|
||||||
|
|
||||||
|
// conf contains filtering parameters.
|
||||||
|
conf *Config
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -358,38 +355,38 @@ func (r Reason) In(reasons ...Reason) (ok bool) { return slices.Contains(reasons
|
||||||
|
|
||||||
// SetEnabled sets the status of the *DNSFilter.
|
// SetEnabled sets the status of the *DNSFilter.
|
||||||
func (d *DNSFilter) SetEnabled(enabled bool) {
|
func (d *DNSFilter) SetEnabled(enabled bool) {
|
||||||
atomic.StoreUint32(&d.enabled, mathutil.BoolToNumber[uint32](enabled))
|
atomic.StoreUint32(&d.conf.enabled, mathutil.BoolToNumber[uint32](enabled))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Settings returns filtering settings.
|
// Settings returns filtering settings.
|
||||||
func (d *DNSFilter) Settings() (s *Settings) {
|
func (d *DNSFilter) Settings() (s *Settings) {
|
||||||
d.confLock.RLock()
|
d.confMu.RLock()
|
||||||
defer d.confLock.RUnlock()
|
defer d.confMu.RUnlock()
|
||||||
|
|
||||||
return &Settings{
|
return &Settings{
|
||||||
FilteringEnabled: atomic.LoadUint32(&d.Config.enabled) != 0,
|
FilteringEnabled: atomic.LoadUint32(&d.conf.enabled) != 0,
|
||||||
SafeSearchEnabled: d.Config.SafeSearchConf.Enabled,
|
SafeSearchEnabled: d.conf.SafeSearchConf.Enabled,
|
||||||
SafeBrowsingEnabled: d.Config.SafeBrowsingEnabled,
|
SafeBrowsingEnabled: d.conf.SafeBrowsingEnabled,
|
||||||
ParentalEnabled: d.Config.ParentalEnabled,
|
ParentalEnabled: d.conf.ParentalEnabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteDiskConfig - write configuration
|
// WriteDiskConfig - write configuration
|
||||||
func (d *DNSFilter) WriteDiskConfig(c *Config) {
|
func (d *DNSFilter) WriteDiskConfig(c *Config) {
|
||||||
func() {
|
func() {
|
||||||
d.confLock.Lock()
|
d.confMu.Lock()
|
||||||
defer d.confLock.Unlock()
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
*c = d.Config
|
*c = *d.conf
|
||||||
c.Rewrites = cloneRewrites(c.Rewrites)
|
c.Rewrites = cloneRewrites(c.Rewrites)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
d.filtersMu.RLock()
|
d.conf.filtersMu.RLock()
|
||||||
defer d.filtersMu.RUnlock()
|
defer d.conf.filtersMu.RUnlock()
|
||||||
|
|
||||||
c.Filters = slices.Clone(d.Filters)
|
c.Filters = slices.Clone(d.conf.Filters)
|
||||||
c.WhitelistFilters = slices.Clone(d.WhitelistFilters)
|
c.WhitelistFilters = slices.Clone(d.conf.WhitelistFilters)
|
||||||
c.UserRules = slices.Clone(d.UserRules)
|
c.UserRules = slices.Clone(d.conf.UserRules)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setFilters sets new filters, synchronously or asynchronously. When filters
|
// setFilters sets new filters, synchronously or asynchronously. When filters
|
||||||
|
@ -461,6 +458,77 @@ func (d *DNSFilter) reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ProtectionStatus returns the status of protection and time until it's
|
||||||
|
// disabled if so.
|
||||||
|
func (d *DNSFilter) ProtectionStatus() (status bool, disabledUntil *time.Time) {
|
||||||
|
d.confMu.RLock()
|
||||||
|
defer d.confMu.RUnlock()
|
||||||
|
|
||||||
|
return d.conf.ProtectionEnabled, d.conf.ProtectionDisabledUntil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProtectionStatus updates the status of protection and time until it's
|
||||||
|
// disabled.
|
||||||
|
func (d *DNSFilter) SetProtectionStatus(status bool, disabledUntil *time.Time) {
|
||||||
|
d.confMu.Lock()
|
||||||
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
|
d.conf.ProtectionEnabled = status
|
||||||
|
d.conf.ProtectionDisabledUntil = disabledUntil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetProtectionEnabled updates the status of protection.
|
||||||
|
func (d *DNSFilter) SetProtectionEnabled(status bool) {
|
||||||
|
d.confMu.Lock()
|
||||||
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
|
d.conf.ProtectionEnabled = status
|
||||||
|
}
|
||||||
|
|
||||||
|
// EtcHostsRecords returns the hosts records for the hostname.
|
||||||
|
func (d *DNSFilter) EtcHostsRecords(hostname string) (recs []*hostsfile.Record) {
|
||||||
|
if d.conf.EtcHosts != nil {
|
||||||
|
return d.conf.EtcHosts.MatchName(hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
return recs
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetBlockingMode sets blocking mode properties.
|
||||||
|
func (d *DNSFilter) SetBlockingMode(mode BlockingMode, bIPv4, bIPv6 netip.Addr) {
|
||||||
|
d.confMu.Lock()
|
||||||
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
|
d.conf.BlockingMode = mode
|
||||||
|
if mode == BlockingModeCustomIP {
|
||||||
|
d.conf.BlockingIPv4 = bIPv4
|
||||||
|
d.conf.BlockingIPv6 = bIPv6
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockingMode returns blocking mode properties.
|
||||||
|
func (d *DNSFilter) BlockingMode() (mode BlockingMode, bIPv4, bIPv6 netip.Addr) {
|
||||||
|
d.confMu.RLock()
|
||||||
|
defer d.confMu.RUnlock()
|
||||||
|
|
||||||
|
return d.conf.BlockingMode, d.conf.BlockingIPv4, d.conf.BlockingIPv6
|
||||||
|
}
|
||||||
|
|
||||||
|
// BlockedResponseTTL returns TTL for blocked responses.
|
||||||
|
func (d *DNSFilter) BlockedResponseTTL() (ttl uint32) {
|
||||||
|
return d.conf.BlockedResponseTTL
|
||||||
|
}
|
||||||
|
|
||||||
|
// SafeBrowsingBlockHost returns a host for safe browsing blocked responses.
|
||||||
|
func (d *DNSFilter) SafeBrowsingBlockHost() (host string) {
|
||||||
|
return d.conf.SafeBrowsingBlockHost
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParentalBlockHost returns a host for parental protection blocked responses.
|
||||||
|
func (d *DNSFilter) ParentalBlockHost() (host string) {
|
||||||
|
return d.conf.ParentalBlockHost
|
||||||
|
}
|
||||||
|
|
||||||
// ResultRule contains information about applied rules.
|
// ResultRule contains information about applied rules.
|
||||||
type ResultRule struct {
|
type ResultRule struct {
|
||||||
// Text is the text of the rule.
|
// Text is the text of the rule.
|
||||||
|
@ -560,14 +628,14 @@ func (d *DNSFilter) matchSysHosts(
|
||||||
setts *Settings,
|
setts *Settings,
|
||||||
) (res Result, err error) {
|
) (res Result, err error) {
|
||||||
// TODO(e.burkov): Where else is this checked?
|
// TODO(e.burkov): Where else is this checked?
|
||||||
if !setts.FilteringEnabled || d.EtcHosts == nil {
|
if !setts.FilteringEnabled || d.conf.EtcHosts == nil {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var recs []*hostsfile.Record
|
var recs []*hostsfile.Record
|
||||||
switch qtype {
|
switch qtype {
|
||||||
case dns.TypeA, dns.TypeAAAA:
|
case dns.TypeA, dns.TypeAAAA:
|
||||||
recs = d.EtcHosts.MatchName(host)
|
recs = d.conf.EtcHosts.MatchName(host)
|
||||||
case dns.TypePTR:
|
case dns.TypePTR:
|
||||||
var ip net.IP
|
var ip net.IP
|
||||||
ip, err = netutil.IPFromReversedAddr(host)
|
ip, err = netutil.IPFromReversedAddr(host)
|
||||||
|
@ -578,7 +646,7 @@ func (d *DNSFilter) matchSysHosts(
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, _ := netip.AddrFromSlice(ip)
|
addr, _ := netip.AddrFromSlice(ip)
|
||||||
recs = d.EtcHosts.MatchAddr(addr)
|
recs = d.conf.EtcHosts.MatchAddr(addr)
|
||||||
default:
|
default:
|
||||||
log.Debug("filtering: unsupported query type %s", dns.Type(qtype))
|
log.Debug("filtering: unsupported query type %s", dns.Type(qtype))
|
||||||
}
|
}
|
||||||
|
@ -618,10 +686,10 @@ func (d *DNSFilter) matchSysHosts(
|
||||||
// accordingly. If the found rewrite has a special value of "A" or "AAAA", the
|
// accordingly. If the found rewrite has a special value of "A" or "AAAA", the
|
||||||
// result is an exception.
|
// result is an exception.
|
||||||
func (d *DNSFilter) processRewrites(host string, qtype uint16) (res Result) {
|
func (d *DNSFilter) processRewrites(host string, qtype uint16) (res Result) {
|
||||||
d.confLock.RLock()
|
d.confMu.RLock()
|
||||||
defer d.confLock.RUnlock()
|
defer d.confMu.RUnlock()
|
||||||
|
|
||||||
rewrites, matched := findRewrites(d.Rewrites, host, qtype)
|
rewrites, matched := findRewrites(d.conf.Rewrites, host, qtype)
|
||||||
if !matched {
|
if !matched {
|
||||||
return Result{}
|
return Result{}
|
||||||
}
|
}
|
||||||
|
@ -661,7 +729,7 @@ func (d *DNSFilter) processRewrites(host string, qtype uint16) (res Result) {
|
||||||
|
|
||||||
cnames.Add(host)
|
cnames.Add(host)
|
||||||
res.CanonName = host
|
res.CanonName = host
|
||||||
rewrites, matched = findRewrites(d.Rewrites, host, qtype)
|
rewrites, matched = findRewrites(d.conf.Rewrites, host, qtype)
|
||||||
}
|
}
|
||||||
|
|
||||||
setRewriteResult(&res, host, rewrites, qtype)
|
setRewriteResult(&res, host, rewrites, qtype)
|
||||||
|
@ -992,6 +1060,7 @@ func New(c *Config, blockFilters []Filter) (d *DNSFilter, err error) {
|
||||||
refreshLock: &sync.Mutex{},
|
refreshLock: &sync.Mutex{},
|
||||||
safeBrowsingChecker: c.SafeBrowsingChecker,
|
safeBrowsingChecker: c.SafeBrowsingChecker,
|
||||||
parentalControlChecker: c.ParentalControlChecker,
|
parentalControlChecker: c.ParentalControlChecker,
|
||||||
|
confMu: &sync.RWMutex{},
|
||||||
}
|
}
|
||||||
|
|
||||||
d.safeSearch = c.SafeSearch
|
d.safeSearch = c.SafeSearch
|
||||||
|
@ -1018,16 +1087,16 @@ func New(c *Config, blockFilters []Filter) (d *DNSFilter, err error) {
|
||||||
|
|
||||||
defer func() { err = errors.Annotate(err, "filtering: %w") }()
|
defer func() { err = errors.Annotate(err, "filtering: %w") }()
|
||||||
|
|
||||||
d.Config = *c
|
d.conf = c
|
||||||
d.filtersMu = &sync.RWMutex{}
|
d.conf.filtersMu = &sync.RWMutex{}
|
||||||
|
|
||||||
err = d.prepareRewrites()
|
err = d.prepareRewrites()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("rewrites: preparing: %s", err)
|
return nil, fmt.Errorf("rewrites: preparing: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if d.BlockedServices != nil {
|
if d.conf.BlockedServices != nil {
|
||||||
err = d.BlockedServices.Validate()
|
err = d.conf.BlockedServices.Validate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("filtering: %w", err)
|
return nil, fmt.Errorf("filtering: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -1042,16 +1111,16 @@ func New(c *Config, blockFilters []Filter) (d *DNSFilter, err error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = os.MkdirAll(filepath.Join(d.DataDir, filterDir), 0o755)
|
_ = os.MkdirAll(filepath.Join(d.conf.DataDir, filterDir), 0o755)
|
||||||
|
|
||||||
d.loadFilters(d.Filters)
|
d.loadFilters(d.conf.Filters)
|
||||||
d.loadFilters(d.WhitelistFilters)
|
d.loadFilters(d.conf.WhitelistFilters)
|
||||||
|
|
||||||
d.Filters = deduplicateFilters(d.Filters)
|
d.conf.Filters = deduplicateFilters(d.conf.Filters)
|
||||||
d.WhitelistFilters = deduplicateFilters(d.WhitelistFilters)
|
d.conf.WhitelistFilters = deduplicateFilters(d.conf.WhitelistFilters)
|
||||||
|
|
||||||
updateUniqueFilterID(d.Filters)
|
updateUniqueFilterID(d.conf.Filters)
|
||||||
updateUniqueFilterID(d.WhitelistFilters)
|
updateUniqueFilterID(d.conf.WhitelistFilters)
|
||||||
|
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ func (d *DNSFilter) handleFilteringAddURL(w http.ResponseWriter, r *http.Request
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
d.EnableFilters(true)
|
d.EnableFilters(true)
|
||||||
|
|
||||||
_, err = fmt.Fprintf(w, "OK %d rules\n", filt.RulesCount)
|
_, err = fmt.Fprintf(w, "OK %d rules\n", filt.RulesCount)
|
||||||
|
@ -149,12 +149,12 @@ func (d *DNSFilter) handleFilteringRemoveURL(w http.ResponseWriter, r *http.Requ
|
||||||
|
|
||||||
var deleted FilterYAML
|
var deleted FilterYAML
|
||||||
func() {
|
func() {
|
||||||
d.filtersMu.Lock()
|
d.conf.filtersMu.Lock()
|
||||||
defer d.filtersMu.Unlock()
|
defer d.conf.filtersMu.Unlock()
|
||||||
|
|
||||||
filters := &d.Filters
|
filters := &d.conf.Filters
|
||||||
if req.Whitelist {
|
if req.Whitelist {
|
||||||
filters = &d.WhitelistFilters
|
filters = &d.conf.WhitelistFilters
|
||||||
}
|
}
|
||||||
|
|
||||||
delIdx := slices.IndexFunc(*filters, func(flt FilterYAML) bool {
|
delIdx := slices.IndexFunc(*filters, func(flt FilterYAML) bool {
|
||||||
|
@ -167,7 +167,7 @@ func (d *DNSFilter) handleFilteringRemoveURL(w http.ResponseWriter, r *http.Requ
|
||||||
}
|
}
|
||||||
|
|
||||||
deleted = (*filters)[delIdx]
|
deleted = (*filters)[delIdx]
|
||||||
p := deleted.Path(d.DataDir)
|
p := deleted.Path(d.conf.DataDir)
|
||||||
err = os.Rename(p, p+".old")
|
err = os.Rename(p, p+".old")
|
||||||
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
if err != nil && !errors.Is(err, os.ErrNotExist) {
|
||||||
log.Error("deleting filter %d: renaming file %q: %s", deleted.ID, p, err)
|
log.Error("deleting filter %d: renaming file %q: %s", deleted.ID, p, err)
|
||||||
|
@ -180,7 +180,7 @@ func (d *DNSFilter) handleFilteringRemoveURL(w http.ResponseWriter, r *http.Requ
|
||||||
log.Info("deleted filter %d", deleted.ID)
|
log.Info("deleted filter %d", deleted.ID)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
d.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
d.EnableFilters(true)
|
d.EnableFilters(true)
|
||||||
|
|
||||||
// NOTE: The old files "filter.txt.old" aren't deleted. It's not really
|
// NOTE: The old files "filter.txt.old" aren't deleted. It's not really
|
||||||
|
@ -242,7 +242,7 @@ func (d *DNSFilter) handleFilteringSetURL(w http.ResponseWriter, r *http.Request
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
if restart {
|
if restart {
|
||||||
d.EnableFilters(true)
|
d.EnableFilters(true)
|
||||||
}
|
}
|
||||||
|
@ -266,8 +266,8 @@ func (d *DNSFilter) handleFilteringSetRules(w http.ResponseWriter, r *http.Reque
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d.UserRules = req.Rules
|
d.conf.UserRules = req.Rules
|
||||||
d.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
d.EnableFilters(true)
|
d.EnableFilters(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,19 +340,19 @@ func filterToJSON(f FilterYAML) filterJSON {
|
||||||
// Get filtering configuration
|
// Get filtering configuration
|
||||||
func (d *DNSFilter) handleFilteringStatus(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleFilteringStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
resp := filteringConfig{}
|
resp := filteringConfig{}
|
||||||
d.filtersMu.RLock()
|
d.conf.filtersMu.RLock()
|
||||||
resp.Enabled = d.FilteringEnabled
|
resp.Enabled = d.conf.FilteringEnabled
|
||||||
resp.Interval = d.FiltersUpdateIntervalHours
|
resp.Interval = d.conf.FiltersUpdateIntervalHours
|
||||||
for _, f := range d.Filters {
|
for _, f := range d.conf.Filters {
|
||||||
fj := filterToJSON(f)
|
fj := filterToJSON(f)
|
||||||
resp.Filters = append(resp.Filters, fj)
|
resp.Filters = append(resp.Filters, fj)
|
||||||
}
|
}
|
||||||
for _, f := range d.WhitelistFilters {
|
for _, f := range d.conf.WhitelistFilters {
|
||||||
fj := filterToJSON(f)
|
fj := filterToJSON(f)
|
||||||
resp.WhitelistFilters = append(resp.WhitelistFilters, fj)
|
resp.WhitelistFilters = append(resp.WhitelistFilters, fj)
|
||||||
}
|
}
|
||||||
resp.UserRules = d.UserRules
|
resp.UserRules = d.conf.UserRules
|
||||||
d.filtersMu.RUnlock()
|
d.conf.filtersMu.RUnlock()
|
||||||
|
|
||||||
aghhttp.WriteJSONResponseOK(w, r, resp)
|
aghhttp.WriteJSONResponseOK(w, r, resp)
|
||||||
}
|
}
|
||||||
|
@ -374,14 +374,14 @@ func (d *DNSFilter) handleFilteringConfig(w http.ResponseWriter, r *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
d.filtersMu.Lock()
|
d.conf.filtersMu.Lock()
|
||||||
defer d.filtersMu.Unlock()
|
defer d.conf.filtersMu.Unlock()
|
||||||
|
|
||||||
d.FilteringEnabled = req.Enabled
|
d.conf.FilteringEnabled = req.Enabled
|
||||||
d.FiltersUpdateIntervalHours = req.Interval
|
d.conf.FiltersUpdateIntervalHours = req.Interval
|
||||||
}()
|
}()
|
||||||
|
|
||||||
d.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
d.EnableFilters(true)
|
d.EnableFilters(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,15 +484,15 @@ func protectedBool(mu *sync.RWMutex, ptr *bool) (val bool) {
|
||||||
// handleSafeBrowsingEnable is the handler for the POST
|
// handleSafeBrowsingEnable is the handler for the POST
|
||||||
// /control/safebrowsing/enable HTTP API.
|
// /control/safebrowsing/enable HTTP API.
|
||||||
func (d *DNSFilter) handleSafeBrowsingEnable(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleSafeBrowsingEnable(w http.ResponseWriter, r *http.Request) {
|
||||||
setProtectedBool(&d.confLock, &d.Config.SafeBrowsingEnabled, true)
|
setProtectedBool(d.confMu, &d.conf.SafeBrowsingEnabled, true)
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleSafeBrowsingDisable is the handler for the POST
|
// handleSafeBrowsingDisable is the handler for the POST
|
||||||
// /control/safebrowsing/disable HTTP API.
|
// /control/safebrowsing/disable HTTP API.
|
||||||
func (d *DNSFilter) handleSafeBrowsingDisable(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleSafeBrowsingDisable(w http.ResponseWriter, r *http.Request) {
|
||||||
setProtectedBool(&d.confLock, &d.Config.SafeBrowsingEnabled, false)
|
setProtectedBool(d.confMu, &d.conf.SafeBrowsingEnabled, false)
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleSafeBrowsingStatus is the handler for the GET
|
// handleSafeBrowsingStatus is the handler for the GET
|
||||||
|
@ -501,7 +501,7 @@ func (d *DNSFilter) handleSafeBrowsingStatus(w http.ResponseWriter, r *http.Requ
|
||||||
resp := &struct {
|
resp := &struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
}{
|
}{
|
||||||
Enabled: protectedBool(&d.confLock, &d.Config.SafeBrowsingEnabled),
|
Enabled: protectedBool(d.confMu, &d.conf.SafeBrowsingEnabled),
|
||||||
}
|
}
|
||||||
|
|
||||||
aghhttp.WriteJSONResponseOK(w, r, resp)
|
aghhttp.WriteJSONResponseOK(w, r, resp)
|
||||||
|
@ -510,15 +510,15 @@ func (d *DNSFilter) handleSafeBrowsingStatus(w http.ResponseWriter, r *http.Requ
|
||||||
// handleParentalEnable is the handler for the POST /control/parental/enable
|
// handleParentalEnable is the handler for the POST /control/parental/enable
|
||||||
// HTTP API.
|
// HTTP API.
|
||||||
func (d *DNSFilter) handleParentalEnable(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleParentalEnable(w http.ResponseWriter, r *http.Request) {
|
||||||
setProtectedBool(&d.confLock, &d.Config.ParentalEnabled, true)
|
setProtectedBool(d.confMu, &d.conf.ParentalEnabled, true)
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleParentalDisable is the handler for the POST /control/parental/disable
|
// handleParentalDisable is the handler for the POST /control/parental/disable
|
||||||
// HTTP API.
|
// HTTP API.
|
||||||
func (d *DNSFilter) handleParentalDisable(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleParentalDisable(w http.ResponseWriter, r *http.Request) {
|
||||||
setProtectedBool(&d.confLock, &d.Config.ParentalEnabled, false)
|
setProtectedBool(d.confMu, &d.conf.ParentalEnabled, false)
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleParentalStatus is the handler for the GET /control/parental/status
|
// handleParentalStatus is the handler for the GET /control/parental/status
|
||||||
|
@ -527,7 +527,7 @@ func (d *DNSFilter) handleParentalStatus(w http.ResponseWriter, r *http.Request)
|
||||||
resp := &struct {
|
resp := &struct {
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
}{
|
}{
|
||||||
Enabled: protectedBool(&d.confLock, &d.Config.ParentalEnabled),
|
Enabled: protectedBool(d.confMu, &d.conf.ParentalEnabled),
|
||||||
}
|
}
|
||||||
|
|
||||||
aghhttp.WriteJSONResponseOK(w, r, resp)
|
aghhttp.WriteJSONResponseOK(w, r, resp)
|
||||||
|
@ -535,7 +535,7 @@ func (d *DNSFilter) handleParentalStatus(w http.ResponseWriter, r *http.Request)
|
||||||
|
|
||||||
// RegisterFilteringHandlers - register handlers
|
// RegisterFilteringHandlers - register handlers
|
||||||
func (d *DNSFilter) RegisterFilteringHandlers() {
|
func (d *DNSFilter) RegisterFilteringHandlers() {
|
||||||
registerHTTP := d.HTTPRegister
|
registerHTTP := d.conf.HTTPRegister
|
||||||
if registerHTTP == nil {
|
if registerHTTP == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,22 +15,27 @@ type rewriteEntryJSON struct {
|
||||||
Answer string `json:"answer"`
|
Answer string `json:"answer"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleRewriteList is the handler for the GET /control/rewrite/list HTTP API.
|
||||||
func (d *DNSFilter) handleRewriteList(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleRewriteList(w http.ResponseWriter, r *http.Request) {
|
||||||
arr := []*rewriteEntryJSON{}
|
arr := []*rewriteEntryJSON{}
|
||||||
|
|
||||||
d.confLock.Lock()
|
func() {
|
||||||
for _, ent := range d.Config.Rewrites {
|
d.confMu.RLock()
|
||||||
jsent := rewriteEntryJSON{
|
defer d.confMu.RUnlock()
|
||||||
|
|
||||||
|
for _, ent := range d.conf.Rewrites {
|
||||||
|
jsonEnt := rewriteEntryJSON{
|
||||||
Domain: ent.Domain,
|
Domain: ent.Domain,
|
||||||
Answer: ent.Answer,
|
Answer: ent.Answer,
|
||||||
}
|
}
|
||||||
arr = append(arr, &jsent)
|
arr = append(arr, &jsonEnt)
|
||||||
}
|
}
|
||||||
d.confLock.Unlock()
|
}()
|
||||||
|
|
||||||
aghhttp.WriteJSONResponseOK(w, r, arr)
|
aghhttp.WriteJSONResponseOK(w, r, arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleRewriteAdd is the handler for the POST /control/rewrite/add HTTP API.
|
||||||
func (d *DNSFilter) handleRewriteAdd(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleRewriteAdd(w http.ResponseWriter, r *http.Request) {
|
||||||
rwJSON := rewriteEntryJSON{}
|
rwJSON := rewriteEntryJSON{}
|
||||||
err := json.NewDecoder(r.Body).Decode(&rwJSON)
|
err := json.NewDecoder(r.Body).Decode(&rwJSON)
|
||||||
|
@ -54,14 +59,24 @@ func (d *DNSFilter) handleRewriteAdd(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d.confLock.Lock()
|
func() {
|
||||||
d.Config.Rewrites = append(d.Config.Rewrites, rw)
|
d.confMu.Lock()
|
||||||
d.confLock.Unlock()
|
defer d.confMu.Unlock()
|
||||||
log.Debug("rewrite: added element: %s -> %s [%d]", rw.Domain, rw.Answer, len(d.Config.Rewrites))
|
|
||||||
|
|
||||||
d.Config.ConfigModified()
|
d.conf.Rewrites = append(d.conf.Rewrites, rw)
|
||||||
|
log.Debug(
|
||||||
|
"rewrite: added element: %s -> %s [%d]",
|
||||||
|
rw.Domain,
|
||||||
|
rw.Answer,
|
||||||
|
len(d.conf.Rewrites),
|
||||||
|
)
|
||||||
|
}()
|
||||||
|
|
||||||
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleRewriteDelete is the handler for the POST /control/rewrite/delete HTTP
|
||||||
|
// API.
|
||||||
func (d *DNSFilter) handleRewriteDelete(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleRewriteDelete(w http.ResponseWriter, r *http.Request) {
|
||||||
jsent := rewriteEntryJSON{}
|
jsent := rewriteEntryJSON{}
|
||||||
err := json.NewDecoder(r.Body).Decode(&jsent)
|
err := json.NewDecoder(r.Body).Decode(&jsent)
|
||||||
|
@ -77,8 +92,11 @@ func (d *DNSFilter) handleRewriteDelete(w http.ResponseWriter, r *http.Request)
|
||||||
}
|
}
|
||||||
arr := []*LegacyRewrite{}
|
arr := []*LegacyRewrite{}
|
||||||
|
|
||||||
d.confLock.Lock()
|
func() {
|
||||||
for _, ent := range d.Config.Rewrites {
|
d.confMu.Lock()
|
||||||
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
|
for _, ent := range d.conf.Rewrites {
|
||||||
if ent.equal(entDel) {
|
if ent.equal(entDel) {
|
||||||
log.Debug("rewrite: removed element: %s -> %s", ent.Domain, ent.Answer)
|
log.Debug("rewrite: removed element: %s -> %s", ent.Domain, ent.Answer)
|
||||||
|
|
||||||
|
@ -87,10 +105,10 @@ func (d *DNSFilter) handleRewriteDelete(w http.ResponseWriter, r *http.Request)
|
||||||
|
|
||||||
arr = append(arr, ent)
|
arr = append(arr, ent)
|
||||||
}
|
}
|
||||||
d.Config.Rewrites = arr
|
d.conf.Rewrites = arr
|
||||||
d.confLock.Unlock()
|
}()
|
||||||
|
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
// rewriteUpdateJSON is a struct for JSON object with rewrite rule update info.
|
// rewriteUpdateJSON is a struct for JSON object with rewrite rule update info.
|
||||||
|
@ -132,21 +150,21 @@ func (d *DNSFilter) handleRewriteUpdate(w http.ResponseWriter, r *http.Request)
|
||||||
index := -1
|
index := -1
|
||||||
defer func() {
|
defer func() {
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
d.confLock.Lock()
|
d.confMu.Lock()
|
||||||
defer d.confLock.Unlock()
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
index = slices.IndexFunc(d.Config.Rewrites, rwDel.equal)
|
index = slices.IndexFunc(d.conf.Rewrites, rwDel.equal)
|
||||||
if index == -1 {
|
if index == -1 {
|
||||||
aghhttp.Error(r, w, http.StatusBadRequest, "target rule not found")
|
aghhttp.Error(r, w, http.StatusBadRequest, "target rule not found")
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Config.Rewrites = slices.Replace(d.Config.Rewrites, index, index+1, rwAdd)
|
d.conf.Rewrites = slices.Replace(d.conf.Rewrites, index, index+1, rwAdd)
|
||||||
|
|
||||||
log.Debug("rewrite: removed element: %s -> %s", rwDel.Domain, rwDel.Answer)
|
log.Debug("rewrite: removed element: %s -> %s", rwDel.Domain, rwDel.Answer)
|
||||||
log.Debug("rewrite: added element: %s -> %s", rwAdd.Domain, rwAdd.Answer)
|
log.Debug("rewrite: added element: %s -> %s", rwAdd.Domain, rwAdd.Answer)
|
||||||
|
|
|
@ -139,7 +139,7 @@ func (rw *LegacyRewrite) Compare(b *LegacyRewrite) (res int) {
|
||||||
|
|
||||||
// prepareRewrites normalizes and validates all legacy DNS rewrites.
|
// prepareRewrites normalizes and validates all legacy DNS rewrites.
|
||||||
func (d *DNSFilter) prepareRewrites() (err error) {
|
func (d *DNSFilter) prepareRewrites() (err error) {
|
||||||
for i, r := range d.Rewrites {
|
for i, r := range d.conf.Rewrites {
|
||||||
err = r.normalize()
|
err = r.normalize()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("at index %d: %w", i, err)
|
return fmt.Errorf("at index %d: %w", i, err)
|
||||||
|
|
|
@ -26,7 +26,7 @@ func TestRewrites(t *testing.T) {
|
||||||
addr2v6 = netip.MustParseAddr("1234::5678")
|
addr2v6 = netip.MustParseAddr("1234::5678")
|
||||||
)
|
)
|
||||||
|
|
||||||
d.Rewrites = []*LegacyRewrite{{
|
d.conf.Rewrites = []*LegacyRewrite{{
|
||||||
// This one and below are about CNAME, A and AAAA.
|
// This one and below are about CNAME, A and AAAA.
|
||||||
Domain: "somecname",
|
Domain: "somecname",
|
||||||
Answer: "somehost.com",
|
Answer: "somehost.com",
|
||||||
|
@ -202,7 +202,7 @@ func TestRewritesLevels(t *testing.T) {
|
||||||
d, _ := newForTest(t, nil, nil)
|
d, _ := newForTest(t, nil, nil)
|
||||||
t.Cleanup(d.Close)
|
t.Cleanup(d.Close)
|
||||||
// Exact host, wildcard L2, wildcard L3.
|
// Exact host, wildcard L2, wildcard L3.
|
||||||
d.Rewrites = []*LegacyRewrite{{
|
d.conf.Rewrites = []*LegacyRewrite{{
|
||||||
Domain: "host.com",
|
Domain: "host.com",
|
||||||
Answer: "1.1.1.1",
|
Answer: "1.1.1.1",
|
||||||
Type: dns.TypeA,
|
Type: dns.TypeA,
|
||||||
|
@ -249,7 +249,7 @@ func TestRewritesExceptionCNAME(t *testing.T) {
|
||||||
d, _ := newForTest(t, nil, nil)
|
d, _ := newForTest(t, nil, nil)
|
||||||
t.Cleanup(d.Close)
|
t.Cleanup(d.Close)
|
||||||
// Wildcard and exception for a sub-domain.
|
// Wildcard and exception for a sub-domain.
|
||||||
d.Rewrites = []*LegacyRewrite{{
|
d.conf.Rewrites = []*LegacyRewrite{{
|
||||||
Domain: "*.host.com",
|
Domain: "*.host.com",
|
||||||
Answer: "2.2.2.2",
|
Answer: "2.2.2.2",
|
||||||
}, {
|
}, {
|
||||||
|
@ -300,7 +300,7 @@ func TestRewritesExceptionIP(t *testing.T) {
|
||||||
d, _ := newForTest(t, nil, nil)
|
d, _ := newForTest(t, nil, nil)
|
||||||
t.Cleanup(d.Close)
|
t.Cleanup(d.Close)
|
||||||
// Exception for AAAA record.
|
// Exception for AAAA record.
|
||||||
d.Rewrites = []*LegacyRewrite{{
|
d.conf.Rewrites = []*LegacyRewrite{{
|
||||||
Domain: "host.com",
|
Domain: "host.com",
|
||||||
Answer: "1.2.3.4",
|
Answer: "1.2.3.4",
|
||||||
Type: dns.TypeA,
|
Type: dns.TypeA,
|
||||||
|
|
|
@ -12,8 +12,8 @@ import (
|
||||||
//
|
//
|
||||||
// Deprecated: Use handleSafeSearchSettings.
|
// Deprecated: Use handleSafeSearchSettings.
|
||||||
func (d *DNSFilter) handleSafeSearchEnable(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleSafeSearchEnable(w http.ResponseWriter, r *http.Request) {
|
||||||
setProtectedBool(&d.confLock, &d.Config.SafeSearchConf.Enabled, true)
|
setProtectedBool(d.confMu, &d.conf.SafeSearchConf.Enabled, true)
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleSafeSearchDisable is the handler for POST /control/safesearch/disable
|
// handleSafeSearchDisable is the handler for POST /control/safesearch/disable
|
||||||
|
@ -21,8 +21,8 @@ func (d *DNSFilter) handleSafeSearchEnable(w http.ResponseWriter, r *http.Reques
|
||||||
//
|
//
|
||||||
// Deprecated: Use handleSafeSearchSettings.
|
// Deprecated: Use handleSafeSearchSettings.
|
||||||
func (d *DNSFilter) handleSafeSearchDisable(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleSafeSearchDisable(w http.ResponseWriter, r *http.Request) {
|
||||||
setProtectedBool(&d.confLock, &d.Config.SafeSearchConf.Enabled, false)
|
setProtectedBool(d.confMu, &d.conf.SafeSearchConf.Enabled, false)
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleSafeSearchStatus is the handler for GET /control/safesearch/status
|
// handleSafeSearchStatus is the handler for GET /control/safesearch/status
|
||||||
|
@ -30,10 +30,10 @@ func (d *DNSFilter) handleSafeSearchDisable(w http.ResponseWriter, r *http.Reque
|
||||||
func (d *DNSFilter) handleSafeSearchStatus(w http.ResponseWriter, r *http.Request) {
|
func (d *DNSFilter) handleSafeSearchStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
var resp SafeSearchConfig
|
var resp SafeSearchConfig
|
||||||
func() {
|
func() {
|
||||||
d.confLock.RLock()
|
d.confMu.RLock()
|
||||||
defer d.confLock.RUnlock()
|
defer d.confMu.RUnlock()
|
||||||
|
|
||||||
resp = d.Config.SafeSearchConf
|
resp = d.conf.SafeSearchConf
|
||||||
}()
|
}()
|
||||||
|
|
||||||
aghhttp.WriteJSONResponseOK(w, r, resp)
|
aghhttp.WriteJSONResponseOK(w, r, resp)
|
||||||
|
@ -59,13 +59,13 @@ func (d *DNSFilter) handleSafeSearchSettings(w http.ResponseWriter, r *http.Requ
|
||||||
}
|
}
|
||||||
|
|
||||||
func() {
|
func() {
|
||||||
d.confLock.Lock()
|
d.confMu.Lock()
|
||||||
defer d.confLock.Unlock()
|
defer d.confMu.Unlock()
|
||||||
|
|
||||||
d.Config.SafeSearchConf = conf
|
d.conf.SafeSearchConf = conf
|
||||||
}()
|
}()
|
||||||
|
|
||||||
d.Config.ConfigModified()
|
d.conf.ConfigModified()
|
||||||
|
|
||||||
aghhttp.OK(w)
|
aghhttp.OK(w)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue