From b004aaaf7c48946d79febd9d145e20b44e338bd8 Mon Sep 17 00:00:00 2001 From: hwdsl2 Date: Thu, 14 Jan 2021 23:21:52 -0600 Subject: [PATCH] Support .mobileconfig for IKEv2 - New feature: For macOS and iOS clients, the IKEv2 helper script can now create .mobileconfig files to simplify client setup and improve VPN performance with ciphers such as AES-GCM. - New feature: VPN On Demand is now supported on macOS and iOS. See https://git.io/ikev2 for more details. - The script no longer exports the IKEv2 VPN CA certificate, since .mobileconfig support has been added. - A random password is now generated for the .p12 and .mobileconfig files, and displayed on the screen when finished. User input is no longer required for this password. --- extras/ikev2setup.sh | 268 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 217 insertions(+), 51 deletions(-) diff --git a/extras/ikev2setup.sh b/extras/ikev2setup.sh index 2b2ed4c..9009f7b 100644 --- a/extras/ikev2setup.sh +++ b/extras/ikev2setup.sh @@ -30,6 +30,195 @@ check_dns_name() { printf '%s' "$1" | tr -d '\n' | grep -Eq "$FQDN_REGEX" } +create_mobileconfig() { + + bigecho2 "Creating .mobileconfig for iOS and macOS..." + + [ -z "$p12_password" ] && exiterr "Password for .p12 file cannot be empty." + + if [ -z "$server_addr" ]; then + server_addr=$(grep "leftcert=" /etc/ipsec.d/ikev2.conf | cut -f2 -d=) + [ -z "$server_addr" ] && server_addr=$(grep "leftcert=" /etc/ipsec.conf | cut -f2 -d=) + check_ip "$server_addr" || check_dns_name "$server_addr" || exiterr "Could not get VPN server address." + fi + + if ! command -v base64 >/dev/null 2>&1 || ! command -v uuidgen >/dev/null 2>&1; then + if [ "$os_type" = "ubuntu" ] || [ "$os_type" = "debian" ] || [ "$os_type" = "raspbian" ]; then + export DEBIAN_FRONTEND=noninteractive + apt-get -yqq update || exiterr "'apt-get update' failed." + apt-get -yqq install coreutils uuid-runtime || exiterr "'apt-get install' failed." + else + yum -yq install coreutils util-linux || exiterr "'yum install' failed." + fi + fi + + if [ "$in_container" = "0" ]; then + p12_base64=$(base64 -w 52 ~/"$client_name-$SYS_DT.p12") + else + p12_base64=$(base64 -w 52 "/etc/ipsec.d/$client_name-$SYS_DT.p12") + fi + [ -z "$p12_base64" ] && exiterr "Could not encode .p12 file." + + ca_base64=$(certutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -a | grep -v CERTIFICATE) + [ -z "$ca_base64" ] && exiterr "Could not encode IKEv2 VPN CA certificate." + + uuid1=$(uuidgen) + [ -z "$uuid1" ] && exiterr "Could not generate UUID value." + + if [ "$in_container" = "0" ]; then + mc_file=~/"$client_name-$SYS_DT.mobileconfig" + else + mc_file="/etc/ipsec.d/$client_name-$SYS_DT.mobileconfig" + fi + +cat > "$mc_file" < + + + + PayloadContent + + + IKEv2 + + AuthenticationMethod + Certificate + ChildSecurityAssociationParameters + + DiffieHellmanGroup + 14 + EncryptionAlgorithm + AES-256-GCM + LifeTimeInMinutes + 1440 + + DeadPeerDetectionRate + Medium + DisableRedirect + + EnableCertificateRevocationCheck + 0 + EnablePFS + 0 + IKESecurityAssociationParameters + + DiffieHellmanGroup + 14 + EncryptionAlgorithm + AES-256 + IntegrityAlgorithm + SHA2-256 + LifeTimeInMinutes + 1440 + + LocalIdentifier + $client_name + PayloadCertificateUUID + $uuid1 + OnDemandEnabled + 0 + OnDemandRules + + + Action + Connect + + + RemoteAddress + $server_addr + RemoteIdentifier + $server_addr + UseConfigurationAttributeInternalIPSubnet + 0 + + IPv4 + + OverridePrimary + 1 + + PayloadDescription + Configures VPN settings + PayloadDisplayName + VPN + PayloadIdentifier + com.apple.vpn.managed.$(uuidgen) + PayloadType + com.apple.vpn.managed + PayloadUUID + $(uuidgen) + PayloadVersion + 1 + Proxies + + HTTPEnable + 0 + HTTPSEnable + 0 + + UserDefinedName + $server_addr + VPNType + IKEv2 + + + PayloadCertificateFileName + $client_name + PayloadContent + +$p12_base64 + + PayloadDescription + Adds a PKCS#12-formatted certificate + PayloadDisplayName + $client_name + PayloadIdentifier + com.apple.security.pkcs12.$(uuidgen) + PayloadType + com.apple.security.pkcs12 + PayloadUUID + $uuid1 + PayloadVersion + 1 + + + PayloadContent + +$ca_base64 + + PayloadCertificateFileName + ikev2vpnca + PayloadDescription + Adds a CA root certificate + PayloadDisplayName + Certificate Authority (CA) + PayloadIdentifier + com.apple.security.root.$(uuidgen) + PayloadType + com.apple.security.root + PayloadUUID + $(uuidgen) + PayloadVersion + 1 + + + PayloadDisplayName + IKEv2 VPN configuration ($server_addr) + PayloadIdentifier + com.apple.vpn.managed.$(uuidgen) + PayloadRemovalDisallowed + + PayloadType + Configuration + PayloadUUID + $(uuidgen) + PayloadVersion + 1 + + +EOF + +} + new_client() { bigecho2 "Generating client certificate..." @@ -44,31 +233,18 @@ new_client() { --keyUsage digitalSignature,keyEncipherment \ --extKeyUsage serverAuth,clientAuth -8 "$client_name" >/dev/null || exit 1 - if [ "$export_ca" = "1" ]; then - bigecho "Exporting CA certificate 'IKEv2 VPN CA'..." - - if [ "$in_container" = "0" ]; then - certutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -a -o ~/"ikev2vpnca-$SYS_DT.cer" || exit 1 - else - certutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -a -o "/etc/ipsec.d/ikev2vpnca-$SYS_DT.cer" || exit 1 - fi - fi - bigecho "Exporting .p12 file..." -cat <<'EOF' -Enter a *secure* password to protect the exported .p12 file. -This file contains the client certificate, private key, and CA certificate. -When importing into an iOS or macOS device, this password cannot be empty. - -EOF - + p12_password=$(LC_CTYPE=C tr -dc 'A-HJ-NPR-Za-km-z2-9' < /dev/urandom | head -c 16) + [ -z "$p12_password" ] && exiterr "Could not generate a random password for .p12 file." if [ "$in_container" = "0" ]; then - pk12util -d sql:/etc/ipsec.d -n "$client_name" -o ~/"$client_name-$SYS_DT.p12" || exit 1 + pk12util -W "$p12_password" -d sql:/etc/ipsec.d -n "$client_name" -o ~/"$client_name-$SYS_DT.p12" || exit 1 else - pk12util -d sql:/etc/ipsec.d -n "$client_name" -o "/etc/ipsec.d/$client_name-$SYS_DT.p12" || exit 1 + pk12util -W "$p12_password" -d sql:/etc/ipsec.d -n "$client_name" -o "/etc/ipsec.d/$client_name-$SYS_DT.p12" || exit 1 fi + create_mobileconfig + } ikev2setup() { @@ -181,25 +357,12 @@ if grep -qs "conn ikev2-cp" /etc/ipsec.conf || [ -f /etc/ipsec.d/ikev2.conf ]; t [ -z "$client_validity" ] && client_validity=120 done - echo - echo "The CA certificate was exported during initial IKEv2 setup. Required for iOS clients only." - printf "Do you want to export the CA certificate again? [y/N] " - read -r response - case $response in - [yY][eE][sS]|[yY]) - export_ca=1 - ;; - *) - export_ca=0 - ;; - esac - # Create client configuration new_client cat <