b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | #!/bin/sh /etc/rc.common |
| 2 | |
| 3 | START=90 |
| 4 | STOP=10 |
| 5 | |
| 6 | USE_PROCD=1 |
| 7 | PROG=/usr/lib/ipsec/starter |
| 8 | |
| 9 | . $IPKG_INSTROOT/lib/functions.sh |
| 10 | . $IPKG_INSTROOT/lib/functions/network.sh |
| 11 | |
| 12 | IPSEC_SECRETS_FILE=/etc/ipsec.secrets |
| 13 | IPSEC_CONN_FILE=/etc/ipsec.conf |
| 14 | STRONGSWAN_CONF_FILE=/etc/strongswan.conf |
| 15 | |
| 16 | IPSEC_VAR_SECRETS_FILE=/var/ipsec/ipsec.secrets |
| 17 | IPSEC_VAR_CONN_FILE=/var/ipsec/ipsec.conf |
| 18 | STRONGSWAN_VAR_CONF_FILE=/var/ipsec/strongswan.conf |
| 19 | |
| 20 | WAIT_FOR_INTF=0 |
| 21 | |
| 22 | file_reset() { |
| 23 | : > "$1" |
| 24 | } |
| 25 | |
| 26 | xappend() { |
| 27 | local file="$1" |
| 28 | shift |
| 29 | |
| 30 | echo "$@" >> "$file" |
| 31 | } |
| 32 | |
| 33 | ipsec_reset() { |
| 34 | file_reset "$IPSEC_VAR_CONN_FILE" |
| 35 | } |
| 36 | |
| 37 | ipsec_xappend() { |
| 38 | xappend "$IPSEC_VAR_CONN_FILE" "$@" |
| 39 | } |
| 40 | |
| 41 | swan_reset() { |
| 42 | file_reset "$STRONGSWAN_VAR_CONF_FILE" |
| 43 | } |
| 44 | |
| 45 | swan_xappend() { |
| 46 | xappend "$STRONGSWAN_VAR_CONF_FILE" "$@" |
| 47 | } |
| 48 | |
| 49 | secret_reset() { |
| 50 | file_reset "$IPSEC_VAR_SECRETS_FILE" |
| 51 | } |
| 52 | |
| 53 | secret_xappend() { |
| 54 | xappend "$IPSEC_VAR_SECRETS_FILE" "$@" |
| 55 | } |
| 56 | |
| 57 | warning() { |
| 58 | echo "WARNING: $@" >&2 |
| 59 | } |
| 60 | |
| 61 | add_crypto_proposal() { |
| 62 | local encryption_algorithm |
| 63 | local hash_algorithm |
| 64 | local dh_group |
| 65 | |
| 66 | config_get encryption_algorithm "$1" encryption_algorithm |
| 67 | config_get hash_algorithm "$1" hash_algorithm |
| 68 | config_get dh_group "$1" dh_group |
| 69 | |
| 70 | [ -n "${encryption_algorithm}" ] && \ |
| 71 | crypto="${crypto:+${crypto},}${encryption_algorithm}${hash_algorithm:+-${hash_algorithm}}${dh_group:+-${dh_group}}" |
| 72 | } |
| 73 | |
| 74 | set_crypto_proposal() { |
| 75 | local conf="$1" |
| 76 | local proposal |
| 77 | |
| 78 | crypto="" |
| 79 | |
| 80 | config_get crypto_proposal "$conf" crypto_proposal "" |
| 81 | for proposal in $crypto_proposal; do |
| 82 | add_crypto_proposal "$proposal" |
| 83 | done |
| 84 | |
| 85 | [ -n "${crypto}" ] && { |
| 86 | local force_crypto_proposal |
| 87 | |
| 88 | config_get_bool force_crypto_proposal "$conf" force_crypto_proposal |
| 89 | |
| 90 | [ "${force_crypto_proposal}" = "1" ] && crypto="${crypto}!" |
| 91 | } |
| 92 | |
| 93 | crypto_proposal="${crypto}" |
| 94 | } |
| 95 | |
| 96 | config_conn() { |
| 97 | # Generic ipsec conn section shared by tunnel and transport |
| 98 | local mode |
| 99 | local local_subnet |
| 100 | local local_nat |
| 101 | local local_sourceip |
| 102 | local local_leftip |
| 103 | local local_updown |
| 104 | local local_firewall |
| 105 | local remote_subnet |
| 106 | local remote_sourceip |
| 107 | local remote_updown |
| 108 | local remote_firewall |
| 109 | local ikelifetime |
| 110 | local lifetime |
| 111 | local margintime |
| 112 | local keyingtries |
| 113 | local dpdaction |
| 114 | local dpddelay |
| 115 | local inactivity |
| 116 | local keyexchange |
| 117 | local reqid |
| 118 | local packet_marker |
| 119 | |
| 120 | config_get mode "$1" mode "route" |
| 121 | config_get local_subnet "$1" local_subnet "" |
| 122 | config_get local_nat "$1" local_nat "" |
| 123 | config_get local_sourceip "$1" local_sourceip "" |
| 124 | config_get local_leftip "$1" local_leftip "%any" |
| 125 | config_get local_updown "$1" local_updown "" |
| 126 | config_get local_firewall "$1" local_firewall "" |
| 127 | config_get remote_subnet "$1" remote_subnet "" |
| 128 | config_get remote_sourceip "$1" remote_sourceip "" |
| 129 | config_get remote_updown "$1" remote_updown "" |
| 130 | config_get remote_firewall "$1" remote_firewall "" |
| 131 | config_get ikelifetime "$1" ikelifetime "3h" |
| 132 | config_get lifetime "$1" lifetime "1h" |
| 133 | config_get margintime "$1" margintime "9m" |
| 134 | config_get keyingtries "$1" keyingtries "3" |
| 135 | config_get dpdaction "$1" dpdaction "none" |
| 136 | config_get dpddelay "$1" dpddelay "30s" |
| 137 | config_get inactivity "$1" inactivity |
| 138 | config_get keyexchange "$1" keyexchange "ikev2" |
| 139 | config_get reqid "$1" reqid |
| 140 | config_get packet_marker "$1" packet_marker |
| 141 | |
| 142 | [ -n "$local_nat" ] && local_subnet=$local_nat |
| 143 | |
| 144 | ipsec_xappend "conn $config_name-$1" |
| 145 | ipsec_xappend " left=$local_leftip" |
| 146 | ipsec_xappend " right=$remote_gateway" |
| 147 | |
| 148 | [ -n "$local_sourceip" ] && ipsec_xappend " leftsourceip=$local_sourceip" |
| 149 | [ -n "$local_subnet" ] && ipsec_xappend " leftsubnet=$local_subnet" |
| 150 | |
| 151 | [ -n "$local_firewall" ] && ipsec_xappend " leftfirewall=$local_firewall" |
| 152 | [ -n "$remote_firewall" ] && ipsec_xappend " rightfirewall=$remote_firewall" |
| 153 | |
| 154 | ipsec_xappend " ikelifetime=$ikelifetime" |
| 155 | ipsec_xappend " lifetime=$lifetime" |
| 156 | ipsec_xappend " margintime=$margintime" |
| 157 | ipsec_xappend " keyingtries=$keyingtries" |
| 158 | ipsec_xappend " dpdaction=$dpdaction" |
| 159 | ipsec_xappend " dpddelay=$dpddelay" |
| 160 | |
| 161 | [ -n "$inactivity" ] && ipsec_xappend " inactivity=$inactivity" |
| 162 | [ -n "$reqid" ] && ipsec_xappend " reqid=$reqid" |
| 163 | |
| 164 | if [ "$auth_method" = "psk" ]; then |
| 165 | ipsec_xappend " leftauth=psk" |
| 166 | ipsec_xappend " rightauth=psk" |
| 167 | |
| 168 | [ "$remote_sourceip" != "" ] && ipsec_xappend " rightsourceip=$remote_sourceip" |
| 169 | [ "$remote_subnet" != "" ] && ipsec_xappend " rightsubnet=$remote_subnet" |
| 170 | |
| 171 | ipsec_xappend " auto=$mode" |
| 172 | else |
| 173 | warning "AuthenticationMethod $auth_method not supported" |
| 174 | fi |
| 175 | |
| 176 | [ -n "$local_identifier" ] && ipsec_xappend " leftid=$local_identifier" |
| 177 | [ -n "$remote_identifier" ] && ipsec_xappend " rightid=$remote_identifier" |
| 178 | [ -n "$local_updown" ] && ipsec_xappend " leftupdown=$local_updown" |
| 179 | [ -n "$remote_updown" ] && ipsec_xappend " rightupdown=$remote_updown" |
| 180 | [ -n "$packet_marker" ] && ipsec_xappend " mark=$packet_marker" |
| 181 | ipsec_xappend " keyexchange=$keyexchange" |
| 182 | |
| 183 | set_crypto_proposal "$1" |
| 184 | [ -n "${crypto_proposal}" ] && ipsec_xappend " esp=$crypto_proposal" |
| 185 | [ -n "${ike_proposal}" ] && ipsec_xappend " ike=$ike_proposal" |
| 186 | } |
| 187 | |
| 188 | config_tunnel() { |
| 189 | config_conn "$1" |
| 190 | |
| 191 | # Specific for the tunnel part |
| 192 | ipsec_xappend " type=tunnel" |
| 193 | } |
| 194 | |
| 195 | config_transport() { |
| 196 | config_conn "$1" |
| 197 | |
| 198 | # Specific for the transport part |
| 199 | ipsec_xappend " type=transport" |
| 200 | } |
| 201 | |
| 202 | config_remote() { |
| 203 | local enabled |
| 204 | local gateway |
| 205 | local pre_shared_key |
| 206 | local auth_method |
| 207 | |
| 208 | config_name=$1 |
| 209 | |
| 210 | config_get_bool enabled "$1" enabled 0 |
| 211 | [ $enabled -eq 0 ] && return |
| 212 | |
| 213 | config_get gateway "$1" gateway |
| 214 | config_get pre_shared_key "$1" pre_shared_key |
| 215 | config_get auth_method "$1" authentication_method |
| 216 | config_get local_identifier "$1" local_identifier "" |
| 217 | config_get remote_identifier "$1" remote_identifier "" |
| 218 | |
| 219 | [ "$gateway" = "any" ] && remote_gateway="%any" || remote_gateway="$gateway" |
| 220 | |
| 221 | [ -z "$local_identifier" ] && { |
| 222 | local ipdest |
| 223 | |
| 224 | [ "$remote_gateway" = "%any" ] && ipdest="1.1.1.1" || ipdest="$remote_gateway" |
| 225 | local_gateway=$(ip -o route get "$ipdest" | awk '/ src / { print gensub(/^.* src ([^ ]*) .*$/, "\\1", "g"); }') |
| 226 | } |
| 227 | |
| 228 | [ -n "$local_identifier" ] && secret_xappend -n "$local_identifier " || secret_xappend -n "$local_gateway " |
| 229 | [ -n "$remote_identifier" ] && secret_xappend -n "$remote_identifier " || secret_xappend -n "$remote_gateway " |
| 230 | |
| 231 | secret_xappend ": PSK \"$pre_shared_key\"" |
| 232 | |
| 233 | set_crypto_proposal "$1" |
| 234 | ike_proposal="$crypto_proposal" |
| 235 | |
| 236 | config_list_foreach "$1" tunnel config_tunnel |
| 237 | |
| 238 | config_list_foreach "$1" transport config_transport |
| 239 | |
| 240 | ipsec_xappend "" |
| 241 | } |
| 242 | |
| 243 | do_preamble() { |
| 244 | ipsec_xappend "# generated by /etc/init.d/ipsec" |
| 245 | ipsec_xappend "version 2" |
| 246 | ipsec_xappend "" |
| 247 | |
| 248 | secret_xappend "# generated by /etc/init.d/ipsec" |
| 249 | } |
| 250 | |
| 251 | config_ipsec() { |
| 252 | local debug |
| 253 | local rtinstall_enabled |
| 254 | local routing_tables_ignored |
| 255 | local routing_table |
| 256 | local routing_table_id |
| 257 | local interface |
| 258 | local device_list |
| 259 | |
| 260 | ipsec_reset |
| 261 | secret_reset |
| 262 | swan_reset |
| 263 | |
| 264 | do_preamble |
| 265 | |
| 266 | config_get debug "$1" debug 0 |
| 267 | config_get_bool rtinstall_enabled "$1" rtinstall_enabled 1 |
| 268 | [ $rtinstall_enabled -eq 1 ] && install_routes=yes || install_routes=no |
| 269 | |
| 270 | # prepare extra charon config option ignore_routing_tables |
| 271 | for routing_table in $(config_get "$1" "ignore_routing_tables"); do |
| 272 | if [ "$routing_table" -ge 0 ] 2>/dev/null; then |
| 273 | routing_table_id=$routing_table |
| 274 | else |
| 275 | routing_table_id=$(sed -n '/[ \t]*[0-9]\+[ \t]\+'$routing_table'[ \t]*$/s/[ \t]*\([0-9]\+\).*/\1/p' /etc/iproute2/rt_tables) |
| 276 | fi |
| 277 | |
| 278 | [ -n "$routing_table_id" ] && append routing_tables_ignored "$routing_table_id" |
| 279 | done |
| 280 | |
| 281 | local interface_list=$(config_get "$1" "interface") |
| 282 | if [ -z "$interface_list" ]; then |
| 283 | WAIT_FOR_INTF=0 |
| 284 | else |
| 285 | for interface in $interface_list; do |
| 286 | network_get_device device $interface |
| 287 | [ -n "$device" ] && append device_list "$device" "," |
| 288 | done |
| 289 | [ -n "$device_list" ] && WAIT_FOR_INTF=0 || WAIT_FOR_INTF=1 |
| 290 | fi |
| 291 | |
| 292 | swan_xappend "# generated by /etc/init.d/ipsec" |
| 293 | swan_xappend "charon {" |
| 294 | swan_xappend " load_modular = yes" |
| 295 | swan_xappend " install_routes = $install_routes" |
| 296 | [ -n "$routing_tables_ignored" ] && swan_xappend " ignore_routing_tables = $routing_tables_ignored" |
| 297 | [ -n "$device_list" ] && swan_xappend " interfaces_use = $device_list" |
| 298 | swan_xappend " plugins {" |
| 299 | swan_xappend " include /etc/strongswan.d/charon/*.conf" |
| 300 | swan_xappend " }" |
| 301 | swan_xappend " syslog {" |
| 302 | swan_xappend " identifier = ipsec" |
| 303 | swan_xappend " daemon {" |
| 304 | swan_xappend " default = $debug" |
| 305 | swan_xappend " }" |
| 306 | swan_xappend " }" |
| 307 | swan_xappend "}" |
| 308 | } |
| 309 | |
| 310 | prepare_env() { |
| 311 | mkdir -p /var/ipsec |
| 312 | config_load ipsec |
| 313 | config_foreach config_ipsec ipsec |
| 314 | config_foreach config_remote remote |
| 315 | } |
| 316 | |
| 317 | service_running() { |
| 318 | ipsec status > /dev/null 2>&1 |
| 319 | } |
| 320 | |
| 321 | reload_service() { |
| 322 | running && { |
| 323 | prepare_env |
| 324 | [ $WAIT_FOR_INTF -eq 0 ] && { |
| 325 | ipsec rereadall |
| 326 | ipsec reload |
| 327 | return |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | start |
| 332 | } |
| 333 | |
| 334 | stop_service() { |
| 335 | ipsec_reset |
| 336 | swan_reset |
| 337 | secret_reset |
| 338 | } |
| 339 | |
| 340 | check_ipsec_interface() { |
| 341 | local intf |
| 342 | |
| 343 | for intf in $(config_get "$1" interface); do |
| 344 | procd_add_interface_trigger "interface.*" "$intf" /etc/init.d/ipsec reload |
| 345 | done |
| 346 | } |
| 347 | |
| 348 | service_triggers() { |
| 349 | procd_add_reload_trigger "ipsec" |
| 350 | config load "ipsec" |
| 351 | config_foreach check_ipsec_interface ipsec |
| 352 | } |
| 353 | |
| 354 | start_service() { |
| 355 | prepare_env |
| 356 | |
| 357 | [ $WAIT_FOR_INTF -eq 1 ] && return |
| 358 | |
| 359 | procd_open_instance |
| 360 | |
| 361 | procd_set_param command $PROG --daemon charon --nofork |
| 362 | |
| 363 | procd_set_param file $IPSEC_CONN_FILE |
| 364 | procd_append_param file $IPSEC_SECRETS_FILE |
| 365 | procd_append_param file $STRONGSWAN_CONF_FILE |
| 366 | procd_append_param file /etc/strongswan.d/*.conf |
| 367 | procd_append_param file /etc/strongswan.d/charon/*.conf |
| 368 | |
| 369 | procd_set_param respawn |
| 370 | |
| 371 | procd_close_instance |
| 372 | } |