diff --git a/README.md b/README.md index 568a2c93..f16e65d8 100644 --- a/README.md +++ b/README.md @@ -17,38 +17,35 @@ NOTE: The code before version 1.x is considered beta quality and is subject to b ## Features - [Logs routing](doc/multiplexer.md) - +- [Queries/Replies JSON encoding](doc/dnsjson.md) - Collectors: - - [DNStap streams](doc/configuration.md#dns-tap) - - [DNS packets sniffer](doc/configuration.md#dns-sniffer) - - [Tail on log file](doc/configuration.md#tail) - - [Protobuf PowerDNS](doc/configuration.md#protobuf-powerdns) - -- Transformers: - - [Queries/Replies JSON encoding](doc/dnsjson.md) - - [DNS filtering](doc/configuration.md#dns-filtering) - - [User Privacy](doc/configuration.md#user-privacy) - - [Normalize Qname](doc/configuration.md#qname-lowercase) - + - [DNStap streams](doc/collectors.md#dns-tap) + - [DNS packets sniffer](doc/collectors.md#dns-sniffer) + - [Tail on log file](doc/collectors.md#tail) + - [Protobuf PowerDNS](doc/collectors.md#protobuf-powerdns) - Loggers: - - [Console](doc/configuration.md#stdout) - - [Prometheus](doc/configuration.md#prometheus) - - [File](doc/configuration.md#log-file) - - [DNStap](doc/configuration.md#dnstap-client) - - [TCP](doc/configuration.md#tcp-client) - - [REST API](doc/configuration.md#rest-api) - - [Syslog](doc/configuration.md#syslog) - - [Fluentd](doc/configuration.md#fluentd-client) - - [Pcap](doc/configuration.md#pcap-file) - - [InfluxDB](doc/configuration.md#influxdb-client) - - [Loki](doc/configuration.md#loki-client) - - [Statsd](doc/configuration.md#statsd-client) + - [Console](doc/loggers.md#stdout) + - [Prometheus](doc/loggers.md#prometheus) + - [File](doc/loggers.md#log-file) + - [DNStap](doc/loggers.md#dnstap-client) + - [TCP](doc/loggers.md#tcp-client) + - [REST API](doc/loggers.md#rest-api) + - [Syslog](doc/loggers.md#syslog) + - [Fluentd](doc/loggers.md#fluentd-client) + - [Pcap](doc/loggers.md#pcap-file) + - [InfluxDB](doc/loggers.md#influxdb-client) + - [Loki](doc/loggers.md#loki-client) + - [Statsd](doc/loggers.md#statsd-client) - Other features - [DNS decoder with extended options support](doc/dnsparser.md) - [Built-in Grafana dashboards](doc/dashboards.md) - [GeoIP support](doc/configuration.md#geoip-support) - [Text format](doc/configuration.md#custom-text-format) + - [DNS filtering](doc/configuration.md#dns-filtering) + - [User Privacy](doc/configuration.md#user-privacy) + - [Normalize Qname](doc/configuration.md#qname-lowercase) + ## Installation **Run-it from binary** diff --git a/collectors/dnssniffer.go b/collectors/dnssniffer.go index 06d80136..adddfcfc 100644 --- a/collectors/dnssniffer.go +++ b/collectors/dnssniffer.go @@ -134,6 +134,12 @@ func (c *DnsSniffer) LogError(msg string, v ...interface{}) { c.logger.Error("["+c.name+"] sniffer collector - "+msg, v...) } +func (c *DnsSniffer) GetName() string { return c.name } + +func (c *DnsSniffer) SetLoggers(loggers []dnsutils.Worker) { + c.loggers = loggers +} + func (c *DnsSniffer) Loggers() []chan dnsutils.DnsMessage { channels := []chan dnsutils.DnsMessage{} for _, p := range c.loggers { diff --git a/collectors/dnssniffer_darwin.go b/collectors/dnssniffer_darwin.go index 0900ca98..6a2a5781 100644 --- a/collectors/dnssniffer_darwin.go +++ b/collectors/dnssniffer_darwin.go @@ -32,6 +32,12 @@ func NewDnsSniffer(loggers []dnsutils.Worker, config *dnsutils.Config, logger *l return s } +func (c *DnsSniffer) GetName() string { return c.name } + +func (c *DnsSniffer) SetLoggers(loggers []dnsutils.Worker) { + c.loggers = loggers +} + func (c *DnsSniffer) LogInfo(msg string, v ...interface{}) { c.logger.Info("["+c.name+"] collector dns sniffer - "+msg, v...) } diff --git a/collectors/dnssniffer_windows.go b/collectors/dnssniffer_windows.go index c7110dd3..29418255 100644 --- a/collectors/dnssniffer_windows.go +++ b/collectors/dnssniffer_windows.go @@ -32,6 +32,11 @@ func NewDnsSniffer(loggers []dnsutils.Worker, config *dnsutils.Config, logger *l return s } +func (c *DnsSniffer) GetName() string { return c.name } + +func (c *DnsSniffer) SetLoggers(loggers []dnsutils.Worker) { + c.loggers = loggers +} func (c *DnsSniffer) LogInfo(msg string, v ...interface{}) { c.logger.Info("["+c.name+"] collector dns sniffer - "+msg, v...) } diff --git a/collectors/dnstap.go b/collectors/dnstap.go index ce84686f..250de99c 100644 --- a/collectors/dnstap.go +++ b/collectors/dnstap.go @@ -37,6 +37,12 @@ func NewDnstap(loggers []dnsutils.Worker, config *dnsutils.Config, logger *logge return s } +func (c *Dnstap) GetName() string { return c.name } + +func (c *Dnstap) SetLoggers(loggers []dnsutils.Worker) { + c.loggers = loggers +} + func (c *Dnstap) Loggers() []chan dnsutils.DnsMessage { channels := []chan dnsutils.DnsMessage{} for _, p := range c.loggers { diff --git a/collectors/powerdns.go b/collectors/powerdns.go index df946c3d..a8aa208d 100644 --- a/collectors/powerdns.go +++ b/collectors/powerdns.go @@ -35,6 +35,12 @@ func NewProtobufPowerDNS(loggers []dnsutils.Worker, config *dnsutils.Config, log return s } +func (c *ProtobufPowerDNS) GetName() string { return c.name } + +func (c *ProtobufPowerDNS) SetLoggers(loggers []dnsutils.Worker) { + c.loggers = loggers +} + func (c *ProtobufPowerDNS) Loggers() []chan dnsutils.DnsMessage { channels := []chan dnsutils.DnsMessage{} for _, p := range c.loggers { diff --git a/collectors/tail.go b/collectors/tail.go index 36d159d1..ccd37922 100644 --- a/collectors/tail.go +++ b/collectors/tail.go @@ -38,6 +38,12 @@ func NewTail(loggers []dnsutils.Worker, config *dnsutils.Config, logger *logger. return s } +func (c *Tail) GetName() string { return c.name } + +func (c *Tail) SetLoggers(loggers []dnsutils.Worker) { + c.loggers = loggers +} + func (c *Tail) Loggers() []chan dnsutils.DnsMessage { channels := []chan dnsutils.DnsMessage{} for _, p := range c.loggers { diff --git a/config.yml b/config.yml index a1751593..a7042866 100644 --- a/config.yml +++ b/config.yml @@ -1,3 +1,62 @@ + + +################################################ +# global configuration +################################################ +global: + # If turned on, log some applications messages + trace: + # debug informations + verbose: true + # log malformed packet + # log-malformed: false + # # filename is the file to write logs to. + # filename: "" + # # maximum size in megabytes of the log file it gets rotated + # max-size: 10 + # # maximum number of old log files to retain + # max-backups: 10 + + # all directives for text format output + # - timestamp-rfc3339ns: timestamp rfc3339 format, with nano support + # - timestamp-unixms: unix timestamp with ms support + # - timestamp-unixus: unix timestamp with us support + # - timestamp-unixns: unix timestamp with nano support + # - localtime: local time + # - identity: dnstap identity + # - operation: dnstap operation + # - opcode: dns opcode (integer) + # - rcode: dns return code + # - queryip: dns query ip + # - queryport: dns query port + # - responseip: dns response ip + # - responseport: dns response port + # - id: dns id + # - family: ip protocol version INET or INET6 + # - protocol: protocol UDP, TCP + # - length: the length of the query or reply + # - qtype: dns qtype + # - qname: dns qname + # - latency: computed latency between queries and replies + # - answercount: the number of answer + # - continent: continent code + # - country: country iso code + # - city: city name + # - as-number: autonomous system number + # - as-owner: autonomous system organization + # - ttl: answer ttl, only the first one value + # - answer: rdata answer, only the first one, prefer to use the JSON format if you wamt all answers + # - malformed: malformed dns packet, integer value 1/0 + # - qr: query or reply flag, string value Q/R + # - tc: truncated flag + # - aa: authoritative answer + # - ra: recursion available + # - ad: authenticated data + # - edns-csubnet: client subnet + # - pdns-tags: powerdns metadata + # - pdns-original-request-client: powerdns metadata + # text-format: "timestamp-rfc3339ns identity operation rcode queryip queryport family protocol length qname qtype latency" + # create your dns collector, please refer bellow to see the list # of supported collectors, loggers and transformers multiplexer: @@ -7,11 +66,6 @@ multiplexer: listen-ip: 0.0.0.0 listen-port: 6000 - transformers: - - name: qnamelower - normalize: - lowercase-qname: true - loggers: - name: console stdout: @@ -19,8 +73,7 @@ multiplexer: routes: - from: [ tap ] - transforms: [ qnamelower ] - to: [ prom ] + to: [ console ] ################################################ # list of supported collectors @@ -386,61 +439,3 @@ multiplexer: # mmdb-city-file: "" # # path file to your mmdb ASN database # mmdb-asn-file: "" - - -################################################ -# global configuration -################################################ -global: - # If turned on, log some applications messages - trace: - # debug informations - verbose: false - # log malformed packet - log-malformed: false - # filename is the file to write logs to. - filename: "" - # maximum size in megabytes of the log file it gets rotated - max-size: 10 - # maximum number of old log files to retain - max-backups: 10 - - # all directives for text format output - # - timestamp-rfc3339ns: timestamp rfc3339 format, with nano support - # - timestamp-unixms: unix timestamp with ms support - # - timestamp-unixus: unix timestamp with us support - # - timestamp-unixns: unix timestamp with nano support - # - localtime: local time - # - identity: dnstap identity - # - operation: dnstap operation - # - opcode: dns opcode (integer) - # - rcode: dns return code - # - queryip: dns query ip - # - queryport: dns query port - # - responseip: dns response ip - # - responseport: dns response port - # - id: dns id - # - family: ip protocol version INET or INET6 - # - protocol: protocol UDP, TCP - # - length: the length of the query or reply - # - qtype: dns qtype - # - qname: dns qname - # - latency: computed latency between queries and replies - # - answercount: the number of answer - # - continent: continent code - # - country: country iso code - # - city: city name - # - as-number: autonomous system number - # - as-owner: autonomous system organization - # - ttl: answer ttl, only the first one value - # - answer: rdata answer, only the first one, prefer to use the JSON format if you wamt all answers - # - malformed: malformed dns packet, integer value 1/0 - # - qr: query or reply flag, string value Q/R - # - tc: truncated flag - # - aa: authoritative answer - # - ra: recursion available - # - ad: authenticated data - # - edns-csubnet: client subnet - # - pdns-tags: powerdns metadata - # - pdns-original-request-client: powerdns metadata - text-format: "timestamp-rfc3339ns identity operation rcode queryip queryport family protocol length qname qtype latency" diff --git a/dnscollector.go b/dnscollector.go index efa57112..613fcede 100644 --- a/dnscollector.go +++ b/dnscollector.go @@ -59,138 +59,132 @@ func main() { logger.SetVerbose(config.Global.Trace.Verbose) logger.Info("main - version %s", Version) - logger.Info("main - config loaded...") logger.Info("main - starting dns-collector...") // load loggers - var allLoggers [][]dnsutils.Worker - var allCollectors [][]dnsutils.Worker + logger.Info("main - loading loggers...") + mapLoggers := make(map[string]dnsutils.Worker) + for _, output := range config.Multiplexer.Loggers { + // load config + cfg := make(map[string]interface{}) + cfg["loggers"] = output.Params + for _, p := range output.Params { + p.(map[string]interface{})["enable"] = true + } - for _, routes := range config.Multiplexer.Routes { - var logwrks2 []dnsutils.Worker - var collwrks2 []dnsutils.Worker + // get config with default values + subcfg := &dnsutils.Config{} + subcfg.SetDefault() - // init loggers - for _, dst := range routes.Dst { + // copy global config + subcfg.Global = config.Global - // search logger according to name - for _, ml := range config.Multiplexer.Loggers { - if ml.Name == dst { - // load config - cfg := make(map[string]interface{}) - cfg["loggers"] = ml.Params - for _, p := range ml.Params { - p.(map[string]interface{})["enable"] = true - } - - // get config with default values - subcfg := &dnsutils.Config{} - subcfg.SetDefault() - - // copy global config - subcfg.Global = config.Global - - yamlcfg, _ := yaml.Marshal(cfg) - if err := yaml.Unmarshal(yamlcfg, subcfg); err != nil { - fmt.Println(err) - break - } - - if subcfg.Loggers.WebServer.Enable { - logwrks2 = append(logwrks2, loggers.NewWebserver(subcfg, logger, Version, ml.Name)) - } - if subcfg.Loggers.Prometheus.Enable { - logwrks2 = append(logwrks2, loggers.NewPrometheus(subcfg, logger, Version, ml.Name)) - } - if subcfg.Loggers.Stdout.Enable { - logwrks2 = append(logwrks2, loggers.NewStdOut(subcfg, logger, ml.Name)) - } - if subcfg.Loggers.LogFile.Enable { - logwrks2 = append(logwrks2, loggers.NewLogFile(subcfg, logger, ml.Name)) - } - if subcfg.Loggers.Dnstap.Enable { - logwrks2 = append(logwrks2, loggers.NewDnstapSender(subcfg, logger, ml.Name)) - } - if subcfg.Loggers.TcpClient.Enable { - logwrks2 = append(logwrks2, loggers.NewTcpClient(config, logger, ml.Name)) - } - if subcfg.Loggers.Syslog.Enable { - logwrks2 = append(logwrks2, loggers.NewSyslog(subcfg, logger, ml.Name)) - } - if subcfg.Loggers.Fluentd.Enable { - logwrks2 = append(logwrks2, loggers.NewFluentdClient(subcfg, logger, ml.Name)) - } - if subcfg.Loggers.PcapFile.Enable { - logwrks2 = append(logwrks2, loggers.NewPcapFile(subcfg, logger, ml.Name)) - } - if subcfg.Loggers.InfluxDB.Enable { - logwrks2 = append(logwrks2, loggers.NewInfluxDBClient(subcfg, logger, ml.Name)) - } - if subcfg.Loggers.LokiClient.Enable { - logwrks2 = append(logwrks2, loggers.NewLokiClient(subcfg, logger, ml.Name)) - } - if subcfg.Loggers.Statsd.Enable { - logwrks2 = append(logwrks2, loggers.NewStatsdClient(subcfg, logger, Version, ml.Name)) - } - } - } + yamlcfg, _ := yaml.Marshal(cfg) + if err := yaml.Unmarshal(yamlcfg, subcfg); err != nil { + panic(fmt.Sprintf("main - yaml logger config error: %v", err)) + } + + if subcfg.Loggers.WebServer.Enable { + mapLoggers[output.Name] = loggers.NewWebserver(subcfg, logger, Version, output.Name) + } + if subcfg.Loggers.Prometheus.Enable { + mapLoggers[output.Name] = loggers.NewPrometheus(subcfg, logger, Version, output.Name) + } + if subcfg.Loggers.Stdout.Enable { + mapLoggers[output.Name] = loggers.NewStdOut(subcfg, logger, output.Name) + } + if subcfg.Loggers.LogFile.Enable { + mapLoggers[output.Name] = loggers.NewLogFile(subcfg, logger, output.Name) + } + if subcfg.Loggers.Dnstap.Enable { + mapLoggers[output.Name] = loggers.NewDnstapSender(subcfg, logger, output.Name) + } + if subcfg.Loggers.TcpClient.Enable { + mapLoggers[output.Name] = loggers.NewTcpClient(config, logger, output.Name) + } + if subcfg.Loggers.Syslog.Enable { + mapLoggers[output.Name] = loggers.NewSyslog(subcfg, logger, output.Name) + } + if subcfg.Loggers.Fluentd.Enable { + mapLoggers[output.Name] = loggers.NewFluentdClient(subcfg, logger, output.Name) + } + if subcfg.Loggers.PcapFile.Enable { + mapLoggers[output.Name] = loggers.NewPcapFile(subcfg, logger, output.Name) + } + if subcfg.Loggers.InfluxDB.Enable { + mapLoggers[output.Name] = loggers.NewInfluxDBClient(subcfg, logger, output.Name) + } + if subcfg.Loggers.LokiClient.Enable { + mapLoggers[output.Name] = loggers.NewLokiClient(subcfg, logger, output.Name) + } + if subcfg.Loggers.Statsd.Enable { + mapLoggers[output.Name] = loggers.NewStatsdClient(subcfg, logger, Version, output.Name) + } + } + + // load collectors + logger.Info("main - loading collectors...") + mapCollectors := make(map[string]dnsutils.Worker) + for _, input := range config.Multiplexer.Collectors { + // load config + cfg := make(map[string]interface{}) + cfg["collectors"] = input.Params + cfg["transformers"] = make(map[string]interface{}) + for _, p := range input.Params { + p.(map[string]interface{})["enable"] = true } - // init collectors + // get config with default values + subcfg := &dnsutils.Config{} + subcfg.SetDefault() + + // add transformer + for k, v := range input.Transforms { + cfg["transformers"].(map[string]interface{})[k] = v + } + + // copy global config + subcfg.Global = config.Global + + yamlcfg, _ := yaml.Marshal(cfg) + if err := yaml.Unmarshal(yamlcfg, subcfg); err != nil { + panic(fmt.Sprintf("main - yaml collector config error: %v", err)) + } + + if subcfg.Collectors.Dnstap.Enable { + mapCollectors[input.Name] = collectors.NewDnstap(nil, subcfg, logger, input.Name) + } + if subcfg.Collectors.DnsSniffer.Enable { + mapCollectors[input.Name] = collectors.NewDnsSniffer(nil, subcfg, logger, input.Name) + } + if subcfg.Collectors.Tail.Enable { + mapCollectors[input.Name] = collectors.NewTail(nil, subcfg, logger, input.Name) + } + if subcfg.Collectors.PowerDNS.Enable { + mapCollectors[input.Name] = collectors.NewProtobufPowerDNS(nil, subcfg, logger, input.Name) + } + } + + // connect collectors between loggers + for _, routes := range config.Multiplexer.Routes { + var logwrks []dnsutils.Worker + for _, dst := range routes.Dst { + if _, ok := mapLoggers[dst]; ok { + logwrks = append(logwrks, mapLoggers[dst]) + } else { + panic(fmt.Sprintf("main - routing error: logger %v doest not exist", dst)) + } + } for _, src := range routes.Src { - // search logger according to name - for _, mc := range config.Multiplexer.Collectors { - if mc.Name == src { - - // load config - cfg := make(map[string]interface{}) - cfg["collectors"] = mc.Params - cfg["subprocessors"] = make(map[string]interface{}) - for _, p := range mc.Params { - p.(map[string]interface{})["enable"] = true - } - - // get config with default values - subcfg := &dnsutils.Config{} - subcfg.SetDefault() - - // add transformer - for _, transform := range routes.Transforms { - for _, tfs := range config.Multiplexer.Transformers { - if tfs.Name == transform { - for k, v := range tfs.Params { - cfg["subprocessors"].(map[string]interface{})[k] = v - } - } - } - } - - // copy global config - subcfg.Global = config.Global - - yamlcfg, _ := yaml.Marshal(cfg) - if err := yaml.Unmarshal(yamlcfg, subcfg); err != nil { - panic(fmt.Sprintf("main - invalid subconfig error: %v", err)) - } - - if subcfg.Collectors.Dnstap.Enable { - collwrks2 = append(collwrks2, collectors.NewDnstap(logwrks2, subcfg, logger, mc.Name)) - } - if subcfg.Collectors.DnsSniffer.Enable { - collwrks2 = append(collwrks2, collectors.NewDnsSniffer(logwrks2, subcfg, logger, mc.Name)) - } - if subcfg.Collectors.Tail.Enable { - collwrks2 = append(collwrks2, collectors.NewTail(logwrks2, subcfg, logger, mc.Name)) - } - if subcfg.Collectors.PowerDNS.Enable { - collwrks2 = append(collwrks2, collectors.NewProtobufPowerDNS(logwrks2, subcfg, logger, mc.Name)) - } - } + if _, ok := mapCollectors[src]; ok { + mapCollectors[src].SetLoggers(logwrks) + } else { + panic(fmt.Sprintf("main - routing error: collector [%v] doest not exist", src)) + } + for _, l := range logwrks { + logger.Info("main - routing: collector[%s] send to logger[%s]", src, l.GetName()) } } - - allLoggers = append(allLoggers, logwrks2) - allCollectors = append(allCollectors, collwrks2) } // Handle Ctrl-C @@ -221,16 +215,12 @@ func main() { // stop all workers logger.Info("main - stopping all collectors and loggers...") - for _, c := range allCollectors { - for _, w := range c { - w.Stop() - } + for _, c := range mapCollectors { + c.Stop() } - for _, l := range allLoggers { - for _, w := range l { - w.Stop() - } + for _, l := range mapLoggers { + l.Stop() } // unblock main function @@ -244,15 +234,11 @@ func main() { // run all workers in background logger.Info("main - running all collectors and loggers...") - for _, l := range allLoggers { - for _, p := range l { - go p.Run() - } + for _, l := range mapLoggers { + go l.Run() } - for _, c := range allCollectors { - for _, p := range c { - go p.Run() - } + for _, c := range mapCollectors { + go c.Run() } // block main diff --git a/dnsutils/config.go b/dnsutils/config.go index 567133a2..ad2920a9 100644 --- a/dnsutils/config.go +++ b/dnsutils/config.go @@ -17,19 +17,20 @@ func IsValidMode(mode string) bool { } type MultiplexTransformers struct { - Name string - Params map[string]interface{} `yaml:",inline"` + Name string `yaml:"naame"` + Transforms map[string]interface{} `yaml:",inline"` + Params map[string]interface{} `yaml:",inline"` } type MultiplexInOut struct { - Name string - Params map[string]interface{} `yaml:",inline"` + Name string `yaml:"name"` + Transforms map[string]interface{} `yaml:"transforms"` + Params map[string]interface{} `yaml:",inline"` } type MultiplexRoutes struct { - Src []string `yaml:"from,flow"` - Transforms []string `yaml:"transforms,flow"` - Dst []string `yaml:"to,flow"` + Src []string `yaml:"from,flow"` + Dst []string `yaml:"to,flow"` } type Config struct { @@ -247,10 +248,9 @@ type Config struct { } `yaml:"loggers"` Multiplexer struct { - Collectors []MultiplexInOut `yaml:"collectors"` - Transformers []MultiplexTransformers `yaml:"transformers"` - Loggers []MultiplexInOut `yaml:"loggers"` - Routes []MultiplexRoutes `yaml:"routes"` + Collectors []MultiplexInOut `yaml:"collectors"` + Loggers []MultiplexInOut `yaml:"loggers"` + Routes []MultiplexRoutes `yaml:"routes"` } `yaml:"multiplexer"` } diff --git a/dnsutils/worker.go b/dnsutils/worker.go index 40b00244..ccaf2d0e 100644 --- a/dnsutils/worker.go +++ b/dnsutils/worker.go @@ -1,6 +1,8 @@ package dnsutils type Worker interface { + SetLoggers(loggers []Worker) + GetName() string Stop() Run() Channel() chan DnsMessage diff --git a/doc/collectors.md b/doc/collectors.md new file mode 100644 index 00000000..a170e937 --- /dev/null +++ b/doc/collectors.md @@ -0,0 +1,158 @@ +# DnsCollector - Collectors Guide + +- [DNS tap](#dns-tap) +- [DNS sniffer](#dns-sniffer) +- [Tail](#tail) +- [Protobuf PowerDNS](#protobuf-powerdns) + +## Collectors + +### DNS tap + +Dnstap stream collector: +* tcp or unix socket listener +* tls support + +Options: +- `listen-ip`: (string) listen on ip +- `listen-port`: (integer) listening on port +- `sock-path`: (string) unix socket path +- `tls-support:`: (boolean) to enable, set to true +- `cert-file`: (string) certificate server file +- `key-file`: (string) private key server file +- `cache-support`: (boolean) disable or enable the cache dns, this feature can be enabled if your dns server doesn't add the latency +- `query-timeout`: (integer) in second, max time to keep the query record in memory +- `quiet-text`: (boolean) Quiet text mode to reduce the size of the logs + +```yaml +dnstap: + listen-ip: 0.0.0.0 + listen-port: 6000 + sock-path: null + tls-support: false + cert-file: "" + key-file: "" + cache-support: false + query-timeout: 5.0 + quiet-text: false +``` + +The following dnstap flag message will be replaced with the small form: +- AUTH_QUERY: `AQ` +- AUTH_RESPONSE: `AR` +- RESOLVER_QUERY: `RQ` +- RESOLVER_RESPONSE: `RR` +- CLIENT_QUERY: `CQ` +- CLIENT_RESPONSE: `CR` +- FORWARDER_QUERY: `FQ` +- FORWARDER_RESPONSE: `FR` +- STUB_QUERY: `SQ` +- STUB_RESPONSE: `SR` +- TOOL_QUERY: `TQ` +- TOOL_RESPONSE: `TR` + +The following dns flag message will be replaced with the small form: +- QUERY: `Q` +- REPLY: `R` + +### DNS sniffer + +Raw DNS packets sniffer. Setting `CAP_NET_RAW` capabilities on executables allows you to run these +program without having to run-it with the root user: +* IPv4, IPv6 support (fragmented packet ignored) +* UDP and TCP transport +* BFP filtering + +``` +sudo setcap cap_net_admin,cap_net_raw=eip go-dnscollector +``` + +Options: +- `port`: (integer) filter on source and destination port +- `device`: (string) if "" bind on all interfaces +- `capture-dns-queries`: (boolean) capture dns queries +- `capture-dns-replies`: (boolean) capture dns replies +- `cache-support`: (boolean) disable or enable the cache dns to compute latency between queries and replies +- `query-timeout`: (integer) in second, max time to keep the query record in memory + +```yaml +dns-sniffer: + port: 53 + device: wlp2s0 + capture-dns-queries: true + capture-dns-replies: true + cache-support: true + query-timeout: 5.0 +``` + +### 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! +* Read DNS events from the tail of text files +* Regex support + + +Enable the tail by provided the path of the file to follow + +Options: +- `file-path`: (string) file to follow +- `time-layout`: (string) Use the exact layout numbers described https://golang.org/src/time/format.go +- `pattern-query`: (string) regexp pattern for queries +- `pattern-reply`: (string) regexp pattern for replies + +```yaml +tail: + file-path: null + time-layout: "2006-01-02T15:04:05.999999999Z07:00" + pattern-query: "^(?P[^ ]*) (?P[^ ]*) (?P.*_QUERY) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*)b (?P[^ ]*) (?P[^ ]*) (?P[^ ]*)$" + pattern-reply: "^(?P[^ ]*) (?P[^ ]*) (?P.*_RESPONSE) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*)b (?P[^ ]*) (?P[^ ]*) (?P[^ ]*)$" +``` + + +### Protobuf PowerDNS + +[Protobuf Logging](https://dnsdist.org/reference/protobuf.html) support for PowerDNS's products. + +Options: +- `listen-ip`: (string) listen on ip +- `listen-port`: (integer) listening on port +- `quiet-text`: (boolean) Quiet text mode to reduce the size of the logs +- `tls-support:`: (boolean) to enable, set to true +- `cert-file`: (string) certificate server file +- `key-file`: (string) private key server file + +```yaml +powerdns: + listen-ip: 0.0.0.0 + listen-port: 6001 + quiet-text: false + tls-support: false + cert-file: "" + key-file: "" +``` + +Example to enable logging in your **dnsdist** + +```lua +rl = newRemoteLogger(":6001") +addAction(AllRule(),RemoteLogAction(rl, nil, {serverID="dnsdist"})) +addResponseAction(AllRule(),RemoteLogResponseAction(rl, nil, true, {serverID="dnsdist"})) +addCacheHitResponseAction(AllRule(), RemoteLogResponseAction(rl, nil, true, {serverID="dnsdist"})) +``` + +Example to enable logging in your **pdns-recursor** + +*/etc/pdns-recursor/recursor.conf* + +```lua +lua-config-file=/etc/pdns-recursor/recursor.lua +``` + +*/etc/pdns-recursor/recursor.lua* + +```lua +protobufServer(":6001", {exportTypes={pdns.A, pdns.AAAA, pdns.CNAME}}) +outgoingProtobufServer(":6001") +``` + diff --git a/doc/configuration.md b/doc/configuration.md index 4359da9d..512ecff0 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -9,30 +9,12 @@ The configuration is done in one yaml file. For the complete configuration, see - [Trace](#trace) - [Custom text format](#custom-text-format) - [Multiplexer](#multiplexer) - - [Collectors](#collectors) - - [DNS tap](#dns-tap) - - [DNS sniffer](#dns-sniffer) - - [Tail](#tail) - - [Protobuf PowerDNS](#protobuf-powerdns) - - [Loggers](#loggers) - - [Console](#stdout) - - [Prometheus](#prometheus) - - [REST API](#rest-api) - - [Log File](#log-file) - - [DNStap](#dnstap-client) - - [TCP](#tcp-client) - - [Syslog](#syslog) - - [Fluentd](#fluentd-client) - - [Pcap File](#pcap-file) - - [InfluxDB](#influxdb-client) - - [Loki](#loki-client) - - [Statsd](#statsd-client) - - [Transformers](#transformers) - - [Qname lowercase](#qname-lowercase) - - [User privacy](#user-privacy) - - [GeoIP Support](#geoip-support) - - [DNS filtering](#dns-filtering) - - [Statistics](#statistics) +- [Transforms](#transforms) + - [Qname lowercase](#qname-lowercase) + - [User privacy](#user-privacy) + - [GeoIP Support](#geoip-support) + - [DNS filtering](#dns-filtering) + - [Statistics](#statistics) ## Global @@ -132,635 +114,30 @@ global: In this part, you can define the list of collectors, loggers and links between all of them. Options: -- `collectors`: list of running collectors -- `loggers`: list of running loggers -- `routes`: list of route +- `collectors`: list of running [collectors](/doc/collectors.md) +- `loggers`: list of running [loggers](/doc/loggers.md) +- `routes`: routing part, connection between loggers and collectors ```yaml multiplexer: collectors: - name: - ... - transformers: - - name: - ... + ..... + loggers: - name: ... routes: ... + - from: [ list of collectors by name ] + to: [ list of loggers by name ] ``` More details [here](/doc/multiplexer.md). -### Collectors - -#### DNS tap - -Dnstap stream collector: -* tcp or unix socket listener -* tls support - -Options: -- `listen-ip`: (string) listen on ip -- `listen-port`: (integer) listening on port -- `sock-path`: (string) unix socket path -- `tls-support:`: (boolean) to enable, set to true -- `cert-file`: (string) certificate server file -- `key-file`: (string) private key server file -- `cache-support`: (boolean) disable or enable the cache dns, this feature can be enabled if your dns server doesn't add the latency -- `query-timeout`: (integer) in second, max time to keep the query record in memory -- `quiet-text`: (boolean) Quiet text mode to reduce the size of the logs - -```yaml -dnstap: - listen-ip: 0.0.0.0 - listen-port: 6000 - sock-path: null - tls-support: false - cert-file: "" - key-file: "" - cache-support: false - query-timeout: 5.0 - quiet-text: false -``` - -The following dnstap flag message will be replaced with the small form: -- AUTH_QUERY: `AQ` -- AUTH_RESPONSE: `AR` -- RESOLVER_QUERY: `RQ` -- RESOLVER_RESPONSE: `RR` -- CLIENT_QUERY: `CQ` -- CLIENT_RESPONSE: `CR` -- FORWARDER_QUERY: `FQ` -- FORWARDER_RESPONSE: `FR` -- STUB_QUERY: `SQ` -- STUB_RESPONSE: `SR` -- TOOL_QUERY: `TQ` -- TOOL_RESPONSE: `TR` - -The following dns flag message will be replaced with the small form: -- QUERY: `Q` -- REPLY: `R` - -#### DNS sniffer - -Raw DNS packets sniffer. Setting `CAP_NET_RAW` capabilities on executables allows you to run these -program without having to run-it with the root user: -* IPv4, IPv6 support (fragmented packet ignored) -* UDP and TCP transport -* BFP filtering - -``` -sudo setcap cap_net_admin,cap_net_raw=eip go-dnscollector -``` - -Options: -- `port`: (integer) filter on source and destination port -- `device`: (string) if "" bind on all interfaces -- `capture-dns-queries`: (boolean) capture dns queries -- `capture-dns-replies`: (boolean) capture dns replies -- `cache-support`: (boolean) disable or enable the cache dns to compute latency between queries and replies -- `query-timeout`: (integer) in second, max time to keep the query record in memory - -```yaml -dns-sniffer: - port: 53 - device: wlp2s0 - capture-dns-queries: true - capture-dns-replies: true - cache-support: true - query-timeout: 5.0 -``` - -#### 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! -* Read DNS events from the tail of text files -* Regex support - - -Enable the tail by provided the path of the file to follow - -Options: -- `file-path`: (string) file to follow -- `time-layout`: (string) Use the exact layout numbers described https://golang.org/src/time/format.go -- `pattern-query`: (string) regexp pattern for queries -- `pattern-reply`: (string) regexp pattern for replies - -```yaml -tail: - file-path: null - time-layout: "2006-01-02T15:04:05.999999999Z07:00" - pattern-query: "^(?P[^ ]*) (?P[^ ]*) (?P.*_QUERY) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*)b (?P[^ ]*) (?P[^ ]*) (?P[^ ]*)$" - pattern-reply: "^(?P[^ ]*) (?P[^ ]*) (?P.*_RESPONSE) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*) (?P[^ ]*)b (?P[^ ]*) (?P[^ ]*) (?P[^ ]*)$" -``` - - -#### Protobuf PowerDNS - -[Protobuf Logging](https://dnsdist.org/reference/protobuf.html) support for PowerDNS's products. - -Options: -- `listen-ip`: (string) listen on ip -- `listen-port`: (integer) listening on port -- `quiet-text`: (boolean) Quiet text mode to reduce the size of the logs -- `tls-support:`: (boolean) to enable, set to true -- `cert-file`: (string) certificate server file -- `key-file`: (string) private key server file - -```yaml -powerdns: - listen-ip: 0.0.0.0 - listen-port: 6001 - quiet-text: false - tls-support: false - cert-file: "" - key-file: "" -``` - -Example to enable logging in your **dnsdist** - -```lua -rl = newRemoteLogger(":6001") -addAction(AllRule(),RemoteLogAction(rl, nil, {serverID="dnsdist"})) -addResponseAction(AllRule(),RemoteLogResponseAction(rl, nil, true, {serverID="dnsdist"})) -addCacheHitResponseAction(AllRule(), RemoteLogResponseAction(rl, nil, true, {serverID="dnsdist"})) -``` - -Example to enable logging in your **pdns-recursor** - -*/etc/pdns-recursor/recursor.conf* - -```lua -lua-config-file=/etc/pdns-recursor/recursor.lua -``` - -*/etc/pdns-recursor/recursor.lua* - -```lua -protobufServer(":6001", {exportTypes={pdns.A, pdns.AAAA, pdns.CNAME}}) -outgoingProtobufServer(":6001") -``` - - -### Loggers - -#### Stdout - -Print to your standard output, all DNS logs received -* in text or json format -* custom text format - -Options: -- `mode`: (string) text or json -- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format - -```yaml -stdout: - mode: text - text-format: "" -``` - -Example: - -``` -2021-08-07T15:33:15.168298439Z dnscollector CQ NOERROR 10.0.0.210 32918 INET UDP 54b www.google.fr A 0.000000 -2021-08-07T15:33:15.457492773Z dnscollector CR NOERROR 10.0.0.210 32918 INET UDP 152b www.google.fr A 0.28919 -``` - -#### Prometheus - -This logger generates **prometheus** metrics. Use the following Grafana [dashboard](https://grafana.com/grafana/dashboards/16630). - -Options: -- `listen-ip`: (string) listening IP -- `listen-port`: (integer) listening port -- `tls-support`: (boolean) tls support -- `tls-mutual`: (boolean) mtls authentication -- `cert-file`: (string) certificate server file -- `key-file`: (string) private key server file -- `prometheus-suffix`: (string) prometheus suffix -- `top-n`: (string) default number of items on top - -```yaml -prometheus: - # listening IP - listen-ip: 0.0.0.0 - # listening port - listen-port: 8081 - # tls support - tls-support: false - # tls mutual - tls-mutual: false - # certificate server file - cert-file: "" - # private key server file - key-file: "" - # prometheus prefix - prometheus-prefix: "dnscollector" - # default number of items on top - top-n: 10 -``` - -#### REST API - -Build-in webserver with REST API to retrieve somes statistics like top domains, clients and more... -Basic authentication supported. Prometheus metrics is also available through this API. - -* prometheus metrics format -* qps, total queries/replies, top domains, clients, rcodes... -* basic auth -* tls support - -See the [swagger](https://generator.swagger.io/?url=https://raw.githubusercontent.com/dmachard/go-dnscollector/main/doc/swagger.yml) documentation. - -Options: -- `listen-ip`: (string) listening IP -- `listen-port`: (integer) listening port -- `basic-auth-login`: (string) default login for basic auth -- `basic-auth-pwd`: (string) default password for basic auth -- `tls-support`: (boolean) tls support -- `cert-file`: (string) certificate server file -- `key-file`: (string) private key server file -- `top-max-items`: (string) default number of items on top -- `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 -- `prometheus-suffix`: (string) prometheus suffix - -```yaml -webserver: - listen-ip: 0.0.0.0 - listen-port: 8080 - basic-auth-login: admin - basic-auth-pwd: changeme - tls-support: true - cert-file: "./testsdata/server.crt" - key-file: "./testsdata/server.key" - top-max-items: 100 - common-qtypes: - - A - - AAAA - - CNAME - - TXT - - PTR - - NAPTR - - DNSKEY - - SRV - threshold-qname-len: 80 - threshold-packet-len: 1000 - threshold-slow: 0.5 - prometheus-suffix: "dnscollector" -``` - -**Prometheus metrics example:** - -Request: - -``` -$ curl --user admin:changeme http://127.0.0.1:8080/metrics -``` - -The `` tag can be configured in the `config.yml` file. - -Metrics list: -- `_qps`: Number of queries per second received -- `_requesters_total`: Number of clients -- `_domains_total`: Number of domains observed -- `_received_bytes_total`: Total bytes received -- `_sent_bytes_total`: Total bytes sent - - -The full metrics can be found [here](doc/metrics.txt). - - -#### Log File - -Enable this logger if you want to log to a file. -* with rotation file support -* supported format: text, json -* gzip compression -* execute external command after each rotation -* custom text format - -Options: -- `file-path`: (string) output logfile name -- `max-size`: (integer) maximum size in megabytes of the file before rotation, A minimum of max-size*max-files megabytes of space disk must be available -- `max-files`: (integer) maximum number of files to retain. Set to zero if you want to disable this feature -- `flush-interval`: (integer) flush buffer to log file every X seconds -- `compress`: (boolean) compress log file -- `compress-interval`: (integer) checking every X seconds if new log files must be compressed -- `compress-command`: (string) run external script after file compress step -- `mode`: (string) output format: text|json -- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format -- `postrotate-command`: (string) run external script after file rotation -- `postrotate-delete-success`: (boolean) delete file on script success - -```yaml -logfile: - file-path: null - max-size: 100 - max-files: 10 - flush-interval: 10 - compress: false - compress-interval: 5 - compress-command: null - mode: text - text-format: "" - postrotate-command: null - postrotate-delete-success: false -``` - -Basic example to use the postrotate command: - -Configure the script to execute after each file rotation, for each call the file is passed as argument. - -``` -logfile: - postrotate-command: "/home/dnscollector/postrotate.sh" -``` - -Script to move the log file to a specific folder - -```bash -#!/bin/bash - -DNSCOLLECTOR=/var/dnscollector/ -BACKUP_FOLDER=$DNSCOLLECTOR/$(date +%Y-%m-%d) -mkdir -p $BACKUP_FOLDER - -mv $1 $BACKUP_FOLDER -``` - -#### DNStap Client - -DNStap stream logger to a remote tcp destination or unix socket. -* to remote tcp destination or unix socket -* tls support - -Options: -- `listen-ip`: (string) remote address -- `listen-port`: (integer) remote tcp port -- `sock-path`: (string) unix socket path -- `retry-interval`: (integer) interval in second between retry reconnect -- `tls-support`: (boolean) enable tls -- `tls-insecure`: (boolean) insecure skip verify -- `server-id`: server identity - -```yaml -dnstap: - remote-address: 10.0.0.1 - remote-port: 6000 - sock-path: null - retry-interval: 5 - tls-support: false - tls-insecure: false - server-id: "dnscollector" -``` - -#### TCP Client - -Tcp/unix stream client logger. -* to remote tcp destination or unix socket -* supported format: text, json -* custom text format -* tls support - -Options: -- `transport`: (string) network transport to use: tcp|unix -- `listen-ip`: (string) remote address -- `listen-port`: (integer) remote tcp port -- `sock-path`: (string) unix socket path -- `retry-interval`: (integer) interval in second between retry reconnect -- `tls-support`: (boolean) enable tls -- `tls-insecure`: (boolean) insecure skip verify -- `mode`: (string) output format: text|json -- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format - -```yaml -tcpclient: - transport: tcp - remote-address: 127.0.0.1 - remote-port: 9999 - sock-path: null - retry-interval: 5 - tls-support: false - tls-insecure: false - mode: json - text-format: "" -``` - -#### Syslog - -Syslog logger to local syslog system or remote one. -* local or remote server -* custom text format -* supported format: text, json -* tls support - -Options: -- `facility`: (string) Set the syslog logging facility -- `transport`: (string) Transport to use to a remote log daemon or local one. local|tcp|udp|unix -- `remote-address`: (string) Remote address host:port -- `mode`: (string) text or json -- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format -- `tls-support`: (boolean) enable tls -- `tls-insecure`: (boolean) insecure skip verify - -```yaml -syslog: - severity: INFO - facility: DAEMON - transport: local - remote-address: "" - text-format: "" - mode: text - tls-support: false - tls-insecure: false -``` - -#### Fluentd Client - -Fluentd client to remote server or unix socket. -* to remote fluentd collector or unix socket -* [msgpask](https://msgpack.org/) -* tls support - -Options: -- `transport`: (string) network transport to use: tcp|unix -- `listen-ip`: (string) remote address -- `listen-port`: (integer) remote tcp port -- `sock-path`: (string) unix socket path -- `retry-interval`: (integer) interval in second between retry reconnect -- `tag`: (string) tag name -- `tls-support`: (boolean) enable tls -- `tls-insecure`: (boolean) insecure skip verify - -```yaml -fluentd: - transport: tcp - remote-address: 127.0.0.1 - remote-port: 24224 - sock-path: null - retry-interval: 5 - tag: "dns.collector" - tls-support: false - tls-insecure: false -``` - -#### Pcap File - -Enable this logger if you want to log into a pcap file. -* with rotation file support -* binary format -* gzip compression -* execute external command after each rotation - -Options: -- `file-path`: (string) output logfile name -- `max-size`: (integer) maximum size in megabytes of the file before rotation -- `max-files`: (integer) maximum number of files to retain. -- `compress`: (boolean) compress pcap file -- `compress-interval`: (integer) checking every X seconds if new log files must be compressed -- `postrotate-command`: (string) run external script after each file rotation -- `postrotate-delete-success`: (boolean) delete file on script success - -```yaml -pcapfile: - file-path: null - max-size: 1 - max-files: 3 - compress: false - compress-interval: 5 - postrotate-command: null - postrotate-delete-success: true -``` - -#### InfluxDB client - -InfluxDB client to remote InfluxDB server - -Options: -- `server-url`: (string) InfluxDB server url -- `auth-token`: (string) authentication token -- `bucket`: (string) bucket name -- `organization`: (string) organization name -- `tls-support`: (boolean) enable tls -- `tls-insecure`: (boolean) insecure skip verify - -```yaml - influxdb: - server-url: "http://localhost:8086" - auth-token: "" - bucket: "db_dns" - organization: "dnscollector" - tls-support: false - tls-insecure: false -``` - -#### Loki client - -Loki client to remote server - -Options: -- `server-url`: (string) Loki server url -- `job-name`: (string) Job name -- `mode`: (string) text or json -- `flush-interval`: (integer) flush batch every X seconds -- `batch-size`: (integer) batch size for log entries in bytes -- `retry-interval`: (integer) interval in second between before to retry to send batch -- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format -- `proxy-url`: (string) Proxy URL -- `tls-support`: (boolean) enable tls -- `tls-insecure`: (boolean) insecure skip verify -- `basic-auth-login`: (string) basic auth login -- `basic-auth-pwd`: (string) basic auth password -- `tenant-id`: (string) tenant/organisation id. If omitted or empty, no X-Scope-OrgID header is sent. - -```yaml - lokiclient: - server-url: "http://localhost:3100/loki/api/v1/push" - job-name: "dnscollector" - mode: "text" - flush-interval: 5 - batch-size: 1048576 - retry-interval: 10 - text-format: "localtime identity qr queryip family protocol qname qtype rcode" - proxy-url: "" - tls-insecure: false - basic-auth-login: "" - basic-auth-pwd: "" - tenant-id: "" -``` - -#### Statsd client - -Statsd client to statsd proxy -* tls support - -**Statsd metrics:** - -The `` tag can be configured in the `config.yml` file. - -Counters: - -``` -- __total_bytes_received -- __total_bytes_sent -- __total_requesters -- __total_domains -- __total_domains_nx -- __total_packets -- __total_packets_[udp|tcp] -- __total_packets_[inet|inet6] -- __total_replies_rrtype_[A|AAAA|TXT|...] -- __total_replies_rcode_[NOERROR|SERVFAIL|...] -``` - -Gauges: - -``` -- __queries_qps -``` - -Options: -- `transport`: (string) network transport to use: udp or tcp -- `listen-ip`: (string) remote address -- `listen-port`: (integer) remote tcp port -- `prefix`: (string) statsd prefix name -- `tls-support`: (boolean) enable tls -- `tls-insecure`: (boolean) insecure skip verify - -```yaml - statsd: - transport: udp - remote-address: 127.0.0.1 - remote-port: 8125 - prefix: "dnscollector" - tls-support: false - tls-insecure: false -``` - -### Routing - -Options: -- `from`: list of collectors by name -- `to`: list of loggers by name - -example: - -```yaml -multiplexer: - routes: - - from: [ tap_in1, tap_in2 ] - to: [ file ] -``` - - ## Transformers +Some transformations can be done after the collect. + ### Qname lowercase Option to convert all domain to lowercase. For example: `Wwww.GooGlE.com` will be equal to `www.google.com` @@ -770,7 +147,8 @@ Options: - `qname-lowercase`: (boolean) enable or disable lowercase ```yaml -qname-lowercase: true +transforms: + qname-lowercase: true ``` ### User Privacy @@ -785,9 +163,10 @@ Options: - `minimaze-qname`: (boolean) keep only the second level domain ```yaml -user-privacy: - anonymize-ip: false - minimaze-qname: false +transforms: + user-privacy: + anonymize-ip: false + minimaze-qname: false ``` ### GeoIP Support @@ -804,10 +183,11 @@ Options: - `mmdb-asn-file`: (string) path file to your mmdb asn database ```yaml -geoip: - mmdb-country-file: "/GeoIP/GeoLite2-Country.mmdb" - mmdb-city-file: "" - mmdb-asn-file: "" +transforms: + geoip: + mmdb-country-file: "/GeoIP/GeoLite2-Country.mmdb" + mmdb-city-file: "" + mmdb-asn-file: "" ``` When the feature is enabled, the following json field are populated: @@ -855,14 +235,15 @@ Options: - `log-replies`: (boolean) forward received replies to configured loggers ```yaml -filtering: - drop-fqdn-file: "" - drop-domain-file: "" - drop-queryip-file: "" - keep-queryip-file: "" - drop-rcodes: [] - log-queries: true - log-replies: true +transforms: + filtering: + drop-fqdn-file: "" + drop-domain-file: "" + drop-queryip-file: "" + keep-queryip-file: "" + drop-rcodes: [] + log-queries: true + log-replies: true ``` Domain list with regex example: diff --git a/doc/loggers.md b/doc/loggers.md new file mode 100644 index 00000000..0ac61b1f --- /dev/null +++ b/doc/loggers.md @@ -0,0 +1,453 @@ +# DnsCollector - Loggers Guide + +- [Console](#stdout) +- [Prometheus](#prometheus) +- [REST API](#rest-api) +- [Log File](#log-file) +- [DNStap](#dnstap-client) +- [TCP](#tcp-client) +- [Syslog](#syslog) +- [Fluentd](#fluentd-client) +- [Pcap File](#pcap-file) +- [InfluxDB](#influxdb-client) +- [Loki](#loki-client) +- [Statsd](#statsd-client) + +## Loggers + +### Stdout + +Print to your standard output, all DNS logs received +* in text or json format +* custom text format + +Options: +- `mode`: (string) text or json +- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format + +```yaml +stdout: + mode: text + text-format: "" +``` + +Example: + +``` +2021-08-07T15:33:15.168298439Z dnscollector CQ NOERROR 10.0.0.210 32918 INET UDP 54b www.google.fr A 0.000000 +2021-08-07T15:33:15.457492773Z dnscollector CR NOERROR 10.0.0.210 32918 INET UDP 152b www.google.fr A 0.28919 +``` + +### Prometheus + +This logger generates **prometheus** metrics. Use the following Grafana [dashboard](https://grafana.com/grafana/dashboards/16630). + +Options: +- `listen-ip`: (string) listening IP +- `listen-port`: (integer) listening port +- `tls-support`: (boolean) tls support +- `tls-mutual`: (boolean) mtls authentication +- `cert-file`: (string) certificate server file +- `key-file`: (string) private key server file +- `prometheus-suffix`: (string) prometheus suffix +- `top-n`: (string) default number of items on top + +```yaml +prometheus: + # listening IP + listen-ip: 0.0.0.0 + # listening port + listen-port: 8081 + # tls support + tls-support: false + # tls mutual + tls-mutual: false + # certificate server file + cert-file: "" + # private key server file + key-file: "" + # prometheus prefix + prometheus-prefix: "dnscollector" + # default number of items on top + top-n: 10 +``` + +### REST API + +Build-in webserver with REST API to retrieve somes statistics like top domains, clients and more... +Basic authentication supported. Prometheus metrics is also available through this API. + +* prometheus metrics format +* qps, total queries/replies, top domains, clients, rcodes... +* basic auth +* tls support + +See the [swagger](https://generator.swagger.io/?url=https://raw.githubusercontent.com/dmachard/go-dnscollector/main/doc/swagger.yml) documentation. + +Options: +- `listen-ip`: (string) listening IP +- `listen-port`: (integer) listening port +- `basic-auth-login`: (string) default login for basic auth +- `basic-auth-pwd`: (string) default password for basic auth +- `tls-support`: (boolean) tls support +- `cert-file`: (string) certificate server file +- `key-file`: (string) private key server file +- `top-max-items`: (string) default number of items on top +- `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 +- `prometheus-suffix`: (string) prometheus suffix + +```yaml +webserver: + listen-ip: 0.0.0.0 + listen-port: 8080 + basic-auth-login: admin + basic-auth-pwd: changeme + tls-support: true + cert-file: "./testsdata/server.crt" + key-file: "./testsdata/server.key" + top-max-items: 100 + common-qtypes: + - A + - AAAA + - CNAME + - TXT + - PTR + - NAPTR + - DNSKEY + - SRV + threshold-qname-len: 80 + threshold-packet-len: 1000 + threshold-slow: 0.5 + prometheus-suffix: "dnscollector" +``` + +**Prometheus metrics example:** + +Request: + +``` +$ curl --user admin:changeme http://127.0.0.1:8080/metrics +``` + +The `` tag can be configured in the `config.yml` file. + +Metrics list: +- `_qps`: Number of queries per second received +- `_requesters_total`: Number of clients +- `_domains_total`: Number of domains observed +- `_received_bytes_total`: Total bytes received +- `_sent_bytes_total`: Total bytes sent + + +The full metrics can be found [here](doc/metrics.txt). + + +### Log File + +Enable this logger if you want to log to a file. +* with rotation file support +* supported format: text, json +* gzip compression +* execute external command after each rotation +* custom text format + +Options: +- `file-path`: (string) output logfile name +- `max-size`: (integer) maximum size in megabytes of the file before rotation, A minimum of max-size*max-files megabytes of space disk must be available +- `max-files`: (integer) maximum number of files to retain. Set to zero if you want to disable this feature +- `flush-interval`: (integer) flush buffer to log file every X seconds +- `compress`: (boolean) compress log file +- `compress-interval`: (integer) checking every X seconds if new log files must be compressed +- `compress-command`: (string) run external script after file compress step +- `mode`: (string) output format: text|json +- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format +- `postrotate-command`: (string) run external script after file rotation +- `postrotate-delete-success`: (boolean) delete file on script success + +```yaml +logfile: + file-path: null + max-size: 100 + max-files: 10 + flush-interval: 10 + compress: false + compress-interval: 5 + compress-command: null + mode: text + text-format: "" + postrotate-command: null + postrotate-delete-success: false +``` + +Basic example to use the postrotate command: + +Configure the script to execute after each file rotation, for each call the file is passed as argument. + +``` +logfile: + postrotate-command: "/home/dnscollector/postrotate.sh" +``` + +Script to move the log file to a specific folder + +```bash +#!/bin/bash + +DNSCOLLECTOR=/var/dnscollector/ +BACKUP_FOLDER=$DNSCOLLECTOR/$(date +%Y-%m-%d) +mkdir -p $BACKUP_FOLDER + +mv $1 $BACKUP_FOLDER +``` + +### DNStap Client + +DNStap stream logger to a remote tcp destination or unix socket. +* to remote tcp destination or unix socket +* tls support + +Options: +- `listen-ip`: (string) remote address +- `listen-port`: (integer) remote tcp port +- `sock-path`: (string) unix socket path +- `retry-interval`: (integer) interval in second between retry reconnect +- `tls-support`: (boolean) enable tls +- `tls-insecure`: (boolean) insecure skip verify +- `server-id`: server identity + +```yaml +dnstap: + remote-address: 10.0.0.1 + remote-port: 6000 + sock-path: null + retry-interval: 5 + tls-support: false + tls-insecure: false + server-id: "dnscollector" +``` + +### TCP Client + +Tcp/unix stream client logger. +* to remote tcp destination or unix socket +* supported format: text, json +* custom text format +* tls support + +Options: +- `transport`: (string) network transport to use: tcp|unix +- `listen-ip`: (string) remote address +- `listen-port`: (integer) remote tcp port +- `sock-path`: (string) unix socket path +- `retry-interval`: (integer) interval in second between retry reconnect +- `tls-support`: (boolean) enable tls +- `tls-insecure`: (boolean) insecure skip verify +- `mode`: (string) output format: text|json +- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format + +```yaml +tcpclient: + transport: tcp + remote-address: 127.0.0.1 + remote-port: 9999 + sock-path: null + retry-interval: 5 + tls-support: false + tls-insecure: false + mode: json + text-format: "" +``` + +### Syslog + +Syslog logger to local syslog system or remote one. +* local or remote server +* custom text format +* supported format: text, json +* tls support + +Options: +- `facility`: (string) Set the syslog logging facility +- `transport`: (string) Transport to use to a remote log daemon or local one. local|tcp|udp|unix +- `remote-address`: (string) Remote address host:port +- `mode`: (string) text or json +- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format +- `tls-support`: (boolean) enable tls +- `tls-insecure`: (boolean) insecure skip verify + +```yaml +syslog: + severity: INFO + facility: DAEMON + transport: local + remote-address: "" + text-format: "" + mode: text + tls-support: false + tls-insecure: false +``` + +### Fluentd Client + +Fluentd client to remote server or unix socket. +* to remote fluentd collector or unix socket +* [msgpask](https://msgpack.org/) +* tls support + +Options: +- `transport`: (string) network transport to use: tcp|unix +- `listen-ip`: (string) remote address +- `listen-port`: (integer) remote tcp port +- `sock-path`: (string) unix socket path +- `retry-interval`: (integer) interval in second between retry reconnect +- `tag`: (string) tag name +- `tls-support`: (boolean) enable tls +- `tls-insecure`: (boolean) insecure skip verify + +```yaml +fluentd: + transport: tcp + remote-address: 127.0.0.1 + remote-port: 24224 + sock-path: null + retry-interval: 5 + tag: "dns.collector" + tls-support: false + tls-insecure: false +``` + +### Pcap File + +Enable this logger if you want to log into a pcap file. +* with rotation file support +* binary format +* gzip compression +* execute external command after each rotation + +Options: +- `file-path`: (string) output logfile name +- `max-size`: (integer) maximum size in megabytes of the file before rotation +- `max-files`: (integer) maximum number of files to retain. +- `compress`: (boolean) compress pcap file +- `compress-interval`: (integer) checking every X seconds if new log files must be compressed +- `postrotate-command`: (string) run external script after each file rotation +- `postrotate-delete-success`: (boolean) delete file on script success + +```yaml +pcapfile: + file-path: null + max-size: 1 + max-files: 3 + compress: false + compress-interval: 5 + postrotate-command: null + postrotate-delete-success: true +``` + +### InfluxDB client + +InfluxDB client to remote InfluxDB server + +Options: +- `server-url`: (string) InfluxDB server url +- `auth-token`: (string) authentication token +- `bucket`: (string) bucket name +- `organization`: (string) organization name +- `tls-support`: (boolean) enable tls +- `tls-insecure`: (boolean) insecure skip verify + +```yaml + influxdb: + server-url: "http://localhost:8086" + auth-token: "" + bucket: "db_dns" + organization: "dnscollector" + tls-support: false + tls-insecure: false +``` + +### Loki client + +Loki client to remote server + +Options: +- `server-url`: (string) Loki server url +- `job-name`: (string) Job name +- `mode`: (string) text or json +- `flush-interval`: (integer) flush batch every X seconds +- `batch-size`: (integer) batch size for log entries in bytes +- `retry-interval`: (integer) interval in second between before to retry to send batch +- `text-format`: (string) output text format, please refer to the default text format to see all available directives, use this parameter if you want a specific format +- `proxy-url`: (string) Proxy URL +- `tls-support`: (boolean) enable tls +- `tls-insecure`: (boolean) insecure skip verify +- `basic-auth-login`: (string) basic auth login +- `basic-auth-pwd`: (string) basic auth password +- `tenant-id`: (string) tenant/organisation id. If omitted or empty, no X-Scope-OrgID header is sent. + +```yaml + lokiclient: + server-url: "http://localhost:3100/loki/api/v1/push" + job-name: "dnscollector" + mode: "text" + flush-interval: 5 + batch-size: 1048576 + retry-interval: 10 + text-format: "localtime identity qr queryip family protocol qname qtype rcode" + proxy-url: "" + tls-insecure: false + basic-auth-login: "" + basic-auth-pwd: "" + tenant-id: "" +``` + +### Statsd client + +Statsd client to statsd proxy +* tls support + +**Statsd metrics:** + +The `` tag can be configured in the `config.yml` file. + +Counters: + +``` +- __total_bytes_received +- __total_bytes_sent +- __total_requesters +- __total_domains +- __total_domains_nx +- __total_packets +- __total_packets_[udp|tcp] +- __total_packets_[inet|inet6] +- __total_replies_rrtype_[A|AAAA|TXT|...] +- __total_replies_rcode_[NOERROR|SERVFAIL|...] +``` + +Gauges: + +``` +- __queries_qps +``` + +Options: +- `transport`: (string) network transport to use: udp or tcp +- `listen-ip`: (string) remote address +- `listen-port`: (integer) remote tcp port +- `prefix`: (string) statsd prefix name +- `tls-support`: (boolean) enable tls +- `tls-insecure`: (boolean) insecure skip verify + +```yaml + statsd: + transport: udp + remote-address: 127.0.0.1 + remote-port: 8125 + prefix: "dnscollector" + tls-support: false + tls-insecure: false +``` \ No newline at end of file diff --git a/doc/multiplexer.md b/doc/multiplexer.md index 3567f061..015a588c 100644 --- a/doc/multiplexer.md +++ b/doc/multiplexer.md @@ -1,4 +1,4 @@ -# DnsCollector - Logs routing +# DnsCollector - Logs routing / Multiplexer The dns collector can be configured with multiple loggers and collectors at the same time. diff --git a/example-config/use-case-2.yml b/example-config/use-case-2.yml index 7ab86da1..5660d3a5 100644 --- a/example-config/use-case-2.yml +++ b/example-config/use-case-2.yml @@ -25,8 +25,4 @@ multiplexer: routes: - from: [tap_in] - to: [web] - -subprocessors: - statistics: - prometheus-prefix: "dnscollector" + to: [web] \ No newline at end of file diff --git a/example-config/use-case-3.yml b/example-config/use-case-3.yml index 9b7ef5e6..72c6a3cb 100644 --- a/example-config/use-case-3.yml +++ b/example-config/use-case-3.yml @@ -16,8 +16,4 @@ multiplexer: routes: - from: [tap_in] - to: [console] - -subprocessors: - filtering: - log-replies: true \ No newline at end of file + to: [console] \ No newline at end of file diff --git a/example-config/use-case-6.yml b/example-config/use-case-6.yml index 2566d079..a3a49d18 100644 --- a/example-config/use-case-6.yml +++ b/example-config/use-case-6.yml @@ -8,12 +8,10 @@ multiplexer: dnstap: listen-ip: 0.0.0.0 listen-port: 6000 - - transformers: - - name: privacy - user-privacy: - anonymize-ip: true - minimaze-qname: true + transforms: + user-privacy: + anonymize-ip: true + minimaze-qname: true loggers: - name: console diff --git a/example-config/use-case-8.yml b/example-config/use-case-8.yml new file mode 100644 index 00000000..17bd5f4e --- /dev/null +++ b/example-config/use-case-8.yml @@ -0,0 +1,35 @@ +global: + trace: + verbose: true + +multiplexer: + collectors: + - name: pdns_internal + powerdns: + listen-ip: 0.0.0.0 + listen-port: 6000 + - name: pdns_internet + powerdns: + listen-ip: 0.0.0.0 + listen-port: 6001 + transforms: + normalize: + lowercase-qname: true + + loggers: + - name: file_internal + logfile: + file-path: "/var/tap/dnscollector_internal.log" + - name: file_internet + logfile: + file-path: "/var/tap/dnscollector_internet.log" + - name: prom + prometheus: + listen-ip: 0.0.0.0 + listen-port: 8081 + + routes: + - from: [ pdns_internal ] + to: [ file_internal, prom ] + - from: [pdns_internet ] + to: [ file_internet, prom ] \ No newline at end of file diff --git a/loggers/dnstap.go b/loggers/dnstap.go index d035db5e..77ba6ea7 100644 --- a/loggers/dnstap.go +++ b/loggers/dnstap.go @@ -41,6 +41,11 @@ func NewDnstapSender(config *dnsutils.Config, logger *logger.Logger, name string return s } +func (c *DnstapSender) GetName() string { return c.name } + +func (c *DnstapSender) SetLoggers(loggers []dnsutils.Worker) { +} + func (o *DnstapSender) ReadConfig() { // get hostname if o.config.Loggers.Dnstap.ServerId == "" { diff --git a/loggers/fakelogger.go b/loggers/fakelogger.go index fc4384f2..dc04860b 100644 --- a/loggers/fakelogger.go +++ b/loggers/fakelogger.go @@ -1,18 +1,26 @@ package loggers -import "github.com/dmachard/go-dnscollector/dnsutils" +import ( + "github.com/dmachard/go-dnscollector/dnsutils" +) type FakeLogger struct { channel chan dnsutils.DnsMessage + name string } func NewFakeLogger() *FakeLogger { o := &FakeLogger{ channel: make(chan dnsutils.DnsMessage, 512), + name: "fake", } return o } +func (c *FakeLogger) GetName() string { return c.name } + +func (c *FakeLogger) SetLoggers(loggers []dnsutils.Worker) {} + func (o *FakeLogger) ReadConfig() {} func (o *FakeLogger) Stop() {} diff --git a/loggers/fluentd.go b/loggers/fluentd.go index cf1fef39..86227e23 100644 --- a/loggers/fluentd.go +++ b/loggers/fluentd.go @@ -37,6 +37,10 @@ func NewFluentdClient(config *dnsutils.Config, logger *logger.Logger, name strin return s } +func (c *FluentdClient) GetName() string { return c.name } + +func (c *FluentdClient) SetLoggers(loggers []dnsutils.Worker) {} + func (o *FluentdClient) ReadConfig() { //tbc } diff --git a/loggers/influxdb.go b/loggers/influxdb.go index 789769df..b1bbe24e 100644 --- a/loggers/influxdb.go +++ b/loggers/influxdb.go @@ -39,6 +39,10 @@ func NewInfluxDBClient(config *dnsutils.Config, logger *logger.Logger, name stri return s } +func (c *InfluxDBClient) GetName() string { return c.name } + +func (c *InfluxDBClient) SetLoggers(loggers []dnsutils.Worker) {} + func (o *InfluxDBClient) ReadConfig() { //tbc } diff --git a/loggers/logfile.go b/loggers/logfile.go index feb44141..8b72a7c3 100644 --- a/loggers/logfile.go +++ b/loggers/logfile.go @@ -61,6 +61,10 @@ func NewLogFile(config *dnsutils.Config, logger *logger.Logger, name string) *Lo return o } +func (c *LogFile) GetName() string { return c.name } + +func (c *LogFile) SetLoggers(loggers []dnsutils.Worker) {} + func (c *LogFile) ReadConfig() { c.filedir = filepath.Dir(c.config.Loggers.LogFile.FilePath) c.filename = filepath.Base(c.config.Loggers.LogFile.FilePath) diff --git a/loggers/lokiclient.go b/loggers/lokiclient.go index 544807bc..ccf0bb3f 100644 --- a/loggers/lokiclient.go +++ b/loggers/lokiclient.go @@ -93,6 +93,10 @@ func NewLokiClient(config *dnsutils.Config, logger *logger.Logger, name string) return s } +func (c *LokiClient) GetName() string { return c.name } + +func (c *LokiClient) SetLoggers(loggers []dnsutils.Worker) {} + func (o *LokiClient) ReadConfig() { if len(o.config.Loggers.LokiClient.TextFormat) > 0 { o.textFormat = strings.Fields(o.config.Loggers.LokiClient.TextFormat) diff --git a/loggers/pcapfile.go b/loggers/pcapfile.go index 60174445..6be64186 100644 --- a/loggers/pcapfile.go +++ b/loggers/pcapfile.go @@ -61,6 +61,10 @@ func NewPcapFile(config *dnsutils.Config, console *logger.Logger, name string) * return o } +func (c *PcapWriter) GetName() string { return c.name } + +func (c *PcapWriter) SetLoggers(loggers []dnsutils.Worker) {} + func (c *PcapWriter) ReadConfig() { c.filedir = filepath.Dir(c.config.Loggers.PcapFile.FilePath) c.filename = filepath.Base(c.config.Loggers.PcapFile.FilePath) diff --git a/loggers/prometheus.go b/loggers/prometheus.go index d9b47d99..5f74f1fe 100644 --- a/loggers/prometheus.go +++ b/loggers/prometheus.go @@ -123,6 +123,10 @@ func NewPrometheus(config *dnsutils.Config, logger *logger.Logger, version strin return o } +func (c *Prometheus) GetName() string { return c.name } + +func (c *Prometheus) SetLoggers(loggers []dnsutils.Worker) {} + func (o *Prometheus) InitProm() { prom_prefix := SanitizeMetricName(o.config.Loggers.Prometheus.PromPrefix) diff --git a/loggers/statsd.go b/loggers/statsd.go index f23c9504..0a4dc3f4 100644 --- a/loggers/statsd.go +++ b/loggers/statsd.go @@ -45,6 +45,10 @@ func NewStatsdClient(config *dnsutils.Config, logger *logger.Logger, version str return s } +func (c *StatsdClient) GetName() string { return c.name } + +func (c *StatsdClient) SetLoggers(loggers []dnsutils.Worker) {} + func (o *StatsdClient) ReadConfig() { //tbc } diff --git a/loggers/stdout.go b/loggers/stdout.go index 008f90a7..87a488ec 100644 --- a/loggers/stdout.go +++ b/loggers/stdout.go @@ -36,6 +36,10 @@ func NewStdOut(config *dnsutils.Config, console *logger.Logger, name string) *St return o } +func (c *StdOut) GetName() string { return c.name } + +func (c *StdOut) SetLoggers(loggers []dnsutils.Worker) {} + func (c *StdOut) ReadConfig() { if len(c.config.Loggers.Stdout.TextFormat) > 0 { c.textFormat = strings.Fields(c.config.Loggers.Stdout.TextFormat) diff --git a/loggers/syslog.go b/loggers/syslog.go index c886d5e5..ee2026a2 100644 --- a/loggers/syslog.go +++ b/loggers/syslog.go @@ -75,6 +75,10 @@ func NewSyslog(config *dnsutils.Config, console *logger.Logger, name string) *Sy return o } +func (c *Syslog) GetName() string { return c.name } + +func (c *Syslog) SetLoggers(loggers []dnsutils.Worker) {} + func (c *Syslog) ReadConfig() { if !dnsutils.IsValidMode(c.config.Loggers.Syslog.Mode) { c.logger.Fatal("logger syslog - invalid mode text or json expected") diff --git a/loggers/tcpclient.go b/loggers/tcpclient.go index 70812c06..9dc264c4 100644 --- a/loggers/tcpclient.go +++ b/loggers/tcpclient.go @@ -40,6 +40,10 @@ func NewTcpClient(config *dnsutils.Config, logger *logger.Logger, name string) * return s } +func (c *TcpClient) GetName() string { return c.name } + +func (c *TcpClient) SetLoggers(loggers []dnsutils.Worker) {} + func (o *TcpClient) ReadConfig() { if len(o.config.Loggers.TcpClient.TextFormat) > 0 { o.textFormat = strings.Fields(o.config.Loggers.TcpClient.TextFormat) diff --git a/loggers/webserver.go b/loggers/webserver.go index d656f9c4..dda2bf71 100644 --- a/loggers/webserver.go +++ b/loggers/webserver.go @@ -46,6 +46,10 @@ func NewWebserver(config *dnsutils.Config, logger *logger.Logger, version string return o } +func (c *Webserver) GetName() string { return c.name } + +func (c *Webserver) SetLoggers(loggers []dnsutils.Worker) {} + func (o *Webserver) ReadConfig() { } diff --git a/tests/config.py b/tests/config.py index 5e5bd78a..f5c5deb9 100644 --- a/tests/config.py +++ b/tests/config.py @@ -16,7 +16,7 @@ def connection_made(self, transport): def pipe_data_received(self, fd, data): print(data.decode(), end="") - if b"config loaded" in data: + if b"main - starting" in data: self.is_configvalid.set_result(True) self.kill() diff --git a/testsdata/config_metrics_dnstaptcp.yml b/testsdata/config_metrics_dnstaptcp.yml index 3971f78a..548fd019 100644 --- a/testsdata/config_metrics_dnstaptcp.yml +++ b/testsdata/config_metrics_dnstaptcp.yml @@ -10,7 +10,7 @@ multiplexer: listen-port: 6000 loggers: - - name: out + - name: console stdout: mode: text - name: web @@ -23,4 +23,4 @@ multiplexer: routes: - from: [tap] - to: [out, web] + to: [console, web] diff --git a/testsdata/config_stdout_dnstaptcp.yml b/testsdata/config_stdout_dnstaptcp.yml index bb2e9e84..b34dc59b 100644 --- a/testsdata/config_stdout_dnstaptcp.yml +++ b/testsdata/config_stdout_dnstaptcp.yml @@ -10,10 +10,10 @@ multiplexer: listen-port: 6000 loggers: - - name: out + - name: console stdout: mode: text routes: - from: [tap] - to: [out] + to: [console] diff --git a/testsdata/config_stdout_dnstapunix.yml b/testsdata/config_stdout_dnstapunix.yml index 19354dbc..97499b82 100644 --- a/testsdata/config_stdout_dnstapunix.yml +++ b/testsdata/config_stdout_dnstapunix.yml @@ -9,10 +9,10 @@ multiplexer: sock-path: /tmp/dnstap.sock loggers: - - name: out + - name: console stdout: mode: text routes: - from: [tap] - to: [out] + to: [console] diff --git a/testsdata/config_stdout_powerdns.yml b/testsdata/config_stdout_powerdns.yml index 5145bc19..73cbda6e 100644 --- a/testsdata/config_stdout_powerdns.yml +++ b/testsdata/config_stdout_powerdns.yml @@ -10,10 +10,10 @@ multiplexer: listen-port: 6001 loggers: - - name: out + - name: console stdout: mode: text routes: - from: [pdns] - to: [out] + to: [console] diff --git a/testsdata/config_verbose.yml b/testsdata/config_verbose.yml index 8887015d..0f5ed666 100644 --- a/testsdata/config_verbose.yml +++ b/testsdata/config_verbose.yml @@ -10,10 +10,10 @@ multiplexer: listen-port: 6000 loggers: - - name: out + - name: console stdout: mode: text routes: - src: [tap] - dst: [out] \ No newline at end of file + dst: [console] \ No newline at end of file