diff --git a/src/opnsense/mvc/app/models/OPNsense/Firewall/Alias.xml b/src/opnsense/mvc/app/models/OPNsense/Firewall/Alias.xml index cb707ad26..edd60c21d 100644 --- a/src/opnsense/mvc/app/models/OPNsense/Firewall/Alias.xml +++ b/src/opnsense/mvc/app/models/OPNsense/Firewall/Alias.xml @@ -37,6 +37,7 @@ Network group MAC address External (advanced) + IPv6 Dynamic Host @@ -46,6 +47,8 @@ IPv6 + + 0 diff --git a/src/opnsense/mvc/app/views/OPNsense/Firewall/alias.volt b/src/opnsense/mvc/app/views/OPNsense/Firewall/alias.volt index ba001896d..d7e779291 100644 --- a/src/opnsense/mvc/app/views/OPNsense/Firewall/alias.volt +++ b/src/opnsense/mvc/app/views/OPNsense/Firewall/alias.volt @@ -215,6 +215,11 @@ $("#copy-paste").show(); break; } + if ($(this).val() === 'dynipv6host') { + $("#row_alias\\.dyninterface").show(); + } else { + $("#row_alias\\.dyninterface").hide(); + } if ($(this).val() === 'port') { $("#row_alias\\.counters").hide(); } else { @@ -472,6 +477,7 @@ + @@ -691,6 +697,23 @@ + + +
+ + {{lang._('dyninterface')}} +
+ + + + + + + + +
diff --git a/src/opnsense/scripts/filter/lib/alias.py b/src/opnsense/scripts/filter/lib/alias.py index 1ec10e20c..0de730c0c 100755 --- a/src/opnsense/scripts/filter/lib/alias.py +++ b/src/opnsense/scripts/filter/lib/alias.py @@ -26,6 +26,9 @@ -------------------------------------------------------------------------------------- Alias representation """ +import socket +import fcntl +import struct import os import re import time @@ -33,6 +36,7 @@ import requests import ipaddress import dns.resolver import syslog +import subprocess from hashlib import md5 from . import geoip from .arpcache import ArpCache @@ -57,6 +61,7 @@ class Alias(object): self._timeout = timeout self._name = None self._type = None + self._dyninterface = None self._proto = 'IPv4,IPv6' self._items = list() self._resolve_content = set() @@ -67,6 +72,8 @@ class Alias(object): self._proto = subelem.text elif subelem.tag == 'name': self._name = subelem.text + elif subelem.tag == 'dyninterface': + self._dyninterface = subelem.text elif subelem.tag == 'ttl': tmp = subelem.text.strip() if len(tmp.split('.')) <= 2 and tmp.replace('.', '').isdigit(): @@ -259,6 +266,31 @@ class Alias(object): # return the addresses and networks of this alias return list(self._resolve_content) + def _fetch_dynipv6(self, address): + + #get the interface /64 address + address = address.strip() + sp = subprocess.run(['/sbin/ifconfig', self._dyninterface,'inet6'], capture_output=True, text=True) + for line in sp.stdout.split('\n'): + if line.find('prefixlen 64') > -1: + i_address = line.split(' ')[1] + if i_address[0] == '1' or i_address[0] == '2' or i_address[0] == 3: + break + # split the mask - if no mask it's a /64 + if address.find('/') > -1: + l_address,l_mask = address.split('/') + else: + l_mask = '64' + l_address = address + + base_mask = int(l_mask) + base_address = ipaddress.ip_address(i_address) + base_size=int((128-base_mask)/16) + combine_address='0'+l_address + ipv6_addr = ipaddress.ip_address(combine_address) + calculated_address = ':'.join(base_address.exploded.split(':')[:8-base_size] + ipv6_addr.exploded.split(':')[8-base_size:]) + for address in self._parse_address(calculated_address): + yield address def get_parser(self): """ fetch address parser to use, None if alias type is not handled here :return: function or None @@ -269,6 +301,8 @@ class Alias(object): return self._fetch_url elif self._type == 'geoip': return self._fetch_geo + elif self._type == 'dynipv6host': + return self._fetch_dynipv6 elif self._type == 'mac': return ArpCache().iter_addresses else: diff --git a/src/opnsense/service/templates/OPNsense/Filter/filter_tables.conf b/src/opnsense/service/templates/OPNsense/Filter/filter_tables.conf index 4deb0b013..c241dfab1 100644 --- a/src/opnsense/service/templates/OPNsense/Filter/filter_tables.conf +++ b/src/opnsense/service/templates/OPNsense/Filter/filter_tables.conf @@ -5,6 +5,8 @@ {% endif %} {% set new_style_aliases = 0 %} +{# Macro import #} +{% from 'OPNsense/Macros/interface.macro' import physical_interface %} {% if helpers.exists('OPNsense.Firewall.Alias.aliases.alias') %} {% set new_style_aliases = OPNsense.Firewall.Alias.aliases.alias|length %} {% for alias in helpers.toList('OPNsense.Firewall.Alias.aliases.alias') %} @@ -21,6 +23,8 @@ {{ alias.content|e|encode_idna }} {% elif alias.content %}
{{ alias.content|e|encode_idna }}
+{% endif %}{% if alias.dyninterface %} + {{ physical_interface(alias.dyninterface)|default('LAN') {% endif %}{% if alias.proto %} {{ alias.proto|e }} {% endif %}{% if alias.updatefreq %}