strongswan: uci config support 3585/head
authorHans Dedecker <dedeckeh@gmail.com>
Fri, 6 Jan 2017 11:10:32 +0000 (12:10 +0100)
committerHans Dedecker <dedeckeh@gmail.com>
Fri, 6 Jan 2017 12:32:13 +0000 (13:32 +0100)
Add support to configure strongswan via uci.

uci support is based on the following sections
-ipsec : Global config items belonging in the strongswan.conf file
-remote : Defines the remote peer(s)
-tunnel : Defines the IPSec connections in tunnel mode
-transport : Defines the IPSec connections in transport mode
-crypto_proposal : Defines the different crypto proposals

Signed-off-by: Pierre Lebleu <pme.lebleu@gmail.com>
Signed-off-by: Gino Peeters <peeters.gino@gmail.com>
Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
net/strongswan/Makefile
net/strongswan/files/ipsec.init

index 029b8bff760a9fb70a88c34e4b82b30631105b05..075414b0c6e345ba7f3ccad721deb0e92065dcb0 100644 (file)
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 
 PKG_NAME:=strongswan
 PKG_VERSION:=5.5.1
-PKG_RELEASE:=1
+PKG_RELEASE:=2
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2
 PKG_SOURCE_URL:=http://download.strongswan.org/ http://download2.strongswan.org/
index 391a2ae8c712d617914c363611baba64df8d46ff..4635eae9cfe092911d83c7ccb480ad564a41c843 100644 (file)
@@ -3,8 +3,327 @@
 START=90
 STOP=10
 
+. $IPKG_INSTROOT/lib/functions.sh
+
+UCI_IPSEC_CONFIG=/etc/config/ipsec
+
+IPSEC_SECRETS_FILE=/etc/ipsec.secrets
+IPSEC_CONN_FILE=/etc/ipsec.conf
+STRONGSWAN_CONF_FILE=/etc/strongswan.conf
+
+IPSEC_VAR_SECRETS_FILE=/var/ipsec/ipsec.secrets
+IPSEC_VAR_CONN_FILE=/var/ipsec/ipsec.conf
+STRONGSWAN_VAR_CONF_FILE=/var/ipsec/strongswan.conf
+
+ENABLED_REMOTE_PEERS=0
+
+file_reset() {
+       : > "$1"
+}
+
+xappend() {
+       local file="$1"
+       shift
+
+       echo "${@}" >> "${file}"
+}
+
+remove_include() {
+       local file="$1"
+       local include="$2"
+
+       sed -i "\_${include}_d" "${file}"
+}
+
+remove_includes() {
+       remove_include "${IPSEC_CONN_FILE}" "${IPSEC_VAR_CONN_FILE}"
+       remove_include "${IPSEC_SECRETS_FILE}" "${IPSEC_VAR_SECRETS_FILE}"
+       remove_include "${STRONGSWAN_CONF_FILE}" "${STRONGSWAN_VAR_CONF_FILE}"
+}
+
+do_include() {
+       local conf="$1"
+       local uciconf="$2"
+       local backup=`mktemp -t -p /tmp/ ipsec-init-XXXXXX`
+
+       [ ! -f "${conf}" ] && rm -rf "${conf}"
+       touch "${conf}"
+
+       cat "${conf}" | grep -v "${uciconf}" > "${backup}"
+       mv "${backup}" "${conf}"
+       xappend "${conf}" "include ${uciconf}"
+       file_reset "${uciconf}"
+}
+
+ipsec_reset() {
+       do_include "${IPSEC_CONN_FILE}" "${IPSEC_VAR_CONN_FILE}"
+}
+
+ipsec_xappend() {
+       xappend "${IPSEC_VAR_CONN_FILE}" "$@"
+}
+
+swan_reset() {
+       do_include "${STRONGSWAN_CONF_FILE}" "${STRONGSWAN_VAR_CONF_FILE}"
+}
+
+swan_xappend() {
+       xappend "${STRONGSWAN_VAR_CONF_FILE}" "$@"
+}
+
+secret_reset() {
+       do_include "${IPSEC_SECRETS_FILE}" "${IPSEC_VAR_SECRETS_FILE}"
+}
+
+secret_xappend() {
+       xappend "${IPSEC_VAR_SECRETS_FILE}" "$@"
+}
+
+warning() {
+       echo "WARNING: $@" >&2
+}
+
+add_crypto_proposal() {
+       local encryption_algorithm
+       local hash_algorithm
+       local dh_group
+
+       config_get encryption_algorithm  "$1" encryption_algorithm
+       config_get hash_algorithm        "$1" hash_algorithm
+       config_get dh_group              "$1" dh_group
+
+       [ -n "${encryption_algorithm}" ] && \
+               crypto="${crypto:+${crypto},}${encryption_algorithm}${hash_algorithm:+-${hash_algorithm}}${dh_group:+-${dh_group}}"
+}
+
+set_crypto_proposal() {
+       local conf="$1"
+       local proposal
+
+       crypto=""
+
+       config_get crypto_proposal "$conf" crypto_proposal ""
+       for proposal in $crypto_proposal; do
+               add_crypto_proposal "$proposal"
+       done
+
+       [ -n "${crypto}" ] && {
+               local force_crypto_proposal
+
+               config_get_bool force_crypto_proposal "$conf" force_crypto_proposal
+
+               [ "${force_crypto_proposal}" = "1" ] && crypto="${crypto}!"
+       }
+
+       crypto_proposal="${crypto}"
+}
+
+config_conn() {
+       # Generic ipsec conn section shared by tunnel and transport
+       local mode
+       local local_subnet
+       local local_nat
+       local local_sourceip
+       local local_updown
+       local local_firewall
+       local remote_subnet
+       local remote_sourceip
+       local remote_updown
+       local remote_firewall
+       local ikelifetime
+       local lifetime
+       local margintime
+       local keyingtries
+       local dpdaction
+       local dpddelay
+       local inactivity
+       local keyexchange
+
+       config_get mode                     "$1"           mode "route"
+       config_get local_subnet             "$1"           local_subnet ""
+       config_get local_nat                "$1"           local_nat ""
+       config_get local_sourceip           "$1"           local_sourceip ""
+       config_get local_updown             "$1"           local_updown ""
+       config_get local_firewall           "$1"           local_firewall ""
+       config_get remote_subnet            "$1"           remote_subnet ""
+       config_get remote_sourceip          "$1"           remote_sourceip ""
+       config_get remote_updown            "$1"           remote_updown ""
+       config_get remote_firewall          "$1"           remote_firewall ""
+       config_get ikelifetime              "$1"           ikelifetime "3h"
+       config_get lifetime                 "$1"           lifetime "1h"
+       config_get margintime               "$1"           margintime "9m"
+       config_get keyingtries              "$1"           keyingtries "3"
+       config_get dpdaction                "$1"           dpdaction "none"
+       config_get dpddelay                 "$1"           dpddelay "30s"
+       config_get inactivity               "$1"           inactivity
+       config_get keyexchange              "$1"           keyexchange "ikev2"
+
+       [ -n "$local_nat" ] && local_subnet=$local_nat
+
+       ipsec_xappend "conn $config_name-$1"
+       ipsec_xappend "  left=%any"
+       ipsec_xappend "  right=$remote_gateway"
+
+       [ -n "$local_sourceip" ] && ipsec_xappend "  leftsourceip=$local_sourceip"
+       [ -n "$local_subnet" ] && ipsec_xappend "  leftsubnet=$local_subnet"
+
+       [ -n "$local_firewall" ] && ipsec_xappend "  leftfirewall=$local_firewall"
+       [ -n "$remote_firewall" ] && ipsec_xappend "  rightfirewall=$remote_firewall"
+
+       ipsec_xappend "  ikelifetime=$ikelifetime"
+       ipsec_xappend "  lifetime=$lifetime"
+       ipsec_xappend "  margintime=$margintime"
+       ipsec_xappend "  keyingtries=$keyingtries"
+       ipsec_xappend "  dpdaction=$dpdaction"
+       ipsec_xappend "  dpddelay=$dpddelay"
+
+       [ -n "$inactivity" ] && ipsec_xappend "  inactivity=$inactivity"
+
+       if [ "$auth_method" = "psk" ]; then
+               ipsec_xappend "  leftauth=psk"
+               ipsec_xappend "  rightauth=psk"
+
+               [ "$remote_sourceip" != "" ] && ipsec_xappend "  rightsourceip=$remote_sourceip"
+               [ "$remote_subnet" != "" ] && ipsec_xappend "  rightsubnet=$remote_subnet"
+
+               ipsec_xappend "  auto=$mode"
+       else
+               warning "AuthenticationMethod $auth_method not supported"
+       fi
+
+       [ -n "$local_identifier" ] && ipsec_xappend "  leftid=$local_identifier"
+       [ -n "$remote_identifier" ] && ipsec_xappend "  rightid=$remote_identifier"
+       [ -n "$local_updown" ] && ipsec_xappend "  leftupdown=$local_updown"
+       [ -n "$remote_updown" ] && ipsec_xappend "  rightupdown=$remote_updown"
+       ipsec_xappend "  keyexchange=$keyexchange"
+
+       set_crypto_proposal "$1"
+       [ -n "${crypto_proposal}" ] && ipsec_xappend "  esp=$crypto_proposal"
+       [ -n "${ike_proposal}" ] && ipsec_xappend "  ike=$ike_proposal"
+}
+
+config_tunnel() {
+       config_conn "$1"
+
+       # Specific for the tunnel part
+       ipsec_xappend "  type=tunnel"
+}
+
+config_transport() {
+       config_conn "$1"
+
+       # Specific for the transport part
+       ipsec_xappend "  type=transport"
+}
+
+config_remote() {
+       local enabled
+       local gateway
+       local pre_shared_key
+       local auth_method
+
+       config_name=$1
+
+       config_get_bool enabled "$1" enabled 0
+       [ "$enabled" = "0" ] && return
+
+       ENABLED_REMOTE_PEERS=$((ENABLED_REMOTE_PEERS + 1))
+
+       config_get gateway           "$1" gateway
+       config_get pre_shared_key    "$1" pre_shared_key
+       config_get auth_method       "$1" authentication_method
+       config_get local_identifier  "$1" local_identifier ""
+       config_get remote_identifier "$1" remote_identifier ""
+
+       [ "$gateway" = "any" ] && remote_gateway="%any" || remote_gateway="$gateway"
+
+       [ -z "$local_identifier" ] && {
+               local ipdest
+
+               [ "$remote_gateway" = "%any" ] && ipdest="1.1.1.1" || ipdest="$remote_gateway"
+               local_gateway=`ip route get $ipdest | awk -F"src" '/src/{gsub(/ /,"");print $2}'`
+       }
+
+       [ -n "$local_identifier" ] && secret_xappend -n "$local_identifier " || secret_xappend -n "$local_gateway "
+       [ -n "$remote_identifier" ] && secret_xappend -n "$remote_identifier " || secret_xappend -n "$remote_gateway "
+
+       secret_xappend ": PSK \"$pre_shared_key\""
+
+       set_crypto_proposal "$1"
+       ike_proposal="$crypto_proposal"
+
+       config_list_foreach "$1" tunnel config_tunnel
+
+       config_list_foreach "$1" transport config_transport
+
+       ipsec_xappend ""
+}
+
+config_ipsec() {
+       local debug
+       local rtinstall_enabled
+       local routing_tables_ignored
+       local routing_table
+       local routing_table_id
+       local interface
+       local device_list
+
+       ipsec_reset
+       secret_reset
+       swan_reset
+
+       ipsec_xappend "# generated by /etc/init.d/ipsec"
+       ipsec_xappend "version 2"
+       ipsec_xappend ""
+
+       secret_xappend "# generated by /etc/init.d/ipsec"
+
+       config_get debug "$1" debug 0
+       config_get_bool rtinstall_enabled "$1" rtinstall_enabled 1
+       [ $rtinstall_enabled = "1" ] && install_routes=yes || install_routes=no
+
+       # prepare extra charon config option ignore_routing_tables
+       for routing_table in $(config_get "$1" "ignore_routing_tables"); do
+               if [ "$routing_table" -ge 0 ] 2>/dev/null; then
+                       routing_table_id=$routing_table
+               else
+                       routing_table_id=$(sed -n '/[ \t]*[0-9]\+[ \t]\+'$routing_table'[ \t]*$/s/[ \t]*\([0-9]\+\).*/\1/p' /etc/iproute2/rt_tables)
+               fi
+
+               [ -n "$routing_table_id" ] && append routing_tables_ignored "$routing_table_id"
+       done
+
+       swan_xappend "# generated by /etc/init.d/ipsec"
+       swan_xappend "charon {"
+       swan_xappend "  load_modular = yes"
+       swan_xappend "  install_routes = $install_routes"
+       [ -n "$routing_tables_ignored" ] && swan_xappend "  ignore_routing_tables = $routing_tables_ignored"
+       swan_xappend "    plugins {"
+       swan_xappend "      include /etc/strongswan.d/charon/*.conf"
+       swan_xappend "    }"
+       swan_xappend "  syslog {"
+       swan_xappend "    identifier = ipsec"
+       swan_xappend "    daemon {"
+       swan_xappend "      default = $debug"
+       swan_xappend "    }"
+       swan_xappend "    auth {"
+       swan_xappend "      default = $debug"
+       swan_xappend "    }"
+       swan_xappend "  }"
+       swan_xappend "}"
+}
+
+prepare_env() {
+       mkdir -p /var/ipsec
+       remove_includes
+       config_load ipsec
+       config_foreach config_ipsec ipsec
+       config_foreach config_remote remote
+}
+
 start() {
-       ipsec start
+       prepare_env
+       [ $ENABLED_REMOTE_PEERS != 0 -o ! -f $UCI_IPSEC_CONFIG ] && ipsec start
 }
 
 stop() {
@@ -12,9 +331,18 @@ stop() {
 }
 
 restart() {
-       ipsec restart
+       prepare_env
+       [ $ENABLED_REMOTE_PEERS != 0 -o ! -f $UCI_IPSEC_CONFIG ] && ipsec restart || ipsec stop
 }
 
 reload() {
-       ipsec update
+       prepare_env
+       [ $ENABLED_REMOTE_PEERS != 0 -o ! -f $UCI_IPSEC_CONFIG ] && {
+               ipsec secrets
+               if [[ ! -z "$(ipsec status)" ]]; then
+                       ipsec reload
+               else
+                       ipsec start
+               fi
+       } || ipsec stop
 }