--- /dev/null
+#/etc/config/racoon
+#
+# Copyright 2015 Vitaly Protsko <villy@sft.ru>
+
+# * WARNING: this is "not working" example
+# * Defaults are commented out
+# * Resuting config will appear in /var/racoon/
+
+config racoon
+# option debug 0
+# option ext_zone 'wan'
+# option int_zone 'lan'
+# option port 500
+# option natt_port 4500
+# following 4 or 6, no default
+# option ipversion 4
+
+config p1_proposal 'example_prop1'
+# option lifetime 28800
+ option enc_alg 'aes'
+ option hash_alg 'sha1'
+ option auth_method 'rsasig'
+ option dh_group 2
+
+config p1_proposal 'example_anon'
+# option lifetime 28800
+ option enc_alg 'aes'
+ option hash_alg 'sha1'
+ option auth_method 'xauth_rsa_server'
+ option dh_group 2
+
+config p1_proposal 'example_xauth'
+# option lifetime 28800
+ option enc_alg 'aes'
+ option hash_alg 'sha1'
+ option auth_method 'xauth_rsa_client'
+ option dh_group 2
+
+config p2_proposal 'example_prop2'
+ option pfs_group 2
+ option enc_alg 'aes'
+ option auth_alg 'hmac_sha1'
+
+config p2_proposal 'example_in2'
+ option pfs_group 2
+# option lifetime 14400
+ option enc_alg 'aes'
+ option auth_alg 'hmac_sha1'
+
+config sainfo 'office'
+ option p2_proposal 'example_prop2'
+ option local_net '192.168.8.0/24'
+ option remote_net '192.168.1.0/24'
+
+config sainfo 'welcome'
+ option p2_proposal 'example_in2'
+ option local_net '192.168.8.0/24'
+ option remote_net '192.168.10.0/24'
+ option dns4 '192.168.8.1'
+ option defdomain 'myhome.local'
+
+config sainfo 'client'
+ p2_proposal 'std_p2'
+
+config tunnel 'Office'
+ option enabled 1
+# initial_contact
+# option init 1
+ option remote 'vpn.example.tld'
+ option exchange_mode 'main'
+ option certificate 'example_cert'
+# option peer_id_type 'asn1dn'
+# option prop_check 'obey'
+# option verify_id 1
+# option weak_p1check 1
+# option dpd_delay ''
+ list p1_proposal 'example_prop1'
+ list sainfo 'office'
+
+# WARNING: Only ONE tunnel with remote anonymous
+# can be configured and it can have only
+# ONE sainfo. Otherwise resulting racoon
+# configuration will be unusable
+config tunnel 'Incoming'
+ option enabled 1
+ option remote 'anonymous'
+ option pre_shared_key 'testitnow'
+ option exchange_mode 'aggressive,main'
+ option my_id_type 'fqdn'
+ option my_id 'myserver.homeip.net'
+ list p1_proposal 'example_anon'
+ list sainfo 'welcome'
+
+config tunnel 'Client'
+ option enabled 1
+ option remote 'vpn.example.tld'
+ option username 'testuser'
+ option password 'testW0rD'
+# option mode_cfg 1
+ list p1_proposal 'example_xauth'
+ list sainfo 'client'
+
+# Insert corresponding data in PEM format as one line
+config 'certificate' 'example_cert'
+ option 'key' '-----BEGIN PRIVATE KEY----- ~ -----END PRIVATE KEY-----'
+ option 'crt' '-----BEGIN CERTIFICATE----- ~ -----END CERTIFICATE-----'
+
+config 'certificate' 'example_ca_cert'
+ option 'crt' '-----BEGIN CERTIFICATE----- ~ -----END CERTIFICATE-----'
#!/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