diff options
author | Christian Poessinger <christian@poessinger.com> | 2021-07-18 21:35:53 +0200 |
---|---|---|
committer | Christian Poessinger <christian@poessinger.com> | 2021-07-18 21:35:53 +0200 |
commit | 48c768abbf53b752a55db2adea1f998cb28da55c (patch) | |
tree | f1f0870c19466ec128264af78701e08cea54744c | |
parent | 0a9ff39b48804af541ccd00f567c54014f8e1db2 (diff) | |
download | vyos-1x-48c768abbf53b752a55db2adea1f998cb28da55c.tar.gz vyos-1x-48c768abbf53b752a55db2adea1f998cb28da55c.zip |
ipsec: T1210: remote-access pools can not hold both IPv4 and IPv6 prefixes
... this enables a dual-stack IKEv2 VPN deployment.
-rw-r--r-- | data/templates/ipsec/swanctl.conf.tmpl | 30 | ||||
-rw-r--r-- | data/templates/ipsec/swanctl/remote_access.tmpl | 14 | ||||
-rw-r--r-- | interface-definitions/vpn_ipsec.xml.in | 1 | ||||
-rwxr-xr-x | src/conf_mode/vpn_ipsec.py | 52 |
4 files changed, 78 insertions, 19 deletions
diff --git a/data/templates/ipsec/swanctl.conf.tmpl b/data/templates/ipsec/swanctl.conf.tmpl index 102d7583f..b85fe7d41 100644 --- a/data/templates/ipsec/swanctl.conf.tmpl +++ b/data/templates/ipsec/swanctl.conf.tmpl @@ -28,13 +28,31 @@ connections { pools { {% if remote_access is defined %} {% for ra, ra_conf in remote_access.items() if ra_conf.pool.dhcp_enable is not defined %} - ra-{{ ra }} { - addrs = {{ ra_conf.pool.prefix }} - dns = {{ ra_conf.pool.name_server | join(",") }} -{% if ra_conf.pool.exclude is defined %} - split_exclude = {{ ra_conf.pool.exclude | join(",") }} -{% endif %} +{% if ra_conf.pool is defined and ra_conf.pool.prefix is defined %} +{% for prefix in ra_conf.pool.prefix %} +{% if prefix | is_ipv4 %} + ra-{{ ra }}-ipv4 { + addrs = {{ prefix }} +{% if ra_conf.pool.name_server_v4 is defined and ra_conf.pool.name_server_v4 is not none %} + dns = {{ ra_conf.pool.name_server_v4 | join(',') }} +{% endif %} +{% if ra_conf.pool.exclude_v4 is defined and ra_conf.pool.exclude_v4 is not none %} + split_exclude = {{ ra_conf.pool.exclude_v4 | join(',') }} +{% endif %} + } +{% elif prefix | is_ipv6 %} + ra-{{ ra }}-ipv6 { + addrs = {{ prefix }} +{% if ra_conf.pool.name_server_v6 is defined and ra_conf.pool.name_server_v6 is not none %} + dns = {{ ra_conf.pool.name_server_v6 | join(',') }} +{% endif %} +{% if ra_conf.pool.exclude_v6 is defined and ra_conf.pool.exclude_v6 is not none %} + split_exclude = {{ ra_conf.pool.exclude_v6 | join(',') }} +{% endif %} } +{% endif %} +{% endfor %} +{% endif %} {% endfor %} {% endif %} } diff --git a/data/templates/ipsec/swanctl/remote_access.tmpl b/data/templates/ipsec/swanctl/remote_access.tmpl index 95f2108fb..ea79a6d6b 100644 --- a/data/templates/ipsec/swanctl/remote_access.tmpl +++ b/data/templates/ipsec/swanctl/remote_access.tmpl @@ -10,10 +10,18 @@ send_certreq = no rekey_time = {{ ike.lifetime }}s keyingtries = 0 -{% if rw_conf.pool.dhcp_enable is defined %} +{% if rw_conf.pool is defined and rw_conf.pool.dhcp_enable is defined %} pools = dhcp -{% else %} - pools = ra-{{ name }} +{% elif rw_conf.pool is defined and rw_conf.pool.prefix is defined and rw_conf.pool.prefix is not none %} +{% set pool = namespace(name='') %} +{% for prefix in rw_conf.pool.prefix %} +{% if not loop.first %} +{% set pool.name = pool.name ~ ',' %} +{% endif %} +{% set afi = '-ipv4' if prefix | is_ipv4 else '-ipv6' %} +{% set pool.name = pool.name + 'ra-' + name + afi %} +{% endfor %} + pools = {{ pool.name }} {% endif %} local { {% if rw_conf.authentication.id is defined and rw_conf.authentication.use_x509_id is not defined %} diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index 9dbebdc0f..14063091d 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -850,6 +850,7 @@ <validator name="ipv4-prefix"/> <validator name="ipv6-prefix"/> </constraint> + <multi/> </properties> </leafNode> <!-- Include Accel-PPP definition here, maybe time for a rename? --> diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index 078b70aee..49c6c6a2d 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -127,6 +127,33 @@ def get_config(config=None): ipsec['l2tp_ike_default'] = 'aes256-sha1-modp1024,3des-sha1-modp1024,3des-sha1-modp1024' ipsec['l2tp_esp_default'] = 'aes256-sha1,3des-sha1' + if 'remote_access' in ipsec: + for name, ra_conf in ipsec['remote_access'].items(): + if 'pool' in ra_conf: + if 'name_server' in ra_conf['pool']: + ns_v4 = [] + ns_v6 = [] + for ns in ra_conf['pool']['name_server']: + if is_ipv4(ns): ns_v4.append(ns) + else: ns_v6.append(ns) + + # Only update nameserver keys if there are address-family specific name-servers + if ns_v4: + ipsec['remote_access'][name]['pool'].update({'name_server_v4' : ns_v4}) + if ns_v6: + ipsec['remote_access'][name]['pool'].update({'name_server_v6' : ns_v6}) + del ipsec['remote_access'][name]['pool']['name_server'] + + if 'exclude' in ra_conf['pool']: + exclude_v4 = [] + exclude_v6 = [] + for exclude in ra_conf['pool']['exclude']: + if is_ipv4(exclude): exclude_v4.append(exclude) + else: exclude_v6.append(exclude) + + ipsec['remote_access'][name]['pool'].update({'exclude_v4' : ns_v4, 'exclude_v6' : ns_v6}) + del ipsec['remote_access'][name]['pool']['exclude'] + return ipsec def get_dhcp_address(iface): @@ -261,16 +288,21 @@ def verify(ipsec): raise ConfigError(f"Missing pre-shared-key on {name} remote-access config") if 'pool' in ra_conf: - if 'name_server' in ra_conf['pool']: - dns_v4 = [] - dns_v6 = [] - for addr in ra_conf['pool']['name_server']: - if is_ipv4(addr): dns_v4.append(addr) - else: dns_v6.append(addr) - if len(dns_v4) > 2: - raise ConfigError(f'IPSec remote-access "{name}" supports only 2 IPv4 name-servers!') - if len(dns_v6) > 2: - raise ConfigError(f'IPSec remote-access "{name}" supports only 2 IPv6 name-servers!') + if 'name_server_ipv4' in ra_conf['pool'] and len(ra_conf['pool']['name_server_ipv4']) > 2: + raise ConfigError(f'IPSec remote-access "{name}" supports only two IPv4 name-servers!') + if 'name_server_ipv6' in ra_conf['pool'] and len(ra_conf['pool']['name_server_ipv6']) > 2: + raise ConfigError(f'IPSec remote-access "{name}" supports only two IPv6 name-servers!') + + if 'prefix' in ra_conf['pool']: + prefix_v4 = [] + prefix_v6 = [] + for prefix in ra_conf['pool']['prefix']: + if is_ipv4(prefix): prefix_v4.append(prefix) + else: prefix_v6.append(prefix) + if len(prefix_v4) > 1: + raise ConfigError(f'IPSec remote-access "{name}" supports only one IPv4 prefix!') + if len(prefix_v6) > 1: + raise ConfigError(f'IPSec remote-access "{name}" supports only one IPv6 prefix!') if 'site_to_site' in ipsec and 'peer' in ipsec['site_to_site']: for peer, peer_conf in ipsec['site_to_site']['peer'].items(): |