openwrt-packages/net/libreswan/files/etc/init.d/ipsec

338 lines
8.4 KiB
Bash

#!/bin/sh /etc/rc.common
. "${IPKG_INSTROOT}/lib/functions/network.sh"
START=90
STOP=10
USE_PROCD=1
PROG="/usr/libexec/ipsec/pluto"
IPSEC_BIN="/usr/sbin/ipsec"
IPSEC_DIR="/var/run/ipsec"
IPSEC_CONF="$IPSEC_DIR/setup.conf"
IPSEC_CONF_DIR="$IPSEC_DIR/conf.d"
IPSEC_AUTO="${IPSEC_BIN} auto"
extra_command "start_tunnel" "Start ipsec tunnel"
extra_command "stop_tunnel" "Stop ipsec tunnel"
extra_command "reload_tunnel" "Reload/restart ipsec tunnel"
set_var() {
export "$1=$2"
}
get_var() {
local var
var=$(eval echo "\"\${${1}}\"")
[ "$var" = "1" ] && return 0
return 1
}
set_restart_flag() {
set_var "RESTART_IPSEC" 1
}
restart_flag() {
get_var RESTART_IPSEC
}
set_replace_flag() {
set_var "REPLACE_${1}" 1
}
replace_flag() {
get_var "REPLACE_${1}"
}
checkconfig() {
${IPSEC_BIN} addconn --checkconfig || return 1
mkdir -p /var/run/pluto
}
expand_ike() {
local id="$1"
local encryption_algorithm hash_algorithm dh_group proposal
config_get encryption_algorithm "${id}" encryption_algorithm
config_get hash_algorithm "${id}" hash_algorithm
config_get dh_group "${id}" dh_group
encryption_algorithm="${encryption_algorithm% *}"
proposal="${encryption_algorithm:+${encryption_algorithm}${hash_algorithm:+-${hash_algorithm}${dh_group:+;${dh_group%% *}}}}"
append ike_proposal "$proposal" ","
}
expand_phase2alg() {
local id="$1"
local encryption_algorithm hash_algorithm dh_group
config_get encryption_algorithm "${id}" encryption_algorithm
config_get hash_algorithm "${id}" hash_algorithm
config_get dh_group "${id}" dh_group
phase2alg_proposal="${encryption_algorithm:+${encryption_algorithm// /+}${hash_algorithm:+-${hash_algorithm// /+}${dh_group:+-${dh_group// /+}}}}"
}
generate_tunnel_config() {
local id=$1
local config_file="$IPSEC_CONF_DIR/$id.conf"
local secret_file="$IPSEC_CONF_DIR/$id.secret"
local tmp_config_file="/tmp/$id.conf"
local tmp_secret_file="/tmp/$id.secret"
local ikey mark_in okey mark_out ifid
config_get auto "$id" auto
config_get left "$id" left
config_get left_interface "$id" left_interface
[ -n "$left_interface" ] && network_get_ipaddr left "$left_interface"
config_get right "$id" right
config_get leftid "$id" leftid "$left"
config_get rightid "$id" rightid "$right"
config_get leftsourceip "$id" leftsourceip
config_get rightsourceip "$id" rightsourceip
config_get leftsubnets "$id" leftsubnets
config_get rightsubnets "$id" rightsubnets
config_get_bool ikev2 "$id" ikev2
[ "$ikev2" = "1" ] && ikev2=yes || ikev2=no
config_get_bool rekey "$id" rekey
[ "$rekey" = "1" ] && rekey=yes || rekey=no
config_get ikelifetime "$id" ikelifetime
config_get rekeymargin "$id" rekeymargin
config_get dpdaction "$id" dpdaction
config_get dpdtimeout "$id" dpdtimeout
config_get dpddelay "$id" dpddelay
config_get phase2 "$id" phase2
config_get phase2alg "$id" phase2alg
config_get nflog "$id" nflog 0
[ "$nflog" = "0" ] && unset nflog
config_list_foreach "$id" ike expand_ike
config_list_foreach "$id" phase2alg expand_phase2alg
config_get authby "$id" authby
config_get psk "$id" psk
if [ -n "$leftsubnets" ]; then
[[ "$leftsubnets" =~ 0.0.0.0* ]] && leftsubnets="0.0.0.0/0"
leftsubnets="{${leftsubnets// /,}}"
fi
if [ -n "$rightsubnets" ]; then
[[ "$rightsubnets" =~ 0.0.0.0* ]] && rightsubnets="0.0.0.0/0"
rightsubnets="{${rightsubnets// /,}}"
fi
config_get interface "$id" interface
cat << EOF > "$tmp_secret_file"
$leftid $rightid : PSK "$psk"
EOF
cat << EOF > "$tmp_config_file"
conn $id
auto=${auto}
authby=${authby}
ikev2=${ikev2}
left=${left%% *}
${leftid:+leftid=${leftid}}
${leftsourceip:+leftsourceip=${leftsourceip}}
${leftsubnets:+leftsubnets=${leftsubnets}}
right=${right%% *}
${rightid:+rightid=${rightid}}
${rightsourceip:+rightsourceip=${rightsourceip}}
${rightsubnets:+rightsubnets=${rightsubnets}}
${dpdaction:+dpdaction=${dpdaction}}
${dpdtimeout:+dpdtimeout=${dpdtimeout}}
${dpddelay:+dpddelay=${dpddelay}}
${ikelifetime:+ikelifetime=${ikelifetime}}
${rekey:+rekey=${rekey}}
${rekeymargin:+rekeymargin=${rekeymargin}}
${rekeyfuzz:+rekeyfuzz=${rekeyfuzz}}
${phase2:+phase2=${phase2}}
${ike_proposal:+ike=${ike_proposal}}
${phase2alg_proposal:+phase2alg=${phase2alg_proposal}}
${nflog:+nflog=${nflog}}
EOF
if [ -n "$interface" ]; then
proto=$(uci_get network "$interface" proto)
case "$proto" in
vti)
ikey=$(uci_get network "$interface" ikey)
okey=$(uci_get network "$interface" okey)
mark_in=$(printf "0x%x" $ikey)
mark_out=$(printf "0x%x" $okey)
echo -e "${mark_in:+\tmark-in=${mark_in}}" >> "$tmp_config_file"
echo -e "${mark_out:+\tmark-out=${mark_out}}" >> "$tmp_config_file"
echo -e "${interface:+\tvti-interface=${interface}}" >> "$tmp_config_file"
;;
xfrm)
ifid=$(uci_get network "$interface" ifid)
echo -e "${ifid:+\tipsec-interface=${ifid}}" >> "$tmp_config_file"
;;
esac
fi
[ -f "$config_file" ] && {
cmp "$config_file" "$tmp_config_file" 2>/dev/null && rm -f "$tmp_config_file"
}
[ -f "$secret_file" ] && {
cmp "$secret_file" "$tmp_secret_file" 2>/dev/null && rm -f "$tmp_secret_file"
}
[ -f "$tmp_config_file" ] && mv "$tmp_config_file" "$config_file" && set_replace_flag "$id"
[ -f "$tmp_secret_file" ] && mv "$tmp_secret_file" "$secret_file" && set_replace_flag "$id"
unset ike_proposal phase2alg_proposal
}
generate_daemon_config() {
local tmp_config_file="/tmp/setup.conf"
config_get_bool debug globals debug 0
[ "$debug" = "0" ] && debug=none || debug=all
config_get_bool uniqueids globals uniqueids 0
[ "$uniqueids" = "0" ] && uniqueids=no || uniqueids=yes
config_get listen globals listen
config_get listen_interface globals listen_interface
[ -n "$listen_interface" ] && network_get_ipaddr listen "$listen_interface"
config_get virtual_private globals virtual_private
[ -z "$virtual_private" ] && virtual_private='10.0.0.0/8 192.168.0.0/16 172.16.0.0/12 25.0.0.0/8 100.64.0.0/10 !100.64.0.0/24'
config_get nflog_all globals nflog_all 0
[ "$nflog_all" = "0" ] && unset nflog_all
[ ! -d $IPSEC_DIR ] && mkdir -p $IPSEC_DIR
[ ! -d $IPSEC_CONF_DIR ] && mkdir -p $IPSEC_CONF_DIR
cat << EOF > "$tmp_config_file"
config setup
${debug:+plutodebug=${debug}}
${uniqueids:+uniqueids=${uniqueids}}
${listen:+listen=${listen}}
${virtual_private:+virtual-private=%v4:${virtual_private// /,%v4:}}
${nflog_all:+nflog-all=${nflog_all}}
EOF
if ! cmp "$IPSEC_CONF" "$tmp_config_file" 2>/dev/null; then
mv "$tmp_config_file" "$IPSEC_CONF"
set_restart_flag 1
else
rm -f "$tmp_config_file"
fi
return 0
}
clean_config() {
rm -f $IPSEC_CONF_DIR/*.conf $IPSEC_CONF_DIR/*.secret
}
config_cb() {
local var="CONFIG_${1}_SECTIONS"
export $var
append "$var" "$2"
}
generate_config() {
config_load libreswan
generate_daemon_config
config_foreach generate_tunnel_config tunnel
}
regenerate_config() {
clean_config
generate_config
}
active_conns() {
local active_conns file _file
active_conns=$(${IPSEC_BIN} --trafficstatus | awk -F'[":/]' '{print $3}' | sort -u)
for file in $IPSEC_CONF_DIR/*.conf; do
_file="${file##*/}"
list_contains active_conns "${_file%%.*}" || append active_conns "${_file%%.*}"
done
echo "$active_conns"
}
start_service() {
generate_config
checkconfig || return 1
${IPSEC_BIN} _stackmanager start
procd_open_instance
procd_set_param command $PROG --nofork
procd_set_param respawn
procd_close_instance
}
stop_service() {
${IPSEC_BIN} whack --shutdown
${IPSEC_BIN} _stackmanager stop
}
stop_tunnel() {
${IPSEC_AUTO} --delete "$1" > /dev/null 2>&1
rm -f ${IPSEC_CONF_DIR}/$1.*
}
start_tunnel() {
generate_tunnel_config "$1"
${IPSEC_AUTO} --add "$1" > /dev/null 2>&1
${IPSEC_AUTO} --rereadsecrets
${IPSEC_AUTO} --up "$1" > /dev/null 2>&1 &
}
reload_tunnel() {
generate_tunnel_config "$1"
replace_flag "$1" || return 0
${IPSEC_AUTO} --rereadsecrets
${IPSEC_AUTO} --replace "$1" > /dev/null 2>&1
${IPSEC_AUTO} --up "$1" > /dev/null 2>&1 &
}
reload_service() {
local active_tunnels uci_tunnels
uci_tunnels="$@"
config_load libreswan
generate_daemon_config
if restart_flag; then
restart
return 0
fi
[ -z "$uci_tunnels" ] && config_get uci_tunnels tunnel SECTIONS
active_tunnels="$(active_conns)"
for tunnel in $active_tunnels; do
list_contains uci_tunnels "$tunnel" || stop_tunnel "$tunnel"
done
for tunnel in $uci_tunnels; do
if list_contains active_tunnels "$tunnel"; then
reload_tunnel "$tunnel"
else
start_tunnel "$tunnel"
fi
done
}
service_triggers() {
procd_add_reload_trigger 'libreswan'
}