diff options
Diffstat (limited to 'src')
| -rwxr-xr-x | src/conf_mode/firewall.py | 21 | ||||
| -rwxr-xr-x | src/conf_mode/nat.py | 20 | ||||
| -rwxr-xr-x | src/helpers/vyos-domain-resolver.py | 107 | ||||
| -rw-r--r-- | src/systemd/vyos-domain-resolver.service | 1 | 
4 files changed, 93 insertions, 56 deletions
| diff --git a/src/conf_mode/firewall.py b/src/conf_mode/firewall.py index 5638a9668..ffbd915a2 100755 --- a/src/conf_mode/firewall.py +++ b/src/conf_mode/firewall.py @@ -36,11 +36,15 @@ from vyos.utils.process import cmd  from vyos.utils.process import rc_cmd  from vyos import ConfigError  from vyos import airbag +from pathlib import Path  from subprocess import run as subp_run  airbag.enable()  nftables_conf = '/run/nftables.conf' +domain_resolver_usage = '/run/use-vyos-domain-resolver-firewall' +domain_resolver_usage_nat = '/run/use-vyos-domain-resolver-nat' +  sysctl_file = r'/run/sysctl/10-vyos-firewall.conf'  valid_groups = [ @@ -128,7 +132,7 @@ def get_config(config=None):      firewall['geoip_updated'] = geoip_updated(conf, firewall) -    fqdn_config_parse(firewall) +    fqdn_config_parse(firewall, 'firewall')      set_dependents('conntrack', conf) @@ -570,12 +574,15 @@ def apply(firewall):      call_dependents() -    # T970 Enable a resolver (systemd daemon) that checks -    # domain-group/fqdn addresses and update entries for domains by timeout -    # If router loaded without internet connection or for synchronization -    domain_action = 'stop' -    if dict_search_args(firewall, 'group', 'domain_group') or firewall['ip_fqdn'] or firewall['ip6_fqdn']: -        domain_action = 'restart' +    ## DOMAIN RESOLVER +    domain_action = 'restart' +    if dict_search_args(firewall, 'group', 'domain_group') or firewall['ip_fqdn'].items() or firewall['ip6_fqdn'].items(): +        text = f'# Automatically generated by firewall.py\nThis file indicates that vyos-domain-resolver service is used by the firewall.\n' +        Path(domain_resolver_usage).write_text(text) +    else: +        Path(domain_resolver_usage).unlink(missing_ok=True) +        if not Path('/run').glob('use-vyos-domain-resolver*'): +            domain_action = 'stop'      call(f'systemctl {domain_action} vyos-domain-resolver.service')      if firewall['geoip_updated']: diff --git a/src/conf_mode/nat.py b/src/conf_mode/nat.py index 39803fa02..98b2f3f29 100755 --- a/src/conf_mode/nat.py +++ b/src/conf_mode/nat.py @@ -26,10 +26,13 @@ from vyos.template import is_ip_network  from vyos.utils.kernel import check_kmod  from vyos.utils.dict import dict_search  from vyos.utils.dict import dict_search_args +from vyos.utils.file import write_file  from vyos.utils.process import cmd  from vyos.utils.process import run +from vyos.utils.process import call  from vyos.utils.network import is_addr_assigned  from vyos.utils.network import interface_exists +from vyos.firewall import fqdn_config_parse  from vyos import ConfigError  from vyos import airbag @@ -39,6 +42,8 @@ k_mod = ['nft_nat', 'nft_chain_nat']  nftables_nat_config = '/run/nftables_nat.conf'  nftables_static_nat_conf = '/run/nftables_static-nat-rules.nft' +domain_resolver_usage = '/run/use-vyos-domain-resolver-nat' +domain_resolver_usage_firewall = '/run/use-vyos-domain-resolver-firewall'  valid_groups = [      'address_group', @@ -71,6 +76,8 @@ def get_config(config=None):      if 'dynamic_group' in nat['firewall_group']:          del nat['firewall_group']['dynamic_group'] +    fqdn_config_parse(nat, 'nat') +      return nat  def verify_rule(config, err_msg, groups_dict): @@ -251,6 +258,19 @@ def apply(nat):      call_dependents() +    # DOMAIN RESOLVER +    if nat and 'deleted' not in nat: +        domain_action = 'restart' +        if nat['ip_fqdn'].items(): +            text = f'# Automatically generated by nat.py\nThis file indicates that vyos-domain-resolver service is used by nat.\n' +            write_file(domain_resolver_usage, text) +        elif os.path.exists(domain_resolver_usage): +            os.unlink(domain_resolver_usage) +            if not os.path.exists(domain_resolver_usage_firewall): +                # Firewall not using domain resolver +                domain_action = 'stop' +        call(f'systemctl {domain_action} vyos-domain-resolver.service') +      return None  if __name__ == '__main__': diff --git a/src/helpers/vyos-domain-resolver.py b/src/helpers/vyos-domain-resolver.py index 57cfcabd7..f5a1d9297 100755 --- a/src/helpers/vyos-domain-resolver.py +++ b/src/helpers/vyos-domain-resolver.py @@ -30,6 +30,8 @@ from vyos.xml_ref import get_defaults  base = ['firewall']  timeout = 300  cache = False +base_firewall = ['firewall'] +base_nat = ['nat']  domain_state = {} @@ -46,25 +48,25 @@ ipv6_tables = {      'ip6 raw'  } -def get_config(conf): -    firewall = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, +def get_config(conf, node): +    node_config = conf.get_config_dict(node, key_mangling=('-', '_'), get_first_key=True,                                      no_tag_node_value_mangle=True) -    default_values = get_defaults(base, get_first_key=True) +    default_values = get_defaults(node, get_first_key=True) -    firewall = dict_merge(default_values, firewall) +    node_config = dict_merge(default_values, node_config)      global timeout, cache -    if 'resolver_interval' in firewall: -        timeout = int(firewall['resolver_interval']) +    if 'resolver_interval' in node_config: +        timeout = int(node_config['resolver_interval']) -    if 'resolver_cache' in firewall: +    if 'resolver_cache' in node_config:          cache = True -    fqdn_config_parse(firewall) +    fqdn_config_parse(node_config, node[0]) -    return firewall +    return node_config  def resolve(domains, ipv6=False):      global domain_state @@ -108,55 +110,60 @@ def nft_valid_sets():      except:          return [] -def update(firewall): +def update_fqdn(config, node):      conf_lines = []      count = 0 -      valid_sets = nft_valid_sets() -    domain_groups = dict_search_args(firewall, 'group', 'domain_group') -    if domain_groups: -        for set_name, domain_config in domain_groups.items(): -            if 'address' not in domain_config: -                continue - -            nft_set_name = f'D_{set_name}' -            domains = domain_config['address'] - -            ip_list = resolve(domains, ipv6=False) -            for table in ipv4_tables: -                if (table, nft_set_name) in valid_sets: -                    conf_lines += nft_output(table, nft_set_name, ip_list) - -            ip6_list = resolve(domains, ipv6=True) -            for table in ipv6_tables: -                if (table, nft_set_name) in valid_sets: -                    conf_lines += nft_output(table, nft_set_name, ip6_list) +    if node == 'firewall': +        domain_groups = dict_search_args(config, 'group', 'domain_group') +        if domain_groups: +            for set_name, domain_config in domain_groups.items(): +                if 'address' not in domain_config: +                    continue +                nft_set_name = f'D_{set_name}' +                domains = domain_config['address'] + +                ip_list = resolve(domains, ipv6=False) +                for table in ipv4_tables: +                    if (table, nft_set_name) in valid_sets: +                        conf_lines += nft_output(table, nft_set_name, ip_list) +                ip6_list = resolve(domains, ipv6=True) +                for table in ipv6_tables: +                    if (table, nft_set_name) in valid_sets: +                        conf_lines += nft_output(table, nft_set_name, ip6_list) +                count += 1 + +        for set_name, domain in config['ip_fqdn'].items(): +            table = 'ip vyos_filter' +            nft_set_name = f'FQDN_{set_name}' +            ip_list = resolve([domain], ipv6=False) +            if (table, nft_set_name) in valid_sets: +                conf_lines += nft_output(table, nft_set_name, ip_list)              count += 1 -    for set_name, domain in firewall['ip_fqdn'].items(): -        table = 'ip vyos_filter' -        nft_set_name = f'FQDN_{set_name}' - -        ip_list = resolve([domain], ipv6=False) - -        if (table, nft_set_name) in valid_sets: -            conf_lines += nft_output(table, nft_set_name, ip_list) -        count += 1 - -    for set_name, domain in firewall['ip6_fqdn'].items(): -        table = 'ip6 vyos_filter' -        nft_set_name = f'FQDN_{set_name}' +        for set_name, domain in config['ip6_fqdn'].items(): +            table = 'ip6 vyos_filter' +            nft_set_name = f'FQDN_{set_name}' +            ip_list = resolve([domain], ipv6=True) +            if (table, nft_set_name) in valid_sets: +                conf_lines += nft_output(table, nft_set_name, ip_list) +            count += 1 -        ip_list = resolve([domain], ipv6=True) -        if (table, nft_set_name) in valid_sets: -            conf_lines += nft_output(table, nft_set_name, ip_list) -        count += 1 +    else: +        # It's NAT +        for set_name, domain in config['ip_fqdn'].items(): +            table = 'ip vyos_nat' +            nft_set_name = f'FQDN_nat_{set_name}' +            ip_list = resolve([domain], ipv6=False) +            if (table, nft_set_name) in valid_sets: +                conf_lines += nft_output(table, nft_set_name, ip_list) +            count += 1      nft_conf_str = "\n".join(conf_lines) + "\n"      code = run(f'nft --file -', input=nft_conf_str) -    print(f'Updated {count} sets - result: {code}') +    print(f'Updated {count} sets in {node} - result: {code}')  if __name__ == '__main__':      print(f'VyOS domain resolver') @@ -169,10 +176,12 @@ if __name__ == '__main__':          time.sleep(1)      conf = ConfigTreeQuery() -    firewall = get_config(conf) +    firewall = get_config(conf, base_firewall) +    nat = get_config(conf, base_nat)      print(f'interval: {timeout}s - cache: {cache}')      while True: -        update(firewall) +        update_fqdn(firewall, 'firewall') +        update_fqdn(nat, 'nat')          time.sleep(timeout) diff --git a/src/systemd/vyos-domain-resolver.service b/src/systemd/vyos-domain-resolver.service index c56b51f0c..e63ae5e34 100644 --- a/src/systemd/vyos-domain-resolver.service +++ b/src/systemd/vyos-domain-resolver.service @@ -1,6 +1,7 @@  [Unit]  Description=VyOS firewall domain resolver  After=vyos-router.service +ConditionPathExistsGlob=/run/use-vyos-domain-resolver*  [Service]  Type=simple | 
