From c31488f0e3206c4477692065781e49f2fbd7c9ed Mon Sep 17 00:00:00 2001 From: Christian Poessinger Date: Mon, 26 Jul 2021 21:54:54 +0200 Subject: ipsec: T1210: extend support for iOS profile generation $ generate ipsec mac-ios-profile remote --- src/op_mode/ikev2_profile_generator.py | 104 +++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/op_mode/ikev2_profile_generator.py b/src/op_mode/ikev2_profile_generator.py index 4ff37341c..ce93ec057 100755 --- a/src/op_mode/ikev2_profile_generator.py +++ b/src/op_mode/ikev2_profile_generator.py @@ -19,11 +19,12 @@ import argparse from jinja2 import Template from sys import exit from socket import getfqdn +from cryptography.x509.oid import NameOID from vyos.config import Config -from vyos.template import render_to_string -from cryptography.x509.oid import NameOID from vyos.pki import load_certificate +from vyos.template import render_to_string +from vyos.util import ask_input parser = argparse.ArgumentParser() parser.add_argument("--connection", action="store", help="IPsec IKEv2 remote-access connection name from CLI", required=True) @@ -73,7 +74,102 @@ data['ca_cn'] = ca_cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].v data['cert_cn'] = cert.subject.get_attributes_for_oid(NameOID.COMMON_NAME)[0].value data['ca_cert'] = conf.return_value(pki_base + ['ca', ca_name, 'certificate']) -data['esp_proposal'] = conf.get_config_dict(ipsec_base + ['esp-group', data['esp_group'], 'proposal'], key_mangling=('-', '_'), get_first_key=True) -data['ike_proposal'] = conf.get_config_dict(ipsec_base + ['ike-group', data['ike_group'], 'proposal'], key_mangling=('-', '_'), get_first_key=True) +# Apple profiles only support one IKE/ESP encryption cipher and hash, whereas +# VyOS comes with a multitude of different proposals for a connection. +# +# We take all available proposals from the VyOS CLI and ask the user which one +# he would like to get enabled in his profile - thus there is limited possibility +# to select a proposal that is not supported on the connection profile. +# +# IOS supports IKE-SA encryption algorithms: +# - DES +# - 3DES +# - AES-128 +# - AES-256 +# - AES-128-GCM +# - AES-256-GCM +# - ChaCha20Poly1305 +# +vyos2apple_cipher = { + '3des' : '3DES', + 'aes128' : 'AES-128', + 'aes256' : 'AES-256', + 'aes128gcm128' : 'AES-128-GCM', + 'aes256gcm128' : 'AES-256-GCM', + 'chacha20poly1305' : 'ChaCha20Poly1305', +} + +# IOS supports IKE-SA integrity algorithms: +# - SHA1-96 +# - SHA1-160 +# - SHA2-256 +# - SHA2-384 +# - SHA2-512 +# +vyos2apple_integrity = { + 'sha1' : 'SHA1-96', + 'sha1_160' : 'SHA1-160', + 'sha256' : 'SHA2-256', + 'sha384' : 'SHA2-384', + 'sha512' : 'SHA2-512', +} + +# IOS 14.2 and later do no support dh-group 1,2 and 5. Supported DH groups would +# be: 14, 15, 16, 17, 18, 19, 20, 21, 31 +supported_dh_groups = ['14', '15', '16', '17', '18', '19', '20', '21', '31'] + +esp_proposals = conf.get_config_dict(ipsec_base + ['esp-group', data['esp_group'], 'proposal'], + key_mangling=('-', '_'), get_first_key=True) +ike_proposal = conf.get_config_dict(ipsec_base + ['ike-group', data['ike_group'], 'proposal'], + key_mangling=('-', '_'), get_first_key=True) + +# Create a dictionary containing Apple conform IKE settings +ike = {} +count = 1 +for _, proposal in ike_proposal.items(): + if {'dh_group', 'encryption', 'hash'} <= set(proposal): + if (proposal['encryption'] in set(vyos2apple_cipher) and + proposal['hash'] in set(vyos2apple_integrity) and + proposal['dh_group'] in set(supported_dh_groups)): + + # We 're-code' from the VyOS IPSec proposals to the Apple naming scheme + proposal['encryption'] = vyos2apple_cipher[ proposal['encryption'] ] + proposal['hash'] = vyos2apple_integrity[ proposal['hash'] ] + + ike.update( { str(count) : proposal } ) + count += 1 + +# Create a dictionary containing Apple conform ESP settings +esp = {} +count = 1 +for _, proposal in esp_proposals.items(): + if {'encryption', 'hash'} <= set(proposal): + if proposal['encryption'] in set(vyos2apple_cipher) and proposal['hash'] in set(vyos2apple_integrity): + # We 're-code' from the VyOS IPSec proposals to the Apple naming scheme + proposal['encryption'] = vyos2apple_cipher[ proposal['encryption'] ] + proposal['hash'] = vyos2apple_integrity[ proposal['hash'] ] + + esp.update( { str(count) : proposal } ) + count += 1 +try: + # Propare the input questions for the user + tmp = '\n' + for number, options in ike.items(): + tmp += f'({number}) Encryption {options["encryption"]}, Integrity {options["hash"]}, DH group {options["dh_group"]}\n' + tmp += '\nSelect one of the above IKE groups: ' + data['ike_encryption'] = ike[ ask_input(tmp, valid_responses=list(ike)) ] + + tmp = '\n' + for number, options in esp.items(): + tmp += f'({number}) Encryption {options["encryption"]}, Integrity {options["hash"]}\n' + tmp += '\nSelect one of the above ESP groups: ' + data['esp_encryption'] = esp[ ask_input(tmp, valid_responses=list(esp)) ] + + +except KeyboardInterrupt: + exit("Interrupted") +print('\n\n==== ====') print(render_to_string('ipsec/ios_profile.tmpl', data)) +print('==== ====\n') +print('Save the XML from above to a new file named "vyos.mobileconfig" and E-Mail it to your phone.') -- cgit v1.2.3