X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=src%2Ffunctions%2Ffunctions.ipsec;h=61bdcb28460ce880e71d298868fb67b3a2ddaee6;hb=e3ffacf7f7793f782ff0656abe6a19fb839a7b84;hp=cd1a50a1d7fc73cdf9d19400f4bfa0e966758379;hpb=db491d1d802a28fb7d2d93362241dda77ac902b1;p=people%2Fms%2Fnetwork.git diff --git a/src/functions/functions.ipsec b/src/functions/functions.ipsec index cd1a50a1..61bdcb28 100644 --- a/src/functions/functions.ipsec +++ b/src/functions/functions.ipsec @@ -19,16 +19,31 @@ # # ############################################################################### -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" @@ -56,7 +71,7 @@ cli_ipsec_connection() { 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) @@ -334,12 +349,157 @@ ipsec_connection_authentication_psk() { 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 @@ -359,6 +519,9 @@ ipsec_connection_local() { shift 2 case ${cmd} in + address) + ipsec_connection_local_address "${connection}" $@ + ;; id) ipsec_connection_id "${connection}" "LOCAL" $@ ;; @@ -396,6 +559,28 @@ ipsec_connection_mode() { 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 @@ -522,7 +707,7 @@ ipsec_connection_prefix() { 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 @@ -601,6 +786,25 @@ ipsec_connection_inactivity_timeout() { 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() { @@ -691,8 +895,13 @@ ipsec_connection_new() { 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} @@ -718,3 +927,279 @@ ipsec_connection_destroy() { 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 "}" +}