You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

475 lines
11 KiB

#!/bin/sh /etc/rc.common
#
# Copyright (C) 2015 Vitaly Protsko <villy@sft.ru>
#set -vx
USE_PROCD=1
START=60
STOP=40
let connWait=2/2
confDir=/var/racoon
confExtZone=
confIntZone=
confPort=
confNATPort=
confIPMode=
confPh1ID=0
log="logger -t init.d/racoon[$$] "
. /etc/racoon/functions.sh
setup_load() {
config_get confExtZone "$1" ext_zone wan
config_get confIntZone "$1" int_zone lan
config_get confPort "$1" port 500
config_get confNATPort "$1" natt_port 4500
config_get confIPMode "$1" ipversion ""
case X$confIPMode in
X4|X6) ;;
*) unset confIPMode ;;
esac
}
write_header() {
echo "
# autogenerated, don't edit, look at /etc/config/racoon
#
path certificate \"$confDir/cert\";
path script \"/etc/racoon\";
path pre_shared_key \"$confDir/psk.txt\";
path pidfile \"$confDir/racoon.pid\";
padding { maximum_length 20; randomize off; strict_check off; exclusive_tail off; }
timer { counter 5; interval 20 sec; persend 1; phase1 30 sec; phase2 15 sec; }
"
}
setup_conf() {
local conf=$confDir/racoon.conf
local peerconf=$confDir/peers.txt
local pskconf=$confDir/psk.txt
local item
local data
data="$(get_zoneiplist $confExtZone)"
if [ "X$data" = X ]; then
$log "No IP addresses found for zone $confExtZone, exitng"
errno=2; return 2
fi
write_header > $conf
echo -n > $peerconf
echo -n > $pskconf
chmod 0600 $conf $peerconf $pskconf
echo "listen {" >> $conf
for item in $data ; do
echo " isakmp $item [$confPort]; isakmp_natt $item [$confNATPort];" >> $conf
done
echo "}" >> $conf
config_get_bool item "$1" debug 0
data=warning
test $item -ne 0 && data=debug
echo "log $data;" >> $conf
setup_fw add
}
setup_p1() {
local conf=$confDir/racoon.conf
local data
echo " proposal {" >> $conf
config_get data "$1" lifetime 28800
echo " lifetime time $data sec;" >> $conf
config_get data "$1" enc_alg
test -n "$data" && echo " encryption_algorithm $data;" >> $conf
config_get data "$1" hash_alg
test -n "$data" && echo " hash_algorithm $data;" >> $conf
config_get data "$1" auth_method
test -n "$data" && echo " authentication_method $data;" >> $conf
config_get data "$1" dh_group 2
echo -e " dh_group $data;\n }" >> $conf
}
setup_fw() {
local cmd=/usr/sbin/iptables
local mode
case "$1" in
add|up|1) mode=A ;;
del|down|0) mode=D ;;
*) return 3 ;;
esac
$cmd -$mode input_${confExtZone}_rule -p AH -j ACCEPT
$cmd -$mode input_${confExtZone}_rule -p ESP -j ACCEPT
$cmd -$mode input_${confExtZone}_rule -p UDP --dport $confPort -j ACCEPT
$cmd -$mode input_${confExtZone}_rule -p UDP --dport $confNATPort -j ACCEPT
}
setup_sa() {
local conf=$confDir/racoon.conf
local remote="${2/ *}"
local client="${2#* }"
local locnet
local remnet
local p2
local data
test "$2" = "$client" && unset client
if [ -z "$client" ]; then
config_get locnet "$1" local_net
config_get remnet "$1" remote_net
if [ -z "$locnet" ] || [ -z "$remnet" ]; then
$log "Remote and local networks for $1 must be configured ($2)"
errno=4; return 4
fi
if [ "$remote" = "anonymous" ]; then
echo "sainfo anonymous {" >> $conf
else
echo "sainfo address $locnet any address $remnet any {" >> $conf
fi
else
echo "sainfo anonymous {" >> $conf
fi
config_get p2 "$1" p2_proposal
if [ -z "$p2" ]; then
$log "Phase2 proposal must be configured in $1 sainfo"
errno=5; return 5
fi
echo " remoteid $confPh1ID;" >> $conf
config_get data "$p2" pfs_group
test -n "$data" && echo " pfs_group $data;" >> $conf
config_get data "$p2" lifetime 14400
test -n "$data" && echo " lifetime time $data sec;" >> $conf
config_get data "$p2" enc_alg
test -n "$data" && echo " encryption_algorithm $data;" >> $conf
config_get data "$p2" auth_alg
test -n "$data" && echo " authentication_algorithm $data;" >> $conf
echo -e " compression_algorithm deflate;\n}" >> $conf
if [ "$remote" = "anonymous" ]; then
echo -e "mode_cfg {\n auth_source system;\n conf_source local;" >> $conf
config_get data "$1" dns4
test -n "$data" && echo " dns4 $data;" >> $conf
config_get data "$1" defdomain
test -n "$data" && echo " default_domain \"$data\";" >> $conf
data=${remnet%/*}
let "data=${data##*.}+1"
echo " network4 ${remnet%.*}.$data;" >> $conf
let "data=255<<(24-${remnet#*/}+8)&255"
echo " netmask4 255.255.255.$data;" >> $conf
echo -e " split_network include $locnet;\n}" >> $conf
elif [ -z "$client" ]; then
manage_sa add $locnet $remnet $remote
test $? -gt 0 -o $errno -gt 0 && return $errno
manage_fw add $confIntZone $confExtZone $remnet
fi
}
setup_tunnel() {
local conf=$confDir/racoon.conf
local peerconf=$confDir/peers.txt
local data
local remote
local xauth
config_get_bool data "$1" enabled 0
test "$data" = "0" && return 0
config_get remote "$1" remote
if [ "$remote" = "anonymous" ]; then
echo -e "remote anonymous {\n generate_policy on;" >> $conf
else
data=$(nslookup "$remote" | awk 'NR == 5 {print $3}')
test -n "$data" && remote="$data"
echo -e "remote \"$1\" {\n remote_address $remote;" >> $conf
echo "$data" >> $peerconf
fi
config_get data "$1" pre_shared_key ""
if [ -n "$data" ]; then
if [ "$remote" != "anonymous" ]; then
echo "$remote $data" >> $confDir/psk.txt
else
echo "* $data" >> $confDir/psk.txt
fi
fi
let confPh1ID=$confPh1ID+1
echo " ph1id $confPh1ID;" >> $conf
config_get xauth "$1" username ""
config_get data "$1" certificate ""
if [ -n "$data" ]; then
echo -en " verify_cert on;\n my_identifier asn1dn;\n certificate_type x509 " >> $conf
echo -en "\"$data.crt\" \"$data.key\";\n send_cr off;\n peers_identifier " >> $conf
else
config_get data "$1" my_id_type ""
if [ -n "$data" ]; then
echo -n " my_identifier $data" >> $conf
config_get data "$1" my_id ""
if [ -n "$data" ]; then
echo " \"$data\";" >> $conf
elif [ -n "$xauth" ]; then
echo " \"$xauth\";" >> $conf
else
echo ";" >> $conf
fi
elif [ -n "$xauth" ]; then
echo " my_identifier user_fqdn \"$xauth\";" >> $conf
fi
echo -n " peers_identifier " >> $conf
fi
if [ "$remote" = "anonymous" ]; then
echo "user_fqdn;" >> $conf
else
config_get data "$1" peer_id_type "asn1dn"
echo -n "$data" >> $conf
config_get data "$1" peer_id ""
test -n "$data" && echo -n " \"$data\"" >> $conf
echo ";" >> $conf
fi
if [ -n "$xauth" ]; then
config_get data "$1" password
if [ -z "$data" ]; then
$log "Password must be given in $1 tunnel"
errno=7; return 7
fi
echo "$xauth $data" >> $confDir/psk.txt
echo " xauth_login \"$xauth\";" >> $conf
echo -e " script \"p1client-up\" phase1_up;\n script \"p1client-down\" phase1_down;" >> $conf
fi
config_get data "$1" exchange_mode
if [ -z "$data" ]; then
data=main
test -n "$xauth" && data="${data},aggressive"
fi
echo -e " exchange_mode $data;\n nat_traversal on;\n support_proxy on;" >> $conf
config_get data "$1" prop_check "obey"
test -n "$data" && echo " proposal_check $data;" >> $conf
config_get_bool data "$1" weak_p1check 1
if [ $data -eq 0 ]; then data=off; else data=on; fi
echo " weak_phase1_check $data;" >> $conf
config_get_bool data "$1" verify_id 1
if [ $data -eq 0 ]; then data=off; else data=on; fi
echo " verify_identifier $data;" >> $conf
config_get data "$1" dpd_delay ""
test -n "$data" && echo " dpd_delay $data;" >> $conf
unset data
test -n "$xauth" && data="on"
config_get data "$1" mode_cfg "$data"
test -n "$data" && echo " mode_cfg $data;" >> $conf
config_get_bool data "$1" init 0
if [ $data -eq 0 ]; then data=off; else data=on; fi
echo " initial_contact $data;" >> $conf
config_list_foreach "$1" p1_proposal setup_p1
echo "}" >> $conf
config_list_foreach "$1" sainfo setup_sa "$remote $xauth"
}
setup_cert() {
local item
local data
for item in key crt ; do
config_get data "$1" $item ""
test -z "$data" && continue
echo "$data" |\
sed 's/-\+[A-Z ]\+-\+/\n&\n/g' | sed 's/.\{50,50\}/&\n/g' | sed '/^$/d'\
> $confDir/cert/$1.$item
chmod 600 $confDir/cert/$1.$item
done
if [ -s $confDir/cert/$1.crt ]; then
data=$(openssl x509 -noout -hash -in $confDir/cert/$1.crt)
ln -sf $confDir/cert/$1.crt $confDir/cert/$data.0
fi
}
destroy_sa() {
local locnet
local remnet
config_get locnet "$1" local_net
config_get remnet "$1" remote_net
if [ -z "$locnet" ] || [ -z "$remnet" ]; then
$log "Remote and local networks for $1 must be configured"
errno=4; return 4
fi
manage_sa del $locnet $remnet $2
manage_fw del $confIntZone $confExtZone $remnet
}
destroy_tunnel() {
local data
config_get_bool data "$1" enabled 0
test "$data" = "0" && return 0
config_get remote "$1" remote
data=$(nslookup "$remote" | awk 'NR == 5 {print $3}')
test -n "$data" && remote="$data"
config_get data "$1" username ""
if [ -z "$data" ]; then
config_list_foreach "$1" sainfo destroy_sa $remote
fi
}
destroy_conf() {
setup_fw del
}
check_software() {
local item
for item in /usr/sbin/setkey /usr/bin/openssl /usr/sbin/ip ; do
if [ ! -x $item ]; then
$log "Needed program $item not found, exiting"
errno=9; return 9
fi
done
}
cleanup_conf() {
config_load racoon
config_foreach setup_load racoon
config_foreach destroy_conf racoon
config_foreach destroy_tunnel tunnel
/usr/sbin/setkey -P -F
/usr/sbin/setkey -F
}
check_dir() {
local item
for item in $confDir $confDir/cert ; do
if [ ! -d $item ]; then
mkdir -m 0700 -p $item
fi
done
}
wait4wanzone() {
local item=$connWait
local data
data="$(get_zoneiplist $confExtZone)"
while [ $item -gt 0 ]; do
test -n "$data" && break
sleep 2
let "item=$item-1"
data="$(get_zoneiplist $confExtZone)"
done
test -z "$data" && return 10
}
start_service() {
check_software
test $? -gt 0 -o $errno -gt 0 && exit $errno
check_dir
config_load racoon
config_foreach setup_load racoon
config_foreach wait4wanzone racoon
if [ $? -gt 0 ] || [ $errno -gt 0 ]; then
$log "No active interfaces in $confExtZone zone found, exiting"
exit $errno
fi
config_foreach setup_conf racoon
test $? -gt 0 -o $errno -gt 0 && exit $errno
config_foreach setup_tunnel tunnel
test $? -gt 0 -o $errno -gt 0 && exit $errno
config_foreach setup_cert certificate
procd_open_instance
procd_set_param command /usr/sbin/racoon
test -n "$confIPMode" && procd_append_param command -$confIPMode
procd_append_param command -F -f $confDir/racoon.conf
procd_set_param file $confDir/racoon.conf
procd_close_instance
if [ -x /etc/racoon/vpnctl ]; then
let connWait=$connWait*2+2
( sleep $connWait; /etc/racoon/vpnctl up ) &
fi
}
service_triggers() {
local item
local data
procd_add_reload_trigger "racoon" "network"
config_load racoon
config_foreach setup_load racoon
data=$(get_zoneiflist $confExtZone)
if [ $? -gt 0 ] || [ $errno -gt 0 ] || [ -z "$data" ]; then
$log "Can not find interfaces for $confExtZone zone"
else
for item in $data ; do
procd_add_reload_interface_trigger $item
done
fi
}
stop_service() {
cleanup_conf
procd_kill racoon
}
trap "cleanup_conf" 1 2 3 4 5 6 7 8 9 10
# EOF /etc/init.d/racoon