From 7f974a7392db8ca8d3a2aa32771d12c2e6f4a93f Mon Sep 17 00:00:00 2001 From: dmachard <5562930+dmachard@users.noreply.github.com> Date: Tue, 4 Jan 2022 14:19:23 +0100 Subject: [PATCH] filter based on rcode #32 --- README.md | 2 +- config.yml | 2 ++ dnsutils/config.go | 10 ++++++---- doc/configuration.md | 17 ++++++++++------- subprocessors/filtering.go | 7 +++++++ subprocessors/filtering_test.go | 28 ++++++++++++++++++++++++++++ 6 files changed, 54 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index e433ac12..a92bdf45 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ NOTE: The code before version 1.x is considered beta quality and is subject to b - [DNS decoder with extended options support](doc/dnsparser.md) - [Built-in Grafana dashboards](doc/dashboards.md) - [GeoIP support](doc/configuration.md#geoip-support) - - [Fqdn/Domain list filtering](doc/configuration.md#fqdn-filtering) + - [Log filtering per domain or rcode](doc/configuration.md#filtering) - [User Privacy](doc/configuration.md#user-privacy) - [Custom text format](doc/configuration.md#custom-text-format) - [DNS caching](doc/configuration.md#DNS-Caching) diff --git a/config.yml b/config.yml index 2f1ec663..7ca2f21a 100644 --- a/config.yml +++ b/config.yml @@ -130,6 +130,8 @@ subprocessors: drop-fqdn-file: "" # domain drop list, domains list can be a partial domain name with regexp expression drop-domain-file: "" + # drop response according to the return code (NOERROR, ...). This list is empty by default + drop-rcodes: [] # forward received queries to configured loggers ? log-queries: true # forward received replies to configured loggers ? diff --git a/dnsutils/config.go b/dnsutils/config.go index dcec3aec..b8474879 100644 --- a/dnsutils/config.go +++ b/dnsutils/config.go @@ -75,10 +75,11 @@ type Config struct { } `yaml:"cache"` ServerId string `yaml:"server-id"` Filtering struct { - DropFqdnFile string `yaml:"drop-fqdn-file"` - DropDomainFile string `yaml:"drop-domain-file"` - LogQueries bool `yaml:"log-queries"` - LogReplies bool `yaml:"log-replies"` + DropFqdnFile string `yaml:"drop-fqdn-file"` + DropDomainFile string `yaml:"drop-domain-file"` + DropRcodes []string `yaml:drop-rcodes,flow` + LogQueries bool `yaml:"log-queries"` + LogReplies bool `yaml:"log-replies"` } `yaml:"filtering"` GeoIP struct { DbCountryFile string `yaml:"mmdb-country-file"` @@ -270,6 +271,7 @@ func (c *Config) SetDefault() { c.Subprocessors.Filtering.DropFqdnFile = "" c.Subprocessors.Filtering.DropDomainFile = "" + c.Subprocessors.Filtering.DropRcodes = []string{} c.Subprocessors.Filtering.LogQueries = true c.Subprocessors.Filtering.LogReplies = true diff --git a/doc/configuration.md b/doc/configuration.md index 04aefeba..a14a471c 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -11,11 +11,12 @@ The configuration is done in one yaml file. For the complete configuration, see - [DNS sniffer](#Dns-Sniffer) - [Tail](#Tail) - [Subprocessors](#Subprocessors) + - [Quiet text](#quiet-text) - [Qname lowercase](#Qname-lowercase) - - [IP anonymization](#Ip-Anonymization) + - [User privacy](#user-privacy) - [GeoIP Support](#GeoIP-Support) - [DNS Caching](#DNS-Caching) - - [Packet Filtering](#Packet-Filtering) + - [Filtering](#Filtering) - [Custom text format](#Custom-Text-Format) - [Statistics](#Statistics) - [Loggers](#Loggers) @@ -126,7 +127,7 @@ dns-sniffer: capture-dns-replies: true ``` -## Tail +### Tail The tail collector enable to read DNS event from text files. DNS servers log server can be followed; any type of server is supported! @@ -284,14 +285,15 @@ subprocessors: query-timeout: 10 ``` -### Fqdn Filtering +### Log filtering per domain or rcode -This feature can be use to ignore queries or replies. You can also use-it to drop -specific domains name. This feature can be useful to increase logging performance. +The filtering feature can be used to ignore some queries or replies according to the qname or return code. +This feature can be useful to increase logging performance.. Options: - `drop-fqdn-file`: (string) path file to a fqdn drop list, domains list must be a full qualified domain name - `drop-domain-file`: (string) path file to domain drop list, domains list can be a partial domain name with regexp expression +- `drop-rcodes`: (list of string) rcode list, empty by default - `log-queries`: (boolean) forward received queries to configured loggers - `log-replies`: (boolean) forward received replies to configured loggers @@ -300,6 +302,7 @@ subprocessors: filtering: drop-fqdn-file: "" drop-domain-file: "" + drop-rcodes: [] log-queries: true log-replies: true ``` @@ -356,7 +359,7 @@ Some options to customize the statitics subprocessor. Options: - `top-max-items`: (string) default number of items on top -- `common-qtypes`: (string) expected common qtype list, other will be considered as suspicious +- `common-qtypes`: (list of string) expected common qtype list, other will be considered as suspicious - `threshold-qname-len`: (string) a length greater than this value will be considered as suspicious - `threshold-packet-len`: (string) a size greater than this value will be considered as suspicious value in bytes - `threshold-slow`: (string) threshold to set a domain considered as slow, value in second diff --git a/subprocessors/filtering.go b/subprocessors/filtering.go index d3c90545..b5245413 100644 --- a/subprocessors/filtering.go +++ b/subprocessors/filtering.go @@ -87,6 +87,13 @@ func (p *FilteringProcessor) CheckIfDrop(dm *dnsutils.DnsMessage) bool { return true } + // drop according to the rcode ? + for _, v := range p.config.Subprocessors.Filtering.DropRcodes { + if v == dm.DNS.Rcode { + return true + } + } + // drop domains ? if p.dropDomains { // fqdn diff --git a/subprocessors/filtering_test.go b/subprocessors/filtering_test.go index 421cf818..4ab48be7 100644 --- a/subprocessors/filtering_test.go +++ b/subprocessors/filtering_test.go @@ -27,3 +27,31 @@ func TestFilteringQR(t *testing.T) { } } + +func TestFilteringByRcodeNOERROR(t *testing.T) { + // config + config := dnsutils.GetFakeConfig() + config.Subprocessors.Filtering.DropRcodes = []string{"NOERROR"} + + // init subproccesor + filtering := NewFilteringProcessor(config, logger.New(false)) + + dm := dnsutils.GetFakeDnsMessage() + if filtering.CheckIfDrop(&dm) == false { + t.Errorf("dns query should be dropped") + } +} + +func TestFilteringByRcodeEmpty(t *testing.T) { + // config + config := dnsutils.GetFakeConfig() + config.Subprocessors.Filtering.DropRcodes = []string{} + + // init subproccesor + filtering := NewFilteringProcessor(config, logger.New(false)) + + dm := dnsutils.GetFakeDnsMessage() + if filtering.CheckIfDrop(&dm) == true { + t.Errorf("dns query should not be dropped!") + } +}