Skip to content

Commit

Permalink
Fixed and working - Date: Thu Feb 16 11:38:28 CST 2023
Browse files Browse the repository at this point in the history
  • Loading branch information
charlieporth1 committed Feb 16, 2023
1 parent bdbd028 commit bab1de4
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 154 deletions.
236 changes: 118 additions & 118 deletions blocklistdb-domain.go
Original file line number Diff line number Diff line change
@@ -1,118 +1,118 @@
package rdns

import (
"fmt"
"net"
"strings"

"github.com/miekg/dns"
)

// DomainDB holds a list of domain strings (potentially with wildcards). Matching
// logic:
// domain.com: matches just domain.com and not subdomains
// .domain.com: matches domain.com and all subdomains
// *.domain.com: matches all subdomains but not domain.com
type DomainDB struct {
name string
root node
loader BlocklistLoader
}

type node map[string]node

var _ BlocklistDB = &DomainDB{}

// NewDomainDB returns a new instance of a matcher for a list of regular expressions.
func NewDomainDB(name string, loader BlocklistLoader) (*DomainDB, error) {
rules, err := loader.Load()
if err != nil {
return nil, err
}
root := make(node)
for _, r := range rules {
r = strings.TrimSpace(r)

// Strip trailing . in case the list has FQDN names with . suffixes.
r = strings.TrimSuffix(r, ".")

// Break up the domain into its parts and iterare backwards over them, building
// a graph of maps
parts := strings.Split(r, ".")
n := root
for i := len(parts) - 1; i >= 0; i-- {
part := parts[i]

// Only allow wildcards as the first domain part, and not in a string
if strings.Contains(part, "*") && (i > 0 || len(part) != 1) {
return nil, fmt.Errorf("invalid blocklist item: '%s'", part)
}

subNode, ok := n[part]
if !ok {
subNode = make(node)
n[part] = subNode
}
n = subNode
}
}
return &DomainDB{name, root, loader}, nil
}

func (m *DomainDB) Reload() (BlocklistDB, error) {
return NewDomainDB(m.name, m.loader)
}

func (m *DomainDB) Match(q dns.Question) (net.IP, string, *BlocklistMatch, bool) {
s := strings.TrimSuffix(q.Name, ".")
var matched []string
parts := strings.Split(s, ".")
n := m.root
for i := len(parts) - 1; i >= 0; i-- {
part := parts[i]
subNode, ok := n[part]
if !ok {
return nil, "", nil, false
}
matched = append(matched, part)
if _, ok := subNode[""]; ok { // exact and sub-domain match
return nil,
"",
&BlocklistMatch{
List: m.name,
Rule: matchedDomainParts(".", matched),
},
true
}
if _, ok := subNode["*"]; ok && i > 0 { // wildcard match on sub-domains
return nil,
"",
&BlocklistMatch{
List: m.name,
Rule: matchedDomainParts("*.", matched),
},
true
}
n = subNode
}
return nil,
"",
&BlocklistMatch{
List: m.name,
Rule: matchedDomainParts("", matched),
},
len(n) == 0 // exact match
}

func (m *DomainDB) String() string {
return "Domain"
}

// Turn a list of matched domain fragments into a domain (rule)
func matchedDomainParts(prefix string, p []string) string {
for i := len(p)/2 - 1; i >= 0; i-- {
opp := len(p) - 1 - i
p[i], p[opp] = p[opp], p[i]
}
return prefix + strings.Join(p, ".")
}
package rdns

import (
"fmt"
"net"
"strings"

"github.com/miekg/dns"
)

// DomainDB holds a list of domain strings (potentially with wildcards). Matching
// logic:
// domain.com: matches just domain.com and not subdomains
// .domain.com: matches domain.com and all subdomains
// *.domain.com: matches all subdomains but not domain.com
type DomainDB struct {
name string
root node
loader BlocklistLoader
}

type node map[string]node

var _ BlocklistDB = &DomainDB{}

// NewDomainDB returns a new instance of a matcher for a list of regular expressions.
func NewDomainDB(name string, loader BlocklistLoader) *DomainDB {
return &DomainDB{name, nil, loader}
}

func (m *DomainDB) Reload() (BlocklistDB, error) {
rules, err := m.loader.Load()
if err != nil {
return nil, err
}
root := make(node)
for _, r := range rules {
r = strings.TrimSpace(r)

// Strip trailing . in case the list has FQDN names with . suffixes.
r = strings.TrimSuffix(r, ".")

// Break up the domain into its parts and iterate backwards over them, building
// a graph of maps
parts := strings.Split(r, ".")
n := root
for i := len(parts) - 1; i >= 0; i-- {
part := parts[i]

// Only allow wildcards as the first domain part, and not in a string
if strings.Contains(part, "*") && (i > 0 || len(part) != 1) {
return nil, fmt.Errorf("invalid blocklist item: '%s'", part)
}

subNode, ok := n[part]
if !ok {
subNode = make(node)
n[part] = subNode
}
n = subNode
}
}
return &DomainDB{m.name, root, m.loader}, nil
}

func (m *DomainDB) Match(q dns.Question) (net.IP, string, *BlocklistMatch, bool) {
s := strings.TrimSuffix(q.Name, ".")
var matched []string
parts := strings.Split(s, ".")
n := m.root
for i := len(parts) - 1; i >= 0; i-- {
part := parts[i]
subNode, ok := n[part]
if !ok {
return nil, "", nil, false
}
matched = append(matched, part)
if _, ok := subNode[""]; ok { // exact and sub-domain match
return nil,
"",
&BlocklistMatch{
List: m.name,
Rule: matchedDomainParts(".", matched),
},
true
}
if _, ok := subNode["*"]; ok && i > 0 { // wildcard match on sub-domains
return nil,
"",
&BlocklistMatch{
List: m.name,
Rule: matchedDomainParts("*.", matched),
},
true
}
n = subNode
}
return nil,
"",
&BlocklistMatch{
List: m.name,
Rule: matchedDomainParts("", matched),
},
len(n) == 0 // exact match
}

func (m *DomainDB) String() string {
return "Domain"
}

// Turn a list of matched domain fragments into a domain (rule)
func matchedDomainParts(prefix string, p []string) string {
for i := len(p)/2 - 1; i >= 0; i-- {
opp := len(p) - 1 - i
p[i], p[opp] = p[opp], p[i]
}
return prefix + strings.Join(p, ".")
}
13 changes: 7 additions & 6 deletions blocklistdb-hosts.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,12 @@ type ipRecords struct {
var _ BlocklistDB = &HostsDB{}

// NewHostsDB returns a new instance of a matcher for a list of regular expressions.
func NewHostsDB(name string, loader BlocklistLoader) (*HostsDB, error) {
rules, err := loader.Load()
func NewHostsDB(name string, loader BlocklistLoader) *HostsDB {
return &HostsDB{name, nil,nil, loader}
}

func (m *HostsDB) Reload() (BlocklistDB, error) {
rules, err := m.loader.Load()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -70,11 +74,8 @@ func NewHostsDB(name string, loader BlocklistLoader) (*HostsDB, error) {
}
ptrMap[reverseAddr] = names[0]
}
return &HostsDB{name, filters, ptrMap, loader}, nil
}
return &HostsDB{m.name, filters, ptrMap, m.loader}, nil

func (m *HostsDB) Reload() (BlocklistDB, error) {
return NewHostsDB(m.name, m.loader)
}

func (m *HostsDB) Match(q dns.Question) (net.IP, string, *BlocklistMatch, bool) {
Expand Down
15 changes: 8 additions & 7 deletions blocklistdb-regexp.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,17 @@ type RegexpDB struct {
var _ BlocklistDB = &RegexpDB{}

// NewRegexpDB returns a new instance of a matcher for a list of regular expressions.
func NewRegexpDB(name string, loader BlocklistLoader) (*RegexpDB, error) {
rules, err := loader.Load()
func NewRegexpDB(name string, loader BlocklistLoader) *RegexpDB {
return &RegexpDB{name, nil, loader}
}

func (m *RegexpDB) Reload() (BlocklistDB, error) {
rules, err := m.loader.Load()
if err != nil {
return nil, err
}
var filters []*regexp.Regexp

for _, r := range rules {
r = strings.TrimSpace(r)
if r == "" || strings.HasPrefix(r, "#") {
Expand All @@ -36,11 +41,7 @@ func NewRegexpDB(name string, loader BlocklistLoader) (*RegexpDB, error) {
filters = append(filters, re)
}

return &RegexpDB{name, filters, loader}, nil
}

func (m *RegexpDB) Reload() (BlocklistDB, error) {
return NewRegexpDB(m.name, m.loader)
return &RegexpDB{m.name, filters, m.loader}, nil
}

func (m *RegexpDB) Match(q dns.Question) (net.IP, string, *BlocklistMatch, bool) {
Expand Down
18 changes: 9 additions & 9 deletions cidr-db.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,20 @@ type CidrDB struct {
var _ IPBlocklistDB = &CidrDB{}

// NewCidrDB returns a new instance of a matcher for a list of networks.
func NewCidrDB(name string, loader BlocklistLoader) (*CidrDB, error) {
rules, err := loader.Load()
func NewCidrDB(name string, loader BlocklistLoader) *CidrDB {
return &CidrDB{name, nil, nil, loader}
}

func (m *CidrDB) Reload() (IPBlocklistDB, error) {
rules, err := m.loader.Load()
if err != nil {
return nil, err
}
db := &CidrDB{
name: name,
name: m.name,
ip4: new(ipBlocklistTrie),
ip6: new(ipBlocklistTrie),
loader: loader,
loader: m.loader,
}
for _, r := range rules {
r = strings.TrimSpace(r)
Expand All @@ -51,11 +55,7 @@ func NewCidrDB(name string, loader BlocklistLoader) (*CidrDB, error) {
db.ip4.add(n)
}
}
return db, nil
}

func (m *CidrDB) Reload() (IPBlocklistDB, error) {
return NewCidrDB(m.name, m.loader)
return &CidrDB{m.name, db.ip4, db.ip6, m.loader}, nil
}

func (m *CidrDB) Match(ip net.IP) (*BlocklistMatch, bool) {
Expand Down
9 changes: 5 additions & 4 deletions cmd/routedns/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,11 @@ type group struct {

// Block/Allowlist items for blocklist-v2
type list struct {
Name string
Format string
Source string
CacheDir string `toml:"cache-dir"` // Where to store copies of remote blocklists for faster startup
Name string
Format string
Source string
CacheDir string `toml:"cache-dir"` // Where to store copies of remote blocklists for faster startup
AllowFailOnStart bool `toml:"allow-fail-on-startup"` // Don't fail if the blocklist can't be loaded on startup, just print a warning
}

type router struct {
Expand Down
Loading

0 comments on commit bab1de4

Please sign in to comment.