summaryrefslogtreecommitdiff
path: root/src/conf_mode
diff options
context:
space:
mode:
Diffstat (limited to 'src/conf_mode')
-rwxr-xr-xsrc/conf_mode/conntrack.py23
-rwxr-xr-xsrc/conf_mode/containers.py28
-rwxr-xr-xsrc/conf_mode/firewall.py94
-rwxr-xr-xsrc/conf_mode/nat.py16
-rwxr-xr-xsrc/conf_mode/policy-route-interface.py8
-rwxr-xr-xsrc/conf_mode/policy-route.py193
-rwxr-xr-xsrc/conf_mode/service_monitoring_telegraf.py25
7 files changed, 304 insertions, 83 deletions
diff --git a/src/conf_mode/conntrack.py b/src/conf_mode/conntrack.py
index c65ef9540..aabf2bdf5 100755
--- a/src/conf_mode/conntrack.py
+++ b/src/conf_mode/conntrack.py
@@ -35,6 +35,7 @@ airbag.enable()
conntrack_config = r'/etc/modprobe.d/vyatta_nf_conntrack.conf'
sysctl_file = r'/run/sysctl/10-vyos-conntrack.conf'
+nftables_ct_file = r'/run/nftables-ct.conf'
# Every ALG (Application Layer Gateway) consists of either a Kernel Object
# also called a Kernel Module/Driver or some rules present in iptables
@@ -81,16 +82,35 @@ def get_config(config=None):
# 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)
+ # XXX: T2665: we can not safely rely on the defaults() when there are
+ # tagNodes in place, it is better to blend in the defaults manually.
+ if 'timeout' in default_values and 'custom' in default_values['timeout']:
+ del default_values['timeout']['custom']
conntrack = dict_merge(default_values, conntrack)
return conntrack
def verify(conntrack):
+ if dict_search('ignore.rule', conntrack) != None:
+ for rule, rule_config in conntrack['ignore']['rule'].items():
+ if dict_search('destination.port', rule_config) or \
+ dict_search('source.port', rule_config):
+ if 'protocol' not in rule_config or rule_config['protocol'] not in ['tcp', 'udp']:
+ raise ConfigError(f'Port requires tcp or udp as protocol in rule {rule}')
+
return None
def generate(conntrack):
render(conntrack_config, 'conntrack/vyos_nf_conntrack.conf.tmpl', conntrack)
render(sysctl_file, 'conntrack/sysctl.conf.tmpl', conntrack)
+ render(nftables_ct_file, 'conntrack/nftables-ct.tmpl', conntrack)
+
+ # dry-run newly generated configuration
+ tmp = run(f'nft -c -f {nftables_ct_file}')
+ if tmp > 0:
+ if os.path.exists(nftables_ct_file):
+ os.unlink(nftables_ct_file)
+ raise ConfigError('Configuration file errors encountered!')
return None
@@ -127,6 +147,9 @@ def apply(conntrack):
if not find_nftables_ct_rule(rule):
cmd(f'nft insert rule ip raw VYOS_CT_HELPER {rule}')
+ # Load new nftables ruleset
+ cmd(f'nft -f {nftables_ct_file}')
+
if process_named_running('conntrackd'):
# Reload conntrack-sync daemon to fetch new sysctl values
resync_conntrackd()
diff --git a/src/conf_mode/containers.py b/src/conf_mode/containers.py
index 2e14e0b25..26c50cab6 100755
--- a/src/conf_mode/containers.py
+++ b/src/conf_mode/containers.py
@@ -298,7 +298,7 @@ def apply(container):
f'--memory {memory}m --memory-swap 0 --restart {restart} ' \
f'--name {name} {port} {volume} {env_opt}'
if 'allow_host_networks' in container_config:
- _cmd(f'{container_base_cmd} --net host {image}')
+ run(f'{container_base_cmd} --net host {image}')
else:
for network in container_config['network']:
ipparam = ''
@@ -306,19 +306,25 @@ def apply(container):
address = container_config['network'][network]['address']
ipparam = f'--ip {address}'
- counter = 0
- while True:
- if counter >= 10:
- break
- try:
- _cmd(f'{container_base_cmd} --net {network} {ipparam} {image}')
- break
- except:
- counter = counter +1
- sleep(0.5)
+ run(f'{container_base_cmd} --net {network} {ipparam} {image}')
return None
+def run(container_cmd):
+ counter = 0
+ while True:
+ if counter >= 10:
+ break
+ try:
+ _cmd(container_cmd)
+ break
+ except:
+ counter = counter +1
+ sleep(0.5)
+
+ return None
+
+
if __name__ == '__main__':
try:
c = get_config()
diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py
index 75382034f..82223d60b 100755
--- a/src/conf_mode/firewall.py
+++ b/src/conf_mode/firewall.py
@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
+import re
from glob import glob
from json import loads
@@ -22,6 +23,7 @@ from sys import exit
from vyos.config import Config
from vyos.configdict import dict_merge
+from vyos.configdict import node_changed
from vyos.configdiff import get_config_diff, Diff
from vyos.template import render
from vyos.util import cmd
@@ -33,7 +35,10 @@ from vyos import ConfigError
from vyos import airbag
airbag.enable()
+policy_route_conf_script = '/usr/libexec/vyos/conf_mode/policy-route.py'
+
nftables_conf = '/run/nftables.conf'
+nftables_defines_conf = '/run/nftables_defines.conf'
sysfs_config = {
'all_ping': {'sysfs': '/proc/sys/net/ipv4/icmp_echo_ignore_all', 'enable': '0', 'disable': '1'},
@@ -97,6 +102,35 @@ def get_firewall_interfaces(conf):
out.update(find_interfaces(iftype_conf))
return out
+def get_firewall_zones(conf):
+ used_v4 = []
+ used_v6 = []
+ zone_policy = conf.get_config_dict(['zone-policy'], key_mangling=('-', '_'), get_first_key=True,
+ no_tag_node_value_mangle=True)
+
+ if 'zone' in zone_policy:
+ for zone, zone_conf in zone_policy['zone'].items():
+ if 'from' in zone_conf:
+ for from_zone, from_conf in zone_conf['from'].items():
+ name = dict_search_args(from_conf, 'firewall', 'name')
+ if name:
+ used_v4.append(name)
+
+ ipv6_name = dict_search_args(from_conf, 'firewall', 'ipv6_name')
+ if ipv6_name:
+ used_v6.append(ipv6_name)
+
+ if 'intra_zone_filtering' in zone_conf:
+ name = dict_search_args(zone_conf, 'intra_zone_filtering', 'firewall', 'name')
+ if name:
+ used_v4.append(name)
+
+ ipv6_name = dict_search_args(zone_conf, 'intra_zone_filtering', 'firewall', 'ipv6_name')
+ if ipv6_name:
+ used_v6.append(ipv6_name)
+
+ return {'name': used_v4, 'ipv6_name': used_v6}
+
def get_config(config=None):
if config:
conf = config
@@ -104,16 +138,15 @@ def get_config(config=None):
conf = Config()
base = ['firewall']
- if not conf.exists(base):
- return {}
-
firewall = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
default_values = defaults(base)
firewall = dict_merge(default_values, firewall)
+ firewall['policy_resync'] = bool('group' in firewall or node_changed(conf, base + ['group']))
firewall['interfaces'] = get_firewall_interfaces(conf)
+ firewall['zone_policy'] = get_firewall_zones(conf)
if 'config_trap' in firewall and firewall['config_trap'] == 'enable':
diff = get_config_diff(conf)
@@ -121,6 +154,7 @@ def get_config(config=None):
firewall['trap_targets'] = conf.get_config_dict(['service', 'snmp', 'trap-target'],
key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
+
return firewall
def verify_rule(firewall, rule_conf, ipv6):
@@ -139,6 +173,17 @@ def verify_rule(firewall, rule_conf, ipv6):
if not {'count', 'time'} <= set(rule_conf['recent']):
raise ConfigError('Recent "count" and "time" values must be defined')
+ tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags')
+ if tcp_flags:
+ if dict_search_args(rule_conf, 'protocol') != 'tcp':
+ raise ConfigError('Protocol must be tcp when specifying tcp flags')
+
+ not_flags = dict_search_args(rule_conf, 'tcp', 'flags', 'not')
+ if not_flags:
+ duplicates = [flag for flag in tcp_flags if flag in not_flags]
+ if duplicates:
+ raise ConfigError(f'Cannot match a tcp flag as set and not set')
+
for side in ['destination', 'source']:
if side in rule_conf:
side_conf = rule_conf[side]
@@ -150,17 +195,16 @@ def verify_rule(firewall, rule_conf, ipv6):
for group in valid_groups:
if group in side_conf['group']:
group_name = side_conf['group'][group]
-
fw_group = f'ipv6_{group}' if ipv6 and group in ['address_group', 'network_group'] else group
+ error_group = fw_group.replace("_", "-")
+ group_obj = dict_search_args(firewall, 'group', fw_group, group_name)
- if not dict_search_args(firewall, 'group', fw_group):
- error_group = fw_group.replace("_", "-")
- raise ConfigError(f'Group defined in rule but {error_group} is not configured')
-
- if group_name not in firewall['group'][fw_group]:
- error_group = group.replace("_", "-")
+ if group_obj is None:
raise ConfigError(f'Invalid {error_group} "{group_name}" on firewall rule')
+ if not group_obj:
+ print(f'WARNING: {error_group} "{group_name}" has no members')
+
if 'port' in side_conf or dict_search_args(side_conf, 'group', 'port_group'):
if 'protocol' not in rule_conf:
raise ConfigError('Protocol must be defined if specifying a port or port-group')
@@ -169,10 +213,6 @@ def verify_rule(firewall, rule_conf, ipv6):
raise ConfigError('Protocol must be tcp, udp, or tcp_udp when specifying a port or port-group')
def verify(firewall):
- # bail out early - looks like removal from running config
- if not firewall:
- return None
-
if 'config_trap' in firewall and firewall['config_trap'] == 'enable':
if not firewall['trap_targets']:
raise ConfigError(f'Firewall config-trap enabled but "service snmp trap-target" is not defined')
@@ -201,8 +241,23 @@ def verify(firewall):
if ipv6_name and not dict_search_args(firewall, 'ipv6_name', ipv6_name):
raise ConfigError(f'Firewall ipv6-name "{ipv6_name}" is still referenced on interface {ifname}')
+ for fw_name, used_names in firewall['zone_policy'].items():
+ for name in used_names:
+ if not dict_search_args(firewall, fw_name, name):
+ raise ConfigError(f'Firewall {fw_name.replace("_", "-")} "{name}" is still referenced in zone-policy')
+
return None
+def cleanup_rule(table, jump_chain):
+ commands = []
+ results = cmd(f'nft -a list table {table}').split("\n")
+ for line in results:
+ if f'jump {jump_chain}' in line:
+ handle_search = re.search('handle (\d+)', line)
+ if handle_search:
+ commands.append(f'delete rule {table} {chain} handle {handle_search[1]}')
+ return commands
+
def cleanup_commands(firewall):
commands = []
for table in ['ip filter', 'ip6 filter']:
@@ -225,6 +280,7 @@ def cleanup_commands(firewall):
elif table == 'ip6 filter' and dict_search_args(firewall, 'ipv6_name', chain):
commands.append(f'flush chain {table} {chain}')
else:
+ commands += cleanup_rule(table, chain)
commands.append(f'delete chain {table} {chain}')
elif 'rule' in item:
rule = item['rule']
@@ -243,6 +299,7 @@ def generate(firewall):
firewall['cleanup_commands'] = cleanup_commands(firewall)
render(nftables_conf, 'firewall/nftables.tmpl', firewall)
+ render(nftables_defines_conf, 'firewall/nftables-defines.tmpl', firewall)
return None
def apply_sysfs(firewall):
@@ -306,6 +363,12 @@ def state_policy_rule_exists():
search_str = cmd(f'nft list chain ip filter VYOS_FW_FORWARD')
return 'VYOS_STATE_POLICY' in search_str
+def resync_policy_route():
+ # Update policy route as firewall groups were updated
+ tmp = run(policy_route_conf_script)
+ if tmp > 0:
+ print('Warning: Failed to re-apply policy route configuration')
+
def apply(firewall):
if 'first_install' in firewall:
run('nfct helper add rpc inet tcp')
@@ -325,6 +388,9 @@ def apply(firewall):
apply_sysfs(firewall)
+ if firewall['policy_resync']:
+ resync_policy_route()
+
post_apply_trap(firewall)
return None
diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py
index 96f8f6fb6..9f319fc8a 100755
--- a/src/conf_mode/nat.py
+++ b/src/conf_mode/nat.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2020-2021 VyOS maintainers and contributors
+# Copyright (C) 2020-2022 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
@@ -28,6 +28,7 @@ from vyos.configdict import dict_merge
from vyos.template import render
from vyos.template import is_ip_network
from vyos.util import cmd
+from vyos.util import run
from vyos.util import check_kmod
from vyos.util import dict_search
from vyos.validate import is_addr_assigned
@@ -179,12 +180,19 @@ def verify(nat):
return None
def generate(nat):
- render(nftables_nat_config, 'firewall/nftables-nat.tmpl', nat,
- permission=0o755)
+ render(nftables_nat_config, 'firewall/nftables-nat.tmpl', nat)
+
+ # dry-run newly generated configuration
+ tmp = run(f'nft -c -f {nftables_nat_config}')
+ if tmp > 0:
+ if os.path.exists(nftables_ct_file):
+ os.unlink(nftables_ct_file)
+ raise ConfigError('Configuration file errors encountered!')
+
return None
def apply(nat):
- cmd(f'{nftables_nat_config}')
+ cmd(f'nft -f {nftables_nat_config}')
if os.path.isfile(nftables_nat_config):
os.unlink(nftables_nat_config)
diff --git a/src/conf_mode/policy-route-interface.py b/src/conf_mode/policy-route-interface.py
index e81135a74..1108aebe6 100755
--- a/src/conf_mode/policy-route-interface.py
+++ b/src/conf_mode/policy-route-interface.py
@@ -52,7 +52,7 @@ def verify(if_policy):
if not if_policy:
return None
- for route in ['route', 'ipv6_route']:
+ for route in ['route', 'route6']:
if route in if_policy:
if route not in if_policy['policy']:
raise ConfigError('Policy route not configured')
@@ -71,7 +71,7 @@ def cleanup_rule(table, chain, ifname, new_name=None):
results = cmd(f'nft -a list chain {table} {chain}').split("\n")
retval = None
for line in results:
- if f'oifname "{ifname}"' in line:
+ if f'ifname "{ifname}"' in line:
if new_name and f'jump {new_name}' in line:
# new_name is used to clear rules for any previously referenced chains
# returns true when rule exists and doesn't need to be created
@@ -98,8 +98,8 @@ def apply(if_policy):
else:
cleanup_rule('ip mangle', route_chain, ifname)
- if 'ipv6_route' in if_policy:
- name = 'VYOS_PBR6_' + if_policy['ipv6_route']
+ if 'route6' in if_policy:
+ name = 'VYOS_PBR6_' + if_policy['route6']
rule_exists = cleanup_rule('ip6 mangle', ipv6_route_chain, ifname, name)
if not rule_exists:
diff --git a/src/conf_mode/policy-route.py b/src/conf_mode/policy-route.py
index d098be68d..ee5197af0 100755
--- a/src/conf_mode/policy-route.py
+++ b/src/conf_mode/policy-route.py
@@ -15,6 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
+import re
from json import loads
from sys import exit
@@ -31,6 +32,35 @@ airbag.enable()
mark_offset = 0x7FFFFFFF
nftables_conf = '/run/nftables_policy.conf'
+preserve_chains = [
+ 'VYOS_PBR_PREROUTING',
+ 'VYOS_PBR_POSTROUTING',
+ 'VYOS_PBR6_PREROUTING',
+ 'VYOS_PBR6_POSTROUTING'
+]
+
+valid_groups = [
+ 'address_group',
+ 'network_group',
+ 'port_group'
+]
+
+def get_policy_interfaces(conf):
+ out = {}
+ interfaces = conf.get_config_dict(['interfaces'], key_mangling=('-', '_'), get_first_key=True,
+ no_tag_node_value_mangle=True)
+ def find_interfaces(iftype_conf, output={}, prefix=''):
+ for ifname, if_conf in iftype_conf.items():
+ if 'policy' in if_conf:
+ output[prefix + ifname] = if_conf['policy']
+ for vif in ['vif', 'vif_s', 'vif_c']:
+ if vif in if_conf:
+ output.update(find_interfaces(if_conf[vif], output, f'{prefix}{ifname}.'))
+ return output
+ for iftype, iftype_conf in interfaces.items():
+ out.update(find_interfaces(iftype_conf))
+ return out
+
def get_config(config=None):
if config:
conf = config
@@ -38,67 +68,142 @@ def get_config(config=None):
conf = Config()
base = ['policy']
- if not conf.exists(base + ['route']) and not conf.exists(base + ['ipv6-route']):
- return None
-
policy = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
+ policy['firewall_group'] = conf.get_config_dict(['firewall', 'group'], key_mangling=('-', '_'), get_first_key=True,
+ no_tag_node_value_mangle=True)
+ policy['interfaces'] = get_policy_interfaces(conf)
+
return policy
-def verify(policy):
- # bail out early - looks like removal from running config
- if not policy:
- return None
+def verify_rule(policy, name, rule_conf, ipv6):
+ icmp = 'icmp' if not ipv6 else 'icmpv6'
+ if icmp in rule_conf:
+ icmp_defined = False
+ if 'type_name' in rule_conf[icmp]:
+ icmp_defined = True
+ if 'code' in rule_conf[icmp] or 'type' in rule_conf[icmp]:
+ raise ConfigError(f'{name} rule {rule_id}: Cannot use ICMP type/code with ICMP type-name')
+ if 'code' in rule_conf[icmp]:
+ icmp_defined = True
+ if 'type' not in rule_conf[icmp]:
+ raise ConfigError(f'{name} rule {rule_id}: ICMP code can only be defined if ICMP type is defined')
+ if 'type' in rule_conf[icmp]:
+ icmp_defined = True
+
+ if icmp_defined and 'protocol' not in rule_conf or rule_conf['protocol'] != icmp:
+ raise ConfigError(f'{name} rule {rule_id}: ICMP type/code or type-name can only be defined if protocol is ICMP')
+
+ if 'set' in rule_conf:
+ if 'tcp_mss' in rule_conf['set']:
+ tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags')
+ if not tcp_flags or 'syn' not in tcp_flags:
+ raise ConfigError(f'{name} rule {rule_id}: TCP SYN flag must be set to modify TCP-MSS')
+
+ tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags')
+ if tcp_flags:
+ if dict_search_args(rule_conf, 'protocol') != 'tcp':
+ raise ConfigError('Protocol must be tcp when specifying tcp flags')
+
+ not_flags = dict_search_args(rule_conf, 'tcp', 'flags', 'not')
+ if not_flags:
+ duplicates = [flag for flag in tcp_flags if flag in not_flags]
+ if duplicates:
+ raise ConfigError(f'Cannot match a tcp flag as set and not set')
+
+ for side in ['destination', 'source']:
+ if side in rule_conf:
+ side_conf = rule_conf[side]
+
+ if 'group' in side_conf:
+ if {'address_group', 'network_group'} <= set(side_conf['group']):
+ raise ConfigError('Only one address-group or network-group can be specified')
+
+ for group in valid_groups:
+ if group in side_conf['group']:
+ group_name = side_conf['group'][group]
+ fw_group = f'ipv6_{group}' if ipv6 and group in ['address_group', 'network_group'] else group
+ error_group = fw_group.replace("_", "-")
+ group_obj = dict_search_args(policy['firewall_group'], fw_group, group_name)
+
+ if group_obj is None:
+ raise ConfigError(f'Invalid {error_group} "{group_name}" on policy route rule')
+
+ if not group_obj:
+ print(f'WARNING: {error_group} "{group_name}" has no members')
+
+ if 'port' in side_conf or dict_search_args(side_conf, 'group', 'port_group'):
+ if 'protocol' not in rule_conf:
+ raise ConfigError('Protocol must be defined if specifying a port or port-group')
+
+ if rule_conf['protocol'] not in ['tcp', 'udp', 'tcp_udp']:
+ raise ConfigError('Protocol must be tcp, udp, or tcp_udp when specifying a port or port-group')
- for route in ['route', 'ipv6_route']:
+def verify(policy):
+ for route in ['route', 'route6']:
+ ipv6 = route == 'route6'
if route in policy:
for name, pol_conf in policy[route].items():
if 'rule' in pol_conf:
- for rule_id, rule_conf in pol_conf.items():
- icmp = 'icmp' if route == 'route' else 'icmpv6'
- if icmp in rule_conf:
- icmp_defined = False
- if 'type_name' in rule_conf[icmp]:
- icmp_defined = True
- if 'code' in rule_conf[icmp] or 'type' in rule_conf[icmp]:
- raise ConfigError(f'{name} rule {rule_id}: Cannot use ICMP type/code with ICMP type-name')
- if 'code' in rule_conf[icmp]:
- icmp_defined = True
- if 'type' not in rule_conf[icmp]:
- raise ConfigError(f'{name} rule {rule_id}: ICMP code can only be defined if ICMP type is defined')
- if 'type' in rule_conf[icmp]:
- icmp_defined = True
-
- if icmp_defined and 'protocol' not in rule_conf or rule_conf['protocol'] != icmp:
- raise ConfigError(f'{name} rule {rule_id}: ICMP type/code or type-name can only be defined if protocol is ICMP')
- if 'set' in rule_conf:
- if 'tcp_mss' in rule_conf['set']:
- tcp_flags = dict_search_args(rule_conf, 'tcp', 'flags')
- if not tcp_flags or 'SYN' not in tcp_flags.split(","):
- raise ConfigError(f'{name} rule {rule_id}: TCP SYN flag must be set to modify TCP-MSS')
- if 'tcp' in rule_conf:
- if 'flags' in rule_conf['tcp']:
- if 'protocol' not in rule_conf or rule_conf['protocol'] != 'tcp':
- raise ConfigError(f'{name} rule {rule_id}: TCP flags can only be set if protocol is set to TCP')
+ for rule_id, rule_conf in pol_conf['rule'].items():
+ verify_rule(policy, name, rule_conf, ipv6)
+
+ for ifname, if_policy in policy['interfaces'].items():
+ name = dict_search_args(if_policy, 'route')
+ ipv6_name = dict_search_args(if_policy, 'route6')
+ if name and not dict_search_args(policy, 'route', name):
+ raise ConfigError(f'Policy route "{name}" is still referenced on interface {ifname}')
+
+ if ipv6_name and not dict_search_args(policy, 'route6', ipv6_name):
+ raise ConfigError(f'Policy route6 "{ipv6_name}" is still referenced on interface {ifname}')
return None
-def generate(policy):
- if not policy:
- if os.path.exists(nftables_conf):
- os.unlink(nftables_conf)
- return None
+def cleanup_rule(table, jump_chain):
+ commands = []
+ results = cmd(f'nft -a list table {table}').split("\n")
+ for line in results:
+ if f'jump {jump_chain}' in line:
+ handle_search = re.search('handle (\d+)', line)
+ if handle_search:
+ commands.append(f'delete rule {table} {chain} handle {handle_search[1]}')
+ return commands
+
+def cleanup_commands(policy):
+ commands = []
+ for table in ['ip mangle', 'ip6 mangle']:
+ json_str = cmd(f'nft -j list table {table}')
+ obj = loads(json_str)
+ if 'nftables' not in obj:
+ continue
+ for item in obj['nftables']:
+ if 'chain' in item:
+ chain = item['chain']['name']
+ if not chain.startswith("VYOS_PBR"):
+ continue
+ if chain not in preserve_chains:
+ if table == 'ip mangle' and dict_search_args(policy, 'route', chain.replace("VYOS_PBR_", "", 1)):
+ commands.append(f'flush chain {table} {chain}')
+ elif table == 'ip6 mangle' and dict_search_args(policy, 'route6', chain.replace("VYOS_PBR6_", "", 1)):
+ commands.append(f'flush chain {table} {chain}')
+ else:
+ commands += cleanup_rule(table, chain)
+ commands.append(f'delete chain {table} {chain}')
+ return commands
+def generate(policy):
if not os.path.exists(nftables_conf):
policy['first_install'] = True
+ else:
+ policy['cleanup_commands'] = cleanup_commands(policy)
render(nftables_conf, 'firewall/nftables-policy.tmpl', policy)
return None
def apply_table_marks(policy):
- for route in ['route', 'ipv6_route']:
+ for route in ['route', 'route6']:
if route in policy:
for name, pol_conf in policy[route].items():
if 'rule' in pol_conf:
@@ -124,14 +229,6 @@ def cleanup_table_marks():
cmd(f'ip rule del fwmark {fwmark} table {table}')
def apply(policy):
- if not policy or 'first_install' not in policy:
- run(f'nft flush table ip mangle')
- run(f'nft flush table ip6 mangle')
-
- if not policy:
- cleanup_table_marks()
- return None
-
install_result = run(f'nft -f {nftables_conf}')
if install_result == 1:
raise ConfigError('Failed to apply policy based routing')
diff --git a/src/conf_mode/service_monitoring_telegraf.py b/src/conf_mode/service_monitoring_telegraf.py
index a1e7a7286..8a972b9fe 100755
--- a/src/conf_mode/service_monitoring_telegraf.py
+++ b/src/conf_mode/service_monitoring_telegraf.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2021 VyOS maintainers and contributors
+# Copyright (C) 2021-2022 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
@@ -22,6 +22,7 @@ from shutil import rmtree
from vyos.config import Config
from vyos.configdict import dict_merge
+from vyos.ifconfig import Section
from vyos.template import render
from vyos.util import call
from vyos.util import chown
@@ -42,6 +43,24 @@ systemd_telegraf_override_dir = '/etc/systemd/system/vyos-telegraf.service.d'
systemd_override = f'{systemd_telegraf_override_dir}/10-override.conf'
+def get_interfaces(type='', vlan=True):
+ """
+ Get interfaces
+ get_interfaces()
+ ['dum0', 'eth0', 'eth1', 'eth1.5', 'lo', 'tun0']
+
+ get_interfaces("dummy")
+ ['dum0']
+ """
+ interfaces = []
+ ifaces = Section.interfaces(type)
+ for iface in ifaces:
+ if vlan == False and '.' in iface:
+ continue
+ interfaces.append(iface)
+
+ return interfaces
+
def get_nft_filter_chains():
"""
Get nft chains for table filter
@@ -57,6 +76,7 @@ def get_nft_filter_chains():
return chain_list
+
def get_config(config=None):
if config:
@@ -75,8 +95,9 @@ def get_config(config=None):
default_values = defaults(base)
monitoring = dict_merge(default_values, monitoring)
- monitoring['nft_chains'] = get_nft_filter_chains()
monitoring['custom_scripts_dir'] = custom_scripts_dir
+ monitoring['interfaces_ethernet'] = get_interfaces('ethernet', vlan=False)
+ monitoring['nft_chains'] = get_nft_filter_chains()
return monitoring