From 1a859a97f840d0205670eb96ff4fbc0dbe263b7e Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 2 Jul 2021 22:12:43 +0200 Subject: xml: provide building block for a generic description node --- interface-definitions/firewall.xml.in | 18 +++++------ .../include/firewall/common-rule.xml.i | 2 +- .../include/firewall/description.xml.i | 11 ------- .../include/generic-description.xml.i | 11 +++++++ .../include/policy/description.xml.i | 11 ------- interface-definitions/policy.xml.in | 36 +++++++++++----------- interface-definitions/vpn_ipsec.xml.in | 9 ++---- 7 files changed, 41 insertions(+), 57 deletions(-) delete mode 100644 interface-definitions/include/firewall/description.xml.i create mode 100644 interface-definitions/include/generic-description.xml.i delete mode 100644 interface-definitions/include/policy/description.xml.i diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in index 5528d6bc5..f07c619a8 100644 --- a/interface-definitions/firewall.xml.in +++ b/interface-definitions/firewall.xml.in @@ -91,7 +91,7 @@ - #include + #include @@ -112,7 +112,7 @@ - #include + #include @@ -120,7 +120,7 @@ Network-group member - #include + #include Network-group member @@ -141,7 +141,7 @@ Firewall network-group - #include + #include Network-group member @@ -162,7 +162,7 @@ Firewall port-group - #include + #include Port-group member @@ -210,15 +210,15 @@ #include - #include #include + #include Rule number (1-9999) #include - #include + #include Destination parameters @@ -578,15 +578,15 @@ #include - #include #include + #include Rule number (1-9999) #include - #include + #include Destination parameters diff --git a/interface-definitions/include/firewall/common-rule.xml.i b/interface-definitions/include/firewall/common-rule.xml.i index 466599e0a..1ee8da73d 100644 --- a/interface-definitions/include/firewall/common-rule.xml.i +++ b/interface-definitions/include/firewall/common-rule.xml.i @@ -1,6 +1,6 @@ #include -#include +#include Option to disable firewall rule diff --git a/interface-definitions/include/firewall/description.xml.i b/interface-definitions/include/firewall/description.xml.i deleted file mode 100644 index b6bae406b..000000000 --- a/interface-definitions/include/firewall/description.xml.i +++ /dev/null @@ -1,11 +0,0 @@ - - - - Description - - txt - Description - - - - diff --git a/interface-definitions/include/generic-description.xml.i b/interface-definitions/include/generic-description.xml.i new file mode 100644 index 000000000..03fc564e6 --- /dev/null +++ b/interface-definitions/include/generic-description.xml.i @@ -0,0 +1,11 @@ + + + + Description + + txt + Description + + + + diff --git a/interface-definitions/include/policy/description.xml.i b/interface-definitions/include/policy/description.xml.i deleted file mode 100644 index e2ff35d02..000000000 --- a/interface-definitions/include/policy/description.xml.i +++ /dev/null @@ -1,11 +0,0 @@ - - - - Description - - txt - Description - - - - diff --git a/interface-definitions/policy.xml.in b/interface-definitions/policy.xml.in index 6a002cc20..5a3c58fa8 100644 --- a/interface-definitions/policy.xml.in +++ b/interface-definitions/policy.xml.in @@ -27,7 +27,7 @@ - #include + #include Rule for this access-list @@ -41,7 +41,7 @@ #include - #include + #include Destination network or address @@ -87,7 +87,7 @@ - #include + #include Rule for this access-list6 @@ -101,7 +101,7 @@ #include - #include + #include Source IPv6 network to match @@ -146,7 +146,7 @@ - #include + #include Rule for this as-path-list @@ -160,7 +160,7 @@ #include - #include + #include Regular expression to match against an AS path @@ -183,7 +183,7 @@ - #include + #include Rule for this BGP community list @@ -197,7 +197,7 @@ #include - #include + #include Regular expression to match against a community-list @@ -243,7 +243,7 @@ - #include + #include Rule for this BGP extended community list @@ -257,7 +257,7 @@ #include - #include + #include Regular expression to match against an extended community list @@ -288,7 +288,7 @@ - #include + #include Rule for this BGP extended community list @@ -302,7 +302,7 @@ #include - #include + #include Regular expression to match against a large community list @@ -329,7 +329,7 @@ Name of prefix-list can only contain alpha-numeric letters, hyphen and underscores - #include + #include Rule for this prefix-list @@ -343,7 +343,7 @@ #include - #include + #include Prefix length to match a netmask greater than or equal to it @@ -397,7 +397,7 @@ Name of prefix-list6 can only contain alpha-numeric letters, hyphen and underscores - #include + #include Rule for this prefix-list6 @@ -411,7 +411,7 @@ #include - #include + #include Prefix length to match a netmask greater than or equal to it @@ -465,7 +465,7 @@ Name of route-map can only contain alpha-numeric letters, hyphen and underscores - #include + #include Rule for this route-map @@ -500,7 +500,7 @@ - #include + #include Route parameters to match diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index 7b1b3a595..f51c2fc92 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -708,7 +708,7 @@ - Site to site VPN + Site-to-site VPN @@ -837,12 +837,7 @@ - - - VPN peer description - - - + #include DHCP interface to listen on -- cgit v1.2.3 From ff004bee54df0b298c56e91b5f41dda075d35220 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Fri, 2 Jul 2021 22:16:38 +0200 Subject: ipsec: T2816: adjust Jinja2 template to coding style * use indent = 2 * prefer 'if foo.bar is defined' over 'if "bar" in foo' --- data/templates/ipsec/swanctl.conf.tmpl | 86 +++++++++--------- data/templates/ipsec/swanctl/peer.tmpl | 146 +++++++++++++++--------------- data/templates/ipsec/swanctl/profile.tmpl | 26 +++--- 3 files changed, 130 insertions(+), 128 deletions(-) diff --git a/data/templates/ipsec/swanctl.conf.tmpl b/data/templates/ipsec/swanctl.conf.tmpl index 0ff08ee15..116d62beb 100644 --- a/data/templates/ipsec/swanctl.conf.tmpl +++ b/data/templates/ipsec/swanctl.conf.tmpl @@ -1,72 +1,72 @@ -# Created by VyOS - manual changes will be overwritten +### Autogenerated by vpn_ipsec.py ### {% 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 { -{% 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) }} -{% endfor %} -{% endif %} +{% 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) }} +{% endfor %} +{% endif %} } secrets { -{% 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 %} +{% 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 %} -{% 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' %} +{% 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 %} +{% 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 %} +{% endif %} id-remote = {{ peer }} -{% if peer_conf.authentication.id is defined %} +{% if peer_conf.authentication.id is defined %} id-localid = {{ peer_conf.authentication.id }} -{% endif %} -{% if peer_conf.authentication.remote_id is defined %} +{% endif %} +{% if peer_conf.authentication.remote_id is defined %} id-remoteid = {{ peer_conf.authentication.remote_id }} -{% endif %} +{% endif %} secret = "{{ peer_conf.authentication.pre_shared_secret }}" } -{% elif peer_conf.authentication.mode == 'x509' %} +{% elif peer_conf.authentication.mode == 'x509' %} private_{{ peer_conn_name }} { file = {{ peer_conf.authentication.x509.certificate }}.pem -{% if peer_conf.authentication.x509.passphrase is defined %} +{% if peer_conf.authentication.x509.passphrase is defined %} secret = "{{ peer_conf.authentication.x509.passphrase }}" -{% endif %} +{% endif %} } -{% elif peer_conf.authentication.mode == 'rsa' and not ns.local_key_set %} -{% set ns.local_key_set = True %} +{% 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 %} +{% endfor %} +{% endif %} } {% endif %} diff --git a/data/templates/ipsec/swanctl/peer.tmpl b/data/templates/ipsec/swanctl/peer.tmpl index c97ac1f67..7cc3fa29f 100644 --- a/data/templates/ipsec/swanctl/peer.tmpl +++ b/data/templates/ipsec/swanctl/peer.tmpl @@ -1,61 +1,61 @@ {% 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" }} + version = {{ ike.key_exchange[4:] if ike.key_exchange is defined 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' %} +{% if peer_conf.authentication is defined and peer_conf.authentication.mode is defined and peer_conf.authentication.mode == 'x509' %} send_cert = always -{% endif %} -{% if "dead_peer_detection" in ike %} +{% endif %} +{% if ike.dead_peer_detection is defined %} 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" %} +{% endif %} +{% if ike.key_exchange is defined and ike.key_exchange == "ikev1" and ike.mode is defined and ike.mode == "aggressive" %} aggressive = yes -{% endif %} - mobike = {{ "yes" if "mobike" not in ike or ike.mobike == "enable" else "no" }} -{% if peer[0:1] == '@' %} +{% endif %} + mobike = {{ "yes" if ike.mobike is not defined 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' %} +{% 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' %} +{% 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' %} +{% endif %} +{% if peer_conf.force_encapsulation is defined and peer_conf.force_encapsulation == 'enable' %} encap = yes -{% endif %} +{% endif %} local { -{% if peer_conf.authentication.id is defined and peer_conf.authentication.use_x509_id is not defined %} +{% 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 %} +{% endif %} +{% if auth_type %} auth = {{ auth_type }} -{% endif %} -{% if peer_conf.authentication.mode == 'x509' %} +{% endif %} +{% if peer_conf.authentication.mode == 'x509' %} certs = {{ peer_conf.authentication.x509.certificate }}.pem -{% elif peer_conf.authentication.mode == 'rsa' %} +{% elif peer_conf.authentication.mode == 'rsa' %} pubkeys = localhost.pub -{% endif %} +{% endif %} } remote { -{% if peer_conf.authentication.remote_id is defined %} +{% if peer_conf.authentication.remote_id is defined %} id = "{{ peer_conf.authentication.remote_id }}" -{% elif peer[0:1] == '@' %} +{% elif peer[0:1] == '@' %} id = "{{ peer }}" -{% endif %} -{% if auth_type %} +{% endif %} +{% if auth_type %} auth = {{ auth_type }} -{% endif %} -{% if peer_conf.authentication.mode == 'rsa' %} +{% endif %} +{% if peer_conf.authentication.mode == 'rsa' %} pubkeys = {{ peer_conf.authentication.rsa_key_name }}.pub -{% endif %} +{% 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 %} +{% 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 @@ -63,74 +63,74 @@ updown = "/etc/ipsec.d/vti-up-down {{ peer_conf.vti.bind }} {{ peer_conf.dhcp_interface if peer_conf.dhcp_interface is defined else 'no' }}" 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] == '@' %} + ipcomp = {{ 'yes' if vti_esp.compression is defined and vti_esp.compression == 'enable' else 'no' }} + mode = {{ vti_esp.mode if vti_esp.mode is defined else "tunnel" }} +{% if peer[0:1] == '@' %} start_action = none -{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %} +{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %} start_action = start -{% elif peer_conf.connection_type == 'respond' %} +{% 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'} %} +{% endif %} +{% if ike.dead_peer_detection is defined %} +{% set dpd_translate = {'clear': 'clear', 'hold': 'trap', 'restart': 'start'} %} dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} -{% endif %} +{% 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 '' %} +{% 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 tunnel_conf.esp_group is defined else peer_conf.default_esp_group %} +{% set tunnel_esp = esp_group[tunnel_esp_name] %} +{% set proto = tunnel_conf.protocol if tunnel_conf.protocol is defined 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'] %} +{% 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'] %} +{% 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' %} +{% 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] == '@' %} +{% endif %} + ipcomp = {{ 'yes' if tunnel_esp.compression is defined and tunnel_esp.compression == 'enable' else 'no' }} + mode = {{ tunnel_esp.mode if tunnel_esp.mode is defined else "tunnel" }} +{% if peer[0:1] == '@' %} start_action = none -{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %} +{% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %} start_action = start -{% elif peer_conf.connection_type == 'respond' %} +{% 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'} %} +{% endif %} +{% if ike.dead_peer_detection is defined %} +{% 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 %} +{% 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' }}" if_id_in = {{ peer_conf.vti.bind | replace('vti', '') }} if_id_out = {{ peer_conf.vti.bind | replace('vti', '') }} -{% endif %} +{% endif %} } -{% if tunnel_conf.passthrough is defined and tunnel_conf.passthrough %} +{% 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 %} +{% endif %} +{% endfor %} +{% endif %} } } {% endmacro %} diff --git a/data/templates/ipsec/swanctl/profile.tmpl b/data/templates/ipsec/swanctl/profile.tmpl index e4b36b99f..f6f6f4d70 100644 --- a/data/templates/ipsec/swanctl/profile.tmpl +++ b/data/templates/ipsec/swanctl/profile.tmpl @@ -1,34 +1,36 @@ {% macro conn(name, profile_conf, ike, esp, ciphers) %} -{% for interface in profile_conf.bind.tunnel %} +{% if profile_conf.bind is defined and profile_conf.bind.tunnel is defined %} +{% 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 + version = {{ ike.key_exchange[4:] if ike.key_exchange is defined else "0" }} + rekey_time = {{ ike.lifetime if ike.lifetime is defined else '28800' }}s keyingtries = 0 -{% if profile_conf.authentication.mode == 'pre-shared-secret' %} +{% if profile_conf.authentication is defined and profile_conf.authentication.mode is defined and profile_conf.authentication.mode == 'pre-shared-secret' %} local { auth = psk } remote { auth = psk } -{% endif %} +{% endif %} children { dmvpn { esp_proposals = {{ ciphers.esp[profile_conf.esp_group] }} - rekey_time = {{ esp.lifetime if 'lifetime' in esp else '3600' }}s + rekey_time = {{ esp.lifetime if esp.lifetime is defined 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 %} + mode = {{ esp.mode if esp.mode is defined else "transport" }} +{% if ike.dead_peer_detection is defined and ike.dead_peer_detection.action is defined %} dpd_action = {{ ike.dead_peer_detection.action }} -{% endif %} -{% if 'compression' in esp and esp['compression'] == 'enable' %} +{% endif %} +{% if esp.compression is defined and esp.compression == 'enable' %} ipcomp = yes -{% endif %} +{% endif %} } } } -{% endfor %} +{% endfor %} +{% endif %} {% endmacro %} -- cgit v1.2.3 From 2d79a5000c8a02fd7570f629c3182fd55fdb8c86 Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 3 Jul 2021 11:40:19 +0000 Subject: ipsec: T2816: add Jinja2 converter for ESP/IKE groups to string --- python/vyos/template.py | 46 +++++++++++++++++++++++++++++++++++ src/tests/test_template.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/python/vyos/template.py b/python/vyos/template.py index 5c12e9914..f03fd7ee7 100644 --- a/python/vyos/template.py +++ b/python/vyos/template.py @@ -387,3 +387,49 @@ def get_ip(interface): """ Get interface IP addresses""" from vyos.ifconfig import Interface return Interface(interface).get_addr() + +@register_filter('get_esp_ike_cipher') +def get_esp_ike_cipher(group_config): + pfs_lut = { + 'dh-group1' : 'modp768', + 'dh-group2' : 'modp1024', + 'dh-group5' : 'modp1536', + 'dh-group14' : 'modp2048', + 'dh-group15' : 'modp3072', + 'dh-group16' : 'modp4096', + 'dh-group17' : 'modp6144', + 'dh-group18' : 'modp8192', + 'dh-group19' : 'ecp256', + 'dh-group20' : 'ecp384', + 'dh-group21' : 'ecp512', + 'dh-group22' : 'modp1024s160', + 'dh-group23' : 'modp2048s224', + 'dh-group24' : 'modp2048s256', + 'dh-group25' : 'ecp192', + 'dh-group26' : 'ecp224', + 'dh-group27' : 'ecp224bp', + 'dh-group28' : 'ecp256bp', + 'dh-group29' : 'ecp384bp', + 'dh-group30' : 'ecp512bp', + 'dh-group31' : 'curve25519', + 'dh-group32' : 'curve448' + } + + ciphers = [] + if 'proposal' in group_config: + for priority, proposal in group_config['proposal'].items(): + # both encryption and hash need to be specified for a proposal + if not {'encryption', 'hash'} <= set(proposal): + continue + + tmp = '{encryption}-{hash}'.format(**proposal) + if 'dh_group' in proposal: + tmp += '-' + pfs_lut[ 'dh-group' + proposal['dh_group'] ] + elif 'pfs' in group_config and group_config['pfs'] != 'disable': + group = group_config['pfs'] + if group_config['pfs'] == 'enable': + group = 'dh-group2' + tmp += '-' + pfs_lut[group] + + ciphers.append(tmp) + return ciphers diff --git a/src/tests/test_template.py b/src/tests/test_template.py index 67c0fe84a..2d065f545 100644 --- a/src/tests/test_template.py +++ b/src/tests/test_template.py @@ -122,3 +122,63 @@ class TestVyOSTemplate(TestCase): self.assertTrue(vyos.template.compare_netmask('2001:db8:1000::/48', '2001:db8:2000::/48')) self.assertTrue(vyos.template.compare_netmask('2001:db8:1000::/64', '2001:db8:2000::/64')) self.assertFalse(vyos.template.compare_netmask('2001:db8:1000::/48', '2001:db8:2000::/64')) + + def test_cipher_to_string(self): + ESP_DEFAULT = 'aes256gcm128-sha256-ecp256,aes128ccm64-sha256-ecp256' + IKEv2_DEFAULT = 'aes256gcm128-sha256-ecp256,aes128ccm128-md5_128-modp1024' + + data = { + 'esp_group': { + 'ESP_DEFAULT': { + 'compression': 'disable', + 'lifetime': '3600', + 'mode': 'tunnel', + 'pfs': 'dh-group19', + 'proposal': { + '10': { + 'encryption': 'aes256gcm128', + 'hash': 'sha256', + }, + '20': { + 'encryption': 'aes128ccm64', + 'hash': 'sha256', + } + } + } + }, + 'ike_group': { + 'IKEv2_DEFAULT': { + 'close_action': 'none', + 'dead_peer_detection': { + 'action': 'hold', + 'interval': '30', + 'timeout': '120' + }, + 'ikev2_reauth': 'no', + 'key_exchange': 'ikev2', + 'lifetime': '10800', + 'mobike': 'disable', + 'proposal': { + '10': { + 'dh_group': '19', + 'encryption': 'aes256gcm128', + 'hash': 'sha256' + }, + '20': { + 'dh_group': '2', + 'encryption': 'aes128ccm128', + 'hash': 'md5_128' + }, + } + } + }, + } + + for group_name, group_config in data['esp_group'].items(): + ciphers = vyos.template.get_esp_ike_cipher(group_config) + self.assertIn(ESP_DEFAULT, ','.join(ciphers)) + + for group_name, group_config in data['ike_group'].items(): + ciphers = vyos.template.get_esp_ike_cipher(group_config) + self.assertIn(IKEv2_DEFAULT, ','.join(ciphers)) + -- cgit v1.2.3 From a1abb118c9eb413f3c78cfb2077f9c0d4b443c3a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 3 Jul 2021 15:31:38 +0200 Subject: ipsec: T2816: rework IKE and ESP key assignment Commit 2d79a500 ("ipsec: T2816: add Jinja2 converter for ESP/IKE groups to string") added a Jinja2 helper function which can be used to transform VyOS CLI ESP and IKE key proposals into a strongSwan compatible string cipher. This commit changes the IPSec implementation to make use of this new Jinja2 filter fubction/Python helper. This is required base work for better automated tests (smoketests) but also for an IKEv2 road-warrior setup. --- data/templates/ipsec/swanctl.conf.tmpl | 34 +++--- data/templates/ipsec/swanctl/peer.tmpl | 24 ++--- data/templates/ipsec/swanctl/profile.tmpl | 13 ++- interface-definitions/vpn_ipsec.xml.in | 46 ++++---- smoketest/scripts/cli/test_vpn_ipsec.py | 5 +- src/conf_mode/vpn_ipsec.py | 167 +++++++++--------------------- 6 files changed, 105 insertions(+), 184 deletions(-) diff --git a/data/templates/ipsec/swanctl.conf.tmpl b/data/templates/ipsec/swanctl.conf.tmpl index 116d62beb..cafe52e78 100644 --- a/data/templates/ipsec/swanctl.conf.tmpl +++ b/data/templates/ipsec/swanctl.conf.tmpl @@ -1,25 +1,17 @@ ### Autogenerated by vpn_ipsec.py ### - {% 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 { -{% 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) }} -{% 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 %} +{{ profile_tmpl.conn(name, profile_conf, ike_group, esp_group) }} +{% 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 %} +{{ peer_tmpl.conn(peer, peer_conf, ike_group, esp_group) }} +{% endfor %} {% endif %} } @@ -38,9 +30,9 @@ secrets { {% 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("@", "") %} +{% set peer_name = peer.replace(".", "-").replace("@", "") %} {% if peer_conf.authentication.mode == 'pre-shared-secret' %} - ike_{{ peer_conn_name }} { + ike_{{ peer_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 %} @@ -54,7 +46,7 @@ secrets { secret = "{{ peer_conf.authentication.pre_shared_secret }}" } {% elif peer_conf.authentication.mode == 'x509' %} - private_{{ peer_conn_name }} { + private_{{ peer_name }} { file = {{ peer_conf.authentication.x509.certificate }}.pem {% if peer_conf.authentication.x509.passphrase is defined %} secret = "{{ peer_conf.authentication.x509.passphrase }}" @@ -69,4 +61,4 @@ secrets { {% endfor %} {% endif %} } -{% endif %} + diff --git a/data/templates/ipsec/swanctl/peer.tmpl b/data/templates/ipsec/swanctl/peer.tmpl index 7cc3fa29f..0559d1dac 100644 --- a/data/templates/ipsec/swanctl/peer.tmpl +++ b/data/templates/ipsec/swanctl/peer.tmpl @@ -1,7 +1,10 @@ -{% macro conn(name, peer, peer_conf, ike, esp, ciphers, esp_group, auth_type) %} +{% macro conn(peer, peer_conf, ike_group, esp_group) %} +{% set name = peer.replace(".", "-").replace("@", "") %} +{# peer needs to reference the global IKE configuration for certain values #} +{% set ike = ike_group[peer_conf.ike_group] %} peer_{{ name }} { - proposals = {{ ciphers.ike[peer_conf.ike_group] }} - version = {{ ike.key_exchange[4:] if ike.key_exchange is defined else "0" }} + proposals = {{ ike | get_esp_ike_cipher | join(',') }} + version = {{ ike.key_exchange[4:] if ike is defined and ike.key_exchange is defined 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 is defined and peer_conf.authentication.mode is defined and peer_conf.authentication.mode == 'x509' %} @@ -31,9 +34,7 @@ {% 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 %} + auth = {{ 'psk' if peer_conf.authentication.mode == 'pre-shared-secret' else 'pubkey' }} {% if peer_conf.authentication.mode == 'x509' %} certs = {{ peer_conf.authentication.x509.certificate }}.pem {% elif peer_conf.authentication.mode == 'rsa' %} @@ -46,9 +47,7 @@ {% elif peer[0:1] == '@' %} id = "{{ peer }}" {% endif %} -{% if auth_type %} - auth = {{ auth_type }} -{% endif %} + auth = {{ 'psk' if peer_conf.authentication.mode == 'pre-shared-secret' else 'pubkey' }} {% if peer_conf.authentication.mode == 'rsa' %} pubkeys = {{ peer_conf.authentication.rsa_key_name }}.pub {% endif %} @@ -57,7 +56,7 @@ {% 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] }} + esp_proposals = {{ vti_esp | get_esp_ike_cipher | join(',') }} 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' }}" @@ -77,8 +76,7 @@ dpd_action = {{ dpd_translate[ike.dead_peer_detection.action] }} {% endif %} } -{% endif %} -{% if peer_conf.tunnel is defined %} +{% 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 tunnel_conf.esp_group is defined else peer_conf.default_esp_group %} {% set tunnel_esp = esp_group[tunnel_esp_name] %} @@ -88,7 +86,7 @@ {% 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] }} + esp_proposals = {{ esp_group[peer_conf.default_esp_group] | get_esp_ike_cipher | join(',') }} {% 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'] %} diff --git a/data/templates/ipsec/swanctl/profile.tmpl b/data/templates/ipsec/swanctl/profile.tmpl index f6f6f4d70..0360972f6 100644 --- a/data/templates/ipsec/swanctl/profile.tmpl +++ b/data/templates/ipsec/swanctl/profile.tmpl @@ -1,9 +1,12 @@ -{% macro conn(name, profile_conf, ike, esp, ciphers) %} +{% macro conn(name, profile_conf, ike_group, esp_group) %} +{# peer needs to reference the global IKE configuration for certain values #} +{% set ike = ike_group[profile_conf.ike_group] %} +{% set esp = esp_group[profile_conf.esp_group] %} {% if profile_conf.bind is defined and profile_conf.bind.tunnel is defined %} {% for interface in profile_conf.bind.tunnel %} dmvpn-{{ name }}-{{ interface }} { - proposals = {{ ciphers.ike[profile_conf.ike_group] }} - version = {{ ike.key_exchange[4:] if ike.key_exchange is defined else "0" }} + proposals = {{ ike_group[profile_conf.ike_group] | get_esp_ike_cipher | join(',') }} + version = {{ ike.key_exchange[4:] if ike is defined and ike.key_exchange is defined else "0" }} rekey_time = {{ ike.lifetime if ike.lifetime is defined else '28800' }}s keyingtries = 0 {% if profile_conf.authentication is defined and profile_conf.authentication.mode is defined and profile_conf.authentication.mode == 'pre-shared-secret' %} @@ -16,12 +19,12 @@ {% endif %} children { dmvpn { - esp_proposals = {{ ciphers.esp[profile_conf.esp_group] }} + esp_proposals = {{ esp | get_esp_ike_cipher | join(',') }} rekey_time = {{ esp.lifetime if esp.lifetime is defined else '3600' }}s rand_time = 540s local_ts = dynamic[gre] remote_ts = dynamic[gre] - mode = {{ esp.mode if esp.mode is defined else "transport" }} + mode = {{ esp.mode if esp.mode is defined else 'transport' }} {% if ike.dead_peer_detection is defined and ike.dead_peer_detection.action is defined %} dpd_action = {{ ike.dead_peer_detection.action }} {% endif %} diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index f51c2fc92..6aff7bef5 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -92,95 +92,95 @@ enable - Enable PFS. Use ike-groups dh-group (default) + Use Diffie-Hellman group 2 (modp1024) - default dh-group1 - Enable PFS. Use Diffie-Hellman group 1 (modp768) + Use Diffie-Hellman group 1 (modp768) dh-group2 - Enable PFS. Use Diffie-Hellman group 2 (modp1024) + Use Diffie-Hellman group 2 (modp1024) dh-group5 - Enable PFS. Use Diffie-Hellman group 5 (modp1536) + Use Diffie-Hellman group 5 (modp1536) dh-group14 - Enable PFS. Use Diffie-Hellman group 14 (modp2048) + Use Diffie-Hellman group 14 (modp2048) dh-group15 - Enable PFS. Use Diffie-Hellman group 15 (modp3072) + Use Diffie-Hellman group 15 (modp3072) dh-group16 - Enable PFS. Use Diffie-Hellman group 16 (modp4096) + Use Diffie-Hellman group 16 (modp4096) dh-group17 - Enable PFS. Use Diffie-Hellman group 17 (modp6144) + Use Diffie-Hellman group 17 (modp6144) dh-group18 - Enable PFS. Use Diffie-Hellman group 18 (modp8192) + Use Diffie-Hellman group 18 (modp8192) dh-group19 - Enable PFS. Use Diffie-Hellman group 19 (ecp256) + Use Diffie-Hellman group 19 (ecp256) dh-group20 - Enable PFS. Use Diffie-Hellman group 20 (ecp384) + Use Diffie-Hellman group 20 (ecp384) dh-group21 - Enable PFS. Use Diffie-Hellman group 21 (ecp521) + Use Diffie-Hellman group 21 (ecp521) dh-group22 - Enable PFS. Use Diffie-Hellman group 22 (modp1024s160) + Use Diffie-Hellman group 22 (modp1024s160) dh-group23 - Enable PFS. Use Diffie-Hellman group 23 (modp2048s224) + Use Diffie-Hellman group 23 (modp2048s224) dh-group24 - Enable PFS. Use Diffie-Hellman group 24 (modp2048s256) + Use Diffie-Hellman group 24 (modp2048s256) dh-group25 - Enable PFS. Use Diffie-Hellman group 25 (ecp192) + Use Diffie-Hellman group 25 (ecp192) dh-group26 - Enable PFS. Use Diffie-Hellman group 26 (ecp224) + Use Diffie-Hellman group 26 (ecp224) dh-group27 - Enable PFS. Use Diffie-Hellman group 27 (ecp224bp) + Use Diffie-Hellman group 27 (ecp224bp) dh-group28 - Enable PFS. Use Diffie-Hellman group 28 (ecp256bp) + Use Diffie-Hellman group 28 (ecp256bp) dh-group29 - Enable PFS. Use Diffie-Hellman group 29 (ecp384bp) + Use Diffie-Hellman group 29 (ecp384bp) dh-group30 - Enable PFS. Use Diffie-Hellman group 30 (ecp512bp) + Use Diffie-Hellman group 30 (ecp512bp) dh-group31 - Enable PFS. Use Diffie-Hellman group 31 (curve25519) + Use Diffie-Hellman group 31 (curve25519) dh-group32 - Enable PFS. Use Diffie-Hellman group 32 (curve448) + Use Diffie-Hellman group 32 (curve448) disable diff --git a/smoketest/scripts/cli/test_vpn_ipsec.py b/smoketest/scripts/cli/test_vpn_ipsec.py index 9c0ad2075..fda8b74b1 100755 --- a/smoketest/scripts/cli/test_vpn_ipsec.py +++ b/smoketest/scripts/cli/test_vpn_ipsec.py @@ -18,8 +18,9 @@ import os import unittest from base_vyostest_shim import VyOSUnitTestSHIM - -from vyos.util import call, process_named_running, read_file +from vyos.util import call +from vyos.util import process_named_running +from vyos.util import read_file ethernet_path = ['interfaces', 'ethernet'] tunnel_path = ['interfaces', 'tunnel'] diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index ce72ee094..e95a3e82d 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -39,46 +39,11 @@ from vyos import ConfigError from vyos import airbag airbag.enable() -authby_translate = { - 'pre-shared-secret': 'psk', - 'rsa': 'pubkey', - 'x509': 'pubkey' -} - -default_pfs = 'dh-group2' -pfs_translate = { - 'dh-group1' : 'modp768', - 'dh-group2' : 'modp1024', - 'dh-group5' : 'modp1536', - 'dh-group14' : 'modp2048', - 'dh-group15' : 'modp3072', - 'dh-group16' : 'modp4096', - 'dh-group17' : 'modp6144', - 'dh-group18' : 'modp8192', - 'dh-group19' : 'ecp256', - 'dh-group20' : 'ecp384', - 'dh-group21' : 'ecp512', - 'dh-group22' : 'modp1024s160', - 'dh-group23' : 'modp2048s224', - 'dh-group24' : 'modp2048s256', - 'dh-group25' : 'ecp192', - 'dh-group26' : 'ecp224', - 'dh-group27' : 'ecp224bp', - 'dh-group28' : 'ecp256bp', - 'dh-group29' : 'ecp384bp', - 'dh-group30' : 'ecp512bp', - 'dh-group31' : 'curve25519', - 'dh-group32' : 'curve448' -} - any_log_modes = [ 'dmn', 'mgr', 'ike', 'chd','job', 'cfg', 'knl', 'net', 'asn', 'enc', 'lib', 'esp', 'tls', 'tnc', 'imc', 'imv', 'pts' ] -ike_ciphers = {} -esp_ciphers = {} - dhcp_wait_attempts = 2 dhcp_wait_sleep = 1 @@ -113,52 +78,18 @@ def get_config(config=None): get_first_key=True, no_tag_node_value_mangle=True) ipsec['dhcp_no_address'] = {} - ipsec['interface_change'] = leaf_node_changed(conf, base + ['ipsec-interfaces', 'interface']) - ipsec['l2tp_exists'] = conf.exists(['vpn', 'l2tp', 'remote-access', 'ipsec-settings']) + ipsec['interface_change'] = leaf_node_changed(conf, base + ['ipsec-interfaces', + 'interface']) + ipsec['l2tp_exists'] = conf.exists(['vpn', 'l2tp', 'remote-access', + 'ipsec-settings']) ipsec['nhrp_exists'] = conf.exists(['protocols', 'nhrp', 'tunnel']) ipsec['pki'] = conf.get_config_dict(['pki'], key_mangling=('-', '_'), - get_first_key=True, no_tag_node_value_mangle=True) - ipsec['rsa_keys'] = conf.get_config_dict(['vpn', 'rsa-keys'], key_mangling=('-', '_'), - get_first_key=True, no_tag_node_value_mangle=True) - - default_ike_pfs = None - - if 'ike_group' in ipsec: - for group, ike_conf in ipsec['ike_group'].items(): - if 'proposal' in ike_conf: - ciphers = [] - for i in ike_conf['proposal']: - proposal = ike_conf['proposal'][i] - enc = proposal['encryption'] if 'encryption' in proposal else None - hash = proposal['hash'] if 'hash' in proposal else None - pfs = ('dh-group' + proposal['dh_group']) if 'dh_group' in proposal else default_pfs - - if not default_ike_pfs: - default_ike_pfs = pfs - - if enc and hash: - ciphers.append(f"{enc}-{hash}-{pfs_translate[pfs]}" if pfs else f"{enc}-{hash}") - ike_ciphers[group] = ','.join(ciphers) - - if 'esp_group' in ipsec: - for group, esp_conf in ipsec['esp_group'].items(): - pfs = esp_conf['pfs'] if 'pfs' in esp_conf else 'enable' - - if pfs == 'disable': - pfs = None - - if pfs == 'enable': - pfs = default_ike_pfs - - if 'proposal' in esp_conf: - ciphers = [] - for i in esp_conf['proposal']: - proposal = esp_conf['proposal'][i] - enc = proposal['encryption'] if 'encryption' in proposal else 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) + get_first_key=True, + no_tag_node_value_mangle=True) + ipsec['rsa_keys'] = conf.get_config_dict(['vpn', 'rsa-keys'], + key_mangling=('-', '_'), + get_first_key=True, + no_tag_node_value_mangle=True) return ipsec @@ -361,58 +292,54 @@ def generate(ipsec): os.unlink(config_file) return - data = {} - if ipsec: - if ipsec['dhcp_no_address']: - with open(DHCP_HOOK_IFLIST, 'w') as f: - f.write(" ".join(ipsec['dhcp_no_address'].values())) + if ipsec['dhcp_no_address']: + with open(DHCP_HOOK_IFLIST, 'w') as f: + f.write(" ".join(ipsec['dhcp_no_address'].values())) - data = ipsec - data['authby'] = authby_translate - data['ciphers'] = {'ike': ike_ciphers, 'esp': esp_ciphers} - data['rsa_local_key'] = verify_rsa_local_key(ipsec) + data = ipsec + data['rsa_local_key'] = verify_rsa_local_key(ipsec) - for path in [swanctl_dir, CERT_PATH, CA_PATH, CRL_PATH]: - if not os.path.exists(path): - os.mkdir(path, mode=0o755) + for path in [swanctl_dir, CERT_PATH, CA_PATH, CRL_PATH]: + if not os.path.exists(path): + os.mkdir(path, mode=0o755) - if not os.path.exists(KEY_PATH): - os.mkdir(KEY_PATH, mode=0o700) + if not os.path.exists(KEY_PATH): + os.mkdir(KEY_PATH, mode=0o700) - if 'site_to_site' in data and 'peer' in data['site_to_site']: - for peer, peer_conf in ipsec['site_to_site']['peer'].items(): - if peer in ipsec['dhcp_no_address']: - continue + if 'site_to_site' in data and 'peer' in data['site_to_site']: + for peer, peer_conf in ipsec['site_to_site']['peer'].items(): + if peer in ipsec['dhcp_no_address']: + continue - if peer_conf['authentication']['mode'] == 'x509': - generate_pki_files(ipsec['pki'], peer_conf['authentication']['x509']) + if peer_conf['authentication']['mode'] == 'x509': + generate_pki_files(ipsec['pki'], peer_conf['authentication']['x509']) - local_ip = '' - if 'local_address' in peer_conf: - local_ip = peer_conf['local_address'] - elif 'dhcp_interface' in peer_conf: - local_ip = get_dhcp_address(peer_conf['dhcp_interface']) + local_ip = '' + if 'local_address' in peer_conf: + local_ip = peer_conf['local_address'] + elif 'dhcp_interface' in peer_conf: + local_ip = get_dhcp_address(peer_conf['dhcp_interface']) - data['site_to_site']['peer'][peer]['local_address'] = local_ip + data['site_to_site']['peer'][peer]['local_address'] = local_ip - if 'tunnel' in peer_conf: - for tunnel, tunnel_conf in peer_conf['tunnel'].items(): - local_prefixes = dict_search('local.prefix', tunnel_conf) - remote_prefixes = dict_search('remote.prefix', tunnel_conf) + if 'tunnel' in peer_conf: + for tunnel, tunnel_conf in peer_conf['tunnel'].items(): + local_prefixes = dict_search('local.prefix', tunnel_conf) + remote_prefixes = dict_search('remote.prefix', tunnel_conf) - if not local_prefixes or not remote_prefixes: - continue + if not local_prefixes or not remote_prefixes: + continue - passthrough = [] + passthrough = [] - for local_prefix in local_prefixes: - for remote_prefix in remote_prefixes: - local_net = ipaddress.ip_network(local_prefix) - remote_net = ipaddress.ip_network(remote_prefix) - if local_net.overlaps(remote_net): - passthrough.append(local_prefix) + for local_prefix in local_prefixes: + for remote_prefix in remote_prefixes: + local_net = ipaddress.ip_network(local_prefix) + remote_net = ipaddress.ip_network(remote_prefix) + if local_net.overlaps(remote_net): + passthrough.append(local_prefix) - data['site_to_site']['peer'][peer]['tunnel'][tunnel]['passthrough'] = passthrough + data['site_to_site']['peer'][peer]['tunnel'][tunnel]['passthrough'] = passthrough if 'logging' in ipsec and 'log_modes' in ipsec['logging']: modes = ipsec['logging']['log_modes'] @@ -448,7 +375,7 @@ def apply(ipsec): if not ipsec: call('sudo /usr/sbin/ipsec stop') else: - should_start = ('profile' in ipsec or dict_search('site_to_site.peer', ipsec)) + should_start = 'profile' in ipsec or dict_search('site_to_site.peer', ipsec) if not process_named_running('charon') and should_start: args = f'--auto-update {ipsec["auto_update"]}' if 'auto_update' in ipsec else '' -- cgit v1.2.3 From 1e74c0df2179c60036e440e15ed9036163039b2a Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Sat, 3 Jul 2021 15:39:17 +0200 Subject: ipsec: T2816: remove default values from Jinja2 template and place them in XML VyOS has a known to work mechanism in supplying CLI default values into the Python configuration scripts. This commit removes hardcoded default values from the Jinja2 template and places them into the appropriate XML definitions. The big advantage is that the default value itself and the corresponding help string are located in the exact same file. --- data/templates/ipsec/swanctl/peer.tmpl | 4 ++-- data/templates/ipsec/swanctl/profile.tmpl | 6 +++--- interface-definitions/vpn_ipsec.xml.in | 4 ++++ src/conf_mode/vpn_ipsec.py | 15 +++++++++++++++ 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/data/templates/ipsec/swanctl/peer.tmpl b/data/templates/ipsec/swanctl/peer.tmpl index 0559d1dac..b35cd4b60 100644 --- a/data/templates/ipsec/swanctl/peer.tmpl +++ b/data/templates/ipsec/swanctl/peer.tmpl @@ -63,7 +63,7 @@ if_id_in = {{ peer_conf.vti.bind | replace('vti', '') }} if_id_out = {{ peer_conf.vti.bind | replace('vti', '') }} ipcomp = {{ 'yes' if vti_esp.compression is defined and vti_esp.compression == 'enable' else 'no' }} - mode = {{ vti_esp.mode if vti_esp.mode is defined else "tunnel" }} + mode = {{ vti_esp.mode }} {% if peer[0:1] == '@' %} start_action = none {% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %} @@ -101,7 +101,7 @@ remote_ts = {{ peer }}{{ remote_suffix }} {% endif %} ipcomp = {{ 'yes' if tunnel_esp.compression is defined and tunnel_esp.compression == 'enable' else 'no' }} - mode = {{ tunnel_esp.mode if tunnel_esp.mode is defined else "tunnel" }} + mode = {{ tunnel_esp.mode }} {% if peer[0:1] == '@' %} start_action = none {% elif peer_conf.connection_type is not defined or peer_conf.connection_type == 'initiate' %} diff --git a/data/templates/ipsec/swanctl/profile.tmpl b/data/templates/ipsec/swanctl/profile.tmpl index 0360972f6..0a7268405 100644 --- a/data/templates/ipsec/swanctl/profile.tmpl +++ b/data/templates/ipsec/swanctl/profile.tmpl @@ -7,7 +7,7 @@ dmvpn-{{ name }}-{{ interface }} { proposals = {{ ike_group[profile_conf.ike_group] | get_esp_ike_cipher | join(',') }} version = {{ ike.key_exchange[4:] if ike is defined and ike.key_exchange is defined else "0" }} - rekey_time = {{ ike.lifetime if ike.lifetime is defined else '28800' }}s + rekey_time = {{ ike.lifetime }}s keyingtries = 0 {% if profile_conf.authentication is defined and profile_conf.authentication.mode is defined and profile_conf.authentication.mode == 'pre-shared-secret' %} local { @@ -20,11 +20,11 @@ children { dmvpn { esp_proposals = {{ esp | get_esp_ike_cipher | join(',') }} - rekey_time = {{ esp.lifetime if esp.lifetime is defined else '3600' }}s + rekey_time = {{ esp.lifetime }}s rand_time = 540s local_ts = dynamic[gre] remote_ts = dynamic[gre] - mode = {{ esp.mode if esp.mode is defined else 'transport' }} + mode = {{ esp.mode }} {% if ike.dead_peer_detection is defined and ike.dead_peer_detection.action is defined %} dpd_action = {{ ike.dead_peer_detection.action }} {% endif %} diff --git a/interface-definitions/vpn_ipsec.xml.in b/interface-definitions/vpn_ipsec.xml.in index 6aff7bef5..a2e9a7a5a 100644 --- a/interface-definitions/vpn_ipsec.xml.in +++ b/interface-definitions/vpn_ipsec.xml.in @@ -64,6 +64,7 @@ + 3600 @@ -83,6 +84,7 @@ ^(tunnel|transport)$ + tunnel @@ -190,6 +192,7 @@ ^(enable|dh-group1|dh-group2|dh-group5|dh-group14|dh-group15|dh-group16|dh-group17|dh-group18|dh-group19|dh-group20|dh-group21|dh-group22|dh-group23|dh-group24|dh-group25|dh-group26|dh-group27|dh-group28|dh-group29|dh-group30|dh-group31|dh-group32|disable)$ + enable @@ -341,6 +344,7 @@ + 28800 diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index e95a3e82d..6d5d24e52 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -23,6 +23,7 @@ from time import sleep from vyos.config import Config from vyos.configdict import leaf_node_changed from vyos.configverify import verify_interface_exists +from vyos.configdict import dict_merge from vyos.ifconfig import Interface from vyos.pki import wrap_certificate from vyos.pki import wrap_crl @@ -35,6 +36,7 @@ from vyos.util import call from vyos.util import dict_search from vyos.util import process_named_running from vyos.util import run +from vyos.xml import defaults from vyos import ConfigError from vyos import airbag airbag.enable() @@ -77,6 +79,19 @@ def get_config(config=None): ipsec = conf.get_config_dict(base, key_mangling=('-', '_'), get_first_key=True, no_tag_node_value_mangle=True) + if 'esp_group' in ipsec: + default_values = defaults(base + ['esp-group']) + for group in ipsec['esp_group']: + ipsec['esp_group'][group] = dict_merge(default_values, + ipsec['esp_group'][group]) + + if 'ike_group' in ipsec: + default_values = defaults(base + ['ike-group']) + for group in ipsec['ike_group']: + ipsec['ike_group'][group] = dict_merge(default_values, + ipsec['ike_group'][group]) + + ipsec['dhcp_no_address'] = {} ipsec['interface_change'] = leaf_node_changed(conf, base + ['ipsec-interfaces', 'interface']) -- cgit v1.2.3