The interface config option allows users to configure logical OpenWRT interface names in the ipsec section; it allows StrongSwan to listen and send traffic on specified interface(s). It translates to interfaces_use StrongSwan option which is a comma sepearted list of network devices that should be used by charon. Since StrongSwan can only be started when one of the specified logical OpenWRT interface is up procd interface triggers are installed to trigger the reload script. Signed-off-by: Hans Dedecker <dedeckeh@gmail.com>
385 lines
10 KiB
Bash
385 lines
10 KiB
Bash
#!/bin/sh /etc/rc.common
|
|
|
|
START=90
|
|
STOP=10
|
|
|
|
USE_PROCD=1
|
|
PROG=/usr/lib/ipsec/starter
|
|
|
|
. $IPKG_INSTROOT/lib/functions.sh
|
|
. $IPKG_INSTROOT/lib/functions/network.sh
|
|
|
|
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
|
|
|
|
WAIT_FOR_INTF=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 -eq 0 ] && return
|
|
|
|
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 -eq 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
|
|
|
|
local interface_list=$(config_get "$1" "interface")
|
|
if [ -z "$interface_list" ]; then
|
|
WAIT_FOR_INTF=0
|
|
else
|
|
for interface in $interface_list; do
|
|
network_get_device device $interface
|
|
[ -n "$device" ] && append device_list "$device" ","
|
|
done
|
|
[ -n "$device_list" ] && WAIT_FOR_INTF=0 || WAIT_FOR_INTF=1
|
|
fi
|
|
|
|
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"
|
|
[ -n "$device_list" ] && swan_xappend " interfaces_use = $device_list"
|
|
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
|
|
}
|
|
|
|
service_running() {
|
|
ipsec status > /dev/null 2>&1
|
|
}
|
|
|
|
reload_service() {
|
|
running && {
|
|
prepare_env
|
|
[ $WAIT_FOR_INTF -eq 0 ] && {
|
|
ipsec rereadall
|
|
ipsec reload
|
|
return
|
|
}
|
|
}
|
|
|
|
start
|
|
}
|
|
|
|
check_ipsec_interface() {
|
|
local intf
|
|
|
|
for intf in $(config_get "$1" interface); do
|
|
procd_add_interface_trigger "interface.*" "$intf" /etc/init.d/ipsec reload
|
|
done
|
|
}
|
|
|
|
service_triggers() {
|
|
procd_add_reload_trigger "ipsec"
|
|
config load "ipsec"
|
|
config_foreach check_ipsec_interface ipsec
|
|
}
|
|
|
|
start_service() {
|
|
prepare_env
|
|
|
|
[ $WAIT_FOR_INTF -eq 1 ] && return
|
|
|
|
procd_open_instance
|
|
|
|
procd_set_param command $PROG --daemon charon --nofork
|
|
|
|
procd_set_param file $IPSEC_CONN_FILE
|
|
procd_append_param file $IPSEC_SECRETS_FILE
|
|
procd_append_param file $STRONGSWAN_CONF_FILE
|
|
procd_append_param file /etc/strongswan.d/*.conf
|
|
procd_append_param file /etc/strongswan.d/charon/*.conf
|
|
|
|
procd_set_param respawn
|
|
|
|
procd_close_instance
|
|
}
|