summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Poessinger <christian@poessinger.com>2021-06-28 22:58:24 +0200
committerChristian Poessinger <christian@poessinger.com>2021-06-28 22:58:24 +0200
commit0751065ffa2161bedd040197dd51ad6ece5ab19b (patch)
tree7fcbdbe7dbc35e1f2b71b383485fd3017ac83fb7
parent5a5c0cd2e6f5d6c459a7f0e2da777834fb4362b2 (diff)
downloadvyos-1x-0751065ffa2161bedd040197dd51ad6ece5ab19b.tar.gz
vyos-1x-0751065ffa2161bedd040197dd51ad6ece5ab19b.zip
ipsec: T1441: switch from vti to xfrm interfaces
XFRM interfaces are similar to VTI devices in their basic functionality but offer several advantages: * No tunnel endpoint addresses have to be configured on the interfaces. Compared to VTIs, which are layer 3 tunnel devices with mandatory endpoints, this resolves issues with wildcard addresses (only one VTI with wildcard endpoints is supported), avoids a 1:1 mapping between SAs and interfaces, and easily allows SAs with multiple peers to share the same interface. * Because there are no endpoint addresses, IPv4 and IPv6 SAs are supported on the same interface (VTI devices only support one address family). * IPsec modes other than tunnel are supported (VTI devices only support tunnel mode). * No awkward configuration via GRE keys and XFRM marks. Instead, a new identifier (XFRM interface ID) links policies and SAs with XFRM interfaces.
-rw-r--r--data/templates/ipsec/swanctl.conf.tmpl2
-rw-r--r--data/templates/ipsec/swanctl/peer.tmpl10
-rw-r--r--python/vyos/ifconfig/vti.py6
-rwxr-xr-xsrc/conf_mode/interfaces-vti.py31
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py18
5 files changed, 14 insertions, 53 deletions
diff --git a/data/templates/ipsec/swanctl.conf.tmpl b/data/templates/ipsec/swanctl.conf.tmpl
index ea6d85743..d082729cb 100644
--- a/data/templates/ipsec/swanctl.conf.tmpl
+++ b/data/templates/ipsec/swanctl.conf.tmpl
@@ -18,7 +18,7 @@ connections {
{% set peer_ike = ike_group[peer_conf.ike_group] %}
{% set peer_esp = esp_group[peer_conf.default_esp_group] if peer_conf.default_esp_group is defined else None %}
{% set auth_type = authby[peer_conf.authentication.mode] %}
-{{ peer_tmpl.conn(peer_conn_name, peer, peer_conf, peer_ike, peer_esp, ciphers, esp_group, auth_type, marks) }}
+{{ peer_tmpl.conn(peer_conn_name, peer, peer_conf, peer_ike, peer_esp, ciphers, esp_group, auth_type) }}
{% endfor %}
{% endif %}
}
diff --git a/data/templates/ipsec/swanctl/peer.tmpl b/data/templates/ipsec/swanctl/peer.tmpl
index 0d01cd546..68284d7d9 100644
--- a/data/templates/ipsec/swanctl/peer.tmpl
+++ b/data/templates/ipsec/swanctl/peer.tmpl
@@ -1,4 +1,4 @@
-{% macro conn(name, peer, peer_conf, ike, esp, ciphers, esp_group, auth_type, marks) %}
+{% macro conn(name, peer, peer_conf, ike, esp, ciphers, esp_group, auth_type) %}
peer_{{ name }} {
proposals = {{ ciphers.ike[peer_conf.ike_group] }}
version = {{ ike['key_exchange'][4:] if "key_exchange" in ike else "0" }}
@@ -61,8 +61,8 @@
local_ts = 0.0.0.0/0,::/0
remote_ts = 0.0.0.0/0,::/0
updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }} {{ peer_conf.dhcp_interface if peer_conf.dhcp_interface is defined else 'no' }}"
- mark_in = {{ marks[peer_conf.vti.bind] }}
- mark_out = {{ marks[peer_conf.vti.bind] }}
+ if_id_in = {{ peer_conf.vti.bind | replace('vti', '') }}
+ if_id_out = {{ peer_conf.vti.bind | replace('vti', '') }}
ipcomp = {{ 'yes' if "compression" in vti_esp and vti_esp.compression == 'enable' else 'no' }}
mode = {{ vti_esp.mode if "mode" in vti_esp else "tunnel" }}
{% if peer[0:1] == '@' %}
@@ -117,8 +117,8 @@
{% endif %}
{% if peer_conf.vti is defined and peer_conf.vti.bind is defined %}
updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }} {{ peer_conf.dhcp_interface if peer_conf.dhcp_interface is defined else 'no' }}"
- mark_in = {{ marks[peer_conf.vti.bind] }}
- mark_out = {{ marks[peer_conf.vti.bind] }}
+ if_id_in = {{ peer_conf.vti.bind | replace('vti', '') }}
+ if_id_out = {{ peer_conf.vti.bind | replace('vti', '') }}
{% endif %}
}
{% if tunnel_conf.passthrough is defined and tunnel_conf.passthrough %}
diff --git a/python/vyos/ifconfig/vti.py b/python/vyos/ifconfig/vti.py
index 9eafcd11b..a217d28ea 100644
--- a/python/vyos/ifconfig/vti.py
+++ b/python/vyos/ifconfig/vti.py
@@ -33,13 +33,11 @@ class VTIIf(Interface):
# - https://man7.org/linux/man-pages/man8/ip-link.8.html
# - https://man7.org/linux/man-pages/man8/ip-tunnel.8.html
mapping = {
- 'source_address' : 'local',
'source_interface' : 'dev',
- 'remote' : 'remote',
- 'key' : 'key',
}
- cmd = 'ip link add {ifname} type vti'
+ if_id = self.ifname.lstrip('vti')
+ cmd = f'ip link add {self.ifname} type xfrm if_id {if_id}'
for vyos_key, iproute2_key in mapping.items():
# dict_search will return an empty dict "{}" for valueless nodes like
# "parameters.nolearning" - thus we need to test the nodes existence
diff --git a/src/conf_mode/interfaces-vti.py b/src/conf_mode/interfaces-vti.py
index 6ff23ae59..1b38304c1 100755
--- a/src/conf_mode/interfaces-vti.py
+++ b/src/conf_mode/interfaces-vti.py
@@ -36,40 +36,9 @@ def get_config(config=None):
conf = Config()
base = ['interfaces', 'vti']
vti = get_interface_dict(conf, base)
-
- # VTI is more then an interface - we retrieve the "real" configuration from
- # the IPsec peer configuration which binds this VTI
- conf.set_level([])
- vti['ipsec'] = conf.get_config_dict(['vpn', 'ipsec', 'site-to-site', 'peer'],
- key_mangling=('-', '_'), get_first_key=True,
- no_tag_node_value_mangle=True)
-
- for peer, peer_config in vti['ipsec'].items():
- if dict_search('vti.bind', peer_config) == vti['ifname']:
- vti['remote'] = peer
- if 'local_address' in peer_config:
- vti['source_address'] = peer_config['local_address']
- # we also need to "calculate" a per vti individual key
- base = 0x900000
- vti['key'] = base + int(vti['ifname'].lstrip('vti'))
-
return vti
def verify(vti):
- if 'deleted' in vti:
- return None
-
- ifname = vti['ifname']
- found = False
- for peer, peer_config in vti['ipsec'].items():
- if dict_search('vti.bind', peer_config) == ifname:
- found = True
- # we can now stop processing the for loop
- break
- if not found:
- tmp = vti['ifname']
- raise ConfigError(f'Interface "{ifname}" not referenced in any VPN configuration!')
-
return None
def generate(vti):
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index d598ff6da..83c99798c 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -79,8 +79,6 @@ esp_ciphers = {}
dhcp_wait_attempts = 2
dhcp_wait_sleep = 1
-mark_base = 0x900000
-
swanctl_dir = '/etc/swanctl'
ipsec_conf = '/etc/ipsec.conf'
ipsec_secrets = '/etc/ipsec.secrets'
@@ -321,8 +319,13 @@ def verify(ipsec):
raise ConfigError(f"Local/remote prefix cannot be used with ESP transport mode on tunnel {tunnel} for site-to-site peer {peer}")
def generate(ipsec):
- data = {}
+ if not ipsec:
+ for config_file in [ipsec_conf, ipsec_secrets, interface_conf, swanctl_conf]:
+ if os.path.isfile(config_file):
+ os.unlink(config_file)
+ return
+ data = {}
if ipsec:
if ipsec['dhcp_no_address']:
with open(DHCP_HOOK_IFLIST, 'w') as f:
@@ -331,7 +334,6 @@ def generate(ipsec):
data = ipsec
data['authby'] = authby_translate
data['ciphers'] = {'ike': ike_ciphers, 'esp': esp_ciphers}
- data['marks'] = {}
data['rsa_local_key'] = verify_rsa_local_key(ipsec)
if 'site_to_site' in data and 'peer' in data['site_to_site']:
@@ -361,10 +363,6 @@ def generate(ipsec):
data['site_to_site']['peer'][peer]['local_address'] = local_ip
- if 'vti' in peer_conf and 'bind' in peer_conf['vti']:
- vti_interface = peer_conf['vti']['bind']
- data['marks'][vti_interface] = get_mark(vti_interface)
-
if 'tunnel' in peer_conf:
for tunnel, tunnel_conf in peer_conf['tunnel'].items():
local_prefixes = dict_search('local.prefix', tunnel_conf)
@@ -436,10 +434,6 @@ def apply(ipsec):
resync_l2tp(ipsec)
resync_nhrp(ipsec)
-def get_mark(vti_interface):
- vti_num = int(vti_interface.lstrip('vti'))
- return mark_base + vti_num
-
if __name__ == '__main__':
try:
ipsec = get_config()