# #
###############################################################################
-IPSEC_CONNECTION_CONFIG_SETTINGS="AUTH_MODE INACTIVITY_TIMEOUT LOCAL_ID LOCAL_PREFIX"
-IPSEC_CONNECTION_CONFIG_SETTINGS="${IPSEC_CONNECTION_CONFIG_SETTINGS} MODE PEER PSK"
-IPSEC_CONNECTION_CONFIG_SETTINGS="${IPSEC_CONNECTION_CONFIG_SETTINGS} REMOTE_ID REMOTE_PREFIX"
-IPSEC_CONNECTION_CONFIG_SETTINGS="${IPSEC_CONNECTION_CONFIG_SETTINGS} SECURITY_POLICY"
+IPSEC_CONNECTION_CONFIG_SETTINGS="\
+ AUTH_MODE \
+ DPD_ACTION \
+ DPD_DELAY \
+ DPD_TIMEOUT \
+ INACTIVITY_TIMEOUT \
+ LOCAL_ADDRESS \
+ LOCAL_ID \
+ LOCAL_PREFIX \
+ MODE \
+ PEER \
+ PSK \
+ REMOTE_ID \
+ REMOTE_PREFIX \
+ SECURITY_POLICY"
# Default values
-IPSEC_DEFAULT_MODE="tunnel"
IPSEC_DEFAULT_AUTH_MODE="PSK"
+IPSEC_DEFAULT_DPD_ACTION="restart"
+IPSEC_DEFAULT_DPD_DELAY="30"
+IPSEC_DEFAULT_DPD_TIMEOUT="120"
IPSEC_DEFAULT_INACTIVITY_TIMEOUT="0"
+IPSEC_DEFAULT_MODE="tunnel"
IPSEC_DEFAULT_SECURITY_POLICY="system"
+IPSEC_DEFAULT_START_ACTION="on-demand"
IPSEC_VALID_MODES="gre-transport tunnel vti"
IPSEC_VALID_AUTH_MODES="PSK"
shift 2
case "${key}" in
- authentication|inactivity-timout|local|mode|peer|remote|security-policy)
+ authentication|down|dpd|inactivity_timeout|local|mode|peer|remote|security_policy|start_action|up)
ipsec_connection_${key} ${connection} $@
;;
show)
log ERROR "Not enough arguments"
return ${EXIT_ERROR}
fi
+
local connection=${1}
local psk=${2}
- # TODO Check if psk is valid
+ local length=${#psk}
+
+ if [ ${length} -lt 4 ]; then
+ error "The PSK must be longer than four characters"
+ return ${EXIT_ERROR}
+ fi
+
+ if [ ${length} -gt 128 ]; then
+ error "The PSK cannot be longer than 128 characters"
+ return ${EXIT_ERROR}
+ fi
+
+ if ! ipsec_connection_write_config_key "${connection}" "PSK" "${psk}"; then
+ log ERROR "Could not write configuration settings"
+ return ${EXIT_ERROR}
+ fi
+
+ return ${EXIT_OK}
+}
+
+ipsec_connection_up() {
+ local connection="${1}"
+
+ if ! ipsec_connection_exists "${connection}"; then
+ error "No such VPN IPsec connection: ${connection}"
+ return ${EXIT_ERROR}
+ fi
+
+ cmd swanctl --initiate --child "${connection}"
+}
+
+ipsec_connection_down() {
+ local connection="${1}"
+
+ if ! ipsec_connection_exists "${connection}"; then
+ error "No such VPN IPsec connection: ${connection}"
+ return ${EXIT_ERROR}
+ fi
+
+ cmd swanctl --terminate --ike "${connection}"
+}
+
+# Handle the cli after authentification
+ipsec_connection_dpd() {
+ if [ ! $# -gt 1 ]; then
+ log ERROR "Not enough arguments"
+ return ${EXIT_ERROR}
+ fi
+
+ local connection=${1}
+ local cmd=${2}
+ shift 2
+
+ case ${cmd} in
+ action)
+ ipsec_connection_dpd_action "${connection}" $@
+ ;;
+ delay)
+ ipsec_connection_dpd_delay "${connection}" $@
+ ;;
+ timeout)
+ ipsec_connection_dpd_timeout "${connection}" $@
+ ;;
+ *)
+ log ERROR "Unrecognized argument: ${cmd}"
+ return ${EXIT_ERROR}
+ ;;
+ esac
+}
+
+# Set the default dpd action
+ipsec_connection_dpd_action() {
+ if [ ! $# -eq 2 ]; then
+ log ERROR "Not enough arguments"
+ return ${EXIT_ERROR}
+ fi
+ local connection=${1}
+ local action=${2}
+
+ if ! isoneof action "restart" "clear"; then
+ log ERROR "dpd action '${action}' is invalid"
+ return ${EXIT_ERROR}
+ fi
+
+ if ! ipsec_connection_write_config_key "${connection}" "DPD_ACTION" ${action}; then
+ log ERROR "Could not write configuration settings"
+ return ${EXIT_ERROR}
+ fi
+}
+
+# Set the dpd delay
+ipsec_connection_dpd_delay() {
+ if [ ! $# -ge 2 ]; then
+ log ERROR "Not enough arguments"
+ return ${EXIT_ERROR}
+ fi
- if ! ipsec_connection_write_config_key "${connection}" "PSK" ${psk}; then
+ local connection=${1}
+ shift 1
+ local value=$@
+
+ if ! isinteger value; then
+ value=$(parse_time $@)
+ if [ ! $? -eq 0 ]; then
+ log ERROR "Parsing the passed time was not sucessful please check the passed values."
+ return ${EXIT_ERROR}
+ fi
+ fi
+
+ if [ ${value} -lt 0 ]; then
+ log ERROR "The passed time value must be in the sum greater or equal zero seconds."
+ return ${EXIT_ERROR}
+ fi
+
+ if ! ipsec_connection_write_config_key "${connection}" "DPD_DELAY" ${value}; then
+ log ERROR "Could not write configuration settings"
+ return ${EXIT_ERROR}
+ fi
+
+ return ${EXIT_OK}
+}
+
+# Set the dpd timeout
+ipsec_connection_dpd_timeout() {
+ if [ ! $# -ge 2 ]; then
+ log ERROR "Not enough arguments"
+ return ${EXIT_ERROR}
+ fi
+
+ local connection=${1}
+ shift 1
+ local value=$@
+
+ if ! isinteger value; then
+ value=$(parse_time $@)
+ if [ ! $? -eq 0 ]; then
+ log ERROR "Parsing the passed time was not sucessful please check the passed values."
+ return ${EXIT_ERROR}
+ fi
+ fi
+
+ if [ ${value} -le 0 ]; then
+ log ERROR "The passed time value must be in the sum greater or equal zero seconds."
+ return ${EXIT_ERROR}
+ fi
+
+ if ! ipsec_connection_write_config_key "${connection}" "DPD_TIMEOUT" ${value}; then
log ERROR "Could not write configuration settings"
return ${EXIT_ERROR}
fi
shift 2
case ${cmd} in
+ address)
+ ipsec_connection_local_address "${connection}" $@
+ ;;
id)
ipsec_connection_id "${connection}" "LOCAL" $@
;;
return ${EXIT_OK}
}
+# Set the local address
+ipsec_connection_local_address() {
+ if [ ! $# -eq 2 ]; then
+ log ERROR "Not enough arguments"
+ return ${EXIT_ERROR}
+ fi
+ local connection=${1}
+ local local_address=${2}
+
+ if ! ipsec_connection_check_peer ${local_address}; then
+ log ERROR "Local address '${local_address}' is invalid"
+ return ${EXIT_ERROR}
+ fi
+
+ if ! ipsec_connection_write_config_key "${connection}" "LOCAL_ADDRESS" ${local_address}; then
+ log ERROR "Could not write configuration settings"
+ return ${EXIT_ERROR}
+ fi
+
+ return ${EXIT_OK}
+}
+
# Set the peer to connect to
ipsec_connection_peer() {
if [ ! $# -eq 2 ]; then
warning "${prefix} is already on the prefix list"
fi
else
- warning "${prefix} is not a valiv IP net and could not be added"
+ warning "${prefix} is not a valid IP network and could not be added"
fi
done
fi
return ${EXIT_OK}
}
+# Set the default start action
+ipsec_connection_start_action() {
+ if [ ! $# -eq 2 ]; then
+ log ERROR "Not enough arguments"
+ return ${EXIT_ERROR}
+ fi
+ local connection=${1}
+ local action=${2}
+
+ if ! isoneof action "on-demand" "always-on"; then
+ log ERROR "Start action '${action}' is invalid"
+ return ${EXIT_ERROR}
+ fi
+
+ if ! ipsec_connection_write_config_key "${connection}" "START_ACTION" ${action}; then
+ log ERROR "Could not write configuration settings"
+ return ${EXIT_ERROR}
+ fi
+}
# Set the security policy to use
ipsec_connection_security_policy() {
local ${IPSEC_CONNECTION_CONFIG_SETTINGS}
- MODE=${IPSEC_DEFAULT_MODE}
AUTH_MODE=${IPSEC_DEFAULT_AUTH_MODE}
+ DPD_ACTION=${IPSEC_DEFAULT_DPD_ACTION}
+ DPD_DELAY=${IPSEC_DEFAULT_DPD_DELAY}
+ DPD_TIMEOUT=${IPSEC_DEFAULT_DPD_TIMEOUT}
+ MODE=${IPSEC_DEFAULT_MODE}
+ START_ACTION=${IPSEC_DEFAULT_START_ACTION}
+
INACTIVITY_TIMEOUT=${IPSEC_DEFAULT_INACTIVITY_TIMEOUT}
SECURITY_POLICY=${IPSEC_DEFAULT_SECURITY_POLICY}
fi
done
}
+
+# List all ipsec connections
+ipsec_list_connections() {
+ local connection
+ for connection in ${NETWORK_IPSEC_CONNS_DIR}/*; do
+ [ -d ${connection} ] || continue
+ basename ${connection}
+ done
+}
+
+ipsec_connection_to_strongswan() {
+ local connection="${1}"
+
+ # Read the config settings
+ local ${IPSEC_CONNECTION_CONFIG_SETTINGS}
+ if ! ipsec_connection_read_config "${connection}"; then
+ error "Could not read the connection ${connection}"
+ return ${EXIT_ERROR}
+ fi
+
+ local path="${NETWORK_IPSEC_SWANCTL_CONNECTIONS_DIR}/${connection}.conf"
+
+ (
+ # Write the connection section
+ _ipsec_connection_to_strongswan_connection "${connection}"
+
+ # Write the secrets section
+ _ipsec_connection_to_strongswan_secrets "${connection}"
+
+ ) > ${path}
+}
+
+_ipsec_connection_to_strongswan_connection() {
+ local connection="${1}"
+
+ # Read the security policy
+ local ${VPN_SECURITY_POLICIES_CONFIG_SETTINGS}
+ if ! vpn_security_policies_read_config "${SECURITY_POLICY}"; then
+ return ${EXIT_ERROR}
+ fi
+
+ # Is DPD enabled?
+ local dpd="false"
+ if isset DPD_DELAY && isinteger DPD_DELAY && [ ${DPD_DELAY} -gt 0 ]; then
+ dpd="true"
+ fi
+
+ print_indent 0 "connections {"
+ print_indent 1 "${connection} {"
+
+ # IKE Version
+ print_indent 2 "# IKE Version"
+ case "${KEY_EXCHANGE^^}" in
+ IKEV1)
+ print_indent 2 "version = 1"
+ ;;
+
+ # Fall back to IKEv2 for any random values
+ IKEV2|*)
+ print_indent 2 "version = 2"
+ ;;
+ esac
+ print # empty line
+
+ # Local Address
+ print_indent 2 "# Local Address"
+ if isset LOCAL_ADDRESS; then
+ print_indent 2 "local_addrs = ${LOCAL_ADDRESS}"
+ else
+ print_indent 2 "local_addrs = %any"
+ fi
+ print
+
+ # Remote Address
+ print_indent 2 "# Remote Address"
+ if isset PEER; then
+ print_indent 2 "remote_addrs = ${PEER}"
+ else
+ print_indent 2 "remote_addrs = %any"
+ fi
+ print
+
+ # IKE Proposals
+ print_indent 2 "# IKE Proposals"
+ print_indent 2 "proposals = $(vpn_security_policies_make_ike_proposal ${SECURITY_POLICY})"
+ print
+
+ # DPD Settings
+ if enabled dpd; then
+ print_indent 2 "# Dead Peer Detection"
+ print_indent 2 "dpd_delay = ${DPD_DELAY}"
+
+ if isset DPD_TIMEOUT; then
+ print_indent 2 "dpd_timeout = ${DPD_TIMEOUT}"
+ fi
+
+ print
+ fi
+
+ # Fragmentation
+ print_indent 2 "# Fragmentation"
+ print_indent 2 "fragmentation = yes"
+ print
+
+ # Local
+ print_indent 2 "local {"
+
+ # Local ID
+ if isset LOCAL_ID; then
+ print_indent 3 "id = ${LOCAL_ID}"
+ fi
+
+ # Authentication
+ case "${AUTH_MODE}" in
+ PSK)
+ print_indent 3 "auth = psk"
+ ;;
+ esac
+
+ print_indent 2 "}"
+ print
+
+ # Remote
+ print_indent 2 "remote {"
+
+ # Remote ID
+ if isset REMOTE_ID; then
+ print_indent 3 "id = ${REMOTE_ID}"
+ fi
+
+ # Authentication
+ case "${AUTH_MODE}" in
+ PSK)
+ print_indent 3 "auth = psk"
+ ;;
+ esac
+
+ print_indent 2 "}"
+ print
+
+ # Children
+
+ print_indent 2 "children {"
+ print_indent 3 "${connection} {"
+
+ print_indent 4 "# ESP Proposals"
+ print_indent 4 "esp_proposals = $(vpn_security_policies_make_esp_proposal ${SECURITY_POLICY})"
+ print
+
+ # Traffic Selectors
+
+ case "${MODE}" in
+ gre-*)
+ print_indent 4 "local_ts = dynamic[gre]"
+ print_indent 4 "remote_ts = dynamic[gre]"
+ ;;
+ *)
+ # Local Prefixes
+ if isset LOCAL_PREFIX; then
+ print_indent 4 "local_ts = $(list_join LOCAL_PREFIX ,)"
+ else
+ print_indent 4 "local_ts = dynamic"
+ fi
+
+ # Remote Prefixes
+ if isset REMOTE_PREFIX; then
+ print_indent 4 "remote_ts = $(list_join REMOTE_PREFIX ,)"
+ else
+ print_indent 4 "remote_ts = dynamic"
+ fi
+ ;;
+ esac
+ print
+
+ # Netfilter Marks
+ print_indent 4 "# Netfilter Marks"
+ print_indent 4 "mark_in = %unique"
+ print_indent 4 "mark_out = %unique"
+ print
+
+ # Dead Peer Detection
+ if enabled dpd; then
+ print_indent 4 "# Dead Peer Detection"
+ print_indent 4 "dpd_action = ${DPD_ACTION}"
+ print
+ fi
+
+ # Rekeying
+ if isset LIFETIME; then
+ print_indent 4 "# Rekey Time"
+ print_indent 4 "rekey_time = ${LIFETIME}"
+ print
+ fi
+
+ # Updown Script
+ print_indent 4 "updown = ${NETWORK_HELPERS_DIR}/ipsec-updown"
+ print
+
+ # Mode
+ print_indent 4 "# Mode"
+ case "${MODE}" in
+ gre-transport)
+ print_indent 4 "mode = transport"
+ ;;
+ tunnel|vti|*)
+ print_indent 4 "mode = tunnel"
+ ;;
+ esac
+ print
+
+ # Compression
+ print_indent 4 "# Compression"
+ if enabled COMPRESSION; then
+ print_indent 4 "ipcomp = yes"
+ else
+ print_indent 4 "ipcomp = no"
+ fi
+ print
+
+ # Inactivity Timeout
+ if isset INACTIVITY_TIMEOUT; then
+ print_indent 4 "# Inactivity Timeout"
+ print_indent 4 "inactivity = ${INACTIVITY_TIMEOUT}"
+ print
+ fi
+
+ # Start Action
+ print_indent 4 "# Start Action"
+ case "${START_ACTION}" in
+ on-demand)
+ print_indent 4 "start_action = trap"
+ print_indent 4 "close_action = trap"
+ ;;
+ wait)
+ print_indent 4 "start_action = none"
+ print_indent 4 "close_action = none"
+ ;;
+ always-on|*)
+ print_indent 4 "start_action = start"
+ print_indent 4 "close_action = start"
+ ;;
+ esac
+ print
+
+ print_indent 3 "}"
+ print_indent 2 "}"
+ print
+
+ print_indent 1 "}"
+ print_indent 0 "}"
+ print
+}
+
+_ipsec_connection_to_strongswan_secrets() {
+ local connection="${1}"
+
+ print_indent 0 "secrets {"
+
+ case "${AUTH_MODE}" in
+ PSK)
+ print_indent 1 "ike {"
+
+ # Secret
+ print_indent 2 "secret = ${PSK}"
+
+ # ID
+ if isset REMOTE_ID; then
+ print_indent 2 "id = ${REMOTE_ID}"
+ fi
+
+ print_indent 1 "}"
+ ;;
+ esac
+
+ print_indent 0 "}"
+}