| #!/bin/sh /etc/rc.common |
| |
| START=90 |
| STOP=10 |
| |
| USE_PROCD=1 |
| PROG=/usr/lib/ipsec/starter |
| |
| . $IPKG_INSTROOT/lib/functions.sh |
| . $IPKG_INSTROOT/lib/functions/network.sh |
| |
| IPSEC_SECRETS_FILE=/etc/ipsec.secrets |
| IPSEC_CONN_FILE=/etc/ipsec.conf |
| STRONGSWAN_CONF_FILE=/etc/strongswan.conf |
| |
| IPSEC_VAR_SECRETS_FILE=/var/ipsec/ipsec.secrets |
| IPSEC_VAR_CONN_FILE=/var/ipsec/ipsec.conf |
| STRONGSWAN_VAR_CONF_FILE=/var/ipsec/strongswan.conf |
| |
| WAIT_FOR_INTF=0 |
| |
| file_reset() { |
| : > "$1" |
| } |
| |
| xappend() { |
| local file="$1" |
| shift |
| |
| echo "$@" >> "$file" |
| } |
| |
| ipsec_reset() { |
| file_reset "$IPSEC_VAR_CONN_FILE" |
| } |
| |
| ipsec_xappend() { |
| xappend "$IPSEC_VAR_CONN_FILE" "$@" |
| } |
| |
| swan_reset() { |
| file_reset "$STRONGSWAN_VAR_CONF_FILE" |
| } |
| |
| swan_xappend() { |
| xappend "$STRONGSWAN_VAR_CONF_FILE" "$@" |
| } |
| |
| secret_reset() { |
| file_reset "$IPSEC_VAR_SECRETS_FILE" |
| } |
| |
| secret_xappend() { |
| xappend "$IPSEC_VAR_SECRETS_FILE" "$@" |
| } |
| |
| warning() { |
| echo "WARNING: $@" >&2 |
| } |
| |
| add_crypto_proposal() { |
| local encryption_algorithm |
| local hash_algorithm |
| local dh_group |
| |
| config_get encryption_algorithm "$1" encryption_algorithm |
| config_get hash_algorithm "$1" hash_algorithm |
| config_get dh_group "$1" dh_group |
| |
| [ -n "${encryption_algorithm}" ] && \ |
| crypto="${crypto:+${crypto},}${encryption_algorithm}${hash_algorithm:+-${hash_algorithm}}${dh_group:+-${dh_group}}" |
| } |
| |
| set_crypto_proposal() { |
| local conf="$1" |
| local proposal |
| |
| crypto="" |
| |
| config_get crypto_proposal "$conf" crypto_proposal "" |
| for proposal in $crypto_proposal; do |
| add_crypto_proposal "$proposal" |
| done |
| |
| [ -n "${crypto}" ] && { |
| local force_crypto_proposal |
| |
| config_get_bool force_crypto_proposal "$conf" force_crypto_proposal |
| |
| [ "${force_crypto_proposal}" = "1" ] && crypto="${crypto}!" |
| } |
| |
| crypto_proposal="${crypto}" |
| } |
| |
| config_conn() { |
| # Generic ipsec conn section shared by tunnel and transport |
| local mode |
| local local_subnet |
| local local_nat |
| local local_sourceip |
| local local_leftip |
| local local_updown |
| local local_firewall |
| local remote_subnet |
| local remote_sourceip |
| local remote_updown |
| local remote_firewall |
| local ikelifetime |
| local lifetime |
| local margintime |
| local keyingtries |
| local dpdaction |
| local dpddelay |
| local inactivity |
| local keyexchange |
| local reqid |
| local packet_marker |
| |
| config_get mode "$1" mode "route" |
| config_get local_subnet "$1" local_subnet "" |
| config_get local_nat "$1" local_nat "" |
| config_get local_sourceip "$1" local_sourceip "" |
| config_get local_leftip "$1" local_leftip "%any" |
| config_get local_updown "$1" local_updown "" |
| config_get local_firewall "$1" local_firewall "" |
| config_get remote_subnet "$1" remote_subnet "" |
| config_get remote_sourceip "$1" remote_sourceip "" |
| config_get remote_updown "$1" remote_updown "" |
| config_get remote_firewall "$1" remote_firewall "" |
| config_get ikelifetime "$1" ikelifetime "3h" |
| config_get lifetime "$1" lifetime "1h" |
| config_get margintime "$1" margintime "9m" |
| config_get keyingtries "$1" keyingtries "3" |
| config_get dpdaction "$1" dpdaction "none" |
| config_get dpddelay "$1" dpddelay "30s" |
| config_get inactivity "$1" inactivity |
| config_get keyexchange "$1" keyexchange "ikev2" |
| config_get reqid "$1" reqid |
| config_get packet_marker "$1" packet_marker |
| |
| [ -n "$local_nat" ] && local_subnet=$local_nat |
| |
| ipsec_xappend "conn $config_name-$1" |
| ipsec_xappend " left=$local_leftip" |
| ipsec_xappend " right=$remote_gateway" |
| |
| [ -n "$local_sourceip" ] && ipsec_xappend " leftsourceip=$local_sourceip" |
| [ -n "$local_subnet" ] && ipsec_xappend " leftsubnet=$local_subnet" |
| |
| [ -n "$local_firewall" ] && ipsec_xappend " leftfirewall=$local_firewall" |
| [ -n "$remote_firewall" ] && ipsec_xappend " rightfirewall=$remote_firewall" |
| |
| ipsec_xappend " ikelifetime=$ikelifetime" |
| ipsec_xappend " lifetime=$lifetime" |
| ipsec_xappend " margintime=$margintime" |
| ipsec_xappend " keyingtries=$keyingtries" |
| ipsec_xappend " dpdaction=$dpdaction" |
| ipsec_xappend " dpddelay=$dpddelay" |
| |
| [ -n "$inactivity" ] && ipsec_xappend " inactivity=$inactivity" |
| [ -n "$reqid" ] && ipsec_xappend " reqid=$reqid" |
| |
| if [ "$auth_method" = "psk" ]; then |
| ipsec_xappend " leftauth=psk" |
| ipsec_xappend " rightauth=psk" |
| |
| [ "$remote_sourceip" != "" ] && ipsec_xappend " rightsourceip=$remote_sourceip" |
| [ "$remote_subnet" != "" ] && ipsec_xappend " rightsubnet=$remote_subnet" |
| |
| ipsec_xappend " auto=$mode" |
| else |
| warning "AuthenticationMethod $auth_method not supported" |
| fi |
| |
| [ -n "$local_identifier" ] && ipsec_xappend " leftid=$local_identifier" |
| [ -n "$remote_identifier" ] && ipsec_xappend " rightid=$remote_identifier" |
| [ -n "$local_updown" ] && ipsec_xappend " leftupdown=$local_updown" |
| [ -n "$remote_updown" ] && ipsec_xappend " rightupdown=$remote_updown" |
| [ -n "$packet_marker" ] && ipsec_xappend " mark=$packet_marker" |
| ipsec_xappend " keyexchange=$keyexchange" |
| |
| set_crypto_proposal "$1" |
| [ -n "${crypto_proposal}" ] && ipsec_xappend " esp=$crypto_proposal" |
| [ -n "${ike_proposal}" ] && ipsec_xappend " ike=$ike_proposal" |
| } |
| |
| config_tunnel() { |
| config_conn "$1" |
| |
| # Specific for the tunnel part |
| ipsec_xappend " type=tunnel" |
| } |
| |
| config_transport() { |
| config_conn "$1" |
| |
| # Specific for the transport part |
| ipsec_xappend " type=transport" |
| } |
| |
| config_remote() { |
| local enabled |
| local gateway |
| local pre_shared_key |
| local auth_method |
| |
| config_name=$1 |
| |
| config_get_bool enabled "$1" enabled 0 |
| [ $enabled -eq 0 ] && return |
| |
| config_get gateway "$1" gateway |
| config_get pre_shared_key "$1" pre_shared_key |
| config_get auth_method "$1" authentication_method |
| config_get local_identifier "$1" local_identifier "" |
| config_get remote_identifier "$1" remote_identifier "" |
| |
| [ "$gateway" = "any" ] && remote_gateway="%any" || remote_gateway="$gateway" |
| |
| [ -z "$local_identifier" ] && { |
| local ipdest |
| |
| [ "$remote_gateway" = "%any" ] && ipdest="1.1.1.1" || ipdest="$remote_gateway" |
| local_gateway=$(ip -o route get "$ipdest" | awk '/ src / { print gensub(/^.* src ([^ ]*) .*$/, "\\1", "g"); }') |
| } |
| |
| [ -n "$local_identifier" ] && secret_xappend -n "$local_identifier " || secret_xappend -n "$local_gateway " |
| [ -n "$remote_identifier" ] && secret_xappend -n "$remote_identifier " || secret_xappend -n "$remote_gateway " |
| |
| secret_xappend ": PSK \"$pre_shared_key\"" |
| |
| set_crypto_proposal "$1" |
| ike_proposal="$crypto_proposal" |
| |
| config_list_foreach "$1" tunnel config_tunnel |
| |
| config_list_foreach "$1" transport config_transport |
| |
| ipsec_xappend "" |
| } |
| |
| do_preamble() { |
| ipsec_xappend "# generated by /etc/init.d/ipsec" |
| ipsec_xappend "version 2" |
| ipsec_xappend "" |
| |
| secret_xappend "# generated by /etc/init.d/ipsec" |
| } |
| |
| config_ipsec() { |
| local debug |
| local rtinstall_enabled |
| local routing_tables_ignored |
| local routing_table |
| local routing_table_id |
| local interface |
| local device_list |
| |
| ipsec_reset |
| secret_reset |
| swan_reset |
| |
| do_preamble |
| |
| config_get debug "$1" debug 0 |
| config_get_bool rtinstall_enabled "$1" rtinstall_enabled 1 |
| [ $rtinstall_enabled -eq 1 ] && install_routes=yes || install_routes=no |
| |
| # prepare extra charon config option ignore_routing_tables |
| for routing_table in $(config_get "$1" "ignore_routing_tables"); do |
| if [ "$routing_table" -ge 0 ] 2>/dev/null; then |
| routing_table_id=$routing_table |
| else |
| routing_table_id=$(sed -n '/[ \t]*[0-9]\+[ \t]\+'$routing_table'[ \t]*$/s/[ \t]*\([0-9]\+\).*/\1/p' /etc/iproute2/rt_tables) |
| fi |
| |
| [ -n "$routing_table_id" ] && append routing_tables_ignored "$routing_table_id" |
| done |
| |
| local interface_list=$(config_get "$1" "interface") |
| if [ -z "$interface_list" ]; then |
| WAIT_FOR_INTF=0 |
| else |
| for interface in $interface_list; do |
| network_get_device device $interface |
| [ -n "$device" ] && append device_list "$device" "," |
| done |
| [ -n "$device_list" ] && WAIT_FOR_INTF=0 || WAIT_FOR_INTF=1 |
| fi |
| |
| swan_xappend "# generated by /etc/init.d/ipsec" |
| swan_xappend "charon {" |
| swan_xappend " load_modular = yes" |
| swan_xappend " install_routes = $install_routes" |
| [ -n "$routing_tables_ignored" ] && swan_xappend " ignore_routing_tables = $routing_tables_ignored" |
| [ -n "$device_list" ] && swan_xappend " interfaces_use = $device_list" |
| swan_xappend " plugins {" |
| swan_xappend " include /etc/strongswan.d/charon/*.conf" |
| swan_xappend " }" |
| swan_xappend " syslog {" |
| swan_xappend " identifier = ipsec" |
| swan_xappend " daemon {" |
| swan_xappend " default = $debug" |
| swan_xappend " }" |
| swan_xappend " }" |
| swan_xappend "}" |
| } |
| |
| prepare_env() { |
| mkdir -p /var/ipsec |
| config_load ipsec |
| config_foreach config_ipsec ipsec |
| config_foreach config_remote remote |
| } |
| |
| service_running() { |
| ipsec status > /dev/null 2>&1 |
| } |
| |
| reload_service() { |
| running && { |
| prepare_env |
| [ $WAIT_FOR_INTF -eq 0 ] && { |
| ipsec rereadall |
| ipsec reload |
| return |
| } |
| } |
| |
| start |
| } |
| |
| stop_service() { |
| ipsec_reset |
| swan_reset |
| secret_reset |
| } |
| |
| check_ipsec_interface() { |
| local intf |
| |
| for intf in $(config_get "$1" interface); do |
| procd_add_interface_trigger "interface.*" "$intf" /etc/init.d/ipsec reload |
| done |
| } |
| |
| service_triggers() { |
| procd_add_reload_trigger "ipsec" |
| config load "ipsec" |
| config_foreach check_ipsec_interface ipsec |
| } |
| |
| start_service() { |
| prepare_env |
| |
| [ $WAIT_FOR_INTF -eq 1 ] && return |
| |
| procd_open_instance |
| |
| procd_set_param command $PROG --daemon charon --nofork |
| |
| procd_set_param file $IPSEC_CONN_FILE |
| procd_append_param file $IPSEC_SECRETS_FILE |
| procd_append_param file $STRONGSWAN_CONF_FILE |
| procd_append_param file /etc/strongswan.d/*.conf |
| procd_append_param file /etc/strongswan.d/charon/*.conf |
| |
| procd_set_param respawn |
| |
| procd_close_instance |
| } |