|
|
@ -1,17 +1,475 @@ |
|
|
|
#!/bin/sh /etc/rc.common |
|
|
|
# Copyright (C) 2009-2011 OpenWrt.org |
|
|
|
# Copyright (C) 2011 Artem Makhutov |
|
|
|
# Copyright (C) 2014 Noah Meyerhans <frodo@morgul.net> |
|
|
|
# |
|
|
|
# Copyright (C) 2015 Vitaly Protsko <villy@sft.ru> |
|
|
|
|
|
|
|
#set -vx |
|
|
|
|
|
|
|
USE_PROCD=1 |
|
|
|
|
|
|
|
START=49 |
|
|
|
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() { |
|
|
|
mkdir -m 0700 -p /var/racoon |
|
|
|
[ -f /etc/ipsec.conf ] && /usr/sbin/setkey -f /etc/ipsec.conf |
|
|
|
procd_open_instance |
|
|
|
procd_set_param command /usr/sbin/racoon -F -f /etc/racoon.conf |
|
|
|
procd_set_param respawn |
|
|
|
procd_close_instance |
|
|
|
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 |