summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/conf_mode/nat.py4
-rwxr-xr-xsrc/conf_mode/policy_route.py4
-rwxr-xr-xsrc/conf_mode/service_dns_forwarding.py36
-rw-r--r--src/etc/systemd/system/pdns-recursor.service.d/override.conf8
-rwxr-xr-xsrc/op_mode/dns.py64
-rwxr-xr-xsrc/op_mode/dns_forwarding_reset.py54
-rwxr-xr-xsrc/op_mode/dns_forwarding_restart.sh8
-rwxr-xr-xsrc/op_mode/dns_forwarding_statistics.py32
-rwxr-xr-xsrc/op_mode/firewall.py57
-rwxr-xr-xsrc/services/vyos-hostsd12
10 files changed, 123 insertions, 156 deletions
diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py
index bd9b5162c..26822b755 100755
--- a/src/conf_mode/nat.py
+++ b/src/conf_mode/nat.py
@@ -69,6 +69,10 @@ def get_config(config=None):
nat['firewall_group'] = conf.get_config_dict(['firewall', 'group'], key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
+ # Remove dynamic firewall groups if present:
+ if 'dynamic_group' in nat['firewall_group']:
+ del nat['firewall_group']['dynamic_group']
+
return nat
def verify_rule(config, err_msg, groups_dict):
diff --git a/src/conf_mode/policy_route.py b/src/conf_mode/policy_route.py
index adad012de..6d7a06714 100755
--- a/src/conf_mode/policy_route.py
+++ b/src/conf_mode/policy_route.py
@@ -53,6 +53,10 @@ def get_config(config=None):
policy['firewall_group'] = conf.get_config_dict(['firewall', 'group'], key_mangling=('-', '_'), get_first_key=True,
no_tag_node_value_mangle=True)
+ # Remove dynamic firewall groups if present:
+ if 'dynamic_group' in policy['firewall_group']:
+ del policy['firewall_group']['dynamic_group']
+
return policy
def verify_rule(policy, name, rule_conf, ipv6, rule_id):
diff --git a/src/conf_mode/service_dns_forwarding.py b/src/conf_mode/service_dns_forwarding.py
index c186f47af..ecad765f4 100755
--- a/src/conf_mode/service_dns_forwarding.py
+++ b/src/conf_mode/service_dns_forwarding.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2018-2022 VyOS maintainers and contributors
+# Copyright (C) 2018-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
@@ -26,18 +26,18 @@ from vyos.template import render
from vyos.template import bracketize_ipv6
from vyos.utils.process import call
from vyos.utils.permission import chown
-from vyos.utils.dict import dict_search
from vyos import ConfigError
from vyos import airbag
airbag.enable()
-pdns_rec_user = pdns_rec_group = 'pdns'
-pdns_rec_run_dir = '/run/powerdns'
+pdns_rec_user_group = 'pdns'
+pdns_rec_run_dir = '/run/pdns-recursor'
pdns_rec_lua_conf_file = f'{pdns_rec_run_dir}/recursor.conf.lua'
pdns_rec_hostsd_lua_conf_file = f'{pdns_rec_run_dir}/recursor.vyos-hostsd.conf.lua'
pdns_rec_hostsd_zones_file = f'{pdns_rec_run_dir}/recursor.forward-zones.conf'
pdns_rec_config_file = f'{pdns_rec_run_dir}/recursor.conf'
+pdns_rec_systemd_override = '/run/systemd/system/pdns-recursor.service.d/override.conf'
hostsd_tag = 'static'
@@ -55,6 +55,9 @@ def get_config(config=None):
get_first_key=True,
with_recursive_defaults=True)
+ dns['config_file'] = pdns_rec_config_file
+ dns['config_dir'] = os.path.dirname(pdns_rec_config_file)
+
# some additions to the default dictionary
if 'system' in dns:
base_nameservers = ['system', 'name-server']
@@ -251,11 +254,16 @@ def generate(dns):
if not dns:
return None
- render(pdns_rec_config_file, 'dns-forwarding/recursor.conf.j2',
- dns, user=pdns_rec_user, group=pdns_rec_group)
+ render(pdns_rec_systemd_override, 'dns-forwarding/override.conf.j2', dns)
+
+ render(pdns_rec_config_file, 'dns-forwarding/recursor.conf.j2', dns,
+ user=pdns_rec_user_group, group=pdns_rec_user_group)
- render(pdns_rec_lua_conf_file, 'dns-forwarding/recursor.conf.lua.j2',
- dns, user=pdns_rec_user, group=pdns_rec_group)
+ render(pdns_rec_config_file, 'dns-forwarding/recursor.conf.j2', dns,
+ user=pdns_rec_user_group, group=pdns_rec_user_group)
+
+ render(pdns_rec_lua_conf_file, 'dns-forwarding/recursor.conf.lua.j2', dns,
+ user=pdns_rec_user_group, group=pdns_rec_user_group)
for zone_filename in glob(f'{pdns_rec_run_dir}/zone.*.conf'):
os.unlink(zone_filename)
@@ -263,21 +271,25 @@ def generate(dns):
if 'authoritative_zones' in dns:
for zone in dns['authoritative_zones']:
render(zone['file'], 'dns-forwarding/recursor.zone.conf.j2',
- zone, user=pdns_rec_user, group=pdns_rec_group)
+ zone, user=pdns_rec_user_group, group=pdns_rec_user_group)
# if vyos-hostsd didn't create its files yet, create them (empty)
for file in [pdns_rec_hostsd_lua_conf_file, pdns_rec_hostsd_zones_file]:
with open(file, 'a'):
pass
- chown(file, user=pdns_rec_user, group=pdns_rec_group)
+ chown(file, user=pdns_rec_user_group, group=pdns_rec_user_group)
return None
def apply(dns):
+ systemd_service = 'pdns-recursor.service'
+ # Reload systemd manager configuration
+ call('systemctl daemon-reload')
+
if not dns:
# DNS forwarding is removed in the commit
- call('systemctl stop pdns-recursor.service')
+ call(f'systemctl stop {systemd_service}')
if os.path.isfile(pdns_rec_config_file):
os.unlink(pdns_rec_config_file)
@@ -345,7 +357,7 @@ def apply(dns):
hc.apply()
### finally (re)start pdns-recursor
- call('systemctl restart pdns-recursor.service')
+ call(f'systemctl reload-or-restart {systemd_service}')
if __name__ == '__main__':
try:
diff --git a/src/etc/systemd/system/pdns-recursor.service.d/override.conf b/src/etc/systemd/system/pdns-recursor.service.d/override.conf
deleted file mode 100644
index 158bac02b..000000000
--- a/src/etc/systemd/system/pdns-recursor.service.d/override.conf
+++ /dev/null
@@ -1,8 +0,0 @@
-[Service]
-WorkingDirectory=
-WorkingDirectory=/run/powerdns
-RuntimeDirectory=
-RuntimeDirectory=powerdns
-RuntimeDirectoryPreserve=yes
-ExecStart=
-ExecStart=/usr/sbin/pdns_recursor --daemon=no --write-pid=no --disable-syslog --log-timestamp=no --config-dir=/run/powerdns --socket-dir=/run/powerdns
diff --git a/src/op_mode/dns.py b/src/op_mode/dns.py
index 2168aef89..309bef3b9 100755
--- a/src/op_mode/dns.py
+++ b/src/op_mode/dns.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python3
#
-# Copyright (C) 2022 VyOS maintainers and contributors
+# Copyright (C) 2022-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
@@ -15,17 +15,16 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import typing
import sys
+import vyos.opmode
from tabulate import tabulate
-
from vyos.configquery import ConfigTreeQuery
-from vyos.utils.process import cmd
+from vyos.utils.process import cmd, rc_cmd
-import vyos.opmode
-
-def _data_to_dict(data, sep="\t") -> dict:
+def _forwarding_data_to_dict(data, sep="\t") -> dict:
"""
Return dictionary from plain text
separated by tab
@@ -52,15 +51,15 @@ def _data_to_dict(data, sep="\t") -> dict:
return dictionary
-def _get_raw_forwarding_statistics() -> dict:
- command = cmd('rec_control --socket-dir=/run/powerdns get-all')
- data = _data_to_dict(command)
+def _get_forwarding_statistics_raw() -> dict:
+ command = cmd('rec_control get-all')
+ data = _forwarding_data_to_dict(command)
data['cache-size'] = "{0:.2f}".format( int(
- cmd('rec_control --socket-dir=/run/powerdns get cache-bytes')) / 1024 )
+ cmd('rec_control get cache-bytes')) / 1024 )
return data
-def _get_formatted_forwarding_statistics(data):
+def _get_forwarding_statistics_formatted(data):
cache_entries = data.get('cache-entries')
max_cache_entries = data.get('max-cache-entries')
cache_size = data.get('cache-size')
@@ -69,19 +68,48 @@ def _get_formatted_forwarding_statistics(data):
output = tabulate(data_entries, headers, numalign="left")
return output
+def _verify_forwarding(func):
+ """Decorator checks if DNS Forwarding config exists"""
+ from functools import wraps
-def show_forwarding_statistics(raw: bool):
-
- config = ConfigTreeQuery()
- if not config.exists('service dns forwarding'):
- raise vyos.opmode.UnconfiguredSubsystem('DNS forwarding is not configured')
+ @wraps(func)
+ def _wrapper(*args, **kwargs):
+ config = ConfigTreeQuery()
+ if not config.exists('service dns forwarding'):
+ raise vyos.opmode.UnconfiguredSubsystem('DNS Forwarding is not configured')
+ return func(*args, **kwargs)
+ return _wrapper
- dns_data = _get_raw_forwarding_statistics()
+@_verify_forwarding
+def show_forwarding_statistics(raw: bool):
+ dns_data = _get_forwarding_statistics_raw()
if raw:
return dns_data
else:
- return _get_formatted_forwarding_statistics(dns_data)
+ return _get_forwarding_statistics_formatted(dns_data)
+@_verify_forwarding
+def reset_forwarding(all: bool, domain: typing.Optional[str]):
+ """
+ Reset DNS Forwarding cache
+
+ :param all (bool): reset cache all domains
+ :param domain (str): reset cache for specified domain
+ """
+ if all:
+ rc, output = rc_cmd('rec_control wipe-cache ".$"')
+ if rc != 0:
+ print(output)
+ return None
+ print('DNS Forwarding cache reset for all domains!')
+ return output
+ elif domain:
+ rc, output = rc_cmd(f'rec_control wipe-cache "{domain}$"')
+ if rc != 0:
+ print(output)
+ return None
+ print(f'DNS Forwarding cache reset for domain "{domain}"!')
+ return output
if __name__ == '__main__':
try:
diff --git a/src/op_mode/dns_forwarding_reset.py b/src/op_mode/dns_forwarding_reset.py
deleted file mode 100755
index 55e20918f..000000000
--- a/src/op_mode/dns_forwarding_reset.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (C) 2018 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/>.
-#
-# File: vyos-show-version
-# Purpose:
-# Displays image version and system information.
-# Used by the "run show version" command.
-
-
-import os
-import argparse
-
-from sys import exit
-from vyos.config import Config
-from vyos.utils.process import call
-
-PDNS_CMD='/usr/bin/rec_control --socket-dir=/run/powerdns'
-
-parser = argparse.ArgumentParser()
-parser.add_argument("-a", "--all", action="store_true", help="Reset all cache")
-parser.add_argument("domain", type=str, nargs="?", help="Domain to reset cache entries for")
-
-if __name__ == '__main__':
- args = parser.parse_args()
-
- # Do nothing if service is not configured
- c = Config()
- if not c.exists_effective(['service', 'dns', 'forwarding']):
- print("DNS forwarding is not configured")
- exit(0)
-
- if args.all:
- call(f"{PDNS_CMD} wipe-cache \'.$\'")
- exit(0)
-
- elif args.domain:
- call(f"{PDNS_CMD} wipe-cache \'{0}$\'".format(args.domain))
-
- else:
- parser.print_help()
- exit(1)
diff --git a/src/op_mode/dns_forwarding_restart.sh b/src/op_mode/dns_forwarding_restart.sh
deleted file mode 100755
index 64cc92115..000000000
--- a/src/op_mode/dns_forwarding_restart.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-if cli-shell-api existsEffective service dns forwarding; then
- echo "Restarting the DNS forwarding service"
- systemctl restart pdns-recursor.service
-else
- echo "DNS forwarding is not configured"
-fi
diff --git a/src/op_mode/dns_forwarding_statistics.py b/src/op_mode/dns_forwarding_statistics.py
deleted file mode 100755
index 32b5c76a7..000000000
--- a/src/op_mode/dns_forwarding_statistics.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python3
-
-import jinja2
-from sys import exit
-
-from vyos.config import Config
-from vyos.utils.process import cmd
-
-PDNS_CMD='/usr/bin/rec_control --socket-dir=/run/powerdns'
-
-OUT_TMPL_SRC = """
-DNS forwarding statistics:
-
-Cache entries: {{ cache_entries }}
-Cache size: {{ cache_size }} kbytes
-
-"""
-
-if __name__ == '__main__':
- # Do nothing if service is not configured
- c = Config()
- if not c.exists_effective('service dns forwarding'):
- print("DNS forwarding is not configured")
- exit(0)
-
- data = {}
-
- data['cache_entries'] = cmd(f'{PDNS_CMD} get cache-entries')
- data['cache_size'] = "{0:.2f}".format( int(cmd(f'{PDNS_CMD} get cache-bytes')) / 1024 )
-
- tmpl = jinja2.Template(OUT_TMPL_SRC)
- print(tmpl.render(data))
diff --git a/src/op_mode/firewall.py b/src/op_mode/firewall.py
index 36bb013fe..4dcffc412 100755
--- a/src/op_mode/firewall.py
+++ b/src/op_mode/firewall.py
@@ -327,6 +327,8 @@ def show_firewall_group(name=None):
dest_group = dict_search_args(rule_conf, 'destination', 'group', group_type)
in_interface = dict_search_args(rule_conf, 'inbound_interface', 'group')
out_interface = dict_search_args(rule_conf, 'outbound_interface', 'group')
+ dyn_group_source = dict_search_args(rule_conf, 'add_address_to_group', 'source_address', group_type)
+ dyn_group_dst = dict_search_args(rule_conf, 'add_address_to_group', 'destination_address', group_type)
if source_group:
if source_group[0] == "!":
source_group = source_group[1:]
@@ -348,6 +350,14 @@ def show_firewall_group(name=None):
if group_name == out_interface:
out.append(f'{item}-{name_type}-{priority}-{rule_id}')
+ if dyn_group_source:
+ if group_name == dyn_group_source:
+ out.append(f'{item}-{name_type}-{priority}-{rule_id}')
+ if dyn_group_dst:
+ if group_name == dyn_group_dst:
+ out.append(f'{item}-{name_type}-{priority}-{rule_id}')
+
+
# Look references in route | route6
for name_type in ['route', 'route6']:
if name_type not in policy:
@@ -423,26 +433,37 @@ def show_firewall_group(name=None):
rows = []
for group_type, group_type_conf in firewall['group'].items():
- for group_name, group_conf in group_type_conf.items():
- if name and name != group_name:
- continue
+ ##
+ if group_type != 'dynamic_group':
- references = find_references(group_type, group_name)
- row = [group_name, group_type, '\n'.join(references) or 'N/D']
- if 'address' in group_conf:
- row.append("\n".join(sorted(group_conf['address'])))
- elif 'network' in group_conf:
- row.append("\n".join(sorted(group_conf['network'], key=ipaddress.ip_network)))
- elif 'mac_address' in group_conf:
- row.append("\n".join(sorted(group_conf['mac_address'])))
- elif 'port' in group_conf:
- row.append("\n".join(sorted(group_conf['port'])))
- elif 'interface' in group_conf:
- row.append("\n".join(sorted(group_conf['interface'])))
- else:
- row.append('N/D')
- rows.append(row)
+ for group_name, group_conf in group_type_conf.items():
+ if name and name != group_name:
+ continue
+ references = find_references(group_type, group_name)
+ row = [group_name, group_type, '\n'.join(references) or 'N/D']
+ if 'address' in group_conf:
+ row.append("\n".join(sorted(group_conf['address'])))
+ elif 'network' in group_conf:
+ row.append("\n".join(sorted(group_conf['network'], key=ipaddress.ip_network)))
+ elif 'mac_address' in group_conf:
+ row.append("\n".join(sorted(group_conf['mac_address'])))
+ elif 'port' in group_conf:
+ row.append("\n".join(sorted(group_conf['port'])))
+ elif 'interface' in group_conf:
+ row.append("\n".join(sorted(group_conf['interface'])))
+ else:
+ row.append('N/D')
+ rows.append(row)
+
+ else:
+ for dynamic_type in ['address_group', 'ipv6_address_group']:
+ if dynamic_type in firewall['group']['dynamic_group']:
+ for dynamic_name, dynamic_conf in firewall['group']['dynamic_group'][dynamic_type].items():
+ references = find_references(dynamic_type, dynamic_name)
+ row = [dynamic_name, dynamic_type + '(dynamic)', '\n'.join(references) or 'N/D']
+ row.append('N/D')
+ rows.append(row)
if rows:
print('Firewall Groups\n')
diff --git a/src/services/vyos-hostsd b/src/services/vyos-hostsd
index e34a4b740..1ba90471e 100755
--- a/src/services/vyos-hostsd
+++ b/src/services/vyos-hostsd
@@ -271,8 +271,8 @@ SOCKET_PATH = "ipc://" + os.path.join(RUN_DIR, 'vyos-hostsd.sock')
RESOLV_CONF_FILE = '/etc/resolv.conf'
HOSTS_FILE = '/etc/hosts'
-PDNS_REC_USER = PDNS_REC_GROUP = 'pdns'
-PDNS_REC_RUN_DIR = '/run/powerdns'
+PDNS_REC_USER_GROUP = 'pdns'
+PDNS_REC_RUN_DIR = '/run/pdns-recursor'
PDNS_REC_LUA_CONF_FILE = f'{PDNS_REC_RUN_DIR}/recursor.vyos-hostsd.conf.lua'
PDNS_REC_ZONES_FILE = f'{PDNS_REC_RUN_DIR}/recursor.forward-zones.conf'
@@ -436,18 +436,18 @@ def make_hosts(state):
def make_pdns_rec_conf(state):
logger.info(f"Writing {PDNS_REC_LUA_CONF_FILE}")
- # on boot, /run/powerdns does not exist, so create it
- makedir(PDNS_REC_RUN_DIR, user=PDNS_REC_USER, group=PDNS_REC_GROUP)
+ # on boot, /run/pdns-recursor does not exist, so create it
+ makedir(PDNS_REC_RUN_DIR, user=PDNS_REC_USER_GROUP, group=PDNS_REC_USER_GROUP)
chmod_755(PDNS_REC_RUN_DIR)
render(PDNS_REC_LUA_CONF_FILE,
'dns-forwarding/recursor.vyos-hostsd.conf.lua.j2',
- state, user=PDNS_REC_USER, group=PDNS_REC_GROUP)
+ state, user=PDNS_REC_USER_GROUP, group=PDNS_REC_USER_GROUP)
logger.info(f"Writing {PDNS_REC_ZONES_FILE}")
render(PDNS_REC_ZONES_FILE,
'dns-forwarding/recursor.forward-zones.conf.j2',
- state, user=PDNS_REC_USER, group=PDNS_REC_GROUP)
+ state, user=PDNS_REC_USER_GROUP, group=PDNS_REC_USER_GROUP)
def set_host_name(state, data):
if data['host_name']: