summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-07-18 21:35:53 +0200
committerChristian Poessinger <christian@poessinger.com>2021-07-18 21:35:53 +0200
commit48c768abbf53b752a55db2adea1f998cb28da55c (patch)
treef1f0870c19466ec128264af78701e08cea54744c
parent0a9ff39b48804af541ccd00f567c54014f8e1db2 (diff)
downloadvyos-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.tmpl30
-rw-r--r--data/templates/ipsec/swanctl/remote_access.tmpl14
-rw-r--r--interface-definitions/vpn_ipsec.xml.in1
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py52
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():