Skip to content

Instantly share code, notes, and snippets.

@danielkza
Created November 29, 2016 13:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielkza/9c151c97d1b2c53b66ae1d190464bc9d to your computer and use it in GitHub Desktop.
Save danielkza/9c151c97d1b2c53b66ae1d190464bc9d to your computer and use it in GitHub Desktop.
Strongswan IPSec init script with UCI support
#!/bin/sh /etc/rc.common
START=90
STOP=10
NAME=ipsec-uci
USE_PROCD=1
IPSEC_BIN=/usr/sbin/ipsec
IPSEC_SECRETS=/var/run/ipsec/ipsec.secrets
IPSEC_CONF=/var/run/ipsec/ipsec.conf
STRONGSWAN_CONF=/var/run/ipsec/strongswan.conf
IPSEC_D=/etc/ipsec.d
. /lib/functions.sh
. /lib/functions/network.sh
clear_ipsec_options() {
ipsec_options=
}
set_ipsec_option() {
if [ -n "$ipsec_options" ]; then
ipsec_options="$(echo "$ipsec_options" | sed "/^$1=/d")"$'\n'
fi
ipsec_options="${ipsec_options}$1=$2"
}
write_ipsec_options() {
echo "$ipsec_options" | sed 's/^/ /' | sort >> "$IPSEC_CONF"
echo >> "$IPSEC_CONF"
clear_ipsec_options
}
parse_custom_opt() {
local key value
key="${1%%=*}"
value="${1##*=}"
set_ipsec_option "$key" "$value"
}
parse_common_opts() {
config_get key_exchange "$1" key_exchange
config_get left_auth "$1" left_auth
config_get left_auth_2 "$1" left_auth_2
config_get right_auth "$1" right_auth
config_get right_auth_2 "$1" right_auth_2
config_get auto "$1" auto
config_get local_subnet "$1" local_subnet
config_get remote_subnet "$1" remote_subnet
config_get remote_virtual_subnet "$1" remote_virtual_subnet
config_get p1_proposal "$1" p1_proposal
config_get p2_proposal "$1" p2_proposal
p1_proposal=$(echo "$p1_proposal" | sed 's/ /,/g')
p2_proposal=$(echo "$p2_proposal" | sed 's/ /,/g')
if [ -n "$site_to_site" ]; then
if [ "$site_to_site" -eq 1 ]; then
set_ipsec_option xauth client
set_ipsec_option auto route
else
set_ipsec_option xauth server
if [ -n "$remote_virtual_subnet" ]; then
set_ipsec_option rightsourceip "$remote_virtual_subnet"
fi
set_ipsec_option auto add
fi
fi
[ -n "$left_auth" ] && set_ipsec_option leftauth "$left_auth"
[ -n "$left_auth_2" ] && set_ipsec_option leftauth2 "$left_auth_2"
[ -n "$right_auth" ] && set_ipsec_option rightauth "$right_auth"
[ -n "$right_auth_2" ] && set_ipsec_option rightauth2 "$right_auth_2"
[ -n "$auto" ] && set_ipsec_option auto "$auto"
[ -n "$key_exchange" ] && set_ipsec_option keyexchange "$key_exchange"
[ -n "$local_subnet" ] && set_ipsec_option leftsubnet "$local_subnet"
[ -n "$remote_subnet" ] && set_ipsec_option rightsubnet "$remote_subnet"
[ -n "$p1_proposal" ] && set_ipsec_option ike "$p1_proposal"
[ -n "$p2_proposal" ] && set_ipsec_option esp "$p2_proposal"
config_list_foreach "$1" custom parse_custom_opt
}
route_get_src() {
head -n1 | awk -F"src" '/src/{gsub(/ /,"");print $2}'
}
parse_remote_opts() {
config_get_bool site_to_site "$1" site_to_site "$site_to_site"
config_get local_address "$1" local_address
config_get remote_gateway "$1" gateway
config_get local_id "$1" local_id
config_get remote_id "$1" remote_id
config_get pre_shared_key "$1" pre_shared_key
[ "$remote_gateway" = any ] && remote_gateway='%any'
[ -n "$local_address" ] && set_ipsec_option left "$local_address"
[ -n "$local_id" ] && set_ipsec_option leftid "$local_id"
[ -n "$remote_gateway" ] && set_ipsec_option right "$remote_gateway"
[ -n "$remote_id" ] && set_ipsec_option rightid "$remote_id"
}
config_defaults() {
clear_ipsec_options
parse_common_opts "$1"
if [ -n "$ipsec_options" ]; then
echo 'conn %default' >> "$IPSEC_CONF"
write_ipsec_options
fi
}
config_remote() {
clear_ipsec_options
site_to_site=0
parse_remote_opts "$1"
parse_common_opts "$1"
remote_opts="$ipsec_options"
if [ -n "$pre_shared_key" ]; then
psk_left="$local_id"
[ -z "$psk_left" ] && psk_left="$local_address"
psk_right="$remote_id"
[ -z "$psk_right" ] && psk_right="$remote_gateway"
echo "$psk_left $psk_right : PSK \"$pre_shared_key\"" >> "$IPSEC_SECRETS"
fi
config_get_bool remote_enabled "$1" enabled 0
config_list_foreach "$1" tunnel config_tunnel "$1" "$ipsec_options"
}
config_tunnel() {
ipsec_options="$3"
parse_common_opts "$1"
set_ipsec_option type tunnel
config_get_bool tunnel_enabled "$1" enabled 0
if [[ "$remote_enabled" -eq 0 || "$tunnel_enabled" -eq 0 ]]; then
set_ipsec_option auto ignored
fi
echo "conn $2-$1" >> "$IPSEC_CONF"
write_ipsec_options
}
config_key() {
local key_enabled key_id key_type password key_file key_pass
config_get_bool key_enabled "$1" enabled 1
[ "$key_enabled" -eq 0 ] && return
config_get key_id "$1" id
config_get key_type "$1" type
config_get password "$1" password
config_get key_file "$1" key_file
config_get key_pass "$1" key_pass
[ -z "$key_id" ] && key_id="$1"
if [ -n "$key_type" ]; then
key_type=$(echo "$key_type" | awk '{print toupper($0);}')
elif [ -z "$key_file" ]; then
key_type=XAUTH
else
key_type=RSA
fi
echo "key $key_type $password $key_enabled"
case "$key_type" in
XAUTH|EAP|NTLM|PSK)
echo "$key_id : $key_type \"$password\"" >> "$IPSEC_SECRETS"
;;
RSA|ECDSA|BLISS|P12)
case "$key_file" in
"") ;;
/*) ;;
*) key_file="$IPSEC_D/private/$key_file" ;;
esac
[ -f "$key_file" ] || echo "warning: missing private key file $key_file" >&2
if [ -n "$key_pass" ]; then
echo "$key_id : $key_type $key_file \"$key_pass\"" >> "$IPSEC_SECRETS"
else
echo "$key_id : $key_type $key_file" >> "$IPSEC_SECRETS"
fi
;;
*)
echo "warning: unsupported key type \"$key_type\", skipping user \"$key_id\"" >&2
;;
esac
}
config_ca() {
clear_ipsec_options
config_get cert "$1" cert
config_get crluri1 "$1" revocation_uri
config_get crluri2 "$1" revocation_alt_uri
config_get ocspuri1 "$1" pinning_uri
config_get ocspuri2 "$1" pinning_alt_uri
config_get baseuri "$1" base_uri
config_get also "$1" include
config_get_bool ca_enabled "$1" enabled 0
if [ "$ca_enabled" -eq 1 ]; then
set_ipsec_option auto add
else
set_ipsec_option auto ignored
fi
set_ipsec_option cacert "$cert"
[ -n "$crluri1" ] && set_ipsec_option crluri1 "$crluri1"
[ -n "$crluri2" ] && set_ipsec_option crluri2 "$crluri2 "
[ -n "$ocspuri1" ] && set_ipsec_option ocspuri1 "$ocspuri1"
[ -n "$ocspuri2" ] && set_ipsec_option ocspuri2 "$ocspuri2"
[ -n "$baseuri" ] && set_ipsec_option baseuri "$baseuri"
[ -n "$also" ] && set_ipsec_option also "$also"
echo "ca $2" >> "$IPSEC_CONF"
write_ipsec_options
}
config_user() {
local user_enabled xauth name password
config_get_bool user_enabled "$1" enabled 0
[ "$user_enabled" -eq 0 ] && return
config_get name "$1" name
config_get password "$1" password
config_get_bool xauth "$1" xauth
if [ $xauth -eq 1 -a -n "$name" -a -n "$password" ]; then
echo "$name : XAUTH \"$password\"" >> "$IPSEC_SECRETS"
fi
}
prepare_environment() {
local debug
mkdir -p "$(dirname "$IPSEC_CONF")"
for d in cacerts aacerts ocspcerts crls acerts private; do
mkdir -p "$IPSEC_D/$d"
chmod 700 "$IPSEC_D/$d"
done
if [ "$(readlink /etc/strongswan.conf 2>/dev/null)" != "$STRONGSWAN_CONF" ]; then
[ -f /etc/strongswan.conf ] && mv /etc/strongswan.conf /etc/strongswan.user.conf
ln -sf "$STRONGSWAN_CONF" /etc/strongswan.conf
fi
# ipsec.conf
cat > "$IPSEC_CONF" <<EOF
# generated by /etc/init.d/$NAME
version 2
EOF
# ipsec.secrets
cat > "$IPSEC_SECRETS" <<EOF
# generated by /etc/init.d/$NAME
include /etc/ipsec.secrets
EOF
# strongswan.conf
config_get debug "$1" debug 0
cat > "$STRONGSWAN_CONF" <<EOF
# generated by /etc/init.d/$NAME
charon {
filelog {
/var/log/charon.log {
time_format = %b %e %T
ike_name = yes
append = yes
default = $debug
flush_line = yes
}
}
load_modular = yes
plugins {
include /etc/strongswan.d/charon/*.conf
stroke {
secrets_file = "$IPSEC_SECRETS"
}
}
}
include /etc/strongswan.user.conf
include /etc/strongswan.d/*.conf
EOF
}
check_installation() {
if ! command -v ip >/dev/null; then
echo "ip command missing" >&2
echo 'install with "opkg install ip"' >&2
exit 1
fi
for f in aes cbc hmac md5 sha1 sha256; do
if ! grep -qF "$f" /proc/crypto; then
echo "kmod-crypto-$f missing" >&2
echo "install with \"opkg install kmod-crypto-$f\"" >&2
exit 1
fi
done
for m in authenc echainiv; do
if ! lsmod | grep -qF "$m"; then
echo "kmod-crypto-$f missing" >&2
echo "install with \"opkg install kmod-crypto-$f\"" >&2
exit 1
fi
done
for f in aes gmp hmac kernel-netlink md5 random sha1 sha2 updown attr resolve; do
if [ ! -f /usr/lib/ipsec/plugins/libstrongswan-${f}.so ]; then
echo "/usr/lib/ipsec/plugins/$f missing" >&2
echo "install with \"opkg install strongswan-mod-$f\"" >&2
exit 1
fi
done
}
config_all()
{
config_load ipsec
config_foreach prepare_environment ipsec
config_foreach config_defaults defaults
config_foreach config_remote remote
config_foreach config_key key
config_load users
config_foreach config_user user
}
start_service() {
check_installation
config_all
procd_open_instance
procd_set_param respawn
procd_set_param command "$IPSEC_BIN" starter --nofork --conf "$IPSEC_CONF"
procd_set_param file \
"$IPSEC_SECRETS" "$IPSEC_CONF" "$STRONGSWAN_CONF" /etc/config/ipsec
procd_close_instance
}
reload_service() {
config_all
"$IPSEC_BIN" rereadsecrets
"$IPSEC_BIN" update
killall -HUP charon
}
service_triggers() {
local wan_iface
network_find_wan wan_iface
if [ -n "$wan_iface" ]; then
procd_add_reload_interface_trigger "$wan_iface"
fi
procd_add_reload_trigger ipsec
}
@RobsonRojas
Copy link

How can I use this script?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment