summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniil Baturin <daniil@vyos.io>2020-07-04 21:47:31 +0700
committerGitHub <noreply@github.com>2020-07-04 21:47:31 +0700
commit65cbd7481d886c450bcc6be763aff3d4b070d719 (patch)
treee44da73f12a79bb838c9f276d5901b955298ac3d
parent05aa25573027953c3578bdc2d0c6be0e46ac1a34 (diff)
parent669d24a5e0abfbecf1557fefe1ebcd69a8ff7f0e (diff)
downloadvyos-1x-65cbd7481d886c450bcc6be763aff3d4b070d719.tar.gz
vyos-1x-65cbd7481d886c450bcc6be763aff3d4b070d719.zip
Merge pull request #487 from DmitriyEshenko/1x-impl-fnm
ids: T2659: Implement fastnetmon support
-rw-r--r--data/templates/ids/fastnetmon.tmpl60
-rw-r--r--data/templates/ids/fastnetmon_networks_list.tmpl7
-rw-r--r--debian/control4
-rw-r--r--interface-definitions/service-ids-ddos-protection.xml.in117
-rwxr-xr-xsrc/conf_mode/service_ids_fastnetmon.py89
5 files changed, 276 insertions, 1 deletions
diff --git a/data/templates/ids/fastnetmon.tmpl b/data/templates/ids/fastnetmon.tmpl
new file mode 100644
index 000000000..71a1b2bd7
--- /dev/null
+++ b/data/templates/ids/fastnetmon.tmpl
@@ -0,0 +1,60 @@
+# enable this option if you want to send logs to local syslog facility
+logging:local_syslog_logging = on
+
+# list of all your networks in CIDR format
+networks_list_path = /etc/networks_list
+
+# list networks in CIDR format which will be not monitored for attacks
+white_list_path = /etc/networks_whitelist
+
+# Enable/Disable any actions in case of attack
+enable_ban = on
+
+## How many packets will be collected from attack traffic
+ban_details_records_count = 500
+
+## How long (in seconds) we should keep an IP in blocked state
+## If you set 0 here it completely disables unban capability
+ban_time = 1900
+
+# Check if the attack is still active, before triggering an unban callback with this option
+# If the attack is still active, check each run of the unban watchdog
+unban_only_if_attack_finished = on
+
+# enable per subnet speed meters
+# For each subnet, list track speed in bps and pps for both directions
+enable_subnet_counters = off
+
+{% if "mirror" in mode %}
+mirror_afpacket = on
+{% endif -%}
+
+{% if "in" in direction %}
+process_incoming_traffic = on
+{% endif -%}
+{% if "out" in direction %}
+process_outgoing_traffic = on
+{% endif -%}
+{% for th in threshold %}
+{% if th == "fps" %}
+ban_for_flows = on
+threshold_flows = {{ threshold[th] }}
+{% endif -%}
+{% if th == "mbps" %}
+ban_for_bandwidth = on
+threshold_mbps = {{ threshold[th] }}
+{% endif -%}
+{% if th == "pps" %}
+ban_for_pps = on
+threshold_pps = {{ threshold[th] }}
+{% endif -%}
+{% endfor -%}
+
+{% if listen_interface %}
+{% set value = listen_interface if listen_interface is string else listen_interface | join(',') %}
+interfaces = {{ value }}
+{% endif -%}
+
+{% if alert_script %}
+notify_script_path = {{ alert_script }}
+{% endif -%}
diff --git a/data/templates/ids/fastnetmon_networks_list.tmpl b/data/templates/ids/fastnetmon_networks_list.tmpl
new file mode 100644
index 000000000..d58990053
--- /dev/null
+++ b/data/templates/ids/fastnetmon_networks_list.tmpl
@@ -0,0 +1,7 @@
+{% if network is string %}
+{{ network }}
+{% else %}
+{% for net in network %}
+{{ net }}
+{% endfor %}
+{% endif %}
diff --git a/debian/control b/debian/control
index d2a1ad54c..6746fe647 100644
--- a/debian/control
+++ b/debian/control
@@ -103,7 +103,9 @@ Depends: python3,
salt-minion,
vyos-utils,
nftables (>= 0.9.3),
- conntrack
+ conntrack,
+ libatomic1,
+ fastnetmon
Description: VyOS configuration scripts and data
VyOS configuration scripts, interface definitions, and everything
diff --git a/interface-definitions/service-ids-ddos-protection.xml.in b/interface-definitions/service-ids-ddos-protection.xml.in
new file mode 100644
index 000000000..741533bb4
--- /dev/null
+++ b/interface-definitions/service-ids-ddos-protection.xml.in
@@ -0,0 +1,117 @@
+<?xml version="1.0"?>
+<interfaceDefinition>
+ <node name="service">
+ <children>
+ <node name="ids">
+ <properties>
+ <help>Intrusion Detection System</help>
+ </properties>
+ <children>
+ <node name="ddos-protection" owner="${vyos_conf_scripts_dir}/service_ids_fastnetmon.py">
+ <properties>
+ <help>FastNetMon detection and protection parameters</help>
+ </properties>
+ <children>
+ <leafNode name="alert-script">
+ <properties>
+ <help>Path to fastnetmon alert script</help>
+ </properties>
+ </leafNode>
+ <leafNode name="direction">
+ <properties>
+ <help>Direction for processing traffic</help>
+ <completionHelp>
+ <list>in out</list>
+ </completionHelp>
+ <constraint>
+ <regex>(in|out)</regex>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
+ <leafNode name="listen-interface">
+ <properties>
+ <help>Listen interface for mirroring traffic</help>
+ <completionHelp>
+ <script>${vyos_completion_dir}/list_interfaces.py</script>
+ </completionHelp>
+ <multi/>
+ </properties>
+ </leafNode>
+ <node name="mode">
+ <properties>
+ <help>Traffic capture modes</help>
+ </properties>
+ <children>
+ <!-- Future modes "mirror" "netflow" "combine (both)" -->
+ <leafNode name="mirror">
+ <properties>
+ <help>Listen mirrored traffic mode</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ <leafNode name="network">
+ <properties>
+ <help>Define monitoring networks</help>
+ <valueHelp>
+ <format>ipv4net</format>
+ <description>Processed network</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-prefix"/>
+ </constraint>
+ <multi/>
+ </properties>
+ </leafNode>
+ <node name="threshold">
+ <properties>
+ <help>Attack limits thresholds</help>
+ </properties>
+ <children>
+ <leafNode name="fps">
+ <properties>
+ <help>Flows per second</help>
+ <valueHelp>
+ <format>&lt;0-4294967294&gt;</format>
+ <description>Flows per second</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967294"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="mbps">
+ <properties>
+ <help>Megabits per second</help>
+ <valueHelp>
+ <format>&lt;0-4294967294&gt;</format>
+ <description>Megabits per second</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967294"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="pps">
+ <properties>
+ <help>Packets per second</help>
+ <valueHelp>
+ <format>&lt;0-4294967294&gt;</format>
+ <description>Packets per second</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967294"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+ </children>
+ </node>
+</interfaceDefinition>
diff --git a/src/conf_mode/service_ids_fastnetmon.py b/src/conf_mode/service_ids_fastnetmon.py
new file mode 100755
index 000000000..71bef08ae
--- /dev/null
+++ b/src/conf_mode/service_ids_fastnetmon.py
@@ -0,0 +1,89 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2018-2020 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 <http://www.gnu.org/licenses/>.
+
+import os
+
+from sys import exit
+
+from vyos.config import Config
+from vyos import ConfigError
+from vyos.util import call
+from vyos.template import render
+from vyos import airbag
+airbag.enable()
+
+config_file = r'/etc/fastnetmon.conf'
+networks_list = r'/etc/networks_list'
+
+def get_config():
+ conf = Config()
+ base = ['service', 'ids', 'ddos-protection']
+ fastnetmon = conf.get_config_dict(base, key_mangling=('-', '_'))
+ return fastnetmon
+
+def verify(fastnetmon):
+ if not fastnetmon:
+ return None
+
+ if not "mode" in fastnetmon:
+ raise ConfigError('ddos-protection mode is mandatory!')
+
+ if not "network" in fastnetmon:
+ raise ConfigError('Required define network!')
+
+ if not "listen_interface" in fastnetmon:
+ raise ConfigError('Define listen-interface is mandatory!')
+
+ if "alert_script" in fastnetmon:
+ if os.path.isfile(fastnetmon["alert_script"]):
+ # Check script permissions
+ if not os.access(fastnetmon["alert_script"], os.X_OK):
+ raise ConfigError('Script {0} does not have permissions for execution'.format(fastnetmon["alert_script"]))
+ else:
+ raise ConfigError('File {0} does not exists!'.format(fastnetmon["alert_script"]))
+
+def generate(fastnetmon):
+ if not fastnetmon:
+ if os.path.isfile(config_file):
+ os.unlink(config_file)
+ if os.path.isfile(networks_list):
+ os.unlink(networks_list)
+
+ return
+
+ render(config_file, 'ids/fastnetmon.tmpl', fastnetmon, trim_blocks=True)
+ render(networks_list, 'ids/fastnetmon_networks_list.tmpl', fastnetmon, trim_blocks=True)
+
+ return None
+
+def apply(fastnetmon):
+ if not fastnetmon:
+ # Stop fastnetmon service if removed
+ call('systemctl stop fastnetmon.service')
+ else:
+ call('systemctl restart fastnetmon.service')
+
+ return None
+
+if __name__ == '__main__':
+ try:
+ c = get_config()
+ verify(c)
+ generate(c)
+ apply(c)
+ except ConfigError as e:
+ print(e)
+ exit(1)