1
0
mirror of synced 2024-11-29 16:16:03 +03:00

Update IKEv2 script

- New: Revoke a client certificate using the helper script. Users can
  also manually revoke a client certificate, see https://git.io/ikev2
- Check for certificate validity when exporting client configurations
- Delete CRL from IPsec database when removing IKEv2
- Cleanup
This commit is contained in:
hwdsl2 2021-06-01 02:30:51 -05:00
parent 55b468bb1f
commit ea52ab4683

View File

@ -117,6 +117,7 @@ EOF
check_utils_exist() { check_utils_exist() {
command -v certutil >/dev/null 2>&1 || exiterr "'certutil' not found. Abort." command -v certutil >/dev/null 2>&1 || exiterr "'certutil' not found. Abort."
command -v crlutil >/dev/null 2>&1 || exiterr "'crlutil' not found. Abort."
command -v pk12util >/dev/null 2>&1 || exiterr "'pk12util' not found. Abort." command -v pk12util >/dev/null 2>&1 || exiterr "'pk12util' not found. Abort."
} }
@ -139,6 +140,7 @@ Options:
--addclient [client name] add a new client using default options (after IKEv2 setup) --addclient [client name] add a new client using default options (after IKEv2 setup)
--exportclient [client name] export configuration for an existing client (after IKEv2 setup) --exportclient [client name] export configuration for an existing client (after IKEv2 setup)
--listclients list the names of existing clients (after IKEv2 setup) --listclients list the names of existing clients (after IKEv2 setup)
--revokeclient Revoke a client certificate (after IKEv2 setup)
--removeikev2 remove IKEv2 and delete all certificates and keys from the IPsec database --removeikev2 remove IKEv2 and delete all certificates and keys from the IPsec database
-h, --help show this help message and exit -h, --help show this help message and exit
@ -161,6 +163,10 @@ check_client_cert_exists() {
certutil -L -d sql:/etc/ipsec.d -n "$client_name" >/dev/null 2>&1 certutil -L -d sql:/etc/ipsec.d -n "$client_name" >/dev/null 2>&1
} }
check_client_cert_status() {
cert_status=$(certutil -V -u C -d sql:/etc/ipsec.d -n "$client_name")
}
check_arguments() { check_arguments() {
if [ "$use_defaults" = "1" ]; then if [ "$use_defaults" = "1" ]; then
if check_ikev2_exists; then if check_ikev2_exists; then
@ -168,8 +174,8 @@ check_arguments() {
echo >&2 echo >&2
fi fi
fi fi
if [ "$((add_client + export_client + list_clients))" -gt 1 ]; then if [ "$((add_client + export_client + list_clients + revoke_client))" -gt 1 ]; then
show_usage "Invalid parameters. Specify only one of '--addclient', '--exportclient' or '--listclients'." show_usage "Invalid parameters. Specify only one of '--addclient', '--exportclient', '--listclients' or '--revokeclient'."
fi fi
if [ "$add_client" = "1" ]; then if [ "$add_client" = "1" ]; then
check_ikev2_exists || exiterr "You must first set up IKEv2 before adding a new client." check_ikev2_exists || exiterr "You must first set up IKEv2 before adding a new client."
@ -191,9 +197,27 @@ check_arguments() {
if [ "$list_clients" = "1" ]; then if [ "$list_clients" = "1" ]; then
check_ikev2_exists || exiterr "You must first set up IKEv2 before listing clients." check_ikev2_exists || exiterr "You must first set up IKEv2 before listing clients."
fi fi
if [ "$revoke_client" = "1" ]; then
check_ikev2_exists || exiterr "You must first set up IKEv2 before revoking a client certificate."
get_server_address
if [ -z "$client_name" ] || ! check_client_name \
|| [ "$client_name" = "IKEv2 VPN CA" ] || [ "$client_name" = "$server_addr" ] \
|| ! check_client_cert_exists; then
exiterr "Invalid client name, or client does not exist."
fi
if ! check_client_cert_status; then
if printf '%s' "$cert_status" | grep -q "revoked"; then
exiterr "Certificate '$client_name' has already been revoked."
elif printf '%s' "$cert_status" | grep -q "expired"; then
exiterr "Certificate '$client_name' has expired."
else
exiterr "Certificate '$client_name' is invalid."
fi
fi
fi
if [ "$remove_ikev2" = "1" ]; then if [ "$remove_ikev2" = "1" ]; then
check_ikev2_exists || exiterr "Cannot remove IKEv2 because it has not been set up on this server." check_ikev2_exists || exiterr "Cannot remove IKEv2 because it has not been set up on this server."
if [ "$((add_client + export_client + list_clients + use_defaults))" -gt 0 ]; then if [ "$((add_client + export_client + list_clients + revoke_client + use_defaults))" -gt 0 ]; then
show_usage "Invalid parameters. '--removeikev2' cannot be specified with other parameters." show_usage "Invalid parameters. '--removeikev2' cannot be specified with other parameters."
fi fi
fi fi
@ -428,23 +452,40 @@ enter_client_name_with_defaults() {
done done
} }
enter_client_name_for_export() { enter_client_name_for() {
echo echo
list_existing_clients list_existing_clients
get_server_address get_server_address
echo echo
read -rp "Enter the name of the IKEv2 client to export: " client_name read -rp "Enter the name of the IKEv2 client to $1: " client_name
while [ -z "$client_name" ] || ! check_client_name \ while [ -z "$client_name" ] || ! check_client_name \
|| [ "$client_name" = "IKEv2 VPN CA" ] || [ "$client_name" = "$server_addr" ] \ || [ "$client_name" = "IKEv2 VPN CA" ] || [ "$client_name" = "$server_addr" ] \
|| ! check_client_cert_exists; do || ! check_client_cert_exists || ! check_client_cert_status; do
if [ -z "$client_name" ] || ! check_client_name \
|| [ "$client_name" = "IKEv2 VPN CA" ] || [ "$client_name" = "$server_addr" ] \
|| ! check_client_cert_exists; then
echo "Invalid client name, or client does not exist." echo "Invalid client name, or client does not exist."
read -rp "Enter the name of the IKEv2 client to export: " client_name else
printf '%s' "Error: Certificate '$client_name' "
if printf '%s' "$cert_status" | grep -q "revoked"; then
if [ "$1" = "revoke" ]; then
echo "has already been revoked."
else
echo "has been revoked."
fi
elif printf '%s' "$cert_status" | grep -q "expired"; then
echo "has expired."
else
echo "is invalid."
fi
fi
read -rp "Enter the name of the IKEv2 client to $1: " client_name
done done
} }
enter_client_cert_validity() { enter_client_cert_validity() {
echo echo
echo "Specify the validity period (in months) for this VPN client certificate." echo "Specify the validity period (in months) for this client certificate."
read -rp "Enter a number between 1 and 120: [120] " client_validity read -rp "Enter a number between 1 and 120: [120] " client_validity
[ -z "$client_validity" ] && client_validity=120 [ -z "$client_validity" ] && client_validity=120
while printf '%s' "$client_validity" | LC_ALL=C grep -q '[^0-9]\+' \ while printf '%s' "$client_validity" | LC_ALL=C grep -q '[^0-9]\+' \
@ -587,10 +628,11 @@ select_menu_option() {
echo " 1) Add a new client" echo " 1) Add a new client"
echo " 2) Export configuration for an existing client" echo " 2) Export configuration for an existing client"
echo " 3) List existing clients" echo " 3) List existing clients"
echo " 4) Remove IKEv2" echo " 4) Revoke a client certificate"
echo " 5) Exit" echo " 5) Remove IKEv2"
echo " 6) Exit"
read -rp "Option: " selected_option read -rp "Option: " selected_option
until [[ "$selected_option" =~ ^[1-5]$ ]]; do until [[ "$selected_option" =~ ^[1-6]$ ]]; do
printf '%s\n' "$selected_option: invalid selection." printf '%s\n' "$selected_option: invalid selection."
read -rp "Option: " selected_option read -rp "Option: " selected_option
done done
@ -1049,6 +1091,28 @@ restart_ipsec_service() {
fi fi
} }
create_crl() {
if ! crlutil -L -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" >/dev/null 2>&1; then
crlutil -G -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" -c /dev/null >/dev/null
fi
sleep 2
}
add_client_cert_to_crl() {
sn_txt=$(certutil -L -d sql:/etc/ipsec.d -n "$client_name" | grep -A 1 'Serial Number' | tail -n 1)
sn_hex=$(printf '%s' "$sn_txt" | sed -e 's/^ *//' -e 's/://g')
sn_dec=$((16#$sn_hex))
[ -z "$sn_dec" ] && exiterr "Could not find serial number of client certificate."
crlutil -M -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" >/dev/null <<EOF || exiterr "Failed to add client certificate to CRL."
addcert $sn_dec $(date -u +%Y%m%d%H%M%SZ)
EOF
}
reload_crls() {
/usr/local/sbin/ipsec crls || exiterr "Failed to let Libreswan re-read the updated CRL."
}
print_client_added() { print_client_added() {
cat <<EOF cat <<EOF
@ -1077,6 +1141,11 @@ VPN client name: $client_name
EOF EOF
} }
print_client_revoked() {
echo
echo "Certificate '$client_name' revoked!"
}
show_swan_update_info() { show_swan_update_info() {
if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$' \ if printf '%s' "$swan_ver_latest" | grep -Eq '^([3-9]|[1-9][0-9]{1,2})(\.([0-9]|[1-9][0-9]{1,2})){1,2}$' \
&& [ "$swan_ver" != "$swan_ver_latest" ] \ && [ "$swan_ver" != "$swan_ver_latest" ] \
@ -1155,6 +1224,25 @@ check_ipsec_conf() {
fi fi
} }
confirm_revoke_cert() {
echo
echo "WARNING: You have selected to revoke IKEv2 client certificate '$client_name'."
echo " After revocation, this certificate *cannot* be used by VPN client(s)"
echo " to connect to this VPN server."
echo
printf "Are you sure you want to revoke certificate '%s'? [y/N] " "$client_name"
read -r response
case $response in
[yY][eE][sS]|[yY])
echo
;;
*)
echo "Abort. No changes were made."
exit 1
;;
esac
}
confirm_remove_ikev2() { confirm_remove_ikev2() {
echo echo
echo "WARNING: This option will remove IKEv2 from this VPN server, but keep the IPsec/L2TP" echo "WARNING: This option will remove IKEv2 from this VPN server, but keep the IPsec/L2TP"
@ -1187,6 +1275,7 @@ delete_certificates() {
certutil -F -d sql:/etc/ipsec.d -n "$line" certutil -F -d sql:/etc/ipsec.d -n "$line"
certutil -D -d sql:/etc/ipsec.d -n "$line" 2>/dev/null certutil -D -d sql:/etc/ipsec.d -n "$line" 2>/dev/null
done done
crlutil -D -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" 2>/dev/null
certutil -F -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" certutil -F -d sql:/etc/ipsec.d -n "IKEv2 VPN CA"
certutil -D -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" 2>/dev/null certutil -D -d sql:/etc/ipsec.d -n "IKEv2 VPN CA" 2>/dev/null
} }
@ -1207,6 +1296,7 @@ ikev2setup() {
add_client=0 add_client=0
export_client=0 export_client=0
list_clients=0 list_clients=0
revoke_client=0
remove_ikev2=0 remove_ikev2=0
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
case $1 in case $1 in
@ -1230,6 +1320,12 @@ ikev2setup() {
list_clients=1 list_clients=1
shift shift
;; ;;
--revokeclient)
revoke_client=1
client_name="$2"
shift
shift
;;
--removeikev2) --removeikev2)
remove_ikev2=1 remove_ikev2=1
shift shift
@ -1271,6 +1367,15 @@ ikev2setup() {
exit 0 exit 0
fi fi
if [ "$revoke_client" = "1" ]; then
confirm_revoke_cert
create_crl
add_client_cert_to_crl
reload_crls
print_client_revoked
exit 0
fi
if [ "$remove_ikev2" = "1" ]; then if [ "$remove_ikev2" = "1" ]; then
check_ipsec_conf check_ipsec_conf
confirm_remove_ikev2 confirm_remove_ikev2
@ -1295,7 +1400,7 @@ ikev2setup() {
exit 0 exit 0
;; ;;
2) 2)
enter_client_name_for_export enter_client_name_for export
select_p12_password select_p12_password
export_client_config export_client_config
print_client_exported print_client_exported
@ -1308,6 +1413,15 @@ ikev2setup() {
exit 0 exit 0
;; ;;
4) 4)
enter_client_name_for revoke
confirm_revoke_cert
create_crl
add_client_cert_to_crl
reload_crls
print_client_revoked
exit 0
;;
5)
check_ipsec_conf check_ipsec_conf
confirm_remove_ikev2 confirm_remove_ikev2
delete_ikev2_conf delete_ikev2_conf