filter

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2023 License: MIT Imports: 24 Imported by: 0

README

filter

Go Reference Coverage Go Report Card

filter - provides domain blocking functionality

Description

The filter plugin is used to block domain name resolution, simliar to Pi-hole®.

Syntax

filter {
    ACTION TYPE DATA
}
  • ACTION: [ allow | block ] What action to take
  • TYPE: [ domain | regex | wildcard ] What type of DATA
  • DATA:
    • domain: A raw domain to match. Subdomains are not matched
    • regex: A Go-formatted Regular Expression
    • wildcard: Common wildcard formats
      • Bare: example.com
      • Generic: *.example.com
      • Adblock Plus: ||example.com^
      • DNSMasq Address: address=/example.com/#
filter {
    ACTION list TYPE DATA
}
  • ACTION: [ allow | block ] What action to take
  • DATA: Lists of the following data types
    • domain: A raw domain to match. Subdomains are not matched
    • hosts: A hostsfile formatted list
    • regex: A Go-formatted Regular Expression
    • wildcard: Common wildcard formats
      • Bare: example.com
      • Generic: *.example.com
      • Adblock Plus: ||example.com^
      • DNSMasq Address: address=/example.com/#
  • DATA: A [ file | http | https ] URL. Must contain only the TYPE specified.
filter {
    response TYPE [ DATA ]
}
  • TYPE [ address | nodata | null | nxdomain ] Record type that should be the response to blocked domains
    • address: Only A and AAAA records are accepted, and only one of each. Lowercase record types are accepted.
    • nodata: Returns success code but no records
    • null (DEFAULT): Returns unspecified address records A 0.0.0.0 and AAAA ::
    • nxdomain: Returns an SOA record for the requested domain.
  • DATA Only used for address responses
filter {
    update DURATION
}
filter {
    listresolver RESOLVER [ SERVER_NAME ]
}
  • RESOLVER: a resolver IP address to use when fetching remote lists. dns and tls schemes are accepted. Ports may be specified. IPv6 address are accepted when used with a scheme and port. Since listresolver is intended to be used when no other resolvers are available, only IP addresses are accepted.
  • SERVER_NAME: Only used when resolver scheme is tls. Must be the host name of the resolver, otherwise resolving will fail due to being unable to verify the resolver's certificate.

Domain Matching

Directive Description
block domain example.com block requests to example.com but allow sub.example.com
block regex .*.example.com block all subdomains of example.com but allow requests to example.com
block wildcard *.example.com block requests to example.com and all subdomains

Values for regex directives are parsed directly by regexp.Compile, so if you're unfamiliar with Go regular expressions, verify them using https://regex101.com/?flavor=golang. Complex regular expressions should be loaded from a list instead of inline to avoid confusing the CoreDNS Corefile parser with symbols.

With how wildcard strings are cleaned and compiled, the following block wildcard directives are identical.

IMPORTANT: Allowed domains always take precedence. If a domain is in an allow list and a domain in that list is blocked explicitly or on block list, it will be allowed. Think of allow directives as force overrides and use them with caution.

filter {
    block wildcard example.com
    block wildcard *.example.com
    block wildcard .*.example.com
    block wildcard ||example.com^
    block wildcard address=/example.com/#
    block wildcard address=/example.com/0.0.0.0
}

AdblockPlus and DNSMasq formats are supported for flexibility and ease of migration from other solutions. Zone and Unbound configuration files are not supported.

Examples

# Use an aggregated block list, but allow `vortex.data.microsoft.com` for XBox
# Live achievements. Retrieve the block list using Quad9 over TLS. Respond to
# blocked domains with `A 0.0.0.0` and `AAAA ::` records. Update list every 24
# hours.

filter {
    listresolver tls://9.9.9.9 dns.quad9.net
    block list domain https://small.oisd.nl/
    allow domain vortex.data.microsoft.com
}
# Block all request except domains explicitly allowed in the list on the
# filesystem. Forward blocked requests to an internal web server to display a
# block page and log unapproved sites. Do not automatically update lists. Only a
# restart of CoreDNS will refresh the list's contents.

filter {
    block regex .*
    allow list domains file:///etc/coredns/whitelist
    response address A 10.0.1.50 AAAA 2001:db8:abcd:0012::ffff:0a00:0132
    update 0
}

Building

Clone the coredns repository and change into it's directory.

git clone https://github.com/coredns/coredns.git
cd coredns

Fetch the plugin and add it to coredns's go.mod file:

go get -u github.com/wranders/coredns-filter

Update plugin.cfg in the root of the directory. The filter declaration should be inserted before cache so that updates to the filter are applied immediately.

# Using sed
sed -i '/^cache:cache/i filter:github.com/wranders/coredns-filter' plugin.cfg
# Using Powershell
(Get-Content plugin.cfg).`
Replace("cache:cache", "filter:github.com/wranders/coredns-filter`ncache:cache") | `
Set-Content -Path plugin.cfg

Build using make:

make

Or if make is not available, simply run:

go generate && go build

The coredns binary will be in the root of the project directory, unless otherwise specified by the -o flag.

Container

A pre-built Container with this plugin is provided at the following locations:

ghcr.io/wranders/coredns-filter:latest
quay.io/wranders/coredns-filter:latest

CPU architectures include armv6 and armv7 (Raspberry Pi), aarch64, and x86_64.

The coredns binary is located at the root of the filesystem, so a Corefile mounted to /Corefile will be automatically detected without futher configuration.

Ports 53/udp (DNS), 443 (DNS-over-HTTPS), and 853 (DNS-over-TLS) are exposed by default.

[docker/podman] run -d -v ./Corefile:/Corefile -p 53:53/udp \
    ghcr.io/wranders/coredns-filter:latest

License

This plugin is licensed under the MIT license. See LICENSE for more information.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DNSNameRegexp = regexp.MustCompile(
	`^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`,
)

DNSNameRegexp matches valid domain names. Sourced from https://github.com/asaskevich/govalidator; const DNSName

MIT Licensed, Copyright (c) 2014-2020 Alex Saskevich

View Source
var HostsRegexp = regexp.MustCompile(`\s+|\t+`)

HostsRegexp matches multiple spaces or tabspaces for cleaning up each entry

Functions

func Parse

func Parse(c *caddy.Controller, f *Filter) error

Parse the Corefile configuration

Types

type ActionConfig

type ActionConfig struct {
	FileLoader FileListLoader
	HTTPLoader HTTPListLoader
	// contains filtered or unexported fields
}

ActionConfig contains the raw domains, expressions and lists that are compiled and used by the Filter

func NewActionConfig

func NewActionConfig(action ActionType) ActionConfig

NewActionConfig returns an action ready to accept configurations

func (ActionConfig) AddDomain

func (a ActionConfig) AddDomain(domain string)

AddDomain to match

func (ActionConfig) AddDomainList

func (a ActionConfig) AddDomainList(url string) error

AddDomainList to match contents

func (ActionConfig) AddHostsList added in v0.2.0

func (a ActionConfig) AddHostsList(url string) error

AddHostsList to match contents

func (ActionConfig) AddRegex

func (a ActionConfig) AddRegex(expr string) error

AddRegex to match

func (ActionConfig) AddRegexList

func (a ActionConfig) AddRegexList(url string) error

AddRegexList to match contents

func (ActionConfig) AddWildcard

func (a ActionConfig) AddWildcard(wildcard string) error

AddWildcard to match

func (ActionConfig) AddWildcardList

func (a ActionConfig) AddWildcardList(url string) error

AddWildcardList to match contents

func (ActionConfig) BuildDomains

func (a ActionConfig) BuildDomains(domains map[string]bool)

BuildDomains creates a map of unique domains from explicit declarations and lists

func (ActionConfig) BuildHosts added in v0.3.0

func (a ActionConfig) BuildHosts(domains map[string]bool)

func (ActionConfig) BuildRegExps

func (a ActionConfig) BuildRegExps(regexps map[string]*regexp.Regexp)

BuildRegExps consolidates individual regular expressions then loads and compiles regular expressions from any configured lists

func (ActionConfig) BuildWildcards added in v0.3.0

func (a ActionConfig) BuildWildcards(wildcards map[string]bool)

func (ActionConfig) GetListLoader added in v0.2.2

func (a ActionConfig) GetListLoader(uri string) (ListLoader, error)

GetListLoader returns the ListLoader associated with the list's URL scheme

type ActionList

type ActionList map[string]ListLoader

ActionList is list of URLs and the functions required to load them

type ActionType

type ActionType int

ActionType represents the action taken upon domains, expressions, or lists

const (
	// ActionTypeAllow represents a domain, expression, or list that will not
	// be filtered, regardless if the domain or expression is set to be blocked
	ActionTypeAllow ActionType = iota

	// ActionTypeBlock represents a domain, expression, or list that will be
	// filtered
	ActionTypeBlock
)

func (ActionType) String

func (a ActionType) String() string

String returns the action type

type FileListLoader added in v0.2.2

type FileListLoader struct{}

FileListLoader retrieves lists from the local filesystem

func (FileListLoader) Load added in v0.2.2

func (FileListLoader) Load(path string) (io.ReadCloser, error)

Load implements ListLoader

type Filter

type Filter struct {
	Next plugin.Handler

	sync.RWMutex
	// contains filtered or unexported fields
}

Filter checks if requested domains are blocked then returns the configured response

func (*Filter) Build

func (f *Filter) Build()

Build the domain and regular expression lists used to determine how domains are handled

func (*Filter) InitUpdate

func (f *Filter) InitUpdate() error

InitUpdate starts the update timer. This should only be run once on startup.

func (*Filter) Name

func (f *Filter) Name() string

Name implements the plugin.Handler interface Returns the name of the CoreDNS plugin, in this case "filter"

func (*Filter) OnShutdown

func (f *Filter) OnShutdown() error

OnShutdown cleans up the filter and prepares it for removal

func (*Filter) ServeDNS

func (f *Filter) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error)

ServeDNS implements the plugin.Handler inteface Checks whether or not the requested domain is allowed or blocked. Allowed domains are passed to the next plugin in the Corefile. Blocked domains return the configured response.

type HTTPListLoader added in v0.2.2

type HTTPListLoader struct {
	Network    string
	ServerName string
	ResolverIP netip.AddrPort
}

HTTPListLoader retrieves lists from remote sources using HTTP/HTTPS

func (HTTPListLoader) Load added in v0.2.2

func (h HTTPListLoader) Load(path string) (io.ReadCloser, error)

Load implements ListLoader

type ListLoader added in v0.2.2

type ListLoader interface {
	Load(string) (io.ReadCloser, error)
}

ListLoader contains the means to retrieve a list

type RenderedResponse

type RenderedResponse struct {
	// RCode is the DNS message response code
	RCode int

	// Authoritative signals if a response is authoritative.
	// Useful for NXDOMAIN responses
	Authoritative bool

	// Answer records if there are any
	Answer []dns.RR
}

RenderedResponse represents the information a response should return to the Filter.ServeDNS function

type RespAddress

type RespAddress struct {
	IP4 netip.Addr
	IP6 netip.Addr
}

RespAddress implements Response Return address records for IPv4 (A) and IPv6 (AAAA)

func (RespAddress) Render

func (r RespAddress) Render(qname string, qtype uint16) RenderedResponse

type RespNXDomain

type RespNXDomain struct{}

RespNXDomain implements Response Returns a dummy SOA record and an NXDOMAIN error code

func (RespNXDomain) Render

func (r RespNXDomain) Render(qname string, _ uint16) RenderedResponse

type RespNoData

type RespNoData struct{}

RespNoData implements Response Returns no records

func (RespNoData) Render

func (r RespNoData) Render(_ string, _ uint16) RenderedResponse

type Response

type Response interface {
	Render(qname string, qtype uint16) RenderedResponse
}

Response represents what ServeDNS expects to call

Jump to

Keyboard shortcuts

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