From: Michael Tremer Date: Wed, 19 Sep 2018 11:43:58 +0000 (+0200) Subject: ipsec: GRE/VTI connections are now possible as on-demand X-Git-Tag: 010~73 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=4f5f487adbb8011957a223d826e3057959365220;p=network.git ipsec: GRE/VTI connections are now possible as on-demand This change implements using zones as GRE/VTI devices so that we can use IPsec connections in on-demand mode, too. The device will be created first (as a zone) and might trigger an IPsec connection. If that happens, the settings of the device will be updated automatically. Signed-off-by: Michael Tremer --- diff --git a/src/functions/functions.ip-tunnel b/src/functions/functions.ip-tunnel index 302a11c3..797a2934 100644 --- a/src/functions/functions.ip-tunnel +++ b/src/functions/functions.ip-tunnel @@ -181,6 +181,76 @@ ip_tunnel_del() { device_delete "$@" } +ip_tunnel_change() { + local device="${1}" + shift + + if ! device_exists "${device}"; then + log ERROR "No such device: ${device}" + return ${EXIT_ERROR} + fi + + # Determine the device type + local type="$(device_tunnel_get_type ${device})" + + local local + local remote + + while [ $# -gt 0 ]; do + case "${1}" in + --local=*) + local="$(cli_get_val "${1}")" + + if ! ip_is_valid "${local}"; then + error "Invalid IP address for --local: ${local}" + return ${EXIT_ERROR} + fi + + if ! isoneof "type" gre gre6 vti vti6; then + log ERROR "Cannot change --local for devices of type ${type}" + return ${EXIT_ERROR} + fi + ;; + --remote=*) + remote="$(cli_get_val "${1}")" + + if ! ip_is_valid "${remote}"; then + error "Invalid IP address for --remote: ${remote}" + return ${EXIT_ERROR} + fi + + if ! isoneof "type" gre gre6 vti vti6; then + log ERROR "Cannot change --remote for devices of type ${type}" + return ${EXIT_ERROR} + fi + ;; + esac + shift + done + + # XXX If a device is of an IP protocol and the protocol of remote and local + # have changed, we will need to destroy the interface and recreate it with + # the correct type + + local cmd_args + + if isset local; then + cmd_args="${cmd_args} local ${local}" + fi + + if isset remote; then + cmd_args="${cmd_args} remote ${remote}" + fi + + # Exit if there is nothing to do + if ! isset cmd_args; then + return ${EXIT_OK} + fi + + # Run ip command + cmd ip link change dev "${device}" type "${type}" ${cmd_args} +} + ip_tunnel_change_keys() { local device="${1}" shift diff --git a/src/functions/functions.ipsec b/src/functions/functions.ipsec index e2af52b0..3f215e40 100644 --- a/src/functions/functions.ipsec +++ b/src/functions/functions.ipsec @@ -529,12 +529,24 @@ ipsec_connection_up() { return ${EXIT_ERROR} fi + # Read configuration options + local ZONE + if ! ipsec_connection_read_config "${connection}" "ZONE"; then + log ERROR "Could not read configuration for IPsec connection ${connection}" + return ${EXIT_ERROR} + fi + if ! [ -f "${NETWORK_IPSEC_SWANCTL_CONNECTIONS_DIR}/${connection}.conf" ]; then log DEBUG "Could not find a swanctl config, generating swanctl config" ipsec_connection_to_strongswan "${connection}" ipsec_strongswan_load fi + # Bring up the zone + if isset ZONE; then + zone_up "${ZONE}" + fi + cmd swanctl --initiate --child "${connection}" } @@ -546,7 +558,20 @@ ipsec_connection_down() { return ${EXIT_ERROR} fi + # Read configuration options + local ZONE + if ! ipsec_connection_read_config "${connection}" "ZONE"; then + log ERROR "Could not read configuration for IPsec connection ${connection}" + return ${EXIT_ERROR} + fi + + # Tell strongswan to bring down any tunnels cmd swanctl --terminate --ike "${connection}" + + # Bring up the zone + if isset ZONE; then + zone_down "${ZONE}" + fi } # Handle the cli after authentification @@ -1315,6 +1340,22 @@ _ipsec_connection_to_strongswan_connection() { dpd="true" fi + local zone_mode + + # Are we connected to a zone? + if isset ZONE; then + # Store MODE + local mode="${MODE}" + + if ! zone_settings_read "${ZONE}" MARK MODE; then + log ERROR "Could not read zone settings from ${zone}" + return ${EXIT_ERROR} + fi + + local zone_mode="${MODE}" + MODE="${mode}" + fi + # Write configuration header config_header "strongSwan configuration for ${connection}" @@ -1439,9 +1480,8 @@ _ipsec_connection_to_strongswan_connection() { print # Traffic Selectors - - case "${MODE}" in - gre-*) + case "${MODE},${zone_mode}" in + *,gre) print_indent 4 "local_ts = dynamic[gre]" print_indent 4 "remote_ts = dynamic[gre]" ;; @@ -1464,11 +1504,13 @@ _ipsec_connection_to_strongswan_connection() { print # Netfilter Marks - case "${MODE}" in + case "${zone_mode}" in vti) + assert isset MARK + print_indent 4 "# Netfilter Marks" - print_indent 4 "mark_in = %unique" - print_indent 4 "mark_out = %unique" + print_indent 4 "mark_in = ${MARK}" + print_indent 4 "mark_out = ${MARK}" print ;; esac diff --git a/src/helpers/ipsec-updown b/src/helpers/ipsec-updown index 185c2c72..1e6c6955 100644 --- a/src/helpers/ipsec-updown +++ b/src/helpers/ipsec-updown @@ -54,37 +54,24 @@ log DEBUG "${0} called for ${CONNECTION}: ${PLUTO_VERB}" case "${PLUTO_VERB}" in up-client|up-client-v6|up-host|up-host-v6) - case "${MODE}" in - gre-*) - if ! device_exists "${INTERFACE}"; then - ip_tunnel_add "${INTERFACE}" \ - --mode="gre" \ - --local-address="${PLUTO_ME}" \ - --remote-address="${PLUTO_PEER}" - - device_set_up "${INTERFACE}" - fi - ;; - vti) - if device_exists "${INTERFACE}"; then - ip_tunnel_change_keys "${INTERFACE}" \ - --ikey="${PLUTO_MARK_IN%/*}" \ - --okey="${PLUTO_MARK_OUT%/*}" + if isset ZONE && zone_exists "${ZONE}"; then + # Bring up the zone if not done, yet + if ! zone_is_up "${ZONE}"; then + zone_up "${ZONE}" + fi - else - if ! ip_tunnel_add "${INTERFACE}" \ - --mode="vti" \ - --local-address="${PLUTO_ME}" \ - --remote-address="${PLUTO_PEER}" \ - --ikey="${PLUTO_MARK_IN%/*}" \ - --okey="${PLUTO_MARK_OUT%/*}"; then - log ERROR "Could not create VTI device for ${CONNECTION}" - fi - fi + # Update peer and local address + if ! ip_tunnel_change "${ZONE}" --remote="${PLUTO_PEER}" --local="${PLUTO_ME}"; then + return ${EXIT_ERROR} + fi - device_set_up "${INTERFACE}" - ;; - esac + # Set keys for VTI devices + if device_is_vti6 "${ZONE}" || device_is_vti "${ZONE}"; then + ip_tunnel_change_keys "${ZONE}" \ + --ikey="${PLUTO_MARK_IN%/*}" \ + --okey="${PLUTO_MARK_OUT%/*}" + fi + fi #Get sources IP for routes SRC_IP=($(ip_get_assigned_addresses_from_net \ @@ -131,17 +118,6 @@ case "${PLUTO_VERB}" in down-client|down-client-v6|down-host|down-host-v6) # Remove routes cmd ip route del "${PLUTO_PEER_CLIENT}" - - # Remove interfaces - case "${MODE}" in - gre-*|vti) - if device_exists "${INTERFACE}"; then - device_set_down "${INTERFACE}" - - ip_tunnel_del "${INTERFACE}" - fi - ;; - esac ;; esac