From 549089a970e39d1ea09c10af5eaf8f696dd19d40 Mon Sep 17 00:00:00 2001
From: Maxime THIEBAUT <46688461+0xThiebaut@users.noreply.github.com>
Date: Wed, 1 May 2024 22:16:03 +0200
Subject: suricata: T751: Initial support for suricata
---
interface-definitions/service_ids_suricata.xml.in | 250 ++++++++++++++++++++++
1 file changed, 250 insertions(+)
create mode 100644 interface-definitions/service_ids_suricata.xml.in
(limited to 'interface-definitions')
diff --git a/interface-definitions/service_ids_suricata.xml.in b/interface-definitions/service_ids_suricata.xml.in
new file mode 100644
index 000000000..8c1973567
--- /dev/null
+++ b/interface-definitions/service_ids_suricata.xml.in
@@ -0,0 +1,250 @@
+
+
+
+
+
+
+
+
+ Network IDS, IPS and Network Security Monitoring
+ 740
+
+
+ #include
+
+
+ Address group name
+
+ home-net external-net http-servers smtp-servers sql-servers dns-servers telnet-servers aim-servers dc-servers dnp3-server dnp3-client modbus-client modbus-server enip-client enip-server
+
+
+ [a-z0-9-]+
+
+
+
+
+
+ IP address or subnet
+
+ ipv4
+ IPv4 address to match
+
+
+ ipv6
+ IPv6 address to match
+
+
+ ipv4net
+ IPv4 prefix to match
+
+
+ ipv6net
+ IPv6 prefix to match
+
+
+ !ipv4
+ Exclude the specified IPv4 address from matches
+
+
+ !ipv6
+ Exclude the specified IPv6 address from matches
+
+
+ !ipv4net
+ Exclude the specified IPv6 prefix from matches
+
+
+ !ipv6net
+ Exclude the specified IPv6 prefix from matches
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Address group
+
+ service ids suricata address-group
+ home-net external-net http-servers smtp-servers sql-servers dns-servers telnet-servers aim-servers dc-servers dnp3-server dnp3-client modbus-client modbus-server enip-client enip-server
+
+
+ string
+ Address group to match
+
+
+ !string
+ Exclude the specified address group from matches
+
+
+ !?[a-z0-9-]+
+
+
+
+
+
+
+
+
+ Port group name
+
+ http-ports shellcode-ports oracle-ports ssh-ports dnp3-ports modbus-ports file-data-ports ftp-ports geneve-ports vxlan-ports teredo-ports
+
+
+ [a-z0-9-]+
+
+
+
+
+
+ Port number
+
+ u32:1-65535
+ Numeric port to match
+
+
+ !u32:1-65535
+ Numeric port to exclude from matches
+
+
+ start-end
+ Numbered port range (e.g. 1001-1005) to match
+
+
+ !start-end
+ Numbered port range (e.g. !1001-1005) to exclude from matches
+
+
+
+
+
+
+
+
+
+
+ Port group
+
+ service ids suricata port-group
+ http-ports shellcode-ports oracle-ports ssh-ports dnp3-ports modbus-ports file-data-ports ftp-ports geneve-ports vxlan-ports teredo-ports
+
+
+ string
+ Port group to match
+
+
+ !string
+ Exclude the specified port group from matches
+
+
+ !?[a-z0-9-]+
+
+
+
+
+
+
+
+
+ Suricata log outputs
+
+
+
+
+ Extensible Event Format (EVE)
+
+
+
+
+ EVE logging destination
+
+ regular syslog
+
+
+ regular
+ Log to filename
+
+
+ syslog
+ Log to syslog
+
+
+ (regular|syslog)
+
+
+ regular
+
+
+
+ Log file
+
+ filename
+ File name in default Suricata log directory
+
+
+ /path
+ Absolute file path
+
+
+ eve.json
+
+
+
+ Log types
+
+ alert anomaly drop files http dns tls smtp dnp3 ftp rdp nfs smb tftp ikev2 dcerpc krb5 snmp rfb sip dhcp ssh mqtt http2 flow netflow
+
+
+ alert
+ Record events for rule matches
+
+
+ anomaly
+ Record unexpected conditions such as truncated packets, packets with invalid IP/UDP/TCP length values, and other events that render the packet invalid for further processing or describe unexpected behavior on an established stream
+
+
+ drop
+ Record events for dropped packets
+
+
+ file
+ Record file details (e.g., MD5) for files extracted from application protocols (e.g., HTTP)
+
+
+ application (http, dns, tls, ...)
+ Record application-level transactions
+
+
+ flow
+ Record bi-directional flows
+
+
+ netflow
+ Record uni-directional flows
+
+
+ (alert|anomaly|http|dns|tls|files|drop|smtp|dnp3|ftp|rdp|nfs|smb|tftp|ikev2|dcerpc|krb5|snmp|rfb|sip|dhcp|ssh|mqtt|http2|flow|netflow)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--
cgit v1.2.3
From cd32928e1856b0a7e9781709cfc3b0db16b6abcb Mon Sep 17 00:00:00 2001
From: Christian Breunig
Date: Thu, 23 May 2024 21:36:04 +0200
Subject: suricata: T751: move CLI from "service ids suricata" -> "service
suricata"
---
interface-definitions/service_ids_suricata.xml.in | 250 ----------------------
interface-definitions/service_suricata.xml.in | 246 +++++++++++++++++++++
src/conf_mode/service_ids_suricata.py | 190 ----------------
src/conf_mode/service_suricata.py | 190 ++++++++++++++++
4 files changed, 436 insertions(+), 440 deletions(-)
delete mode 100644 interface-definitions/service_ids_suricata.xml.in
create mode 100644 interface-definitions/service_suricata.xml.in
delete mode 100755 src/conf_mode/service_ids_suricata.py
create mode 100755 src/conf_mode/service_suricata.py
(limited to 'interface-definitions')
diff --git a/interface-definitions/service_ids_suricata.xml.in b/interface-definitions/service_ids_suricata.xml.in
deleted file mode 100644
index 8c1973567..000000000
--- a/interface-definitions/service_ids_suricata.xml.in
+++ /dev/null
@@ -1,250 +0,0 @@
-
-
-
-
-
-
-
-
- Network IDS, IPS and Network Security Monitoring
- 740
-
-
- #include
-
-
- Address group name
-
- home-net external-net http-servers smtp-servers sql-servers dns-servers telnet-servers aim-servers dc-servers dnp3-server dnp3-client modbus-client modbus-server enip-client enip-server
-
-
- [a-z0-9-]+
-
-
-
-
-
- IP address or subnet
-
- ipv4
- IPv4 address to match
-
-
- ipv6
- IPv6 address to match
-
-
- ipv4net
- IPv4 prefix to match
-
-
- ipv6net
- IPv6 prefix to match
-
-
- !ipv4
- Exclude the specified IPv4 address from matches
-
-
- !ipv6
- Exclude the specified IPv6 address from matches
-
-
- !ipv4net
- Exclude the specified IPv6 prefix from matches
-
-
- !ipv6net
- Exclude the specified IPv6 prefix from matches
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Address group
-
- service ids suricata address-group
- home-net external-net http-servers smtp-servers sql-servers dns-servers telnet-servers aim-servers dc-servers dnp3-server dnp3-client modbus-client modbus-server enip-client enip-server
-
-
- string
- Address group to match
-
-
- !string
- Exclude the specified address group from matches
-
-
- !?[a-z0-9-]+
-
-
-
-
-
-
-
-
- Port group name
-
- http-ports shellcode-ports oracle-ports ssh-ports dnp3-ports modbus-ports file-data-ports ftp-ports geneve-ports vxlan-ports teredo-ports
-
-
- [a-z0-9-]+
-
-
-
-
-
- Port number
-
- u32:1-65535
- Numeric port to match
-
-
- !u32:1-65535
- Numeric port to exclude from matches
-
-
- start-end
- Numbered port range (e.g. 1001-1005) to match
-
-
- !start-end
- Numbered port range (e.g. !1001-1005) to exclude from matches
-
-
-
-
-
-
-
-
-
-
- Port group
-
- service ids suricata port-group
- http-ports shellcode-ports oracle-ports ssh-ports dnp3-ports modbus-ports file-data-ports ftp-ports geneve-ports vxlan-ports teredo-ports
-
-
- string
- Port group to match
-
-
- !string
- Exclude the specified port group from matches
-
-
- !?[a-z0-9-]+
-
-
-
-
-
-
-
-
- Suricata log outputs
-
-
-
-
- Extensible Event Format (EVE)
-
-
-
-
- EVE logging destination
-
- regular syslog
-
-
- regular
- Log to filename
-
-
- syslog
- Log to syslog
-
-
- (regular|syslog)
-
-
- regular
-
-
-
- Log file
-
- filename
- File name in default Suricata log directory
-
-
- /path
- Absolute file path
-
-
- eve.json
-
-
-
- Log types
-
- alert anomaly drop files http dns tls smtp dnp3 ftp rdp nfs smb tftp ikev2 dcerpc krb5 snmp rfb sip dhcp ssh mqtt http2 flow netflow
-
-
- alert
- Record events for rule matches
-
-
- anomaly
- Record unexpected conditions such as truncated packets, packets with invalid IP/UDP/TCP length values, and other events that render the packet invalid for further processing or describe unexpected behavior on an established stream
-
-
- drop
- Record events for dropped packets
-
-
- file
- Record file details (e.g., MD5) for files extracted from application protocols (e.g., HTTP)
-
-
- application (http, dns, tls, ...)
- Record application-level transactions
-
-
- flow
- Record bi-directional flows
-
-
- netflow
- Record uni-directional flows
-
-
- (alert|anomaly|http|dns|tls|files|drop|smtp|dnp3|ftp|rdp|nfs|smb|tftp|ikev2|dcerpc|krb5|snmp|rfb|sip|dhcp|ssh|mqtt|http2|flow|netflow)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/interface-definitions/service_suricata.xml.in b/interface-definitions/service_suricata.xml.in
new file mode 100644
index 000000000..e21320bfe
--- /dev/null
+++ b/interface-definitions/service_suricata.xml.in
@@ -0,0 +1,246 @@
+
+
+
+
+
+
+ Network IDS, IPS and Security Monitoring
+ 740
+
+
+ #include
+
+
+ Address group name
+
+ home-net external-net http-servers smtp-servers sql-servers dns-servers telnet-servers aim-servers dc-servers dnp3-server dnp3-client modbus-client modbus-server enip-client enip-server
+
+
+ [a-z0-9-]+
+
+
+
+
+
+ IP address or subnet
+
+ ipv4
+ IPv4 address to match
+
+
+ ipv6
+ IPv6 address to match
+
+
+ ipv4net
+ IPv4 prefix to match
+
+
+ ipv6net
+ IPv6 prefix to match
+
+
+ !ipv4
+ Exclude the specified IPv4 address from matches
+
+
+ !ipv6
+ Exclude the specified IPv6 address from matches
+
+
+ !ipv4net
+ Exclude the specified IPv6 prefix from matches
+
+
+ !ipv6net
+ Exclude the specified IPv6 prefix from matches
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Address group
+
+ service ids suricata address-group
+ home-net external-net http-servers smtp-servers sql-servers dns-servers telnet-servers aim-servers dc-servers dnp3-server dnp3-client modbus-client modbus-server enip-client enip-server
+
+
+ string
+ Address group to match
+
+
+ !string
+ Exclude the specified address group from matches
+
+
+ !?[a-z0-9-]+
+
+
+
+
+
+
+
+
+ Port group name
+
+ http-ports shellcode-ports oracle-ports ssh-ports dnp3-ports modbus-ports file-data-ports ftp-ports geneve-ports vxlan-ports teredo-ports
+
+
+ [a-z0-9-]+
+
+
+
+
+
+ Port number
+
+ u32:1-65535
+ Numeric port to match
+
+
+ !u32:1-65535
+ Numeric port to exclude from matches
+
+
+ start-end
+ Numbered port range (e.g. 1001-1005) to match
+
+
+ !start-end
+ Numbered port range (e.g. !1001-1005) to exclude from matches
+
+
+
+
+
+
+
+
+
+
+ Port group
+
+ service ids suricata port-group
+ http-ports shellcode-ports oracle-ports ssh-ports dnp3-ports modbus-ports file-data-ports ftp-ports geneve-ports vxlan-ports teredo-ports
+
+
+ string
+ Port group to match
+
+
+ !string
+ Exclude the specified port group from matches
+
+
+ !?[a-z0-9-]+
+
+
+
+
+
+
+
+
+ Suricata log outputs
+
+
+
+
+ Extensible Event Format (EVE)
+
+
+
+
+ EVE logging destination
+
+ regular syslog
+
+
+ regular
+ Log to filename
+
+
+ syslog
+ Log to syslog
+
+
+ (regular|syslog)
+
+
+ regular
+
+
+
+ Log file
+
+ filename
+ File name in default Suricata log directory
+
+
+ /path
+ Absolute file path
+
+
+ eve.json
+
+
+
+ Log types
+
+ alert anomaly drop files http dns tls smtp dnp3 ftp rdp nfs smb tftp ikev2 dcerpc krb5 snmp rfb sip dhcp ssh mqtt http2 flow netflow
+
+
+ alert
+ Record events for rule matches
+
+
+ anomaly
+ Record unexpected conditions such as truncated packets, packets with invalid IP/UDP/TCP length values, and other events that render the packet invalid for further processing or describe unexpected behavior on an established stream
+
+
+ drop
+ Record events for dropped packets
+
+
+ file
+ Record file details (e.g., MD5) for files extracted from application protocols (e.g., HTTP)
+
+
+ application (http, dns, tls, ...)
+ Record application-level transactions
+
+
+ flow
+ Record bi-directional flows
+
+
+ netflow
+ Record uni-directional flows
+
+
+ (alert|anomaly|http|dns|tls|files|drop|smtp|dnp3|ftp|rdp|nfs|smb|tftp|ikev2|dcerpc|krb5|snmp|rfb|sip|dhcp|ssh|mqtt|http2|flow|netflow)
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/conf_mode/service_ids_suricata.py b/src/conf_mode/service_ids_suricata.py
deleted file mode 100755
index 49fbce244..000000000
--- a/src/conf_mode/service_ids_suricata.py
+++ /dev/null
@@ -1,190 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2024 VyOS maintainers and contributors
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License version 2 or later as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-import os
-
-from sys import exit
-
-from vyos.base import Warning
-from vyos.config import Config
-from vyos.template import render
-from vyos.utils.process import call
-from vyos import ConfigError
-from vyos import airbag
-airbag.enable()
-
-config_file = '/run/suricata/suricata.yaml'
-rotate_file = '/etc/logrotate.d/suricata'
-
-address_group_defaults = {
- 'home-net': {'address': ['192.168.0.0/16','10.0.0.0/8','172.16.0.0/12']},
- 'external-net': {'group': ['!home-net']},
- 'http-servers': {'group': ['home-net']},
- 'smtp-servers': {'group': ['home-net']},
- 'sql-servers': {'group': ['home-net']},
- 'dns-servers': {'group': ['home-net']},
- 'telnet-servers': {'group': ['home-net']},
- 'aim-servers': {'group': ['external-net']},
- 'dc-servers': {'group': ['home-net']},
- 'dnp3-server': {'group': ['home-net']},
- 'modbus-client': {'group': ['home-net']},
- 'modbus-server': {'group': ['home-net']},
- 'enip-client': {'group': ['home-net']},
- 'enip-server': {'group': ['home-net']},
-}
-
-port_group_defaults = {
- 'http-ports': {'port': ['80']},
- 'shellcode-ports': {'port': ['!80']},
- 'oracle-ports': {'port': ['1521']},
- 'ssh-ports': {'port': ['22']},
- 'dnp3-ports': {'port': ['20000']},
- 'modbus-ports': {'port': ['502']},
- 'file-data-ports': {'port': ['110', '143'], 'group': ['http-ports']},
- 'ftp-ports': {'port': ['21']},
- 'geneve-ports': {'port': ['6081']},
- 'vxlan-ports': {'port': ['4789']},
- 'teredo-ports': {'port': ['3544']},
-}
-
-def get_config(config=None):
- if config:
- conf = config
- else:
- conf = Config()
- base = ['service', 'ids', 'suricata']
- if not conf.exists(base):
- return None
-
- suricata = conf.get_config_dict(base,
- get_first_key=True,
- with_recursive_defaults=True)
-
- # Ensure minimal defaults are present
- suricata['address-group'] = address_group_defaults | suricata.get('address-group', {})
- suricata['port-group'] = port_group_defaults | suricata.get('port-group', {})
-
- return suricata
-
-# https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
-def topological_sort(source):
- sorted_nodes = []
- permanent_marks = set()
- temporary_marks = set()
-
- def visit(n, v):
- if n in permanent_marks:
- return
- if n in temporary_marks:
- raise ConfigError('At least one cycle exists in the referenced groups')
-
- temporary_marks.add(n)
-
- for m in v.get('group', []):
- m = m.lstrip('!')
- if m not in source:
- raise ConfigError(f'Undefined referenced group "{m}"')
- visit(m, source[m])
-
- temporary_marks.remove(n)
- permanent_marks.add(n)
- sorted_nodes.append((n, v))
-
- while len(permanent_marks) < len(source):
- n = next(n for n in source.keys() if n not in permanent_marks)
- visit(n, source[n])
-
- return sorted_nodes
-
-def verify(suricata):
- if not suricata:
- return None
-
- if 'interface' not in suricata:
- raise ConfigError('No interfaces configured')
-
- try:
- topological_sort(suricata['address-group'])
- except (ConfigError,StopIteration) as e:
- raise ConfigError(f'Invalid address-group: {e}')
-
- try:
- topological_sort(suricata['port-group'])
- except (ConfigError,StopIteration) as e:
- raise ConfigError(f'Invalid port-group: {e}')
-
-def generate(suricata):
- if not suricata:
- for file in [config_file, rotate_file]:
- if os.path.isfile(file):
- os.unlink(file)
-
- return None
-
- # Config-related formatters
- def to_var(s:str):
- return s.replace('-','_').upper()
-
- def to_val(s:str):
- return s.replace('-',':')
-
- def to_ref(s:str):
- if s[0] == '!':
- return '!$' + to_var(s[1:])
- return '$' + to_var(s)
-
- def to_config(kind:str):
- def format_group(group):
- (name, value) = group
- property = [to_val(property) for property in value.get(kind,[])]
- group = [to_ref(group) for group in value.get('group',[])]
- return (to_var(name), property + group)
- return format_group
-
- # Format the address group
- suricata['address-group'] = map(to_config('address'),
- topological_sort(suricata['address-group']))
-
- # Format the port group
- suricata['port-group'] = map(to_config('port'),
- topological_sort(suricata['port-group']))
-
- render(config_file, 'ids/suricata.j2', {'suricata': suricata})
- render(rotate_file, 'ids/suricata_logrotate.j2', suricata)
- return None
-
-def apply(suricata):
- systemd_service = 'suricata.service'
- if not suricata or 'interface' not in suricata:
- # Stop suricata service if removed
- call(f'systemctl stop {systemd_service}')
- else:
- Warning('To fetch the latest rules, use "update suricata"; '
- 'To periodically fetch the latest rules, '
- 'use the task scheduler!')
- call(f'systemctl restart {systemd_service}')
-
- return None
-
-if __name__ == '__main__':
- try:
- c = get_config()
- verify(c)
- generate(c)
- apply(c)
- except ConfigError as e:
- print(e)
- exit(1)
diff --git a/src/conf_mode/service_suricata.py b/src/conf_mode/service_suricata.py
new file mode 100755
index 000000000..cce4de6e3
--- /dev/null
+++ b/src/conf_mode/service_suricata.py
@@ -0,0 +1,190 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2024 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import os
+
+from sys import exit
+
+from vyos.base import Warning
+from vyos.config import Config
+from vyos.template import render
+from vyos.utils.process import call
+from vyos import ConfigError
+from vyos import airbag
+airbag.enable()
+
+config_file = '/run/suricata/suricata.yaml'
+rotate_file = '/etc/logrotate.d/suricata'
+
+address_group_defaults = {
+ 'home-net': {'address': ['192.168.0.0/16','10.0.0.0/8','172.16.0.0/12']},
+ 'external-net': {'group': ['!home-net']},
+ 'http-servers': {'group': ['home-net']},
+ 'smtp-servers': {'group': ['home-net']},
+ 'sql-servers': {'group': ['home-net']},
+ 'dns-servers': {'group': ['home-net']},
+ 'telnet-servers': {'group': ['home-net']},
+ 'aim-servers': {'group': ['external-net']},
+ 'dc-servers': {'group': ['home-net']},
+ 'dnp3-server': {'group': ['home-net']},
+ 'modbus-client': {'group': ['home-net']},
+ 'modbus-server': {'group': ['home-net']},
+ 'enip-client': {'group': ['home-net']},
+ 'enip-server': {'group': ['home-net']},
+}
+
+port_group_defaults = {
+ 'http-ports': {'port': ['80']},
+ 'shellcode-ports': {'port': ['!80']},
+ 'oracle-ports': {'port': ['1521']},
+ 'ssh-ports': {'port': ['22']},
+ 'dnp3-ports': {'port': ['20000']},
+ 'modbus-ports': {'port': ['502']},
+ 'file-data-ports': {'port': ['110', '143'], 'group': ['http-ports']},
+ 'ftp-ports': {'port': ['21']},
+ 'geneve-ports': {'port': ['6081']},
+ 'vxlan-ports': {'port': ['4789']},
+ 'teredo-ports': {'port': ['3544']},
+}
+
+def get_config(config=None):
+ if config:
+ conf = config
+ else:
+ conf = Config()
+ base = ['service', 'suricata']
+ if not conf.exists(base):
+ return None
+
+ suricata = conf.get_config_dict(base,
+ get_first_key=True,
+ with_recursive_defaults=True)
+
+ # Ensure minimal defaults are present
+ suricata['address-group'] = address_group_defaults | suricata.get('address-group', {})
+ suricata['port-group'] = port_group_defaults | suricata.get('port-group', {})
+
+ return suricata
+
+# https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
+def topological_sort(source):
+ sorted_nodes = []
+ permanent_marks = set()
+ temporary_marks = set()
+
+ def visit(n, v):
+ if n in permanent_marks:
+ return
+ if n in temporary_marks:
+ raise ConfigError('At least one cycle exists in the referenced groups')
+
+ temporary_marks.add(n)
+
+ for m in v.get('group', []):
+ m = m.lstrip('!')
+ if m not in source:
+ raise ConfigError(f'Undefined referenced group "{m}"')
+ visit(m, source[m])
+
+ temporary_marks.remove(n)
+ permanent_marks.add(n)
+ sorted_nodes.append((n, v))
+
+ while len(permanent_marks) < len(source):
+ n = next(n for n in source.keys() if n not in permanent_marks)
+ visit(n, source[n])
+
+ return sorted_nodes
+
+def verify(suricata):
+ if not suricata:
+ return None
+
+ if 'interface' not in suricata:
+ raise ConfigError('No interfaces configured')
+
+ try:
+ topological_sort(suricata['address-group'])
+ except (ConfigError,StopIteration) as e:
+ raise ConfigError(f'Invalid address-group: {e}')
+
+ try:
+ topological_sort(suricata['port-group'])
+ except (ConfigError,StopIteration) as e:
+ raise ConfigError(f'Invalid port-group: {e}')
+
+def generate(suricata):
+ if not suricata:
+ for file in [config_file, rotate_file]:
+ if os.path.isfile(file):
+ os.unlink(file)
+
+ return None
+
+ # Config-related formatters
+ def to_var(s:str):
+ return s.replace('-','_').upper()
+
+ def to_val(s:str):
+ return s.replace('-',':')
+
+ def to_ref(s:str):
+ if s[0] == '!':
+ return '!$' + to_var(s[1:])
+ return '$' + to_var(s)
+
+ def to_config(kind:str):
+ def format_group(group):
+ (name, value) = group
+ property = [to_val(property) for property in value.get(kind,[])]
+ group = [to_ref(group) for group in value.get('group',[])]
+ return (to_var(name), property + group)
+ return format_group
+
+ # Format the address group
+ suricata['address-group'] = map(to_config('address'),
+ topological_sort(suricata['address-group']))
+
+ # Format the port group
+ suricata['port-group'] = map(to_config('port'),
+ topological_sort(suricata['port-group']))
+
+ render(config_file, 'ids/suricata.j2', {'suricata': suricata})
+ render(rotate_file, 'ids/suricata_logrotate.j2', suricata)
+ return None
+
+def apply(suricata):
+ systemd_service = 'suricata.service'
+ if not suricata or 'interface' not in suricata:
+ # Stop suricata service if removed
+ call(f'systemctl stop {systemd_service}')
+ else:
+ Warning('To fetch the latest rules, use "update suricata"; '
+ 'To periodically fetch the latest rules, '
+ 'use the task scheduler!')
+ call(f'systemctl restart {systemd_service}')
+
+ return None
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)
--
cgit v1.2.3
From 2af04a53a4c1aa30118f4c799eb7d1c4cd63be66 Mon Sep 17 00:00:00 2001
From: Christian Breunig
Date: Thu, 23 May 2024 21:54:26 +0200
Subject: suricata: T751: remove implicit default dictionary
---
interface-definitions/service_suricata.xml.in | 16 +++------
src/conf_mode/service_suricata.py | 47 +++++----------------------
2 files changed, 13 insertions(+), 50 deletions(-)
(limited to 'interface-definitions')
diff --git a/interface-definitions/service_suricata.xml.in b/interface-definitions/service_suricata.xml.in
index e21320bfe..e0159e2ba 100644
--- a/interface-definitions/service_suricata.xml.in
+++ b/interface-definitions/service_suricata.xml.in
@@ -12,9 +12,6 @@
Address group name
-
- home-net external-net http-servers smtp-servers sql-servers dns-servers telnet-servers aim-servers dc-servers dnp3-server dnp3-client modbus-client modbus-server enip-client enip-server
-
[a-z0-9-]+
@@ -73,14 +70,13 @@
Address group
service ids suricata address-group
- home-net external-net http-servers smtp-servers sql-servers dns-servers telnet-servers aim-servers dc-servers dnp3-server dnp3-client modbus-client modbus-server enip-client enip-server
- string
+ txt
Address group to match
- !string
+ !txt
Exclude the specified address group from matches
@@ -94,9 +90,6 @@
Port group name
-
- http-ports shellcode-ports oracle-ports ssh-ports dnp3-ports modbus-ports file-data-ports ftp-ports geneve-ports vxlan-ports teredo-ports
-
[a-z0-9-]+
@@ -133,14 +126,13 @@
Port group
service ids suricata port-group
- http-ports shellcode-ports oracle-ports ssh-ports dnp3-ports modbus-ports file-data-ports ftp-ports geneve-ports vxlan-ports teredo-ports
- string
+ txt
Port group to match
- !string
+ !txt
Exclude the specified port group from matches
diff --git a/src/conf_mode/service_suricata.py b/src/conf_mode/service_suricata.py
index cce4de6e3..06d68a637 100755
--- a/src/conf_mode/service_suricata.py
+++ b/src/conf_mode/service_suricata.py
@@ -29,53 +29,18 @@ airbag.enable()
config_file = '/run/suricata/suricata.yaml'
rotate_file = '/etc/logrotate.d/suricata'
-address_group_defaults = {
- 'home-net': {'address': ['192.168.0.0/16','10.0.0.0/8','172.16.0.0/12']},
- 'external-net': {'group': ['!home-net']},
- 'http-servers': {'group': ['home-net']},
- 'smtp-servers': {'group': ['home-net']},
- 'sql-servers': {'group': ['home-net']},
- 'dns-servers': {'group': ['home-net']},
- 'telnet-servers': {'group': ['home-net']},
- 'aim-servers': {'group': ['external-net']},
- 'dc-servers': {'group': ['home-net']},
- 'dnp3-server': {'group': ['home-net']},
- 'modbus-client': {'group': ['home-net']},
- 'modbus-server': {'group': ['home-net']},
- 'enip-client': {'group': ['home-net']},
- 'enip-server': {'group': ['home-net']},
-}
-
-port_group_defaults = {
- 'http-ports': {'port': ['80']},
- 'shellcode-ports': {'port': ['!80']},
- 'oracle-ports': {'port': ['1521']},
- 'ssh-ports': {'port': ['22']},
- 'dnp3-ports': {'port': ['20000']},
- 'modbus-ports': {'port': ['502']},
- 'file-data-ports': {'port': ['110', '143'], 'group': ['http-ports']},
- 'ftp-ports': {'port': ['21']},
- 'geneve-ports': {'port': ['6081']},
- 'vxlan-ports': {'port': ['4789']},
- 'teredo-ports': {'port': ['3544']},
-}
-
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
base = ['service', 'suricata']
+
if not conf.exists(base):
return None
suricata = conf.get_config_dict(base,
- get_first_key=True,
- with_recursive_defaults=True)
-
- # Ensure minimal defaults are present
- suricata['address-group'] = address_group_defaults | suricata.get('address-group', {})
- suricata['port-group'] = port_group_defaults | suricata.get('port-group', {})
+ get_first_key=True, with_recursive_defaults=True)
return suricata
@@ -114,7 +79,13 @@ def verify(suricata):
return None
if 'interface' not in suricata:
- raise ConfigError('No interfaces configured')
+ raise ConfigError('No interfaces configured!')
+
+ if 'address-group' not in suricata:
+ raise ConfigError('No address-group configured!')
+
+ if 'port-group' not in suricata:
+ raise ConfigError('No port-group configured!')
try:
topological_sort(suricata['address-group'])
--
cgit v1.2.3