From 6810e631f7dd4097be155dfedbd94f0549cef01c Mon Sep 17 00:00:00 2001 From: Thermi Date: Thu, 23 Feb 2023 20:45:03 +0100 Subject: [PATCH] WIP: TZSP support (#172) * Full support tzsp encapsulation protocol (used by Mikrotik devices for sending of data, can be used to capture DNS packets) * remove debug prints from tzsp processor * skip processing of packets that are too short (less than 12 byte only for example) * gofmt'd the tzsp processor code * check for err in address resolution * gofmt'd config.go * make "0.0.0.0" a constant * amend documentation * fix * remove tap from collector list * only build tzsp_processor.go on Linux * tzsp_processor implementation for darwin; Only syscall and usage of timestamp is different * doc/collectors: change highlighting to routeros * collectors/tzsp_processor_darwin.go: try to use ReadMsgUDP instead of ReadMsgUDPAddrPort * collectors/tzsp_processor_darwin.go: gofmt * try * test * remove incomplete macos implementation * Bump github.com/cilium/ebpf from 0.9.3 to 0.10.0 (#198) Bumps [github.com/cilium/ebpf](https://github.com/cilium/ebpf) from 0.9.3 to 0.10.0. - [Release notes](https://github.com/cilium/ebpf/releases) - [Commits](https://github.com/cilium/ebpf/compare/v0.9.3...v0.10.0) --- updated-dependencies: - dependency-name: github.com/cilium/ebpf dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Optimization - breaking changes in JSON format (#218) * fix dns parser: ignore too short decode error if reply is truncated (#221) * bypass macos and windows * fix readme.md --------- Signed-off-by: dependabot[bot] Co-authored-by: Denis MACHARD <5562930+dmachard@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- README.md | 11 +- collectors/tzsp.go | 276 +++++++++++++++++++++++++++++++++ collectors/tzsp_darwin.go | 78 ++++++++++ collectors/tzsp_windows.go | 78 ++++++++++ config.yml | 10 ++ dnscollector.go | 3 + dnsutils/config.go | 17 ++ doc/collectors.md | 63 ++++++++ example-config/use-case-12.yml | 4 +- example-config/use-case-15.yml | 4 +- example-config/use-case-17.yml | 29 ++++ go.mod | 2 + go.sum | 2 + 13 files changed, 569 insertions(+), 8 deletions(-) create mode 100644 collectors/tzsp.go create mode 100644 collectors/tzsp_darwin.go create mode 100644 collectors/tzsp_windows.go create mode 100644 example-config/use-case-17.yml diff --git a/README.md b/README.md index 87861d41..24d4bdd6 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,13 @@ Additionally, DNS-collector also contains DNS parser with [`EDNS`](doc/dnsparser - Protobuf [`DNStap`](doc/collectors.md#dns-tap) with `tls`, `tcp` or `unix` support - Protobuf [`PowerDNS`](doc/collectors.md#protobuf-powerdns) streams with full [`metadata`](doc/powerdns.md) support - [`Proxifier`](doc/collectors.md#dns-tap-proxifier) for DNSTap streams -- *Live capture on a network interface* +- *Live capture on a network interface* - [`AF_PACKET`](doc/collectors.md#live-capture-with-af_packet) socket with BPF filter - [`eBPF XDP`](doc/collectors.md#live-capture-with-ebpf-xdp) ingress traffic - *Read text or binary files as input* - Read and tail on [`Plain text`](doc/collectors.md#tail) files - Ingest [`PCAP`](doc/collectors.md#file-ingestor) or [`DNSTap`](doc/collectors.md#file-ingestor) files by watching a directory +- Listen for [`TZSP`](doc/collectors.md#tzsp) packets containg DNS packets **Loggers**: @@ -86,14 +87,13 @@ See the full [configuration guide](doc/configuration.md) for more details. You will find below some examples of configuration to manage your DNS logs. - -- Capture DNS traffic with incoming DNSTap streams +- Capture DNS traffic from incoming DNSTap streams - [x] [Read from UNIX DNSTap socket and forward it to TLS stream](example-config/use-case-5.yml) - [x] [Transform DNSTap as input to JSON format as output](example-config/use-case-3.yml) - [x] [Relays DNSTap stream to multiple remote destination without decoding](example-config/use-case-12.yml) - [x] [Aggregate several DNSTap stream and forward it to the same file](example-config/use-case-7.yml) -- Capture DNS traffic with PowerDNS +- Capture DNS traffic from PowerDNS products - [x] [Capture multiple PowerDNS streams](example-config/use-case-8.yml) - Observe your DNS traffic from logs @@ -113,6 +113,9 @@ You will find below some examples of configuration to manage your DNS logs. - Capture DNS traffic from PCAP files - [x] [Capture DNSTap stream and backup-it to text and pcap files](example-config/use-case-1.yml) - [x] [Watch for PCAP files as input and JSON as output](example-config/use-case-15.yml) + +- Capture DNS traffic from Mikrotik device + - [x] [Capture TZSP packets containing DNS packets and process them as json](example-config/use-case-17.yml) ## Contributing diff --git a/collectors/tzsp.go b/collectors/tzsp.go new file mode 100644 index 00000000..a2eabf8b --- /dev/null +++ b/collectors/tzsp.go @@ -0,0 +1,276 @@ +//go:build linux +// +build linux + +// Written by Noel Kuntze + +package collectors + +import ( + "encoding/binary" + "fmt" + "net" + "syscall" + + "github.com/dmachard/go-dnscollector/dnsutils" + "github.com/dmachard/go-logger" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" + "github.com/rs/tzsp" +) + +type TzspSniffer struct { + done chan bool + exit chan bool + listen net.UDPConn + loggers []dnsutils.Worker + config *dnsutils.Config + logger *logger.Logger + name string + identity string + port int + ip string + dropQueries bool + dropReplies bool +} + +func NewTzsp(loggers []dnsutils.Worker, config *dnsutils.Config, logger *logger.Logger, name string) *TzspSniffer { + logger.Info("[%s] tzsp collector - enabled", name) + s := &TzspSniffer{ + done: make(chan bool), + exit: make(chan bool), + config: config, + loggers: loggers, + logger: logger, + name: name, + } + s.ReadConfig() + return s +} + +func (c *TzspSniffer) GetName() string { return c.name } + +func (c *TzspSniffer) SetLoggers(loggers []dnsutils.Worker) { + c.loggers = loggers +} + +func (c *TzspSniffer) Loggers() []chan dnsutils.DnsMessage { + channels := []chan dnsutils.DnsMessage{} + for _, p := range c.loggers { + channels = append(channels, p.Channel()) + } + return channels +} + +func (c *TzspSniffer) LogInfo(msg string, v ...interface{}) { + c.logger.Info("["+c.name+"] tzsp collector - "+msg, v...) +} + +func (c *TzspSniffer) LogError(msg string, v ...interface{}) { + c.logger.Error("["+c.name+"] tzsp collector - "+msg, v...) +} + +func (c *TzspSniffer) ReadConfig() { + + c.port = c.config.Collectors.Tzsp.ListenPort + c.ip = c.config.Collectors.Tzsp.ListenIp + c.identity = c.config.GetServerIdentity() + c.dropQueries = c.config.Collectors.Tzsp.DropQueries + c.dropReplies = c.config.Collectors.Tzsp.DropReplies + // TODO: Implement +} + +func (c *TzspSniffer) Listen() error { + c.logger.Info("running in background...") + + ServerAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", c.ip, c.port)) + if err != nil { + return err + } + + ServerConn, err := net.ListenUDP("udp", ServerAddr) + if err != nil { + return err + } + file, err := ServerConn.File() + + if err != nil { + return err + } + + err = syscall.SetsockoptInt(int(file.Fd()), syscall.SOL_SOCKET, syscall.SO_TIMESTAMPNS, 1) + + if err != nil { + return err + } + c.LogInfo("is listening on %s", ServerConn.LocalAddr()) + c.listen = *ServerConn + return nil +} + +func (c *TzspSniffer) Channel() chan dnsutils.DnsMessage { + return nil +} + +func (c *TzspSniffer) Stop() { + c.LogInfo("stopping...") + + // Finally close the listener to unblock accept + c.exit <- true + + // read done channel and block until run is terminated + <-c.done + close(c.done) +} + +func (c *TzspSniffer) Run() { + c.logger.Info("starting collector...") + + if err := c.Listen(); err != nil { + c.logger.Fatal("collector tzsp listening failed: ", err) + } + + dnsProcessor := NewDnsProcessor(c.config, c.logger, c.name) + dnsProcessor.cacheSupport = c.config.Collectors.Tzsp.CacheSupport + dnsProcessor.queryTimeout = c.config.Collectors.Tzsp.QueryTimeout + + go dnsProcessor.Run(c.Loggers()) + + go func() { + buf := make([]byte, 65536) + oob := make([]byte, 100) + for { + //flags, from + bufN, oobn, _, _, err := c.listen.ReadMsgUDPAddrPort(buf, oob) + if err != nil { + panic(err) + } + if bufN == 0 { + panic("buf empty") + } + if bufN > len(buf) { + panic("buf overflow") + } + if oobn == 0 { + panic("oob missing") + } + c.LogInfo("Packet received") + scms, err := syscall.ParseSocketControlMessage(oob[:oobn]) + if err != nil { + panic(err) + } + if len(scms) != 1 { + c.LogInfo("len(scms) != 1") + continue + } + scm := scms[0] + if scm.Header.Type != syscall.SCM_TIMESTAMPNS { + panic("scm timestampns missing") + } + tsec := binary.LittleEndian.Uint32(scm.Data[:4]) + nsec := binary.LittleEndian.Uint32(scm.Data[8:12]) + + // copy packet data from buffer + pkt := make([]byte, bufN) + copy(pkt, buf[:bufN]) + + tzsp_packet, err := tzsp.Parse(pkt) + + if err != nil { + c.LogError("Failed to parse packet: ", err) + continue + } + + var eth layers.Ethernet + var ip4 layers.IPv4 + var ip6 layers.IPv6 + var tcp layers.TCP + var udp layers.UDP + parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ð, &ip4, &ip6, &tcp, &udp) + decodedLayers := make([]gopacket.LayerType, 0, 4) + + // decode-it + parser.DecodeLayers(tzsp_packet.Data, &decodedLayers) + + dm := dnsutils.DnsMessage{} + dm.Init() + + ignore_packet := false + for _, layertyp := range decodedLayers { + switch layertyp { + case layers.LayerTypeIPv4: + dm.NetworkInfo.Family = dnsutils.PROTO_IPV4 + dm.NetworkInfo.QueryIp = ip4.SrcIP.String() + dm.NetworkInfo.ResponseIp = ip4.DstIP.String() + + case layers.LayerTypeIPv6: + dm.NetworkInfo.QueryIp = ip6.SrcIP.String() + dm.NetworkInfo.ResponseIp = ip6.DstIP.String() + dm.NetworkInfo.Family = dnsutils.PROTO_IPV6 + + case layers.LayerTypeUDP: + dm.NetworkInfo.QueryPort = fmt.Sprint(int(udp.SrcPort)) + dm.NetworkInfo.ResponsePort = fmt.Sprint(int(udp.DstPort)) + dm.DNS.Payload = udp.Payload + dm.DNS.Length = len(udp.Payload) + dm.NetworkInfo.Protocol = dnsutils.PROTO_UDP + + case layers.LayerTypeTCP: + // ignore SYN/ACK packet + // Note: disabled because SYN/SYN+Ack might contain data if TCP Fast open is used + // if !tcp.PSH { + // ignore_packet = true + // continue + // } + if len(tcp.Payload) < 12 { + // packet way too short; 12 byte is the minimum size a DNS packet (header only, + // no questions, answers, authorities, or additional RRs) + continue + } + dnsLengthField := binary.BigEndian.Uint16(tcp.Payload[0:2]) + if len(tcp.Payload) < int(dnsLengthField) { + ignore_packet = true + continue + } + + dm.NetworkInfo.QueryPort = fmt.Sprint(int(tcp.SrcPort)) + dm.NetworkInfo.ResponsePort = fmt.Sprint(int(tcp.DstPort)) + dm.DNS.Payload = tcp.Payload[2:] + dm.DNS.Length = len(tcp.Payload[2:]) + dm.NetworkInfo.Protocol = dnsutils.PROTO_TCP + } + } + + if !ignore_packet { + dm.DnsTap.Identity = c.identity + + // set timestamp + dm.DnsTap.TimeSec = int(tsec) + dm.DnsTap.TimeNsec = int(nsec) + + // just decode QR + if len(dm.DNS.Payload) < 4 { + continue + } + qr := binary.BigEndian.Uint16(dm.DNS.Payload[2:4]) >> 15 + + // is query ? + if int(qr) == 0 && !c.dropQueries { + dnsProcessor.GetChannel() <- dm + } + + // is reply ? + if int(qr) == 1 && !c.dropReplies { + dnsProcessor.GetChannel() <- dm + } + } + } + }() + + <-c.exit + + // stop dns processor + dnsProcessor.Stop() + + c.LogInfo("run terminated") + c.done <- true +} diff --git a/collectors/tzsp_darwin.go b/collectors/tzsp_darwin.go new file mode 100644 index 00000000..5cfc7866 --- /dev/null +++ b/collectors/tzsp_darwin.go @@ -0,0 +1,78 @@ +//go:build darwin +// +build darwin + +package collectors + +import ( + "github.com/dmachard/go-dnscollector/dnsutils" + "github.com/dmachard/go-logger" +) + +type TzspSniffer struct { + done chan bool + exit chan bool + loggers []dnsutils.Worker + config *dnsutils.Config + logger *logger.Logger + name string +} + +// workaround for macos, not yet supported +func NewTzsp(loggers []dnsutils.Worker, config *dnsutils.Config, logger *logger.Logger, name string) *AfpacketSniffer { + logger.Info("[%s] tzsp collector - enabled", name) + s := &AfpacketSniffer{ + done: make(chan bool), + exit: make(chan bool), + config: config, + loggers: loggers, + logger: logger, + name: name, + } + s.ReadConfig() + return s +} + +func (c *TzspSniffer) GetName() string { return c.name } + +func (c *TzspSniffer) SetLoggers(loggers []dnsutils.Worker) { + c.loggers = loggers +} + +func (c *TzspSniffer) LogInfo(msg string, v ...interface{}) { + c.logger.Info("["+c.name+"] tzsp collector - "+msg, v...) +} + +func (c *TzspSniffer) LogError(msg string, v ...interface{}) { + c.logger.Error("["+c.name+"] tzsp collector - "+msg, v...) +} + +func (c *TzspSniffer) Loggers() []chan dnsutils.DnsMessage { + channels := []chan dnsutils.DnsMessage{} + for _, p := range c.loggers { + channels = append(channels, p.Channel()) + } + return channels +} + +func (c *TzspSniffer) ReadConfig() { +} + +func (c *TzspSniffer) Channel() chan dnsutils.DnsMessage { + return nil +} + +func (c *TzspSniffer) Stop() { + c.LogInfo("stopping...") + + // exit to close properly + c.exit <- true + + // read done channel and block until run is terminated + <-c.done + close(c.done) +} + +func (c *TzspSniffer) Run() { + c.LogInfo("run terminated") + c.done <- true +} diff --git a/collectors/tzsp_windows.go b/collectors/tzsp_windows.go new file mode 100644 index 00000000..55ea3d6a --- /dev/null +++ b/collectors/tzsp_windows.go @@ -0,0 +1,78 @@ +//go:build windows +// +build windows + +package collectors + +import ( + "github.com/dmachard/go-dnscollector/dnsutils" + "github.com/dmachard/go-logger" +) + +type TzspSniffer struct { + done chan bool + exit chan bool + loggers []dnsutils.Worker + config *dnsutils.Config + logger *logger.Logger + name string +} + +// workaround for macos, not yet supported +func NewTzsp(loggers []dnsutils.Worker, config *dnsutils.Config, logger *logger.Logger, name string) *AfpacketSniffer { + logger.Info("[%s] tzsp collector - enabled", name) + s := &AfpacketSniffer{ + done: make(chan bool), + exit: make(chan bool), + config: config, + loggers: loggers, + logger: logger, + name: name, + } + s.ReadConfig() + return s +} + +func (c *TzspSniffer) GetName() string { return c.name } + +func (c *TzspSniffer) SetLoggers(loggers []dnsutils.Worker) { + c.loggers = loggers +} + +func (c *TzspSniffer) LogInfo(msg string, v ...interface{}) { + c.logger.Info("["+c.name+"] tzsp collector - "+msg, v...) +} + +func (c *TzspSniffer) LogError(msg string, v ...interface{}) { + c.logger.Error("["+c.name+"] tzsp collector - "+msg, v...) +} + +func (c *TzspSniffer) Loggers() []chan dnsutils.DnsMessage { + channels := []chan dnsutils.DnsMessage{} + for _, p := range c.loggers { + channels = append(channels, p.Channel()) + } + return channels +} + +func (c *TzspSniffer) ReadConfig() { +} + +func (c *TzspSniffer) Channel() chan dnsutils.DnsMessage { + return nil +} + +func (c *TzspSniffer) Stop() { + c.LogInfo("stopping...") + + // exit to close properly + c.exit <- true + + // read done channel and block until run is terminated + <-c.done + close(c.done) +} + +func (c *TzspSniffer) Run() { + c.LogInfo("run terminated") + c.done <- true +} diff --git a/config.yml b/config.yml index 564ed653..16e1209c 100644 --- a/config.yml +++ b/config.yml @@ -183,6 +183,16 @@ multiplexer: # # private key server file # key-file: "" +# # ztsp +# ztsp: +# # listen on ip +# listen-ip: 0.0.0.0 +# listen-port: 10000 +# # drop all queries +# drop-queries: false +# # drop all replies +# drop-replies: false + ################################################ # list of supported loggers ################################################ diff --git a/dnscollector.go b/dnscollector.go index aa8e2e69..d9e0de93 100644 --- a/dnscollector.go +++ b/dnscollector.go @@ -202,6 +202,9 @@ func main() { if subcfg.Collectors.FileIngestor.Enable && IsCollectorRouted(config, input.Name) { mapCollectors[input.Name] = collectors.NewFileIngestor(nil, subcfg, logger, input.Name) } + if subcfg.Collectors.Tzsp.Enable { + mapCollectors[input.Name] = collectors.NewTzsp(nil, subcfg, logger, input.Name) + } } // here the multiplexer logic diff --git a/dnsutils/config.go b/dnsutils/config.go index 5e751b56..6d6fc200 100644 --- a/dnsutils/config.go +++ b/dnsutils/config.go @@ -195,6 +195,15 @@ type Config struct { PcapDnsPort int `yaml:"pcap-dns-port"` DeleteAfter bool `yaml:"delete-after"` } `yaml:"file-ingestor"` + Tzsp struct { + Enable bool `yaml:"enable"` + ListenIp string `yaml:"listen-ip"` + ListenPort int `yaml:"listen-port"` + DropQueries bool `yaml:"drop-queries"` + DropReplies bool `yaml:"drop-replies"` + CacheSupport bool `yaml:"cache-support"` + QueryTimeout int `yaml:"query-timeout"` + } } `yaml:"collectors"` IngoingTransformers ConfigTransformers `yaml:"ingoing-transformers"` @@ -412,6 +421,14 @@ func (c *Config) SetDefault() { c.Collectors.FileIngestor.WatchMode = MODE_PCAP c.Collectors.FileIngestor.DeleteAfter = false + c.Collectors.Tzsp.Enable = false + c.Collectors.Tzsp.ListenIp = ANY_IP + c.Collectors.Tzsp.ListenPort = 10000 + c.Collectors.Tzsp.DropQueries = false + c.Collectors.Tzsp.DropReplies = false + c.Collectors.Tzsp.QueryTimeout = 5 + c.Collectors.Tzsp.CacheSupport = true + // Transformers for collectors c.IngoingTransformers.SetDefault() diff --git a/doc/collectors.md b/doc/collectors.md index 28b042f5..33a3fb59 100644 --- a/doc/collectors.md +++ b/doc/collectors.md @@ -205,3 +205,66 @@ file-ingestor: pcap-dns-port: 53 delete-after: false ``` + +### TZSP + +This collector receives TZSP packets that contain a full DNS packet, meaning Ethernet, IPv4/IPv6, UDP, then DNS. +Its primary purpose is to suppport DNS packet capture from Mikrotik brand devices. These devices allow cloning of packets and sending them via TZSP to remote hosts. + +Options: +- `listen-ip`: (string) listen on ip +- `listen-port`: (integer) listening on port +- `drop-queries`: (boolean) drop all queries +- `drop-replies`: (boolean) drop all 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 + +Default values: + +```yaml +tzsp: + listen-ip: "0.0.0.0" + listen-port: 10000 + drop-queries: false + drop-replies: false + cache-support: true + query-timeout: 5 +``` + +Example rules for Mikrotik brand devices to send the traffic (only works if routed or the device serves as DNS server). +```routeros +/ipv6 firewall mangle +add action=sniff-tzsp chain=prerouting comment="Sniff DNS (TCP)" dst-port=53 \ + protocol=tcp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=prerouting comment="Sniff DNS (TCP)" src-port=53 \ + protocol=tcp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=prerouting comment="Sniff DNS (UDP)" dst-port=53 \ + protocol=udp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=prerouting comment="Sniff DNS (UDP)" src-port=53 \ + protocol=udp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=output comment="Sniff DNS (TCP)" dst-port=53 \ + protocol=tcp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=output comment="Sniff DNS (TCP)" src-port=53 \ + protocol=tcp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=output comment="Sniff DNS (UDP)" dst-port=53 \ + protocol=udp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=output comment="Sniff DNS (UDP)" src-port=53 \ + protocol=udp sniff-target=10.0.10.2 sniff-target-port=10000 +/ip firewall mangle +add action=sniff-tzsp chain=prerouting comment="Sniff DNS (TCP)" dst-port=53 \ + protocol=tcp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=prerouting comment="Sniff DNS (TCP)" src-port=53 \ + protocol=tcp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=prerouting comment="Sniff DNS (UDP)" dst-port=53 \ + protocol=udp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=prerouting comment="Sniff DNS (UDP)" src-port=53 \ + protocol=udp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=output comment="Sniff DNS (TCP)" dst-port=53 \ + protocol=tcp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=output comment="Sniff DNS (TCP)" src-port=53 \ + protocol=tcp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=output comment="Sniff DNS (UDP)" dst-port=53 \ + protocol=udp sniff-target=10.0.10.2 sniff-target-port=10000 +add action=sniff-tzsp chain=output comment="Sniff DNS (UDP)" src-port=53 \ + protocol=udp sniff-target=10.0.10.2 sniff-target-port=10000 +``` diff --git a/example-config/use-case-12.yml b/example-config/use-case-12.yml index a0cfe685..b4997c3a 100644 --- a/example-config/use-case-12.yml +++ b/example-config/use-case-12.yml @@ -1,7 +1,7 @@ # Example 12: Relays DNStap stream to multiple listeners without decoding it. # -# As prerequisites, we assume you have -# - a DNS server which supports DNSTap (unbound, bind, powerdns, etc) for more informations about dnstap, +# As prerequisites, we assume you have +# - a DNS server which supports DNSTap (unbound, bind, powerdns, etc) for more informations about dnstap, # read the following page: https://dmachard.github.io/posts/0001-dnstap-testing/ # If turned on, debug messages are printed in the standard output diff --git a/example-config/use-case-15.yml b/example-config/use-case-15.yml index 3e1efdfc..5533ee7a 100644 --- a/example-config/use-case-15.yml +++ b/example-config/use-case-15.yml @@ -10,7 +10,7 @@ multiplexer: collectors: - name: pcap file-ingestor: - watch-dir: /home/denis/Lab/pcap/ + watch-dir: /home/pcap/ watch-mode: pcap transforms: normalize: @@ -24,4 +24,4 @@ multiplexer: routes: - from: [ pcap ] - to: [ console ] + to: [ console ] \ No newline at end of file diff --git a/example-config/use-case-17.yml b/example-config/use-case-17.yml new file mode 100644 index 00000000..c112e5a5 --- /dev/null +++ b/example-config/use-case-17.yml @@ -0,0 +1,29 @@ +# Example 15: Capture TZSP packets containing DNS packets and process them as json +# +# As prerequisites, we assume you have +# - a Mikrotik brand device that routes DNS packets and can use the "tzsp" Action in the firewall +# or firewall6 mangle table. + + +# If turned on, debug messages are printed in the standard output +global: + trace: + verbose: true + +multiplexer: + collectors: + - name: tzsp + tzsp: + enable: true + listen-ip: "0.0.0.0" + listen-port: 10000 + + # Redirect output to the console + loggers: + - name: console + stdout: + mode: json + + routes: + - from: [ tzsp ] + to: [ console ] diff --git a/go.mod b/go.mod index d14bf9b5..53865b28 100644 --- a/go.mod +++ b/go.mod @@ -32,6 +32,8 @@ require ( ) require ( + github.com/farsightsec/golang-framestream v0.3.0 // indirect + github.com/rs/tzsp v0.0.0-20161230003637-8ce729c826b9 // indirect go4.org/intern v0.0.0-20211027215823-ae77deb06f29 // indirect go4.org/unsafe/assume-no-moving-gc v0.0.0-20230204201903-c31fa085b70e // indirect ) diff --git a/go.sum b/go.sum index b928690b..42e8e740 100644 --- a/go.sum +++ b/go.sum @@ -1144,6 +1144,8 @@ github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6po github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.8.0/go.mod h1:EBwu+T5AvHOcXwvZIkQFjUN6s8Czyqw12GL/Y0tUyRM= +github.com/rs/tzsp v0.0.0-20161230003637-8ce729c826b9 h1:upQjqUCvtoYMwHSXn0eGc1lsVJpEi90u3oMjmLKa9ac= +github.com/rs/tzsp v0.0.0-20161230003637-8ce729c826b9/go.mod h1:pFz3aQBXB8wqK0Mnt7iOEgcrpRHgpP+1xNnOy7Ok1Bw= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=