1
0
Fork 0

Adding upstream version 1.34.4.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-24 07:26:29 +02:00
parent e393c3af3f
commit 4978089aab
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
4963 changed files with 677545 additions and 0 deletions

View file

@ -0,0 +1,194 @@
# Suricata Input Plugin
This plugin reports internal performance counters of the Suricata IDS/IPS
engine, such as captured traffic volume, memory usage, uptime, flow counters,
and much more. It provides a socket for the Suricata log output to write JSON
stats output to, and processes the incoming data to fit Telegraf's format.
It can also report for triggered Suricata IDS/IPS alerts.
## Service Input <!-- @/docs/includes/service_input.md -->
This plugin is a service input. Normal plugins gather metrics determined by the
interval setting. Service plugins start a service to listen and wait for
metrics or events to occur. Service plugins have two key differences from
normal plugins:
1. The global or plugin specific `interval` setting may not apply
2. The CLI options of `--test`, `--test-wait`, and `--once` may not produce
output for this plugin
## Global configuration options <!-- @/docs/includes/plugin_config.md -->
In addition to the plugin-specific configuration settings, plugins support
additional global and plugin configuration settings. These settings are used to
modify metrics, tags, and field or create aliases and configure ordering, etc.
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins
## Configuration
```toml @sample.conf
# Suricata stats and alerts plugin
[[inputs.suricata]]
## Source
## Data sink for Suricata stats log. This is expected to be a filename of a
## unix socket to be created for listening.
# source = "/var/run/suricata-stats.sock"
## Delimiter
## Used for flattening field keys, e.g. subitem "alert" of "detect" becomes
## "detect_alert" when delimiter is "_".
# delimiter = "_"
## Metric version
## Version 1 only collects stats and optionally will look for alerts if
## the configuration setting alerts is set to true.
## Version 2 parses any event type message by default and produced metrics
## under a single metric name using a tag to differentiate between event
## types. The timestamp for the message is applied to the generated metric.
## Additional tags and fields are included as well.
# version = "1"
## Alerts
## In metric version 1, only status is captured by default, alerts must be
## turned on with this configuration option. This option does not apply for
## metric version 2.
# alerts = false
```
## Metrics
Fields in the 'suricata' measurement follow the JSON format used by Suricata's
stats output.
See <http://suricata.readthedocs.io/en/latest/performance/statistics.html> for
more information.
All fields for Suricata stats are numeric.
- suricata
- tags:
- thread: `Global` for global statistics (if enabled), thread IDs (e.g. `W#03-enp0s31f6`) for thread-specific statistics
- fields:
- app_layer_flow_dcerpc_udp
- app_layer_flow_dns_tcp
- app_layer_flow_dns_udp
- app_layer_flow_enip_udp
- app_layer_flow_failed_tcp
- app_layer_flow_failed_udp
- app_layer_flow_http
- app_layer_flow_ssh
- app_layer_flow_tls
- app_layer_tx_dns_tcp
- app_layer_tx_dns_udp
- app_layer_tx_enip_udp
- app_layer_tx_http
- app_layer_tx_smtp
- capture_kernel_drops
- capture_kernel_packets
- decoder_avg_pkt_size
- decoder_bytes
- decoder_ethernet
- decoder_gre
- decoder_icmpv4
- decoder_icmpv4_ipv4_unknown_ver
- decoder_icmpv6
- decoder_invalid
- decoder_ipv4
- decoder_ipv6
- decoder_max_pkt_size
- decoder_pkts
- decoder_tcp
- decoder_tcp_hlen_too_small
- decoder_tcp_invalid_optlen
- decoder_teredo
- decoder_udp
- decoder_vlan
- detect_alert
- dns_memcap_global
- dns_memuse
- flow_memuse
- flow_mgr_closed_pruned
- flow_mgr_est_pruned
- flow_mgr_flows_checked
- flow_mgr_flows_notimeout
- flow_mgr_flows_removed
- flow_mgr_flows_timeout
- flow_mgr_flows_timeout_inuse
- flow_mgr_new_pruned
- flow_mgr_rows_checked
- flow_mgr_rows_empty
- flow_mgr_rows_maxlen
- flow_mgr_rows_skipped
- flow_spare
- flow_tcp_reuse
- http_memuse
- tcp_memuse
- tcp_pseudo
- tcp_reassembly_gap
- tcp_reassembly_memuse
- tcp_rst
- tcp_sessions
- tcp_syn
- tcp_synack
- ...
Some fields of the Suricata alerts are strings, for example the signatures. See
the Suricata [event docs][1] for more information.
- suricata_alert
- fields:
- action
- gid
- severity
- signature
- source_ip
- source_port
- target_port
- target_port
- ...
[1]: https://suricata.readthedocs.io/en/suricata-6.0.0/output/eve/eve-json-format.html?highlight=priority#event-type-alert
### Suricata configuration
Suricata needs to deliver the 'stats' event type to a given unix socket for
this plugin to pick up. This can be done, for example, by creating an additional
output in the Suricata configuration file:
```yaml
- eve-log:
enabled: yes
filetype: unix_stream
filename: /tmp/suricata-stats.sock
types:
- stats:
threads: yes
```
### FreeBSD tuning
Under FreeBSD it is necessary to increase the localhost buffer space to at least
16384, default is 8192 otherwise messages from Suricata are truncated as they
exceed the default available buffer space, consequently no statistics are
processed by the plugin.
```text
sysctl -w net.local.stream.recvspace=16384
sysctl -w net.local.stream.sendspace=16384
```
## Example Output
```text
suricata,host=myhost,thread=FM#01 flow_mgr_rows_empty=0,flow_mgr_rows_checked=65536,flow_mgr_closed_pruned=0,flow_emerg_mode_over=0,flow_mgr_flows_timeout_inuse=0,flow_mgr_rows_skipped=65535,flow_mgr_bypassed_pruned=0,flow_mgr_flows_removed=0,flow_mgr_est_pruned=0,flow_mgr_flows_notimeout=1,flow_mgr_flows_checked=1,flow_mgr_rows_busy=0,flow_spare=10000,flow_mgr_rows_maxlen=1,flow_mgr_new_pruned=0,flow_emerg_mode_entered=0,flow_tcp_reuse=0,flow_mgr_flows_timeout=0 1568368562545197545
suricata,host=myhost,thread=W#04-wlp4s0 decoder_ltnull_pkt_too_small=0,decoder_ipraw_invalid_ip_version=0,defrag_ipv4_reassembled=0,tcp_no_flow=0,app_layer_flow_tls=1,decoder_udp=25,defrag_ipv6_fragments=0,defrag_ipv4_fragments=0,decoder_tcp=59,decoder_vlan=0,decoder_pkts=84,decoder_vlan_qinq=0,decoder_avg_pkt_size=574,flow_memcap=0,defrag_max_frag_hits=0,tcp_ssn_memcap_drop=0,capture_kernel_packets=84,app_layer_flow_dcerpc_udp=0,app_layer_tx_dns_tcp=0,tcp_rst=0,decoder_icmpv4=0,app_layer_tx_tls=0,decoder_ipv4=84,decoder_erspan=0,decoder_ltnull_unsupported_type=0,decoder_invalid=0,app_layer_flow_ssh=0,capture_kernel_drops=0,app_layer_flow_ftp=0,app_layer_tx_http=0,tcp_pseudo_failed=0,defrag_ipv6_reassembled=0,defrag_ipv6_timeouts=0,tcp_pseudo=0,tcp_sessions=1,decoder_ethernet=84,decoder_raw=0,decoder_sctp=0,app_layer_flow_dns_udp=1,decoder_gre=0,app_layer_flow_http=0,app_layer_flow_imap=0,tcp_segment_memcap_drop=0,detect_alert=0,app_layer_flow_failed_tcp=0,decoder_teredo=0,decoder_mpls=0,decoder_ppp=0,decoder_max_pkt_size=1422,decoder_ipv6=0,tcp_reassembly_gap=0,app_layer_flow_dcerpc_tcp=0,decoder_ipv4_in_ipv6=0,tcp_stream_depth_reached=0,app_layer_flow_dns_tcp=0,app_layer_flow_smtp=0,tcp_syn=1,decoder_sll=0,tcp_invalid_checksum=0,app_layer_tx_dns_udp=1,decoder_bytes=48258,defrag_ipv4_timeouts=0,app_layer_flow_msn=0,decoder_pppoe=0,decoder_null=0,app_layer_flow_failed_udp=3,app_layer_tx_smtp=0,decoder_icmpv6=0,decoder_ipv6_in_ipv6=0,tcp_synack=1,app_layer_flow_smb=0,decoder_dce_pkt_too_small=0 1568368562545174807
suricata,host=myhost,thread=W#01-wlp4s0 tcp_synack=0,app_layer_flow_imap=0,decoder_ipv4_in_ipv6=0,decoder_max_pkt_size=684,decoder_gre=0,defrag_ipv4_timeouts=0,tcp_invalid_checksum=0,decoder_ipv4=53,flow_memcap=0,app_layer_tx_http=0,app_layer_tx_smtp=0,decoder_null=0,tcp_no_flow=0,app_layer_tx_tls=0,app_layer_flow_ssh=0,app_layer_flow_smtp=0,decoder_pppoe=0,decoder_teredo=0,decoder_ipraw_invalid_ip_version=0,decoder_ltnull_pkt_too_small=0,tcp_rst=0,decoder_ppp=0,decoder_ipv6=29,app_layer_flow_dns_udp=3,decoder_vlan=0,app_layer_flow_dcerpc_tcp=0,tcp_syn=0,defrag_ipv4_fragments=0,defrag_ipv6_timeouts=0,decoder_raw=0,defrag_ipv6_reassembled=0,tcp_reassembly_gap=0,tcp_sessions=0,decoder_udp=44,tcp_segment_memcap_drop=0,app_layer_tx_dns_udp=3,app_layer_flow_tls=0,decoder_tcp=37,defrag_ipv4_reassembled=0,app_layer_flow_failed_udp=6,app_layer_flow_ftp=0,decoder_icmpv6=1,tcp_stream_depth_reached=0,capture_kernel_drops=0,decoder_sll=0,decoder_bytes=15883,decoder_ethernet=91,tcp_pseudo=0,app_layer_flow_http=0,decoder_sctp=0,decoder_pkts=91,decoder_avg_pkt_size=174,decoder_erspan=0,app_layer_flow_msn=0,app_layer_flow_smb=0,capture_kernel_packets=91,decoder_icmpv4=0,decoder_ipv6_in_ipv6=0,tcp_ssn_memcap_drop=0,decoder_vlan_qinq=0,decoder_ltnull_unsupported_type=0,decoder_invalid=0,defrag_max_frag_hits=0,tcp_pseudo_failed=0,detect_alert=0,app_layer_tx_dns_tcp=0,app_layer_flow_failed_tcp=0,app_layer_flow_dcerpc_udp=0,app_layer_flow_dns_tcp=0,defrag_ipv6_fragments=0,decoder_mpls=0,decoder_dce_pkt_too_small=0 1568368562545148438
suricata,host=myhost flow_memuse=7094464,tcp_memuse=3276800,tcp_reassembly_memuse=12332832,dns_memuse=0,dns_memcap_state=0,dns_memcap_global=0,http_memuse=0,http_memcap=0 1568368562545144569
suricata,host=myhost,thread=W#07-wlp4s0 app_layer_tx_http=0,app_layer_tx_dns_tcp=0,decoder_vlan=0,decoder_pppoe=0,decoder_sll=0,decoder_tcp=0,flow_memcap=0,app_layer_flow_msn=0,tcp_no_flow=0,tcp_rst=0,tcp_segment_memcap_drop=0,tcp_sessions=0,detect_alert=0,defrag_ipv6_reassembled=0,decoder_ipraw_invalid_ip_version=0,decoder_erspan=0,decoder_icmpv4=0,app_layer_tx_dns_udp=2,decoder_ltnull_pkt_too_small=0,decoder_bytes=1998,decoder_ipv6=1,defrag_ipv4_fragments=0,defrag_ipv6_fragments=0,app_layer_tx_smtp=0,decoder_ltnull_unsupported_type=0,decoder_max_pkt_size=342,app_layer_flow_ftp=0,decoder_ipv6_in_ipv6=0,defrag_ipv4_reassembled=0,defrag_ipv6_timeouts=0,app_layer_flow_dns_tcp=0,decoder_avg_pkt_size=181,defrag_ipv4_timeouts=0,tcp_stream_depth_reached=0,decoder_mpls=0,app_layer_flow_dns_udp=2,tcp_ssn_memcap_drop=0,app_layer_flow_dcerpc_tcp=0,app_layer_flow_failed_udp=2,app_layer_flow_smb=0,app_layer_flow_failed_tcp=0,decoder_invalid=0,decoder_null=0,decoder_gre=0,decoder_ethernet=11,app_layer_flow_ssh=0,defrag_max_frag_hits=0,capture_kernel_drops=0,tcp_pseudo_failed=0,app_layer_flow_smtp=0,decoder_udp=10,decoder_sctp=0,decoder_teredo=0,decoder_icmpv6=1,tcp_pseudo=0,tcp_synack=0,app_layer_tx_tls=0,app_layer_flow_imap=0,capture_kernel_packets=11,decoder_pkts=11,decoder_raw=0,decoder_ppp=0,tcp_syn=0,tcp_invalid_checksum=0,app_layer_flow_tls=0,decoder_ipv4_in_ipv6=0,app_layer_flow_http=0,decoder_dce_pkt_too_small=0,decoder_ipv4=10,decoder_vlan_qinq=0,tcp_reassembly_gap=0,app_layer_flow_dcerpc_udp=0 1568368562545110847
suricata,host=myhost,thread=W#06-wlp4s0 app_layer_tx_smtp=0,decoder_ipv6_in_ipv6=0,decoder_dce_pkt_too_small=0,tcp_segment_memcap_drop=0,tcp_sessions=1,decoder_ppp=0,tcp_pseudo_failed=0,app_layer_tx_dns_tcp=0,decoder_invalid=0,defrag_ipv4_timeouts=0,app_layer_flow_smb=0,app_layer_flow_ssh=0,decoder_bytes=19407,decoder_null=0,app_layer_flow_tls=1,decoder_avg_pkt_size=473,decoder_pkts=41,decoder_pppoe=0,decoder_tcp=32,defrag_ipv4_reassembled=0,tcp_reassembly_gap=0,decoder_raw=0,flow_memcap=0,defrag_ipv6_timeouts=0,app_layer_flow_smtp=0,app_layer_tx_http=0,decoder_sll=0,decoder_udp=8,decoder_ltnull_pkt_too_small=0,decoder_ltnull_unsupported_type=0,decoder_ipv4_in_ipv6=0,decoder_vlan=0,decoder_max_pkt_size=1422,tcp_no_flow=0,app_layer_flow_failed_tcp=0,app_layer_flow_dns_tcp=0,app_layer_flow_ftp=0,decoder_icmpv4=0,defrag_max_frag_hits=0,tcp_rst=0,app_layer_flow_msn=0,app_layer_flow_failed_udp=2,app_layer_flow_dns_udp=0,app_layer_flow_dcerpc_udp=0,decoder_ipv4=39,decoder_ethernet=41,defrag_ipv6_reassembled=0,tcp_ssn_memcap_drop=0,app_layer_tx_tls=0,decoder_gre=0,decoder_vlan_qinq=0,tcp_pseudo=0,app_layer_flow_imap=0,app_layer_flow_dcerpc_tcp=0,defrag_ipv4_fragments=0,defrag_ipv6_fragments=0,tcp_synack=1,app_layer_flow_http=0,app_layer_tx_dns_udp=0,capture_kernel_packets=41,decoder_ipv6=2,tcp_invalid_checksum=0,tcp_stream_depth_reached=0,decoder_ipraw_invalid_ip_version=0,decoder_icmpv6=1,tcp_syn=1,detect_alert=0,capture_kernel_drops=0,decoder_teredo=0,decoder_erspan=0,decoder_sctp=0,decoder_mpls=0 1568368562545084670
suricata,host=myhost,thread=W#02-wlp4s0 decoder_tcp=53,tcp_rst=3,tcp_reassembly_gap=0,defrag_ipv6_timeouts=0,tcp_ssn_memcap_drop=0,app_layer_flow_dcerpc_tcp=0,decoder_max_pkt_size=1422,decoder_ipv6_in_ipv6=0,tcp_no_flow=0,app_layer_flow_ftp=0,app_layer_flow_ssh=0,decoder_pkts=82,decoder_sctp=0,tcp_invalid_checksum=0,app_layer_flow_dns_tcp=0,decoder_ipraw_invalid_ip_version=0,decoder_bytes=26441,decoder_erspan=0,tcp_pseudo_failed=0,tcp_syn=1,app_layer_tx_http=0,app_layer_tx_smtp=0,decoder_teredo=0,decoder_ipv4=80,defrag_ipv4_fragments=0,tcp_stream_depth_reached=0,app_layer_flow_smb=0,capture_kernel_packets=82,decoder_null=0,decoder_ltnull_pkt_too_small=0,decoder_ppp=0,decoder_icmpv6=1,app_layer_flow_dns_udp=2,app_layer_flow_http=0,app_layer_tx_dns_udp=3,decoder_mpls=0,decoder_sll=0,defrag_ipv4_reassembled=0,tcp_segment_memcap_drop=0,app_layer_flow_imap=0,decoder_ltnull_unsupported_type=0,decoder_icmpv4=0,decoder_raw=0,defrag_ipv4_timeouts=0,app_layer_flow_failed_udp=8,decoder_gre=0,capture_kernel_drops=0,defrag_ipv6_reassembled=0,tcp_pseudo=0,app_layer_flow_tls=1,decoder_avg_pkt_size=322,decoder_dce_pkt_too_small=0,decoder_ethernet=82,defrag_ipv6_fragments=0,tcp_sessions=1,tcp_synack=1,app_layer_tx_dns_tcp=0,decoder_vlan=0,flow_memcap=0,decoder_vlan_qinq=0,decoder_udp=28,decoder_invalid=0,detect_alert=0,app_layer_flow_failed_tcp=0,app_layer_tx_tls=0,decoder_pppoe=0,decoder_ipv6=2,decoder_ipv4_in_ipv6=0,defrag_max_frag_hits=0,app_layer_flow_dcerpc_udp=0,app_layer_flow_smtp=0,app_layer_flow_msn=0 1568368562545061864
suricata,host=myhost,thread=W#08-wlp4s0 decoder_dce_pkt_too_small=0,app_layer_tx_dns_tcp=0,decoder_pkts=58,decoder_ppp=0,decoder_raw=0,decoder_ipv4_in_ipv6=0,decoder_max_pkt_size=1392,tcp_invalid_checksum=0,tcp_syn=0,decoder_ipv4=51,decoder_ipv6_in_ipv6=0,decoder_tcp=0,decoder_ltnull_pkt_too_small=0,flow_memcap=0,decoder_udp=58,tcp_ssn_memcap_drop=0,tcp_pseudo=0,app_layer_flow_dcerpc_udp=0,app_layer_flow_dns_udp=5,app_layer_tx_http=0,capture_kernel_drops=0,decoder_vlan=0,tcp_segment_memcap_drop=0,app_layer_flow_ftp=0,app_layer_flow_imap=0,app_layer_flow_http=0,app_layer_flow_tls=0,decoder_icmpv4=0,decoder_sctp=0,defrag_ipv4_timeouts=0,tcp_reassembly_gap=0,detect_alert=0,decoder_ethernet=58,tcp_pseudo_failed=0,decoder_teredo=0,defrag_ipv4_reassembled=0,tcp_sessions=0,app_layer_flow_msn=0,decoder_ipraw_invalid_ip_version=0,tcp_no_flow=0,app_layer_flow_dns_tcp=0,decoder_null=0,defrag_ipv4_fragments=0,app_layer_flow_dcerpc_tcp=0,app_layer_flow_failed_udp=8,app_layer_tx_tls=0,decoder_bytes=15800,decoder_ipv6=7,tcp_stream_depth_reached=0,decoder_invalid=0,decoder_ltnull_unsupported_type=0,app_layer_tx_dns_udp=6,decoder_pppoe=0,decoder_avg_pkt_size=272,decoder_erspan=0,defrag_ipv6_timeouts=0,app_layer_flow_failed_tcp=0,decoder_gre=0,decoder_sll=0,defrag_max_frag_hits=0,app_layer_flow_ssh=0,capture_kernel_packets=58,decoder_mpls=0,decoder_vlan_qinq=0,tcp_rst=0,app_layer_flow_smb=0,app_layer_tx_smtp=0,decoder_icmpv6=0,defrag_ipv6_fragments=0,defrag_ipv6_reassembled=0,tcp_synack=0,app_layer_flow_smtp=0 1568368562545035575
suricata,host=myhost,thread=W#05-wlp4s0 tcp_reassembly_gap=0,capture_kernel_drops=0,decoder_ltnull_unsupported_type=0,tcp_sessions=0,tcp_stream_depth_reached=0,tcp_pseudo_failed=0,app_layer_flow_failed_tcp=0,app_layer_tx_dns_tcp=0,decoder_null=0,decoder_dce_pkt_too_small=0,decoder_udp=7,tcp_rst=3,app_layer_flow_dns_tcp=0,decoder_invalid=0,defrag_ipv4_reassembled=0,tcp_synack=0,app_layer_flow_ftp=0,decoder_bytes=3117,decoder_pppoe=0,app_layer_flow_dcerpc_tcp=0,app_layer_flow_smb=0,decoder_ipv6_in_ipv6=0,decoder_ipraw_invalid_ip_version=0,app_layer_flow_imap=0,app_layer_tx_dns_udp=2,decoder_ppp=0,decoder_ipv4=21,decoder_tcp=14,flow_memcap=0,tcp_syn=0,tcp_invalid_checksum=0,decoder_teredo=0,decoder_ltnull_pkt_too_small=0,defrag_max_frag_hits=0,app_layer_tx_tls=0,decoder_pkts=24,decoder_sll=0,defrag_ipv6_fragments=0,app_layer_flow_dcerpc_udp=0,app_layer_flow_smtp=0,decoder_icmpv6=3,defrag_ipv6_timeouts=0,decoder_ipv6=3,decoder_raw=0,defrag_ipv6_reassembled=0,tcp_no_flow=0,detect_alert=0,app_layer_flow_tls=0,decoder_ethernet=24,decoder_vlan=0,decoder_icmpv4=0,decoder_ipv4_in_ipv6=0,app_layer_flow_failed_udp=1,decoder_mpls=0,decoder_max_pkt_size=653,decoder_sctp=0,defrag_ipv4_timeouts=0,tcp_ssn_memcap_drop=0,app_layer_flow_dns_udp=1,app_layer_tx_smtp=0,capture_kernel_packets=24,decoder_vlan_qinq=0,decoder_gre=0,app_layer_flow_ssh=0,app_layer_flow_msn=0,defrag_ipv4_fragments=0,app_layer_flow_http=0,tcp_segment_memcap_drop=0,tcp_pseudo=0,app_layer_tx_http=0,decoder_erspan=0,decoder_avg_pkt_size=129 1568368562545009684
suricata,host=myhost,thread=W#03-wlp4s0 app_layer_flow_failed_tcp=0,decoder_teredo=0,decoder_ipv6_in_ipv6=0,tcp_pseudo_failed=0,tcp_stream_depth_reached=0,tcp_syn=0,decoder_gre=0,tcp_segment_memcap_drop=0,tcp_ssn_memcap_drop=0,app_layer_tx_smtp=0,decoder_raw=0,decoder_ltnull_pkt_too_small=0,tcp_sessions=0,tcp_reassembly_gap=0,app_layer_flow_ssh=0,app_layer_flow_imap=0,decoder_ipv4=463,decoder_ethernet=463,capture_kernel_packets=463,decoder_pppoe=0,defrag_ipv4_reassembled=0,app_layer_flow_tls=0,app_layer_flow_dcerpc_udp=0,app_layer_flow_dns_udp=0,decoder_vlan=0,decoder_ipraw_invalid_ip_version=0,decoder_mpls=0,tcp_no_flow=0,decoder_avg_pkt_size=445,decoder_udp=432,flow_memcap=0,app_layer_tx_dns_udp=0,app_layer_flow_msn=0,app_layer_flow_http=0,app_layer_flow_dcerpc_tcp=0,decoder_ipv6=0,decoder_ipv4_in_ipv6=0,defrag_ipv4_timeouts=0,defrag_ipv4_fragments=0,defrag_ipv6_timeouts=0,decoder_sctp=0,defrag_ipv6_fragments=0,app_layer_flow_dns_tcp=0,app_layer_tx_tls=0,defrag_max_frag_hits=0,decoder_bytes=206345,decoder_vlan_qinq=0,decoder_invalid=0,decoder_ppp=0,tcp_rst=0,detect_alert=0,capture_kernel_drops=0,app_layer_flow_failed_udp=4,decoder_null=0,decoder_icmpv4=0,decoder_icmpv6=0,decoder_ltnull_unsupported_type=0,defrag_ipv6_reassembled=0,tcp_invalid_checksum=0,tcp_synack=0,decoder_tcp=31,tcp_pseudo=0,app_layer_flow_smb=0,app_layer_flow_smtp=0,decoder_max_pkt_size=1463,decoder_dce_pkt_too_small=0,app_layer_tx_http=0,decoder_pkts=463,decoder_sll=0,app_layer_flow_ftp=0,app_layer_tx_dns_tcp=0,decoder_erspan=0 1568368562544966078
```

View file

@ -0,0 +1,26 @@
# Suricata stats and alerts plugin
[[inputs.suricata]]
## Source
## Data sink for Suricata stats log. This is expected to be a filename of a
## unix socket to be created for listening.
# source = "/var/run/suricata-stats.sock"
## Delimiter
## Used for flattening field keys, e.g. subitem "alert" of "detect" becomes
## "detect_alert" when delimiter is "_".
# delimiter = "_"
## Metric version
## Version 1 only collects stats and optionally will look for alerts if
## the configuration setting alerts is set to true.
## Version 2 parses any event type message by default and produced metrics
## under a single metric name using a tag to differentiate between event
## types. The timestamp for the message is applied to the generated metric.
## Additional tags and fields are included as well.
# version = "1"
## Alerts
## In metric version 1, only status is captured by default, alerts must be
## turned on with this configuration option. This option does not apply for
## metric version 2.
# alerts = false

View file

@ -0,0 +1,352 @@
//go:generate ../../../tools/readme_config_includer/generator
package suricata
import (
"bufio"
"context"
_ "embed"
"encoding/json"
"errors"
"fmt"
"io"
"net"
"strings"
"sync"
"time"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/internal"
"github.com/influxdata/telegraf/plugins/inputs"
)
//go:embed sample.conf
var sampleConfig string
const (
// inBufSize is the input buffer size for JSON received via socket.
// Set to 10MB, as depending on the number of threads the output might be
// large.
inBufSize = 10 * 1024 * 1024
)
type Suricata struct {
Source string `toml:"source"`
Delimiter string `toml:"delimiter"`
Alerts bool `toml:"alerts"`
Version string `toml:"version"`
inputListener *net.UnixListener
cancel context.CancelFunc
Log telegraf.Logger `toml:"-"`
wg sync.WaitGroup
}
func (*Suricata) SampleConfig() string {
return sampleConfig
}
func (s *Suricata) Init() error {
if s.Source == "" {
s.Source = "/var/run/suricata-stats.sock"
}
if s.Delimiter == "" {
s.Delimiter = "_"
}
switch s.Version {
case "":
s.Version = "1"
case "1", "2":
default:
return fmt.Errorf("invalid version %q, use either 1 or 2", s.Version)
}
return nil
}
// Start initiates background collection of JSON data from the socket provided to Suricata.
func (s *Suricata) Start(acc telegraf.Accumulator) error {
var err error
s.inputListener, err = net.ListenUnix("unix", &net.UnixAddr{
Name: s.Source,
Net: "unix",
})
if err != nil {
return err
}
ctx, cancel := context.WithCancel(context.Background())
s.cancel = cancel
s.inputListener.SetUnlinkOnClose(true)
s.wg.Add(1)
go func() {
defer s.wg.Done()
go s.handleServerConnection(ctx, acc)
}()
return nil
}
// Gather measures and submits one full set of telemetry to Telegraf.
// Not used here, submission is completely input-driven.
func (*Suricata) Gather(telegraf.Accumulator) error {
return nil
}
// Stop causes the plugin to cease collecting JSON data from the socket provided to Suricata.
func (s *Suricata) Stop() {
s.inputListener.Close()
if s.cancel != nil {
s.cancel()
}
s.wg.Wait()
}
func (s *Suricata) readInput(ctx context.Context, acc telegraf.Accumulator, conn net.Conn) error {
reader := bufio.NewReaderSize(conn, inBufSize)
for {
select {
case <-ctx.Done():
return nil
default:
line, rerr := reader.ReadBytes('\n')
if rerr != nil {
return rerr
}
if len(line) > 0 {
err := s.parse(acc, line)
if err != nil {
acc.AddError(err)
}
}
}
}
}
func (s *Suricata) handleServerConnection(ctx context.Context, acc telegraf.Accumulator) {
var err error
for {
select {
case <-ctx.Done():
return
default:
var conn net.Conn
conn, err = s.inputListener.Accept()
if err != nil {
if !strings.HasSuffix(err.Error(), ": use of closed network connection") {
acc.AddError(err)
}
continue
}
err = s.readInput(ctx, acc, conn)
// we want to handle EOF as an opportunity to wait for a new
// connection -- this could, for example, happen when Suricata is
// restarted while Telegraf is running.
if !errors.Is(err, io.EOF) {
acc.AddError(err)
return
}
}
}
}
func flexFlatten(outmap map[string]interface{}, field string, v interface{}, delimiter string) error {
switch t := v.(type) {
case map[string]interface{}:
for k, v := range t {
var err error
if field == "" {
err = flexFlatten(outmap, k, v, delimiter)
} else {
err = flexFlatten(outmap, fmt.Sprintf("%s%s%s", field, delimiter, k), v, delimiter)
}
if err != nil {
return err
}
}
case []interface{}:
for _, v := range t {
err := flexFlatten(outmap, field, v, delimiter)
if err != nil {
return err
}
}
case string:
outmap[field] = v
case float64:
outmap[field] = t
default:
return fmt.Errorf("unsupported type %T encountered", t)
}
return nil
}
func (s *Suricata) parseAlert(acc telegraf.Accumulator, result map[string]interface{}) {
if _, ok := result["alert"].(map[string]interface{}); !ok {
s.Log.Debug("'alert' sub-object does not have required structure")
return
}
totalmap := make(map[string]interface{})
for k, v := range result["alert"].(map[string]interface{}) {
// source and target fields are maps
err := flexFlatten(totalmap, k, v, s.Delimiter)
if err != nil {
s.Log.Debugf("Flattening alert failed: %v", err)
// we skip this subitem as something did not parse correctly
continue
}
}
// threads field do not exist in alert output, always global
acc.AddFields("suricata_alert", totalmap, nil)
}
func (s *Suricata) parseStats(acc telegraf.Accumulator, result map[string]interface{}) {
if _, ok := result["stats"].(map[string]interface{}); !ok {
s.Log.Debug("The 'stats' sub-object does not have required structure")
return
}
fields := make(map[string]map[string]interface{})
totalmap := make(map[string]interface{})
for k, v := range result["stats"].(map[string]interface{}) {
if k == "threads" {
if v, ok := v.(map[string]interface{}); ok {
for k, t := range v {
outmap := make(map[string]interface{})
if threadStruct, ok := t.(map[string]interface{}); ok {
err := flexFlatten(outmap, "", threadStruct, s.Delimiter)
if err != nil {
s.Log.Debugf("Flattening alert failed: %v", err)
// we skip this thread as something did not parse correctly
continue
}
fields[k] = outmap
}
}
} else {
s.Log.Debug("The 'threads' sub-object does not have required structure")
}
} else {
err := flexFlatten(totalmap, k, v, s.Delimiter)
if err != nil {
s.Log.Debugf("Flattening alert failed: %v", err)
// we skip this subitem as something did not parse correctly
continue
}
}
}
fields["total"] = totalmap
for k := range fields {
if k == "Global" {
acc.AddFields("suricata", fields[k], nil)
} else {
acc.AddFields("suricata", fields[k], map[string]string{"thread": k})
}
}
}
func (s *Suricata) parseGeneric(acc telegraf.Accumulator, result map[string]interface{}) error {
eventType := ""
if _, ok := result["event_type"]; !ok {
return fmt.Errorf("unable to determine event type of message: %s", result)
}
value, err := internal.ToString(result["event_type"])
if err != nil {
return fmt.Errorf("unable to convert event type %q to string: %w", result["event_type"], err)
}
eventType = value
timestamp := time.Now()
if val, ok := result["timestamp"]; ok {
value, err := internal.ToString(val)
if err != nil {
return fmt.Errorf("unable to convert timestamp %q to string: %w", val, err)
}
timestamp, err = time.Parse("2006-01-02T15:04:05.999999-0700", value)
if err != nil {
return fmt.Errorf("unable to parse timestamp %q: %w", val, err)
}
}
// Make sure the event key exists first
if _, ok := result[eventType].(map[string]interface{}); !ok {
return fmt.Errorf("unable to find key %q in %s", eventType, result)
}
fields := make(map[string]interface{})
for k, v := range result[eventType].(map[string]interface{}) {
err := flexFlatten(fields, k, v, s.Delimiter)
if err != nil {
s.Log.Debugf("Flattening %q failed: %v", eventType, err)
continue
}
}
tags := map[string]string{
"event_type": eventType,
}
// best effort to gather these tags and fields, if errors are encountered
// we ignore and move on
for _, key := range []string{"proto", "out_iface", "in_iface"} {
if val, ok := result[key]; ok {
if convertedVal, err := internal.ToString(val); err == nil {
tags[key] = convertedVal
}
}
}
for _, key := range []string{"src_ip", "dest_ip"} {
if val, ok := result[key]; ok {
if convertedVal, err := internal.ToString(val); err == nil {
fields[key] = convertedVal
}
}
}
for _, key := range []string{"src_port", "dest_port"} {
if val, ok := result[key]; ok {
if convertedVal, err := internal.ToInt64(val); err == nil || errors.Is(err, internal.ErrOutOfRange) {
fields[key] = convertedVal
}
}
}
acc.AddFields("suricata", fields, tags, timestamp)
return nil
}
func (s *Suricata) parse(acc telegraf.Accumulator, sjson []byte) error {
// initial parsing
var result map[string]interface{}
err := json.Unmarshal(sjson, &result)
if err != nil {
return err
}
if s.Version == "2" {
return s.parseGeneric(acc, result)
}
// Version 1 parsing of stats and optionally alerts
if _, ok := result["stats"]; ok {
s.parseStats(acc, result)
} else if _, ok := result["alert"]; ok {
if s.Alerts {
s.parseAlert(acc, result)
}
} else {
s.Log.Debugf("Invalid input without 'stats' or 'alert' object: %v", result)
return errors.New("input does not contain 'stats' or 'alert' object")
}
return nil
}
func init() {
inputs.Add("suricata", func() telegraf.Input {
return &Suricata{}
})
}

View file

@ -0,0 +1,570 @@
package suricata
import (
"fmt"
"log"
"math/rand"
"net"
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/testutil"
)
var ex2 = `{"timestamp":"2017-03-06T07:43:39.000397+0000","event_type":"stats","stats":` +
`{"capture":{"kernel_packets":905344474,"kernel_drops":78355440,"kernel_packets_delta":2376742,"kernel_drops_delta":82049}}}`
var ex3 = `{"timestamp":"2017-03-06T07:43:39.000397+0000","event_type":"stats","stats":` +
`{"threads": { "W#05-wlp4s0": { "capture":{"kernel_packets":905344474,"kernel_drops":78355440}}}}}`
func TestSuricataLarge(t *testing.T) {
dir := t.TempDir()
tmpfn := filepath.Join(dir, fmt.Sprintf("t%d", rand.Int63()))
s := Suricata{
Source: tmpfn,
Delimiter: ".",
Alerts: true,
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
require.NoError(t, s.Start(&acc))
defer s.Stop()
data, err := os.ReadFile("testdata/test1.json")
require.NoError(t, err)
c, err := net.Dial("unix", tmpfn)
require.NoError(t, err)
_, err = c.Write(data)
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
// test suricata alerts
data2, err := os.ReadFile("testdata/test2.json")
require.NoError(t, err)
_, err = c.Write(data2)
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
require.NoError(t, c.Close())
acc.Wait(1)
}
func TestSuricataAlerts(t *testing.T) {
dir := t.TempDir()
tmpfn := filepath.Join(dir, fmt.Sprintf("t%d", rand.Int63()))
s := Suricata{
Source: tmpfn,
Delimiter: ".",
Alerts: true,
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
require.NoError(t, s.Start(&acc))
defer s.Stop()
data, err := os.ReadFile("testdata/test3.json")
require.NoError(t, err)
c, err := net.Dial("unix", tmpfn)
require.NoError(t, err)
_, err = c.Write(data)
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
require.NoError(t, c.Close())
acc.Wait(1)
expected := []telegraf.Metric{
testutil.MustMetric(
"suricata_alert",
map[string]string{},
map[string]interface{}{
"action": "allowed",
"category": "Misc activity",
"gid": float64(1),
"rev": float64(0),
"signature": "Corrupted HTTP body",
"signature_id": float64(6),
"severity": float64(3),
"source.ip": "10.0.0.5",
"target.ip": "179.60.192.3",
"source.port": float64(18715),
"target.port": float64(80),
},
time.Unix(0, 0),
),
}
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime())
}
func TestSuricata(t *testing.T) {
dir := t.TempDir()
tmpfn := filepath.Join(dir, fmt.Sprintf("t%d", rand.Int63()))
s := Suricata{
Source: tmpfn,
Delimiter: ".",
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
require.NoError(t, s.Start(&acc))
defer s.Stop()
c, err := net.Dial("unix", tmpfn)
require.NoError(t, err)
_, err = c.Write([]byte(ex2))
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
require.NoError(t, c.Close())
acc.Wait(1)
expected := []telegraf.Metric{
testutil.MustMetric(
"suricata",
map[string]string{
"thread": "total",
},
map[string]interface{}{
"capture.kernel_packets": float64(905344474),
"capture.kernel_drops": float64(78355440),
"capture.kernel_packets_delta": float64(2376742),
"capture.kernel_drops_delta": float64(82049),
},
time.Unix(0, 0),
),
}
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime())
}
func TestThreadStats(t *testing.T) {
dir := t.TempDir()
tmpfn := filepath.Join(dir, fmt.Sprintf("t%d", rand.Int63()))
s := Suricata{
Source: tmpfn,
Delimiter: ".",
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
require.NoError(t, s.Start(&acc))
defer s.Stop()
c, err := net.Dial("unix", tmpfn)
require.NoError(t, err)
_, err = c.Write([]byte(""))
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
_, err = c.Write([]byte("foobard}\n"))
require.NoError(t, err)
_, err = c.Write([]byte(ex3))
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
require.NoError(t, c.Close())
acc.Wait(2)
expected := []telegraf.Metric{
testutil.MustMetric(
"suricata",
map[string]string{
"thread": "W#05-wlp4s0",
},
map[string]interface{}{
"capture.kernel_packets": float64(905344474),
"capture.kernel_drops": float64(78355440),
},
time.Unix(0, 0),
),
}
testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime())
}
func TestSuricataInvalid(t *testing.T) {
dir := t.TempDir()
tmpfn := filepath.Join(dir, fmt.Sprintf("t%d", rand.Int63()))
s := Suricata{
Source: tmpfn,
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
acc.SetDebug(true)
require.NoError(t, s.Start(&acc))
defer s.Stop()
c, err := net.Dial("unix", tmpfn)
require.NoError(t, err)
_, err = c.Write([]byte("sfjiowef"))
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
require.NoError(t, c.Close())
acc.WaitError(1)
}
func TestSuricataInvalidPath(t *testing.T) {
tmpfn := fmt.Sprintf("/t%d/X", rand.Int63())
s := Suricata{
Source: tmpfn,
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
require.Error(t, s.Start(&acc))
}
func TestSuricataTooLongLine(t *testing.T) {
tmpfn := testutil.TempSocket(t)
s := Suricata{
Source: tmpfn,
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
require.NoError(t, s.Start(&acc))
defer s.Stop()
c, err := net.Dial("unix", tmpfn)
require.NoError(t, err)
_, err = c.Write([]byte(strings.Repeat("X", 20000000)))
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
require.NoError(t, c.Close())
acc.WaitError(1)
}
func TestSuricataEmptyJSON(t *testing.T) {
tmpfn := testutil.TempSocket(t)
s := Suricata{
Source: tmpfn,
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
require.NoError(t, s.Start(&acc))
defer s.Stop()
c, err := net.Dial("unix", tmpfn)
if err != nil {
log.Println(err)
}
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
require.NoError(t, c.Close())
acc.WaitError(1)
}
func TestSuricataDisconnectSocket(t *testing.T) {
tmpfn := testutil.TempSocket(t)
s := Suricata{
Source: tmpfn,
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
require.NoError(t, s.Start(&acc))
defer s.Stop()
c, err := net.Dial("unix", tmpfn)
require.NoError(t, err)
_, err = c.Write([]byte(ex2))
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
require.NoError(t, c.Close())
c, err = net.Dial("unix", tmpfn)
require.NoError(t, err)
_, err = c.Write([]byte(ex3))
require.NoError(t, err)
_, err = c.Write([]byte("\n"))
require.NoError(t, err)
require.NoError(t, c.Close())
acc.Wait(2)
}
func TestSuricataStartStop(t *testing.T) {
tmpfn := testutil.TempSocket(t)
s := Suricata{
Source: tmpfn,
Log: testutil.Logger{
Name: "inputs.suricata",
},
}
acc := testutil.Accumulator{}
require.NoError(t, s.Start(&acc))
s.Stop()
}
func TestSuricataParse(t *testing.T) {
tests := []struct {
filename string
expected []telegraf.Metric
}{{
filename: "test2.json",
expected: []telegraf.Metric{
testutil.MustMetric(
"suricata",
map[string]string{
"thread": "W#01-ens2f1",
},
map[string]interface{}{
"detect_alert": float64(0),
"detect_engines_id": float64(0),
"detect_engines_last_reload": "2021-06-08T06:33:05.084872+0000",
"detect_engines_rules_failed": float64(0),
"detect_engines_rules_loaded": float64(22712),
},
time.Unix(0, 0),
),
},
},
}
for _, tc := range tests {
data, err := os.ReadFile("testdata/" + tc.filename)
require.NoError(t, err)
s := Suricata{
Delimiter: "_",
}
acc := testutil.Accumulator{}
err = s.parse(&acc, data)
require.NoError(t, err)
testutil.RequireMetricsEqual(t, tc.expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime())
}
}
func TestSuricataParseVersion2(t *testing.T) {
tests := []struct {
filename string
expected []telegraf.Metric
}{
{
filename: "v2/alert.json",
expected: []telegraf.Metric{
testutil.MustMetric(
"suricata",
map[string]string{
"event_type": "alert",
"in_iface": "s1-suricata",
"proto": "TCP",
},
map[string]interface{}{
"action": "allowed",
"category": "Misc activity",
"dest_ip": "179.60.192.3",
"dest_port": int64(80),
"gid": float64(1),
"rev": float64(0),
"severity": float64(3),
"signature": "Corrupted HTTP body",
"signature_id": float64(6),
"sourceip": "10.0.0.5",
"sourceport": float64(18715),
"src_ip": "10.0.0.5",
"src_port": int64(18715),
"targetip": "179.60.192.3",
"targetport": float64(80),
},
time.Unix(0, 0),
),
},
},
{
filename: "v2/dns.json",
expected: []telegraf.Metric{
testutil.MustMetric(
"suricata",
map[string]string{
"event_type": "dns",
"in_iface": "eth1",
"proto": "UDP",
},
map[string]interface{}{
"dest_ip": "192.168.0.1",
"dest_port": int64(53),
"id": float64(7145),
"rrname": "reddit.com",
"rrtype": "A",
"src_ip": "192.168.0.100",
"type": "query",
"src_port": int64(39262),
"tx_id": float64(10),
},
time.Unix(0, 0),
),
},
},
{
filename: "v2/drop.json",
expected: []telegraf.Metric{
testutil.MustMetric(
"suricata",
map[string]string{
"event_type": "drop",
"in_iface": "eth1",
"proto": "TCP",
},
map[string]interface{}{
"dest_ip": "54.192.18.125",
"dest_port": int64(443),
"ipid": float64(62316),
"len": float64(76),
"reason": "stream error",
"src_ip": "192.168.0.110",
"src_port": int64(46016),
"tcpack": float64(2339873683),
"tcpres": float64(0),
"tcpseq": float64(3900248957),
"tcpurgp": float64(0),
"tcpwin": float64(501),
"tos": float64(0),
"ttl": float64(64),
},
time.Unix(0, 0),
),
},
},
{
filename: "v2/flow.json",
expected: []telegraf.Metric{
testutil.MustMetric(
"suricata",
map[string]string{
"event_type": "flow",
"in_iface": "eth1",
"proto": "TCP",
},
map[string]interface{}{
"age": float64(0),
"dest_ip": "142.251.130.3",
"dest_port": int64(443),
"src_ip": "192.168.0.121",
"src_port": int64(50212),
"state": "new",
},
time.Unix(0, 0),
),
},
},
{
filename: "v2/http.json",
expected: []telegraf.Metric{
testutil.MustMetric(
"suricata",
map[string]string{
"event_type": "http",
"in_iface": "eth2",
"proto": "TCP",
},
map[string]interface{}{
"dest_ip": "203.205.239.179",
"dest_port": int64(80),
"hostname": "hkminorshort.weixin.qq.com",
"http_content_type": "application/octet-stream",
"http_method": "POST",
"http_user_agent": "MicroMessenger Client",
"length": float64(245),
"protocol": "HTTP/1.1",
"src_ip": "192.168.0.120",
"src_port": int64(33950),
"status": float64(200),
"url": "/mmtls/2d6d45f1",
},
time.Unix(0, 0),
),
},
},
{
filename: "v2/status.json",
expected: []telegraf.Metric{
testutil.MustMetric(
"suricata",
map[string]string{
"event_type": "stats",
},
map[string]interface{}{
"captureerrors": float64(0),
"capturekernel_drops": float64(0),
"capturekernel_packets": float64(522),
"flowemerg_mode_entered": float64(0),
"flowemerg_mode_over": float64(0),
"flowmemcap": float64(0),
"flowmemuse": float64(9965056),
"flowmgrclosed_pruned": float64(0),
"flowmgrfull_hash_pass": float64(1),
"flowmgrnew_pruned": float64(0),
"flowspare": float64(10100),
"flowtcp": float64(15),
"flowudp": float64(13),
"flowwrkspare_sync": float64(11),
"flowwrkspare_sync_avg": float64(100),
"uptime": float64(160),
},
time.Unix(0, 0),
),
},
},
}
for _, tc := range tests {
data, err := os.ReadFile("testdata/" + tc.filename)
require.NoError(t, err)
s := Suricata{
Version: "2",
Log: testutil.Logger{},
}
acc := testutil.Accumulator{}
require.NoError(t, s.parse(&acc, data))
testutil.RequireMetricsEqual(t, tc.expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime())
}
}

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,21 @@
{
"timestamp": "2021-06-08T06:34:49.237367+0000",
"event_type": "stats",
"stats": {
"threads": {
"W#01-ens2f1": {
"detect": {
"engines": [
{
"id": 0,
"last_reload": "2021-06-08T06:33:05.084872+0000",
"rules_loaded": 22712,
"rules_failed": 0
}
],
"alert": 0
}
}
}
}
}

View file

@ -0,0 +1 @@
{"timestamp":"2021-05-30T20:07:13.208777+0200","flow_id":1696236471136137,"in_iface":"s1-suricata","event_type":"alert","src_ip":"10.0.0.5","src_port":18715,"dest_ip":"179.60.192.3","dest_port":80,"proto":"TCP","alert":{"action":"allowed","gid":1,"source":{"ip":"10.0.0.5","port":18715},"target":{"ip":"179.60.192.3","port":80},"signature_id":6,"rev":0,"signature":"Corrupted HTTP body","severity": 3,"category":"Misc activity","severity":3},"flow":{"pkts_toserver":1,"pkts_toclient":0,"bytes_toserver":174,"bytes_toclient":0,"start":"2021-05-30T20:07:13.208777+0200"}}

View file

@ -0,0 +1,35 @@
{
"timestamp": "2021-05-30T20:07:13.208777+0200",
"flow_id": 1696236471136137,
"in_iface": "s1-suricata",
"event_type": "alert",
"src_ip": "10.0.0.5",
"src_port": 18715,
"dest_ip": "179.60.192.3",
"dest_port": 80,
"proto": "TCP",
"alert": {
"action": "allowed",
"gid": 1,
"source": {
"ip": "10.0.0.5",
"port": 18715
},
"target": {
"ip": "179.60.192.3",
"port": 80
},
"signature_id": 6,
"rev": 0,
"signature": "Corrupted HTTP body",
"severity": 3,
"category": "Misc activity"
},
"flow": {
"pkts_toserver": 1,
"pkts_toclient": 0,
"bytes_toserver": 174,
"bytes_toclient": 0,
"start": "2021-05-30T20:07:13.208777+0200"
}
}

View file

@ -0,0 +1,18 @@
{
"timestamp": "2023-04-07T00:20:57.995497+0800",
"flow_id": 2150129093506313,
"in_iface": "eth1",
"event_type": "dns",
"src_ip": "192.168.0.100",
"src_port": 39262,
"dest_ip": "192.168.0.1",
"dest_port": 53,
"proto": "UDP",
"dns": {
"type": "query",
"id": 7145,
"rrname": "reddit.com",
"rrtype": "A",
"tx_id": 10
}
}

View file

@ -0,0 +1,29 @@
{
"timestamp": "2023-04-07T00:21:01.318245+0800",
"flow_id": 180225164834117,
"in_iface": "eth1",
"event_type": "drop",
"src_ip": "192.168.0.110",
"src_port": 46016,
"dest_ip": "54.192.18.125",
"dest_port": 443,
"proto": "TCP",
"drop": {
"len": 76,
"tos": 0,
"ttl": 64,
"ipid": 62316,
"tcpseq": 3900248957,
"tcpack": 2339873683,
"tcpwin": 501,
"syn": false,
"ack": true,
"psh": true,
"rst": false,
"urg": false,
"fin": true,
"tcpres": 0,
"tcpurgp": 0,
"reason": "stream error"
}
}

View file

@ -0,0 +1,21 @@
{
"timestamp": "2023-04-07T00:28:22.136079+0800",
"flow_id": 911610881873910,
"in_iface": "eth1",
"event_type": "flow",
"src_ip": "192.168.0.121",
"src_port": 50212,
"dest_ip": "142.251.130.3",
"dest_port": 443,
"proto": "TCP",
"flow": {
"age": 0,
"state": "new",
"alerted": false
},
"tcp": {
"tcp_flags": "00",
"tcp_flags_ts": "00",
"tcp_flags_tc": "00"
}
}

View file

@ -0,0 +1,22 @@
{
"timestamp": "2023-04-07T00:27:50.220224+0800",
"flow_id": 1124332026121723,
"in_iface": "eth2",
"event_type": "http",
"src_ip": "192.168.0.120",
"src_port": 33950,
"dest_ip": "203.205.239.179",
"dest_port": 80,
"proto": "TCP",
"tx_id": 0,
"http": {
"hostname": "hkminorshort.weixin.qq.com",
"url": "/mmtls/2d6d45f1",
"http_user_agent": "MicroMessenger Client",
"http_content_type": "application/octet-stream",
"http_method": "POST",
"protocol": "HTTP/1.1",
"status": 200,
"length": 245
}
}

View file

@ -0,0 +1,30 @@
{
"timestamp": "2023-04-07T00:21:07.805683+0800",
"event_type": "stats",
"stats": {
"uptime": 160,
"capture": {
"kernel_packets": 522,
"kernel_drops": 0,
"errors": 0
},
"flow": {
"memcap": 0,
"tcp": 15,
"udp": 13,
"wrk": {
"spare_sync_avg": 100,
"spare_sync": 11
},
"mgr": {
"full_hash_pass": 1,
"closed_pruned": 0,
"new_pruned": 0
},
"spare": 10100,
"emerg_mode_entered": 0,
"emerg_mode_over": 0,
"memuse": 9965056
}
}
}