forked from icyflame/blocker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
block_domains_decider_abp.go
111 lines (86 loc) · 2.62 KB
/
block_domains_decider_abp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package blocker
import (
"bufio"
"strings"
"sync"
"sync/atomic"
"time"
"github.com/miekg/dns"
)
type BlockDomainsDeciderABP struct {
blocklistResolver *BlocklistResolver
lastUpdated time.Time
log Logger
blocklistLock sync.RWMutex
blocklist map[string]bool
ready atomic.Bool
}
// Name ...
func NewBlockDomainsDeciderABP(blocklistResolver *BlocklistResolver, logger Logger) BlockDomainsDecider {
d := &BlockDomainsDeciderABP{
blocklistResolver: blocklistResolver,
log: logger,
blocklistLock: sync.RWMutex{},
blocklist: map[string]bool{},
ready: atomic.Bool{},
}
d.ready.Store(false)
ch := make(chan string, 1)
blocklistResolver.Subscribe(ch)
go func() {
for contents := range ch {
d.log.Infof("received updated blocklist contents. Length %d", len(contents))
d.UpdateBlocklist(contents)
d.ready.Store(true)
}
}()
return d
}
func (d *BlockDomainsDeciderABP) Ready() bool {
return d.ready.Load()
}
// IsDomainBlocked ...
func (d *BlockDomainsDeciderABP) IsDomainBlocked(domain string) bool {
d.blocklistLock.RLock()
defer d.blocklistLock.RUnlock()
// We will check every subdomain of the given domain against the blocklist. i.e. if example.com
// is blocked, then every subdomain of that (subdomain.example.com, sub1.sub2.example.com) is
// blocked. However, example.com.org is not blocked.
comps := strings.Split(domain, ".")
current := comps[len(comps)-1]
for i := len(comps) - 2; i >= 0; i-- {
newCurrent := strings.Join([]string{
comps[i],
current,
}, ".")
if d.blocklist[newCurrent] {
return true
}
current = newCurrent
}
return false
}
// UpdateBlocklist ...
func (d *BlockDomainsDeciderABP) UpdateBlocklist(contents string) error {
d.blocklistLock.Lock()
defer d.blocklistLock.Unlock()
// Update process
numBlockedDomainsBefore := len(d.blocklist)
lastUpdatedBefore := d.lastUpdated
scanner := bufio.NewScanner(strings.NewReader(contents))
for scanner.Scan() {
hostLine := scanner.Text()
if !strings.HasPrefix(hostLine, "||") || !strings.HasSuffix(hostLine, "^") {
d.log.Warningf("line \"%s\" does not match parseable ABP syntax subset", hostLine)
continue
}
hostLine = strings.TrimPrefix(hostLine, "||")
hostLine = strings.TrimSuffix(hostLine, "^")
d.blocklist[dns.Fqdn(hostLine)] = true
}
d.lastUpdated = time.Now()
d.log.Infof("updated blocklist; blocked domains: before: %d, after: %d; last updated: before: %v, after: %v",
numBlockedDomainsBefore, len(d.blocklist), lastUpdatedBefore, d.lastUpdated)
blocklistSize.WithLabelValues(d.blocklistResolver.uri).Set(float64(len(d.blocklist)))
return nil
}