summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsarthurdev <965089+sarthurdev@users.noreply.github.com>2021-06-14 13:04:04 +0200
committersarthurdev <965089+sarthurdev@users.noreply.github.com>2021-06-15 00:16:42 +0200
commit11b5636519b360074eb2877006f2d8d63d9f6610 (patch)
tree1ff04e1e0aba2167b746f2f1373544e3d38b055d
parent78099bccc510c90ad7cfa5f56475ba024d5d53a7 (diff)
downloadvyos-1x-11b5636519b360074eb2877006f2d8d63d9f6610.tar.gz
vyos-1x-11b5636519b360074eb2877006f2d8d63d9f6610.zip
ipsec: T2816: T645: T3613: Migrated IPsec to swanctl, includes multiple selectors, and selectors with VTI.
-rw-r--r--data/templates/ipsec/ike-esp.tmpl32
-rw-r--r--data/templates/ipsec/ipsec.conf.tmpl104
-rw-r--r--data/templates/ipsec/ipsec.secrets.tmpl19
-rw-r--r--data/templates/ipsec/swanctl.conf.tmpl106
-rw-r--r--data/templates/ipsec/swanctl/peer.tmpl136
-rw-r--r--data/templates/ipsec/swanctl/profile.tmpl34
-rw-r--r--interface-definitions/vpn_ipsec.xml.in40
-rwxr-xr-xsmoketest/scripts/cli/test_vpn_ipsec.py109
-rwxr-xr-xsrc/conf_mode/vpn_ipsec.py41
-rwxr-xr-xsrc/conf_mode/vpn_rsa-keys.py6
-rwxr-xr-xsrc/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook30
-rwxr-xr-xsrc/etc/ipsec.d/vti-up-down14
-rwxr-xr-xsrc/op_mode/vpn_ike_sa.py4
-rwxr-xr-xsrc/op_mode/vpn_ipsec.py13
14 files changed, 401 insertions, 287 deletions
diff --git a/data/templates/ipsec/ike-esp.tmpl b/data/templates/ipsec/ike-esp.tmpl
deleted file mode 100644
index deeb8c80d..000000000
--- a/data/templates/ipsec/ike-esp.tmpl
+++ /dev/null
@@ -1,32 +0,0 @@
-{% macro conn(ike, ike_ciphers, esp, esp_ciphers) -%}
-{% if ike %}
-{% if "key_exchange" in ike %}
- keyexchange = {{ ike.key_exchange }}
-{% endif %}
- ike = {{ ike_ciphers }}
-{% if "lifetime" in ike %}
- ikelifetime = {{ ike.lifetime }}s
-{% endif %}
- reauth = {{ ike.ikev2_reauth if "ikev2_reauth" in ike else "no" }}
- closeaction = {{ ike.close_action if "close_action" in ike else "none" }}
-{% if "dead_peer_detection" in ike %}
- dpdaction = {{ ike.dead_peer_detection.action }}
- dpdtimeout = {{ ike.dead_peer_detection.timeout }}
- dpddelay = {{ ike.dead_peer_detection.interval }}
-{% endif %}
-{% if "key_exchange" in ike and ike.key_exchange == "ikev1" and "mode" in ike and ike.mode == "aggressive" %}
- aggressive = yes
-{% endif %}
-{% if "key_exchange" in ike and ike.key_exchange == "ikev2" %}
- mobike = {{ "yes" if "mobike" not in ike or ike.mobike == "enable" else "no" }}
-{% endif %}
-{% endif %}
-{% if esp %}
- esp = {{ esp_ciphers }}
-{% if "lifetime" in esp %}
- keylife = {{ esp.lifetime }}s
-{% endif %}
- compress = {{ 'yes' if "compression" in esp and esp.compression == 'enable' else 'no' }}
- type = {{ esp.mode if "mode" in esp else "tunnel" }}
-{% endif %}
-{%- endmacro %}
diff --git a/data/templates/ipsec/ipsec.conf.tmpl b/data/templates/ipsec/ipsec.conf.tmpl
index 18f6c0988..6550ea419 100644
--- a/data/templates/ipsec/ipsec.conf.tmpl
+++ b/data/templates/ipsec/ipsec.conf.tmpl
@@ -1,113 +1,9 @@
# Created by VyOS - manual changes will be overwritten
-{% import 'ipsec/ike-esp.tmpl' as ike_esp %}
-
config setup
charondebug = "{{ charondebug }}"
uniqueids = {{ "no" if disable_uniqreqids is defined else "yes" }}
-{% if site_to_site is defined and site_to_site.peer is defined %}
-{% for peer, peer_conf in site_to_site.peer.items() if peer not in dhcp_no_address and peer_conf.disable is not defined %}
-{% set peer_index = loop.index %}
-{% 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 %}
-conn peer-{{ peer }}
-{% if peer_conf.authentication.mode in authby %}
- authby = {{ authby[peer_conf.authentication.mode] }}
-{% endif %}
-{% if peer_conf.authentication.mode == 'x509' %}
-{% set cert_file = peer_conf.authentication.x509.cert_file %}
- leftcert = {{ cert_file if cert_file.startswith(x509_path) else (x509_path + cert_file) }}
- leftsendcert = always
- rightca = %same
-{% elif peer_conf.authentication.mode == 'rsa' %}
- leftsigkey = localhost.pub
- rightsigkey = {{ peer_conf.authentication.rsa_key_name }}.pub
-{% endif %}
- left = {{ peer_conf.local_address if peer_conf.local_address != 'any' else '%defaultroute' }} # dhcp:{{ peer_conf.dhcp_interface if 'dhcp_interface' in peer_conf else 'no' }}
-{% if peer_conf.authentication.id is defined and peer_conf.authentication.use_x509_id is not defined %}
- leftid = "{{ peer_conf.authentication.id }}"
-{% endif %}
- right = {{ peer if peer not in ['any', '0.0.0.0'] and peer[0:1] != '@' else '%any' }}
-{% if peer_conf.authentication.remote_id is defined %}
- rightid = "{{ peer_conf.authentication.remote_id }}"
-{% elif peer[0:1] == '@' %}
- rightid = "{{ peer }}"
-{% endif %}
- keylife = 3600s
- rekeymargin = 540s
-{{ ike_esp.conn(peer_ike, ciphers.ike[peer_conf.ike_group], peer_esp, ciphers.esp[peer_conf.default_esp_group] if peer_esp else None) }}
-{% if peer_conf.vti is defined and peer_conf.vti.bind is defined %}
-{% set vti_esp = esp_group[peer_conf.vti.esp_group] if peer_conf.vti.esp_group is defined else None %}
-conn peer-{{ peer }}-vti
- also = peer-{{ peer }}
- leftsubnet = 0.0.0.0/0
- leftupdown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }} {{ peer_conf.dhcp_interface if peer_conf.dhcp_interface is defined else 'no' }}"
- rightsubnet = 0.0.0.0/0
- mark = {{ marks[peer_conf.vti.bind] }}
-{{ ike_esp.conn(None, None, vti_esp, ciphers.esp[peer_conf.vti.esp_group] if vti_esp else None) }}
-{% if peer[0:1] == '@' %}
- rekey = no
- auto = add
- keyingtries = %forever
-{% else %}
-{% if peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %}
- auto = start
- keyingtries = %forever
-{% elif peer_conf.connection_type == 'respond' %}
- auto = route
- keyingtries = 1
-{% endif %}
-{% endif %}
-{% elif peer_conf.tunnel is defined %}
-{% for tunnel_id, tunnel_conf in peer_conf.tunnel.items() if tunnel_conf.disable is not defined %}
-{% set tunnel_esp_name = tunnel_conf.esp_group if "esp_group" in tunnel_conf else peer_conf.default_esp_group %}
-{% set tunnel_esp = esp_group[tunnel_esp_name] %}
-{% set proto = tunnel_conf.protocol if "protocol" in tunnel_conf else '%any' %}
-conn peer-{{ peer }}-tunnel-{{tunnel_id}}
- also = peer-{{ peer }}
-{% if tunnel_esp.mode is not defined or tunnel_esp.mode == 'tunnel' %}
-{% if tunnel_conf.local is defined and tunnel_conf.local.prefix is defined %}
- leftsubnet = {{ tunnel_conf.local.prefix if tunnel_conf.local.prefix != 'any' else '0.0.0.0/0' }}[{{ proto }}/{{ tunnel_conf.local.port if "port" in tunnel_conf.local else '%any' }}]
-{% endif %}
-{% if tunnel_conf.remote is defined and tunnel_conf.remote.prefix is defined %}
- rightsubnet = {{ tunnel_conf.remote.prefix if tunnel_conf.remote.prefix != 'any' else '0.0.0.0/0' }}[{{ proto }}/{{ tunnel_conf.remote.port if "port" in tunnel_conf.remote else '%any' }}]
-{% endif %}
-{% elif tunnel_esp.mode == 'transport' %}
- leftsubnet = {{ peer_conf.local_address }}[{{ proto }}/{{ tunnel_conf.local.port if "local" in tunnel_conf and "port" in tunnel_conf.local else '%any' }}]
- rightsubnet = {{ peer }}[{{ proto }}/{{ tunnel_conf.local.port if "local" in tunnel_conf and "port" in tunnel_conf.local else '%any' }}]
-{% endif %}
-{% if tunnel_conf.esp_group is defined %}
-{{ ike_esp.conn(None, None, tunnel_esp, ciphers.esp[tunnel_esp_name]) }}
-{% endif %}
-{% if peer[0:1] == '@' %}
- rekey = no
- auto = add
- keyingtries = %forever
-{% else %}
-{% if peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %}
- auto = start
- keyingtries = %forever
-{% elif peer_conf.connection_type == 'respond' %}
- auto = route
- keyingtries = 1
-{% endif %}
-{% endif %}
-{% if tunnel_conf.passthrough is defined and tunnel_conf.passthrough is not none %}
-conn peer-{{ peer }}-tunnel-{{ tunnel_id }}-passthough
- left = {{ peer_conf.local_address if peer_conf.local_address != 'any' else '%defaultroute' }}
- right = {{ peer if peer not in ['any', '0.0.0.0'] and peer[0:1] != '@' else '%any' }}
- leftsubnet = {{ tunnel_conf.local.prefix }}
- rightsubnet = {{ tunnel_conf.local.prefix }}
- type = passthrough
- authby = never
- auto = route
-{% endif %}
-{% endfor %}
-{% endif %}
-{% endfor %}
-{% endif %}
-
{% if include_ipsec_conf is defined %}
include {{ include_ipsec_conf }}
{% endif %}
diff --git a/data/templates/ipsec/ipsec.secrets.tmpl b/data/templates/ipsec/ipsec.secrets.tmpl
index 0d2654abc..43b5fe0d2 100644
--- a/data/templates/ipsec/ipsec.secrets.tmpl
+++ b/data/templates/ipsec/ipsec.secrets.tmpl
@@ -1,24 +1,5 @@
# Created by VyOS - manual changes will be overwritten
-{% if site_to_site is defined and "peer" in site_to_site %}
-{% set ns = namespace(local_key_set=False) %}
-{% for peer, peer_conf in site_to_site.peer.items() if peer not in dhcp_no_address and peer_conf.disable is not defined %}
-{% if peer_conf.authentication.mode == 'pre-shared-secret' %}
-{{ (peer_conf.local_address if "local_address" in peer_conf else "%any") ~
- (" " ~ peer) ~
- ((" " ~ peer_conf.authentication.id) if "id" in peer_conf.authentication else "") ~
- ((" " ~ peer_conf.authentication.remote_id) if "remote_id" in peer_conf.authentication else "")
-}} : PSK "{{ peer_conf.authentication.pre_shared_secret }}" # dhcp:{{ peer_conf.dhcp_interface if 'dhcp_interface' in peer_conf else 'no' }}
-{% elif peer_conf.authentication.mode == 'x509' %}
-{% set key_file = peer_conf.authentication.x509.key.file %}
-: RSA {{ key_file if key_file.startswith(x509_path) else (x509_path + key_file) }}{% if "password" in peer_conf.authentication.x509.key and peer_conf.authentication.x509.key.password %} "{{ peer_conf.authentication.x509.key.password}}"{% endif %}
-{% elif peer_conf.authentication.mode == 'rsa' and not ns.local_key_set %}
-{% set ns.local_key_set = True %}
-: RSA {{ rsa_local_key }}
-{% endif %}
-{% endfor %}
-{% endif %}
-
{% if include_ipsec_secrets is defined %}
include {{ include_ipsec_secrets }}
{% endif %}
diff --git a/data/templates/ipsec/swanctl.conf.tmpl b/data/templates/ipsec/swanctl.conf.tmpl
index ce007c1fd..ea6d85743 100644
--- a/data/templates/ipsec/swanctl.conf.tmpl
+++ b/data/templates/ipsec/swanctl.conf.tmpl
@@ -1,54 +1,72 @@
# Created by VyOS - manual changes will be overwritten
-{% if profile is defined %}
+{% import 'ipsec/swanctl/profile.tmpl' as profile_tmpl %}
+{% import 'ipsec/swanctl/peer.tmpl' as peer_tmpl %}
+
+{% if profile is defined or site_to_site is defined %}
connections {
-{% for name, profile_conf in profile.items() if profile_conf.disable is not defined and profile_conf.bind is defined and profile_conf.bind.tunnel is defined %}
-{% set dmvpn_ike = ike_group[profile_conf.ike_group] %}
-{% set dmvpn_esp = esp_group[profile_conf.esp_group] %}
-{% for interface in profile_conf.bind.tunnel %}
- dmvpn-{{ name }}-{{ interface }} {
- proposals = {{ ciphers.ike[profile_conf.ike_group][:-1] }}
- version = {{ dmvpn_ike.key_exchange[4:] if "key_exchange" in dmvpn_ike else "0" }}
- rekey_time = {{ dmvpn_ike.lifetime if 'lifetime' in dmvpn_ike else '28800' }}s
- keyingtries = 0
-{% if profile_conf.authentication.mode == 'pre-shared-secret' %}
- local {
- auth = psk
- }
- remote {
- auth = psk
- }
-{% endif %}
- children {
- dmvpn {
- esp_proposals = {{ ciphers.esp[profile_conf.esp_group][:-1] }}
- rekey_time = {{ dmvpn_esp.lifetime if 'lifetime' in dmvpn_esp else '3600' }}s
- rand_time = 540s
- local_ts = dynamic[gre]
- remote_ts = dynamic[gre]
- mode = {{ dmvpn_esp.mode if "mode" in dmvpn_esp else "transport" }}
-{% if 'dead_peer_detection' in dmvpn_ike and 'action' in dmvpn_ike.dead_peer_detection %}
- dpd_action = {{ dmvpn_ike.dead_peer_detection.action }}
-{% endif %}
-{% if 'compression' in dmvpn_esp and dmvpn_esp['compression'] == 'enable' %}
- ipcomp = yes
-{% endif %}
- }
- }
- }
-{% endfor %}
-{% endfor %}
+{% if profile is defined %}
+{% for name, profile_conf in profile.items() if profile_conf.disable is not defined and profile_conf.bind is defined and profile_conf.bind.tunnel is defined %}
+{% set dmvpn_ike = ike_group[profile_conf.ike_group] %}
+{% set dmvpn_esp = esp_group[profile_conf.esp_group] %}
+{{ profile_tmpl.conn(name, profile_conf, dmvpn_ike, dmvpn_esp, ciphers) }}
+{% endfor %}
+{% endif %}
+{% if site_to_site is defined and site_to_site.peer is defined %}
+{% for peer, peer_conf in site_to_site.peer.items() if peer not in dhcp_no_address and peer_conf.disable is not defined %}
+{% set peer_conn_name = peer.replace(".", "-").replace("@", "") %}
+{% 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) }}
+{% endfor %}
+{% endif %}
}
secrets {
-{% for name, profile_conf in profile.items() if profile_conf.disable is not defined and profile_conf.bind is defined and profile_conf.bind.tunnel is defined %}
-{% if profile_conf.authentication.mode == 'pre-shared-secret' %}
-{% for interface in profile_conf.bind.tunnel %}
+{% if profile is defined %}
+{% for name, profile_conf in profile.items() if profile_conf.disable is not defined and profile_conf.bind is defined and profile_conf.bind.tunnel is defined %}
+{% if profile_conf.authentication.mode == 'pre-shared-secret' %}
+{% for interface in profile_conf.bind.tunnel %}
ike-dmvpn-{{ interface }} {
secret = {{ profile_conf.authentication.pre_shared_secret }}
}
-{% endfor %}
-{% endif %}
-{% endfor %}
+{% endfor %}
+{% endif %}
+{% endfor %}
+{% endif %}
+{% if site_to_site is defined and site_to_site.peer is defined %}
+{% set ns = namespace(local_key_set=False) %}
+{% for peer, peer_conf in site_to_site.peer.items() if peer not in dhcp_no_address and peer_conf.disable is not defined %}
+{% set peer_conn_name = peer.replace(".", "-").replace("@", "") %}
+{% if peer_conf.authentication.mode == 'pre-shared-secret' %}
+ ike_{{ peer_conn_name }} {
+{% if peer_conf.local_address is defined %}
+ id-local = {{ peer_conf.local_address }} # dhcp:{{ peer_conf.dhcp_interface if 'dhcp_interface' in peer_conf else 'no' }}
+{% endif %}
+ id-remote = {{ peer }}
+{% if peer_conf.authentication.id is defined %}
+ id-localid = {{ peer_conf.authentication.id }}
+{% endif %}
+{% if peer_conf.authentication.remote_id is defined %}
+ id-remoteid = {{ peer_conf.authentication.remote_id }}
+{% endif %}
+ secret = "{{ peer_conf.authentication.pre_shared_secret }}"
+ }
+{% elif peer_conf.authentication.mode == 'x509' %}
+ private_{{ peer_conn_name }} {
+ file = {{ peer_conf.authentication.x509.key.file }}
+{% if "password" in peer_conf.authentication.x509.key and peer_conf.authentication.x509.key.password %}
+ secret = "{{ peer_conf.authentication.x509.key.password}}"
+{% endif %}
+ }
+{% elif peer_conf.authentication.mode == 'rsa' and not ns.local_key_set %}
+{% set ns.local_key_set = True %}
+ rsa_local {
+ file = {{ rsa_local_key }}
+ }
+{% endif %}
+{% endfor %}
+{% endif %}
}
-{% endif %}
+{% endif %}
diff --git a/data/templates/ipsec/swanctl/peer.tmpl b/data/templates/ipsec/swanctl/peer.tmpl
new file mode 100644
index 000000000..0d01cd546
--- /dev/null
+++ b/data/templates/ipsec/swanctl/peer.tmpl
@@ -0,0 +1,136 @@
+{% macro conn(name, peer, peer_conf, ike, esp, ciphers, esp_group, auth_type, marks) %}
+ peer_{{ name }} {
+ proposals = {{ ciphers.ike[peer_conf.ike_group] }}
+ version = {{ ike['key_exchange'][4:] if "key_exchange" in ike else "0" }}
+ local_addrs = {{ peer_conf.local_address if peer_conf.local_address != 'any' else '0.0.0.0/0' }} # dhcp:{{ peer_conf.dhcp_interface if 'dhcp_interface' in peer_conf else 'no' }}
+ remote_addrs = {{ peer if peer not in ['any', '0.0.0.0'] and peer[0:1] != '@' else '0.0.0.0/0' }}
+{% if peer_conf.authentication.mode == 'x509' %}
+ send_cert = always
+{% endif %}
+{% if "dead_peer_detection" in ike %}
+ dpd_timeout = {{ ike.dead_peer_detection.timeout }}
+ dpd_delay = {{ ike.dead_peer_detection.interval }}
+{% endif %}
+{% if "key_exchange" in ike and ike.key_exchange == "ikev1" and "mode" in ike and ike.mode == "aggressive" %}
+ aggressive = yes
+{% endif %}
+ mobike = {{ "yes" if "mobike" not in ike or ike.mobike == "enable" else "no" }}
+{% if peer[0:1] == '@' %}
+ keyingtries = 0
+ rekey_time = 0
+ reauth_time = 0
+{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %}
+ keyingtries = 0
+{% elif peer_conf.connection_type is defined and peer_conf.connection_type == 'respond' %}
+ keyingtries = 1
+{% endif %}
+{% if peer_conf.force_encapsulation is defined and peer_conf.force_encapsulation == 'enable' %}
+ encap = yes
+{% endif %}
+ local {
+{% if peer_conf.authentication.id is defined and peer_conf.authentication.use_x509_id is not defined %}
+ id = "{{ peer_conf.authentication.id }}"
+{% endif %}
+{% if auth_type %}
+ auth = {{ auth_type }}
+{% endif %}
+{% if peer_conf.authentication.mode == 'x509' %}
+ certs = {{ peer_conf.authentication.x509.cert_file }}
+{% elif peer_conf.authentication.mode == 'rsa' %}
+ pubkeys = localhost.pub
+{% endif %}
+ }
+ remote {
+{% if peer_conf.authentication.remote_id is defined %}
+ id = "{{ peer_conf.authentication.remote_id }}"
+{% elif peer[0:1] == '@' %}
+ id = "{{ peer }}"
+{% endif %}
+{% if auth_type %}
+ auth = {{ auth_type }}
+{% endif %}
+{% if peer_conf.authentication.mode == 'rsa' %}
+ pubkeys = {{ peer_conf.authentication.rsa_key_name }}.pub
+{% endif %}
+ }
+ children {
+{% if peer_conf.vti is defined and peer_conf.vti.bind is defined and peer_conf.tunnel is not defined %}
+{% set vti_esp = esp_group[peer_conf.vti.esp_group] if peer_conf.vti.esp_group is defined else None %}
+ peer_{{ name }}_vti {
+ esp_proposals = {{ ciphers.esp[peer_conf.vti.esp_group] }}
+ 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] }}
+ 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] == '@' %}
+ start_action = none
+{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %}
+ start_action = start
+{% elif peer_conf.connection_type == 'respond' %}
+ start_action = trap
+{% endif %}
+{% if "dead_peer_detection" in ike %}
+{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'start'} %}
+ dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }}
+{% endif %}
+ }
+{% endif %}
+{% if peer_conf.tunnel is defined %}
+{% for tunnel_id, tunnel_conf in peer_conf.tunnel.items() if tunnel_conf.disable is not defined %}
+{% set tunnel_esp_name = tunnel_conf.esp_group if "esp_group" in tunnel_conf else peer_conf.default_esp_group %}
+{% set tunnel_esp = esp_group[tunnel_esp_name] %}
+{% set proto = tunnel_conf.protocol if "protocol" in tunnel_conf else '' %}
+{% set local_port = tunnel_conf.local.port if tunnel_conf.local is defined and tunnel_conf.local.port is defined else '' %}
+{% set local_suffix = '[{0}/{1}]'.format(proto, local_port) if proto or local_port else '' %}
+{% set remote_port = tunnel_conf.remote.port if tunnel_conf.remote is defined and tunnel_conf.remote.port is defined else '' %}
+{% set remote_suffix = '[{0}/{1}]'.format(proto, remote_port) if proto or remote_port else '' %}
+ peer_{{ name }}_tunnel_{{ tunnel_id }} {
+ esp_proposals = {{ ciphers.esp[tunnel_esp_name] }}
+{% if tunnel_esp.mode is not defined or tunnel_esp.mode == 'tunnel' %}
+{% if tunnel_conf.local is defined and tunnel_conf.local.prefix is defined %}
+{% set local_prefix = tunnel_conf.local.prefix if 'any' not in tunnel_conf.local.prefix else ['0.0.0.0/0', '::/0'] %}
+ local_ts = {{ local_prefix | join(local_suffix + ",") }}{{ local_suffix }}
+{% endif %}
+{% if tunnel_conf.remote is defined and tunnel_conf.remote.prefix is defined %}
+{% set remote_prefix = tunnel_conf.remote.prefix if 'any' not in tunnel_conf.remote.prefix else ['0.0.0.0/0', '::/0'] %}
+ remote_ts = {{ remote_prefix | join(remote_suffix + ",") }}{{ remote_suffix }}
+{% endif %}
+{% elif tunnel_esp.mode == 'transport' %}
+ local_ts = {{ peer_conf.local_address }}{{ local_suffix }}
+ remote_ts = {{ peer }}{{ remote_suffix }}
+{% endif %}
+ ipcomp = {{ 'yes' if "compression" in tunnel_esp and tunnel_esp.compression == 'enable' else 'no' }}
+ mode = {{ tunnel_esp.mode if "mode" in tunnel_esp else "tunnel" }}
+{% if peer[0:1] == '@' %}
+ start_action = none
+{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %}
+ start_action = start
+{% elif peer_conf.connection_type == 'respond' %}
+ start_action = trap
+{% endif %}
+{% if "dead_peer_detection" in ike %}
+{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'start'} %}
+ dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }}
+{% 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] }}
+{% endif %}
+ }
+{% if tunnel_conf.passthrough is defined and tunnel_conf.passthrough %}
+ peer_{{ name }}_tunnel_{{ tunnel_id }}_passthough {
+ local_ts = {{ tunnel_conf.passthrough | join(",") }}
+ remote_ts = {{ tunnel_conf.passthrough | join(",") }}
+ start_action = trap
+ mode = pass
+ }
+{% endif %}
+{% endfor %}
+{% endif %}
+ }
+ }
+{% endmacro %}
diff --git a/data/templates/ipsec/swanctl/profile.tmpl b/data/templates/ipsec/swanctl/profile.tmpl
new file mode 100644
index 000000000..e4b36b99f
--- /dev/null
+++ b/data/templates/ipsec/swanctl/profile.tmpl
@@ -0,0 +1,34 @@
+{% macro conn(name, profile_conf, ike, esp, ciphers) %}
+{% for interface in profile_conf.bind.tunnel %}
+ dmvpn-{{ name }}-{{ interface }} {
+ proposals = {{ ciphers.ike[profile_conf.ike_group] }}
+ version = {{ ike.key_exchange[4:] if "key_exchange" in ike else "0" }}
+ rekey_time = {{ ike.lifetime if 'lifetime' in ike else '28800' }}s
+ keyingtries = 0
+{% if profile_conf.authentication.mode == 'pre-shared-secret' %}
+ local {
+ auth = psk
+ }
+ remote {
+ auth = psk
+ }
+{% endif %}
+ children {
+ dmvpn {
+ esp_proposals = {{ ciphers.esp[profile_conf.esp_group] }}
+ rekey_time = {{ esp.lifetime if 'lifetime' in esp else '3600' }}s
+ rand_time = 540s
+ local_ts = dynamic[gre]
+ remote_ts = dynamic[gre]
+ mode = {{ esp.mode if "mode" in esp else "transport" }}
+{% if 'dead_peer_detection' in ike and 'action' in ike.dead_peer_detection %}
+ dpd_action = {{ ike.dead_peer_detection.action }}
+{% endif %}
+{% if 'compression' in esp and esp['compression'] == 'enable' %}
+ ipcomp = yes
+{% endif %}
+ }
+ }
+ }
+{% endfor %}
+{% endmacro %}
diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in
index d7435d6df..2031217ba 100644
--- a/interface-definitions/vpn_ipsec.xml.in
+++ b/interface-definitions/vpn_ipsec.xml.in
@@ -969,44 +969,6 @@
</valueHelp>
</properties>
<children>
- <leafNode name="allow-nat-networks">
- <properties>
- <help>Option to allow NAT networks</help>
- <completionHelp>
- <list>enable disable</list>
- </completionHelp>
- <valueHelp>
- <format>enable</format>
- <description>Enable NAT networks</description>
- </valueHelp>
- <valueHelp>
- <format>disable</format>
- <description>Disable NAT networks (default)</description>
- </valueHelp>
- <constraint>
- <regex>^(enable|disable)$</regex>
- </constraint>
- </properties>
- </leafNode>
- <leafNode name="allow-public-networks">
- <properties>
- <help>Option to allow public networks</help>
- <completionHelp>
- <list>enable disable</list>
- </completionHelp>
- <valueHelp>
- <format>enable</format>
- <description>Enable public networks</description>
- </valueHelp>
- <valueHelp>
- <format>disable</format>
- <description>Disable public networks (default)</description>
- </valueHelp>
- <constraint>
- <regex>^(enable|disable)$</regex>
- </constraint>
- </properties>
- </leafNode>
#include <include/generic-disable-node.xml.i>
<leafNode name="esp-group">
<properties>
@@ -1049,6 +1011,7 @@
<validator name="ipv4-prefix"/>
<validator name="ipv6-prefix"/>
</constraint>
+ <multi/>
</properties>
</leafNode>
</children>
@@ -1087,6 +1050,7 @@
<validator name="ipv4-prefix"/>
<validator name="ipv6-prefix"/>
</constraint>
+ <multi/>
</properties>
</leafNode>
</children>
diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py
index 627d73d5c..b27ed3ca5 100755
--- a/smoketest/scripts/cli/test_vpn_ipsec.py
+++ b/smoketest/scripts/cli/test_vpn_ipsec.py
@@ -23,16 +23,19 @@ from vyos.util import call, process_named_running, read_file
ethernet_path = ['interfaces', 'ethernet']
tunnel_path = ['interfaces', 'tunnel']
+vti_path = ['interfaces', 'vti']
nhrp_path = ['protocols', 'nhrp']
base_path = ['vpn', 'ipsec']
dhcp_waiting_file = '/tmp/ipsec_dhcp_waiting'
+swanctl_file = '/etc/swanctl/swanctl.conf'
class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
def tearDown(self):
self.cli_delete(base_path)
self.cli_delete(nhrp_path)
self.cli_delete(tunnel_path)
+ self.cli_delete(vti_path)
self.cli_delete(ethernet_path)
self.cli_commit()
@@ -77,6 +80,7 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "dh-group", "2"])
self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "encryption", "aes128"])
self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "hash", "sha1"])
+ self.cli_set(base_path + ["ike-group", "MyIKEGroup", "key-exchange", "ikev2"])
# Site to site
self.cli_set(base_path + ["ipsec-interfaces", "interface", "eth0"])
@@ -85,33 +89,104 @@ class TestVPNIPsec(VyOSUnitTestSHIM.TestCase):
self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "ike-group", "MyIKEGroup"])
self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "default-esp-group", "MyESPGroup"])
self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "local-address", "192.0.2.10"])
- self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "protocol", "gre"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "protocol", "tcp"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "prefix", "172.16.10.0/24"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "prefix", "172.16.11.0/24"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "port", "443"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "prefix", "172.17.10.0/24"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "prefix", "172.17.11.0/24"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "port", "443"])
self.cli_commit()
- ipsec_conf_lines = [
- 'authby = secret',
- 'ike = aes128-sha1-modp1024!',
- 'esp = aes128-sha1-modp1024!',
- 'left = 192.0.2.10',
- 'right = 203.0.113.45',
- 'type = tunnel'
+ swanctl_conf_lines = [
+ 'version = 2',
+ 'auth = psk',
+ 'proposals = aes128-sha1-modp1024',
+ 'esp_proposals = aes128-sha1-modp1024',
+ 'local_addrs = 192.0.2.10 # dhcp:no',
+ 'remote_addrs = 203.0.113.45',
+ 'mode = tunnel',
+ 'local_ts = 172.16.10.0/24[tcp/443],172.16.11.0/24[tcp/443]',
+ 'remote_ts = 172.17.10.0/24[tcp/443],172.17.11.0/24[tcp/443]'
+ ]
+
+ swanctl_secrets_lines = [
+ 'id-local = 192.0.2.10 # dhcp:no',
+ 'id-remote = 203.0.113.45',
+ 'secret = "MYSECRETKEY"'
]
- ipsec_secrets_lines = [
- '192.0.2.10 203.0.113.45 : PSK "MYSECRETKEY" # dhcp:no'
+ tmp_swanctl_conf = read_file(swanctl_file)
+
+ for line in swanctl_conf_lines:
+ self.assertIn(line, tmp_swanctl_conf)
+
+ for line in swanctl_secrets_lines:
+ self.assertIn(line, tmp_swanctl_conf)
+
+ # Check for running process
+ self.assertTrue(process_named_running('charon'))
+
+ def test_site_to_site_vti(self):
+ self.cli_delete(base_path)
+ self.cli_delete(vti_path)
+
+ # VTI interface
+ self.cli_set(vti_path + ["vti10", "address", "10.1.1.1/24"])
+
+ # IKE/ESP Groups
+ self.cli_set(base_path + ["esp-group", "MyESPGroup", "proposal", "1", "encryption", "aes128"])
+ self.cli_set(base_path + ["esp-group", "MyESPGroup", "proposal", "1", "hash", "sha1"])
+ self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "dh-group", "2"])
+ self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "encryption", "aes128"])
+ self.cli_set(base_path + ["ike-group", "MyIKEGroup", "proposal", "1", "hash", "sha1"])
+ self.cli_set(base_path + ["ike-group", "MyIKEGroup", "key-exchange", "ikev2"])
+
+ # Site to site
+ self.cli_set(base_path + ["ipsec-interfaces", "interface", "eth0"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "authentication", "mode", "pre-shared-secret"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "authentication", "pre-shared-secret", "MYSECRETKEY"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "ike-group", "MyIKEGroup"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "default-esp-group", "MyESPGroup"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "local-address", "192.0.2.10"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "prefix", "172.16.10.0/24"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "local", "prefix", "172.16.11.0/24"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "prefix", "172.17.10.0/24"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "tunnel", "1", "remote", "prefix", "172.17.11.0/24"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "vti", "bind", "vti10"])
+ self.cli_set(base_path + ["site-to-site", "peer", "203.0.113.45", "vti", "esp-group", "MyESPGroup"])
+
+ self.cli_commit()
+
+ swanctl_conf_lines = [
+ 'version = 2',
+ 'auth = psk',
+ 'proposals = aes128-sha1-modp1024',
+ 'esp_proposals = aes128-sha1-modp1024',
+ 'local_addrs = 192.0.2.10 # dhcp:no',
+ 'remote_addrs = 203.0.113.45',
+ 'mode = tunnel',
+ 'local_ts = 172.16.10.0/24,172.16.11.0/24',
+ 'remote_ts = 172.17.10.0/24,172.17.11.0/24',
+ 'mark_in = 9437194', # 0x900000 + (vti)10
+ 'mark_out = 9437194',
+ 'updown = "/etc/ipsec.d/vti-up-down vti10 no"'
]
- tmp_ipsec_conf = read_file('/etc/ipsec.conf')
+ swanctl_secrets_lines = [
+ 'id-local = 192.0.2.10 # dhcp:no',
+ 'id-remote = 203.0.113.45',
+ 'secret = "MYSECRETKEY"'
+ ]
- for line in ipsec_conf_lines:
- self.assertIn(line, tmp_ipsec_conf)
+ tmp_swanctl_conf = read_file(swanctl_file)
- call('sudo chmod 644 /etc/ipsec.secrets') # Needs to be readable
- tmp_ipsec_secrets = read_file('/etc/ipsec.secrets')
+ for line in swanctl_conf_lines:
+ self.assertIn(line, tmp_swanctl_conf)
- for line in ipsec_secrets_lines:
- self.assertIn(line, tmp_ipsec_secrets)
+ for line in swanctl_secrets_lines:
+ self.assertIn(line, tmp_swanctl_conf)
# Check for running process
self.assertTrue(process_named_running('charon'))
diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py
index f80a9455a..433c51e7e 100755
--- a/src/conf_mode/vpn_ipsec.py
+++ b/src/conf_mode/vpn_ipsec.py
@@ -28,7 +28,6 @@ from vyos.template import render
from vyos.validate import is_ipv6_link_local
from vyos.util import call
from vyos.util import dict_search
-from vyos.util import get_interface_address
from vyos.util import process_named_running
from vyos.util import run
from vyos.util import cidr_fit
@@ -37,9 +36,9 @@ from vyos import airbag
airbag.enable()
authby_translate = {
- 'pre-shared-secret': 'secret',
- 'rsa': 'rsasig',
- 'x509': 'rsasig'
+ 'pre-shared-secret': 'psk',
+ 'rsa': 'pubkey',
+ 'x509': 'pubkey'
}
default_pfs = 'dh-group2'
pfs_translate = {
@@ -80,8 +79,10 @@ dhcp_wait_sleep = 1
mark_base = 0x900000
-CA_PATH = "/etc/ipsec.d/cacerts/"
-CRL_PATH = "/etc/ipsec.d/crls/"
+CERT_PATH="/etc/swanctl/x509/"
+KEY_PATH="/etc/swanctl/private/"
+CA_PATH = "/etc/swanctl/x509ca/"
+CRL_PATH = "/etc/swanctl/x509crl/"
DHCP_BASE = "/var/lib/dhcp/dhclient"
DHCP_HOOK_IFLIST="/tmp/ipsec_dhcp_waiting"
@@ -126,7 +127,7 @@ def get_config(config=None):
if enc and hash:
ciphers.append(f"{enc}-{hash}-{pfs_translate[pfs]}" if pfs else f"{enc}-{hash}")
- ike_ciphers[group] = ','.join(ciphers) + '!'
+ ike_ciphers[group] = ','.join(ciphers)
if 'esp_group' in ipsec:
for group, esp_conf in ipsec['esp_group'].items():
@@ -146,7 +147,7 @@ def get_config(config=None):
hash = proposal['hash'] if 'hash' in proposal else None
if enc and hash:
ciphers.append(f"{enc}-{hash}-{pfs_translate[pfs]}" if pfs else f"{enc}-{hash}")
- esp_ciphers[group] = ','.join(ciphers) + '!'
+ esp_ciphers[group] = ','.join(ciphers)
return ipsec
@@ -324,7 +325,6 @@ def generate(ipsec):
data['ciphers'] = {'ike': ike_ciphers, 'esp': esp_ciphers}
data['marks'] = {}
data['rsa_local_key'] = verify_rsa_local_key(ipsec)
- data['x509_path'] = X509_PATH
if 'site_to_site' in data and 'peer' in data['site_to_site']:
for peer, peer_conf in ipsec['site_to_site']['peer'].items():
@@ -332,6 +332,12 @@ def generate(ipsec):
continue
if peer_conf['authentication']['mode'] == 'x509':
+ cert_file = os.path.join(X509_PATH, peer_conf['authentication']['x509']['cert_file'])
+ call(f'cp -f {cert_file} {CERT_PATH}')
+
+ key_file = os.path.join(X509_PATH, peer_conf['authentication']['x509']['key']['file'])
+ call(f'cp -f {key_file} {KEY_PATH}')
+
ca_cert_file = os.path.join(X509_PATH, peer_conf['authentication']['x509']['ca_cert_file'])
call(f'cp -f {ca_cert_file} {CA_PATH}')
@@ -350,15 +356,22 @@ def generate(ipsec):
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)
- else:
+
+ if 'tunnel' in peer_conf:
for tunnel, tunnel_conf in peer_conf['tunnel'].items():
- local_prefix = dict_search('local.prefix', tunnel_conf)
- remote_prefix = dict_search('remote.prefix', tunnel_conf)
+ local_prefixes = dict_search('local.prefix', tunnel_conf)
+ remote_prefixes = dict_search('remote.prefix', tunnel_conf)
- if not local_prefix or not remote_prefix:
+ if not local_prefixes or not remote_prefixes:
continue
- passthrough = cidr_fit(local_prefix, remote_prefix)
+ passthrough = []
+
+ for local_prefix in local_prefixes:
+ for remote_prefix in remote_prefixes:
+ if cidr_fit(local_prefix, remote_prefix):
+ passthrough.append(local_prefix)
+
data['site_to_site']['peer'][peer]['tunnel'][tunnel]['passthrough'] = passthrough
if 'logging' in ipsec and 'log_modes' in ipsec['logging']:
diff --git a/src/conf_mode/vpn_rsa-keys.py b/src/conf_mode/vpn_rsa-keys.py
index 6cf7eba6e..c6ff369ad 100755
--- a/src/conf_mode/vpn_rsa-keys.py
+++ b/src/conf_mode/vpn_rsa-keys.py
@@ -29,7 +29,8 @@ from Crypto.PublicKey.RSA import construct
airbag.enable()
LOCAL_KEY_PATHS = ['/config/auth/', '/config/ipsec.d/rsa-keys/']
-LOCAL_OUTPUT = '/etc/ipsec.d/certs/localhost.pub'
+LOCAL_OUTPUT = '/etc/swanctl/pubkey/localhost.pub'
+LOCAL_KEY_OUTPUT = '/etc/swanctl/private/localhost.key'
def get_config(config=None):
if config:
@@ -68,6 +69,7 @@ def generate(conf):
if 'local_key' in conf and 'file' in conf['local_key']:
local_key = conf['local_key']['file']
local_key_path = get_local_key(local_key)
+ call(f'sudo cp -f {local_key_path} {LOCAL_KEY_OUTPUT}')
call(f'sudo /usr/bin/openssl rsa -in {local_key_path} -pubout -out {LOCAL_OUTPUT}')
if 'rsa_key_name' in conf:
@@ -82,7 +84,7 @@ def generate(conf):
else:
remote_key = bytes('-----BEGIN PUBLIC KEY-----\n' + remote_key + '\n-----END PUBLIC KEY-----\n', 'utf-8')
- with open(f'/etc/ipsec.d/certs/{key_name}.pub', 'wb') as f:
+ with open(f'/etc/swanctl/pubkey/{key_name}.pub', 'wb') as f:
f.write(remote_key)
def migrate_from_vyatta_key(data):
diff --git a/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook b/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook
index e00e5fe6e..a7a9a2ce6 100755
--- a/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook
+++ b/src/etc/dhcp/dhclient-exit-hooks.d/ipsec-dhclient-hook
@@ -1,4 +1,18 @@
#!/bin/bash
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
if [ "$reason" == "REBOOT" ] || [ "$reason" == "EXPIRE" ]; then
exit 0
@@ -24,8 +38,7 @@ import re
from vyos.util import call
from vyos.util import cmd
-IPSEC_CONF="/etc/ipsec.conf"
-IPSEC_SECRETS="/etc/ipsec.secrets"
+SWANCTL_CONF="/etc/swanctl/swanctl.conf"
def getlines(file):
with open(file, 'r') as f:
@@ -41,7 +54,7 @@ def ipsec_down(ip_address):
connection_name = None
for line in status.split("\n"):
if line.find(ip_address) > 0:
- regex_match = re.search(r'(peer-[^:\[]+)', line)
+ regex_match = re.search(r'(peer_[^:\[]+)', line)
if regex_match:
connection_name = regex_match[1]
break
@@ -53,8 +66,7 @@ if __name__ == '__main__':
new_ip = os.getenv('new_ip_address')
old_ip = os.getenv('old_ip_address')
- conf_lines = getlines(IPSEC_CONF)
- secrets_lines = getlines(IPSEC_SECRETS)
+ conf_lines = getlines(SWANCTL_CONF)
found = False
to_match = f'# dhcp:{interface}'
@@ -68,9 +80,9 @@ if __name__ == '__main__':
secrets_lines[i] = line.replace(old_ip, new_ip)
if found:
- writelines(IPSEC_CONF, conf_lines)
- writelines(IPSEC_SECRETS, secrets_lines)
+ writelines(SWANCTL_CONF, conf_lines)
ipsec_down(old_ip)
- call('sudo /usr/sbin/ipsec rereadall')
- call('sudo /usr/sbin/ipsec reload')
+ call('sudo ipsec rereadall')
+ call('sudo ipsec reload')
+ call('sudo swanctl -q')
PYEND \ No newline at end of file
diff --git a/src/etc/ipsec.d/vti-up-down b/src/etc/ipsec.d/vti-up-down
index 0e1cd7753..2b66dd9e6 100755
--- a/src/etc/ipsec.d/vti-up-down
+++ b/src/etc/ipsec.d/vti-up-down
@@ -1,4 +1,18 @@
#!/usr/bin/env python3
+#
+# Copyright (C) 2021 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
## Script called up strongswan to bring the vti interface up/down based on the state of the IPSec tunnel.
## Called as vti_up_down vti_intf_name
diff --git a/src/op_mode/vpn_ike_sa.py b/src/op_mode/vpn_ike_sa.py
index 28da9f8dc..fe016da45 100755
--- a/src/op_mode/vpn_ike_sa.py
+++ b/src/op_mode/vpn_ike_sa.py
@@ -36,9 +36,9 @@ def ike_sa(peer, nat):
peers = []
for conn in sas:
for name, sa in conn.items():
- if peer and not name.startswith('peer-' + peer):
+ if peer and not name.startswith('peer_' + peer):
continue
- if name.startswith('peer-') and name in peers:
+ if name.startswith('peer_') and name in peers:
continue
if nat and 'nat-local' not in sa:
continue
diff --git a/src/op_mode/vpn_ipsec.py b/src/op_mode/vpn_ipsec.py
index 434186abb..582b5ef95 100755
--- a/src/op_mode/vpn_ipsec.py
+++ b/src/op_mode/vpn_ipsec.py
@@ -100,13 +100,13 @@ def generate_x509_pair(name):
print(f'Private key: {X509_PATH}{name}.key')
def get_peer_connections(peer, tunnel, return_all = False):
- search = rf'^conn (peer-{peer}-(tunnel-[\d]+|vti))$'
+ search = rf'^[\s]*(peer_{peer}_(tunnel_[\d]+|vti)).*'
matches = []
- with open(IPSEC_CONF, 'r') as f:
+ with open(SWANCTL_CONF, 'r') as f:
for line in f.readlines():
result = re.match(search, line)
if result:
- suffix = f'tunnel-{tunnel}' if tunnel.isnumeric() else tunnel
+ suffix = f'tunnel_{tunnel}' if tunnel.isnumeric() else tunnel
if return_all or (result[2] == suffix):
matches.append(result[1])
return matches
@@ -171,13 +171,14 @@ def debug_peer(peer, tunnel):
if not tunnel or tunnel == 'all':
tunnel = ''
- conn = get_peer_connection(peer, tunnel)
+ conn = get_peer_connections(peer, tunnel)
- if not conn:
+ if not conns:
print('Peer not found, aborting')
return
- call(f'sudo /usr/sbin/ipsec statusall | grep {conn}')
+ for conn in conns:
+ call(f'sudo /usr/sbin/ipsec statusall | grep {conn}')
if __name__ == '__main__':
parser = argparse.ArgumentParser()