filtering

package
v0.107.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 29, 2021 License: GPL-3.0 Imports: 32 Imported by: 0

README

AdGuard Home's DNS filtering go library

Example use:

[ -z "$GOPATH" ] && export GOPATH=$HOME/go
go get -d github.com/AdguardTeam/AdGuardHome/filtering

Create file filter.go

package main

import (
    "github.com/AdguardTeam/AdGuardHome/filtering"
    "log"
)

func main() {
    filter := filtering.New()
    filter.AddRule("||dou*ck.net^")
    host := "www.doubleclick.net"
    res, err := filter.CheckHost(host)
    if err != nil {
        // temporary failure
        log.Fatalf("Failed to check host %q: %s", host, err)
    }
    if res.IsFiltered {
        log.Printf("Host %s is filtered, reason - %q, matched rule: %q", host, res.Reason, res.Rule)
    } else {
        log.Printf("Host %s is not filtered, reason - %q", host, res.Reason)
    }
}

And then run it:

go run filter.go

You will get:

2000/01/01 00:00:00 Host www.doubleclick.net is filtered, reason - 'FilteredBlackList', matched rule: '||dou*ck.net^'

You can also enable checking against AdGuard's SafeBrowsing:

package main

import (
    "github.com/AdguardTeam/AdGuardHome/filtering"
    "log"
)

func main() {
    filter := filtering.New()
    filter.EnableSafeBrowsing()
    host := "wmconvirus.narod.ru" // hostname for testing safebrowsing
    res, err := filter.CheckHost(host)
    if err != nil {
        // temporary failure
        log.Fatalf("Failed to check host %q: %s", host, err)
    }
    if res.IsFiltered {
        log.Printf("Host %s is filtered, reason - %q, matched rule: %q", host, res.Reason, res.Rule)
    } else {
        log.Printf("Host %s is not filtered, reason - %q", host, res.Reason)
    }
}

Documentation

Overview

Package filtering implements a DNS request and response filter.

Index

Constants

View Source
const (
	CustomListID = -iota
	SysHostsListID
	BlockedSvcsListID
	ParentalListID
	SafeBrowsingListID
	SafeSearchListID
)

The IDs of built-in filter lists.

Keep in sync with client/src/helpers/constants.js.

Variables

This section is empty.

Functions

func BlockedSvcKnown

func BlockedSvcKnown(s string) bool

BlockedSvcKnown - return TRUE if a blocked service name is known

func InitModule

func InitModule()

InitModule manually initializes blocked services map.

Types

type Config

type Config struct {
	ParentalEnabled     bool `yaml:"parental_enabled"`
	SafeSearchEnabled   bool `yaml:"safesearch_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)
	CacheTime             uint `yaml:"cache_time"`              // Element's TTL (in minutes)

	Rewrites []*LegacyRewrite `yaml:"rewrites"`

	// Names of services to block (globally).
	// Per-client settings can override this configuration.
	BlockedServices []string `yaml:"blocked_services"`

	// EtcHosts is a container of IP-hostname pairs taken from the operating
	// system configuration files (e.g. /etc/hosts).
	EtcHosts *aghnet.HostsContainer `yaml:"-"`

	// Called when the configuration is changed by HTTP request
	ConfigModified func() `yaml:"-"`

	// Register an HTTP handler
	HTTPRegister func(string, string, func(http.ResponseWriter, *http.Request)) `yaml:"-"`

	// CustomResolver is the resolver used by DNSFilter.
	CustomResolver Resolver `yaml:"-"`
	// contains filtered or unexported fields
}

Config allows you to configure DNS filtering with New() or just change variables directly.

type DNSFilter

type DNSFilter struct {
	Config // for direct access by library users, even a = assignment
	// contains filtered or unexported fields
}

DNSFilter matches hostnames and DNS requests against filtering rules.

func New

func New(c *Config, blockFilters []Filter) (d *DNSFilter)

New creates properly initialized DNS Filter that is ready to be used.

func (*DNSFilter) ApplyBlockedServices

func (d *DNSFilter) ApplyBlockedServices(setts *Settings, list []string, global bool)

ApplyBlockedServices - set blocked services settings for this DNS request

func (*DNSFilter) CheckHost

func (d *DNSFilter) CheckHost(
	host string,
	qtype uint16,
	setts *Settings,
) (res Result, err error)

CheckHost tries to match the host against filtering rules, then safebrowsing and parental control rules, if they are enabled.

func (*DNSFilter) CheckHostRules

func (d *DNSFilter) CheckHostRules(host string, qtype uint16, setts *Settings) (Result, error)

CheckHostRules tries to match the host against filtering rules only.

func (*DNSFilter) Close

func (d *DNSFilter) Close()

Close - close the object

func (*DNSFilter) GetConfig

func (d *DNSFilter) GetConfig() (s Settings)

GetConfig - get configuration

func (*DNSFilter) SafeSearchDomain

func (d *DNSFilter) SafeSearchDomain(host string) (string, bool)

SafeSearchDomain returns replacement address for search engine

func (*DNSFilter) SetEnabled

func (d *DNSFilter) SetEnabled(enabled bool)

SetEnabled sets the status of the *DNSFilter.

func (*DNSFilter) SetFilters

func (d *DNSFilter) SetFilters(blockFilters, allowFilters []Filter, async bool) error

SetFilters - set new filters (synchronously or asynchronously) When filters are set asynchronously, the old filters continue working until the new filters are ready.

In this case the caller must ensure that the old filter files are intact.

func (*DNSFilter) SetParentalUpstream

func (d *DNSFilter) SetParentalUpstream(u upstream.Upstream)

SetParentalUpstream sets the parental upstream for *DNSFilter.

TODO(e.burkov): Remove this in v1 API to forbid the direct access.

func (*DNSFilter) SetSafeBrowsingUpstream

func (d *DNSFilter) SetSafeBrowsingUpstream(u upstream.Upstream)

SetSafeBrowsingUpstream sets the safe browsing upstream for *DNSFilter.

TODO(e.burkov): Remove this in v1 API to forbid the direct access.

func (*DNSFilter) Start

func (d *DNSFilter) Start()

Start - start the module: . start async filtering initializer goroutine . register web handlers

func (*DNSFilter) WriteDiskConfig

func (d *DNSFilter) WriteDiskConfig(c *Config)

WriteDiskConfig - write configuration

type DNSRewriteResult

type DNSRewriteResult struct {
	Response DNSRewriteResultResponse `json:",omitempty"`
	RCode    rules.RCode              `json:",omitempty"`
}

DNSRewriteResult is the result of application of $dnsrewrite rules.

type DNSRewriteResultResponse

type DNSRewriteResultResponse map[rules.RRType][]rules.RRValue

DNSRewriteResultResponse is the collection of DNS response records the server returns.

type Filter

type Filter struct {
	// FilePath is the path to a filtering rules list file.
	FilePath string `yaml:"-"`

	// Data is the content of the file.
	Data []byte `yaml:"-"`

	// ID is automatically assigned when filter is added using nextFilterID.
	ID int64
}

Filter represents a filter list

type LegacyRewrite added in v0.107.1

type LegacyRewrite struct {
	// Domain is the domain pattern for which this rewrite should work.
	Domain string `yaml:"domain"`

	// Answer is the IP address, canonical name, or one of the special
	// values: "A" or "AAAA".
	Answer string `yaml:"answer"`

	// IP is the IP address that should be used in the response if Type is
	// dns.TypeA or dns.TypeAAAA.
	IP net.IP `yaml:"-"`

	// Type is the DNS record type: A, AAAA, or CNAME.
	Type uint16 `yaml:"-"`
}

LegacyRewrite is a single legacy DNS rewrite record.

Instances of *LegacyRewrite must never be nil.

type LookupStats

type LookupStats struct {
	Requests   uint64 // number of HTTP requests that were sent
	CacheHits  uint64 // number of lookups that didn't need HTTP requests
	Pending    int64  // number of currently pending HTTP requests
	PendingMax int64  // maximum number of pending HTTP requests
}

LookupStats store stats collected during safebrowsing or parental checks

type Reason

type Reason int

Reason holds an enum detailing why it was filtered or not filtered

const (

	// NotFilteredNotFound - host was not find in any checks, default value for result
	NotFilteredNotFound Reason = iota
	// NotFilteredAllowList - the host is explicitly allowed
	NotFilteredAllowList
	// NotFilteredError is returned when there was an error during
	// checking.  Reserved, currently unused.
	NotFilteredError

	// FilteredBlockList - the host was matched to be advertising host
	FilteredBlockList
	// FilteredSafeBrowsing - the host was matched to be malicious/phishing
	FilteredSafeBrowsing
	// FilteredParental - the host was matched to be outside of parental control settings
	FilteredParental
	// FilteredInvalid - the request was invalid and was not processed
	FilteredInvalid
	// FilteredSafeSearch - the host was replaced with safesearch variant
	FilteredSafeSearch
	// FilteredBlockedService - the host is blocked by "blocked services" settings
	FilteredBlockedService

	// Rewritten is returned when there was a rewrite by a legacy DNS rewrite
	// rule.
	Rewritten

	// RewrittenAutoHosts is returned when there was a rewrite by autohosts
	// rules (/etc/hosts and so on).
	RewrittenAutoHosts

	// RewrittenRule is returned when a $dnsrewrite filter rule was applied.
	//
	// TODO(a.garipov): Remove Rewritten and RewrittenAutoHosts by merging their
	// functionality into RewrittenRule.
	//
	// See https://github.com/AdguardTeam/AdGuardHome/issues/2499.
	RewrittenRule
)

func (Reason) In

func (r Reason) In(reasons ...Reason) (ok bool)

In returns true if reasons include r.

func (Reason) Matched

func (r Reason) Matched() bool

Matched returns true if any match at all was found regardless of whether it was filtered or not.

func (Reason) String

func (r Reason) String() string

type Resolver

type Resolver interface {
	LookupIP(ctx context.Context, network, host string) (ips []net.IP, err error)
}

Resolver is the interface for net.Resolver to simplify testing.

type Result

type Result struct {
	// IsFiltered is true if the request is filtered.
	IsFiltered bool `json:",omitempty"`

	// Reason is the reason for blocking or unblocking the request.
	Reason Reason `json:",omitempty"`

	// Rules are applied rules.  If Rules are not empty, each rule is not nil.
	Rules []*ResultRule `json:",omitempty"`

	// IPList is the lookup rewrite result.  It is empty unless Reason is set to
	// Rewritten.
	IPList []net.IP `json:",omitempty"`

	// CanonName is the CNAME value from the lookup rewrite result.  It is empty
	// unless Reason is set to Rewritten or RewrittenRule.
	CanonName string `json:",omitempty"`

	// ServiceName is the name of the blocked service.  It is empty unless
	// Reason is set to FilteredBlockedService.
	ServiceName string `json:",omitempty"`

	// DNSRewriteResult is the $dnsrewrite filter rule result.
	DNSRewriteResult *DNSRewriteResult `json:",omitempty"`
}

Result contains the result of a request check.

All fields transitively have omitempty tags so that the query log doesn't become too large.

TODO(a.garipov): Clarify relationships between fields. Perhaps replace with a sum type or an interface?

type ResultRule

type ResultRule struct {
	// Text is the text of the rule.
	Text string `json:",omitempty"`
	// IP is the host IP.  It is nil unless the rule uses the
	// /etc/hosts syntax or the reason is FilteredSafeSearch.
	IP net.IP `json:",omitempty"`
	// FilterListID is the ID of the rule's filter list.
	FilterListID int64 `json:",omitempty"`
}

ResultRule contains information about applied rules.

type ServiceEntry

type ServiceEntry struct {
	Name  string
	Rules []*rules.NetworkRule
}

ServiceEntry - blocked service array element

type Settings

type Settings struct {
	ClientName string
	ClientIP   net.IP
	ClientTags []string

	ServicesRules []ServiceEntry

	ProtectionEnabled   bool
	FilteringEnabled    bool
	SafeSearchEnabled   bool
	SafeBrowsingEnabled bool
	ParentalEnabled     bool
}

Settings are custom filtering settings for a client.

type Stats

type Stats struct {
	Safebrowsing LookupStats
	Parental     LookupStats
	Safesearch   LookupStats
}

Stats store LookupStats for safebrowsing, parental and safesearch

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL