Page Menu
Home
VyOS Platform
Search
Configure Global Search
Log In
Files
F118309931
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/data/templates/ids/fastnetmon.j2 b/data/templates/ids/fastnetmon.j2
index 0340d3c92..f6f03d0db 100644
--- a/data/templates/ids/fastnetmon.j2
+++ b/data/templates/ids/fastnetmon.j2
@@ -1,112 +1,121 @@
# enable this option if you want to send logs to local syslog facility
logging:logging_level = debug
logging:local_syslog_logging = on
# list of all your networks in CIDR format
networks_list_path = /run/fastnetmon/networks_list
# list networks in CIDR format which will be not monitored for attacks
white_list_path = /run/fastnetmon/excluded_networks_list
# Enable/Disable any actions in case of attack
enable_ban = on
enable_ban_ipv6 = 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
{% if ban_time is vyos_defined %}
ban_time = {{ ban_time }}
{% endif %}
# 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 mode.mirror is vyos_defined %}
+{% if mode is vyos_defined('mirror') %}
mirror_afpacket = on
+{% elif mode is vyos_defined('sflow') %}
+sflow = on
+{% if sflow.port is vyos_defined %}
+sflow_port = {{ sflow.port }}
+{% endif %}
+{% if sflow.listen_address is vyos_defined %}
+sflow_host = {{ sflow.listen_address }}
+{% endif %}
{% endif %}
+
process_incoming_traffic = {{ 'on' if direction is vyos_defined and 'in' in direction else 'off' }}
process_outgoing_traffic = {{ 'on' if direction is vyos_defined and 'out' in direction else 'off' }}
{% if threshold is vyos_defined %}
{% if threshold.general is vyos_defined %}
# General threshold
{% for thr, thr_value in threshold.general.items() %}
{% if thr is vyos_defined('fps') %}
ban_for_flows = on
threshold_flows = {{ thr_value }}
{% elif thr is vyos_defined('mbps') %}
ban_for_bandwidth = on
threshold_mbps = {{ thr_value }}
{% elif thr is vyos_defined('pps') %}
ban_for_pps = on
threshold_pps = {{ thr_value }}
{% endif %}
{% endfor %}
{% endif %}
{% if threshold.tcp is vyos_defined %}
# TCP threshold
{% for thr, thr_value in threshold.tcp.items() %}
{% if thr is vyos_defined('fps') %}
ban_for_tcp_flows = on
threshold_tcp_flows = {{ thr_value }}
{% elif thr is vyos_defined('mbps') %}
ban_for_tcp_bandwidth = on
threshold_tcp_mbps = {{ thr_value }}
{% elif thr is vyos_defined('pps') %}
ban_for_tcp_pps = on
threshold_tcp_pps = {{ thr_value }}
{% endif %}
{% endfor %}
{% endif %}
{% if threshold.udp is vyos_defined %}
# UDP threshold
{% for thr, thr_value in threshold.udp.items() %}
{% if thr is vyos_defined('fps') %}
ban_for_udp_flows = on
threshold_udp_flows = {{ thr_value }}
{% elif thr is vyos_defined('mbps') %}
ban_for_udp_bandwidth = on
threshold_udp_mbps = {{ thr_value }}
{% elif thr is vyos_defined('pps') %}
ban_for_udp_pps = on
threshold_udp_pps = {{ thr_value }}
{% endif %}
{% endfor %}
{% endif %}
{% if threshold.icmp is vyos_defined %}
# ICMP threshold
{% for thr, thr_value in threshold.icmp.items() %}
{% if thr is vyos_defined('fps') %}
ban_for_icmp_flows = on
threshold_icmp_flows = {{ thr_value }}
{% elif thr is vyos_defined('mbps') %}
ban_for_icmp_bandwidth = on
threshold_icmp_mbps = {{ thr_value }}
{% elif thr is vyos_defined('pps') %}
ban_for_icmp_pps = on
threshold_icmp_pps = {{ thr_value }}
{% endif %}
{% endfor %}
{% endif %}
{% endif %}
{% if listen_interface is vyos_defined %}
interfaces = {{ listen_interface | join(',') }}
{% endif %}
{% if alert_script is vyos_defined %}
notify_script_path = {{ alert_script }}
{% endif %}
diff --git a/data/templates/ids/fastnetmon_networks_list.j2 b/data/templates/ids/fastnetmon_networks_list.j2
index 5f1b3ba4d..0a0576d2a 100644
--- a/data/templates/ids/fastnetmon_networks_list.j2
+++ b/data/templates/ids/fastnetmon_networks_list.j2
@@ -1,5 +1,5 @@
-{% if network is vyos_defined() %}
+{% if network is vyos_defined %}
{% for net in network %}
{{ net }}
{% endfor %}
{% endif %}
diff --git a/interface-definitions/service-ids-ddos-protection.xml.in b/interface-definitions/service-ids-ddos-protection.xml.in
index bb06189bc..78463136b 100644
--- a/interface-definitions/service-ids-ddos-protection.xml.in
+++ b/interface-definitions/service-ids-ddos-protection.xml.in
@@ -1,150 +1,167 @@
<?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>
<priority>731</priority>
</properties>
<children>
<leafNode name="alert-script">
<properties>
<help>Path to fastnetmon alert script</help>
</properties>
</leafNode>
<leafNode name="ban-time">
<properties>
<help>How long we should keep an IP in blocked state</help>
<valueHelp>
<format>u32:1-4294967294</format>
<description>Time in seconds</description>
</valueHelp>
<constraint>
<validator name="numeric" argument="--range 1-4294967294"/>
</constraint>
</properties>
<defaultValue>1900</defaultValue>
</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="excluded-network">
<properties>
<help>Specify IPv4 and IPv6 networks which are going to be excluded from protection</help>
<valueHelp>
<format>ipv4net</format>
<description>IPv4 prefix(es) to exclude</description>
</valueHelp>
<valueHelp>
<format>ipv6net</format>
<description>IPv6 prefix(es) to exclude</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
<validator name="ipv6-prefix"/>
</constraint>
<multi/>
</properties>
</leafNode>
<leafNode name="listen-interface">
<properties>
<help>Listen interface for mirroring traffic</help>
<completionHelp>
<script>${vyos_completion_dir}/list_interfaces</script>
</completionHelp>
<multi/>
</properties>
</leafNode>
- <node name="mode">
+ <leafNode name="mode">
<properties>
- <help>Traffic capture modes</help>
+ <help>Traffic capture mode</help>
+ <completionHelp>
+ <list>mirror sflow</list>
+ </completionHelp>
+ <valueHelp>
+ <format>mirror</format>
+ <description>Listen to mirrored traffic</description>
+ </valueHelp>
+ <valueHelp>
+ <format>sflow</format>
+ <description>Capture sFlow flows</description>
+ </valueHelp>
+ <constraint>
+ <regex>(mirror|sflow)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <node name="sflow">
+ <properties>
+ <help>Sflow settings</help>
</properties>
<children>
- <!-- Future modes "mirror" "netflow" "combine (both)" -->
- <leafNode name="mirror">
- <properties>
- <help>Listen mirrored traffic mode</help>
- <valueless/>
- </properties>
+ #include <include/listen-address-ipv4-single.xml.i>
+ #include <include/port-number.xml.i>
+ <leafNode name="port">
+ <defaultValue>6343</defaultValue>
</leafNode>
</children>
</node>
<leafNode name="network">
<properties>
<help>Specify IPv4 and IPv6 networks which belong to you</help>
<valueHelp>
<format>ipv4net</format>
<description>Your IPv4 prefix(es)</description>
</valueHelp>
<valueHelp>
<format>ipv6net</format>
<description>Your IPv6 prefix(es)</description>
</valueHelp>
<constraint>
<validator name="ipv4-prefix"/>
<validator name="ipv6-prefix"/>
</constraint>
<multi/>
</properties>
</leafNode>
<node name="threshold">
<properties>
<help>Attack limits thresholds</help>
</properties>
<children>
<node name="general">
<properties>
<help>General threshold</help>
</properties>
<children>
#include <include/ids/threshold.xml.i>
</children>
</node>
<node name="tcp">
<properties>
<help>TCP threshold</help>
</properties>
<children>
#include <include/ids/threshold.xml.i>
</children>
</node>
<node name="udp">
<properties>
<help>UDP threshold</help>
</properties>
<children>
#include <include/ids/threshold.xml.i>
</children>
</node>
<node name="icmp">
<properties>
<help>ICMP threshold</help>
</properties>
<children>
#include <include/ids/threshold.xml.i>
</children>
</node>
</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
index 2e678cf0b..f6b80552b 100755
--- a/src/conf_mode/service_ids_fastnetmon.py
+++ b/src/conf_mode/service_ids_fastnetmon.py
@@ -1,100 +1,108 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2022 VyOS maintainers and contributors
+# Copyright (C) 2018-2023 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.configdict import dict_merge
from vyos.template import render
from vyos.utils.process import call
from vyos.xml import defaults
from vyos import ConfigError
from vyos import airbag
airbag.enable()
config_file = r'/run/fastnetmon/fastnetmon.conf'
networks_list = r'/run/fastnetmon/networks_list'
excluded_networks_list = r'/run/fastnetmon/excluded_networks_list'
+attack_dir = '/var/log/fastnetmon_attacks'
def get_config(config=None):
if config:
conf = config
else:
conf = Config()
base = ['service', 'ids', 'ddos-protection']
if not conf.exists(base):
return None
fastnetmon = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True)
# We have gathered the dict representation of the CLI, but there are default
# options which we need to update into the dictionary retrived.
default_values = defaults(base)
fastnetmon = dict_merge(default_values, fastnetmon)
return fastnetmon
def verify(fastnetmon):
if not fastnetmon:
return None
if 'mode' not in fastnetmon:
raise ConfigError('Specify operating mode!')
- if 'listen_interface' not in fastnetmon:
- raise ConfigError('Specify interface(s) for traffic capture')
+ if fastnetmon.get('mode') == 'mirror' and 'listen_interface' not in fastnetmon:
+ raise ConfigError("Incorrect settings for 'mode mirror': must specify interface(s) for traffic mirroring")
+
+ if fastnetmon.get('mode') == 'sflow' and 'listen_address' not in fastnetmon.get('sflow', {}):
+ raise ConfigError("Incorrect settings for 'mode sflow': must specify sFlow 'listen-address'")
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 "{alert_script}" is not executable!'.format(fastnetmon['alert_script']))
else:
raise ConfigError('File "{alert_script}" does not exists!'.format(fastnetmon))
def generate(fastnetmon):
if not fastnetmon:
for file in [config_file, networks_list]:
if os.path.isfile(file):
os.unlink(file)
return None
+ # Create dir for log attack details
+ if not os.path.exists(attack_dir):
+ os.mkdir(attack_dir)
+
render(config_file, 'ids/fastnetmon.j2', fastnetmon)
render(networks_list, 'ids/fastnetmon_networks_list.j2', fastnetmon)
render(excluded_networks_list, 'ids/fastnetmon_excluded_networks_list.j2', fastnetmon)
return None
def apply(fastnetmon):
systemd_service = 'fastnetmon.service'
if not fastnetmon:
# Stop fastnetmon service if removed
call(f'systemctl stop {systemd_service}')
else:
call(f'systemctl reload-or-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)
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Oct 17, 12:53 AM (1 d, 18 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4403497
Default Alt Text
(15 KB)
Attached To
Mode
rVYOSONEX vyos-1x
Attached
Detach File
Event Timeline
Log In to Comment