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.

685 lines
16 KiB

  1. #!/bin/sh /etc/rc.common
  2. START=90
  3. STOP=10
  4. USE_PROCD=1
  5. PROG=/usr/lib/ipsec/charon
  6. . $IPKG_INSTROOT/lib/functions.sh
  7. . $IPKG_INSTROOT/lib/functions/network.sh
  8. STRONGSWAN_CONF_FILE=/etc/strongswan.conf
  9. STRONGSWAN_VAR_CONF_FILE=/var/ipsec/strongswan.conf
  10. SWANCTL_CONF_FILE=/etc/swanctl/swanctl.conf
  11. SWANCTL_VAR_CONF_FILE=/var/swanctl/swanctl.conf
  12. WAIT_FOR_INTF=0
  13. CONFIG_FAIL=0
  14. time2seconds() {
  15. local timestring="$1"
  16. local multiplier number suffix
  17. suffix="${timestring//[0-9 ]}"
  18. number="${timestring%%$suffix}"
  19. [ "$number$suffix" != "$timestring" ] && return 1
  20. case "$suffix" in
  21. ""|s)
  22. multiplier=1 ;;
  23. m)
  24. multiplier=60 ;;
  25. h)
  26. multiplier=3600 ;;
  27. d)
  28. multiplier=86400 ;;
  29. *)
  30. return 1 ;;
  31. esac
  32. echo $(( number * multiplier ))
  33. }
  34. seconds2time() {
  35. local seconds="$1"
  36. if [ $seconds -eq 0 ]; then
  37. echo "0s"
  38. elif [ $((seconds % 86400)) -eq 0 ]; then
  39. echo "$((seconds / 86400))d"
  40. elif [ $((seconds % 3600)) -eq 0 ]; then
  41. echo "$((seconds / 3600))h"
  42. elif [ $((seconds % 60)) -eq 0 ]; then
  43. echo "$((seconds / 60))m"
  44. else
  45. echo "${seconds}s"
  46. fi
  47. }
  48. file_reset() {
  49. : > "$1"
  50. }
  51. xappend() {
  52. local file="$1"
  53. shift
  54. echo "$@" >> "$file"
  55. }
  56. swan_reset() {
  57. file_reset "$STRONGSWAN_VAR_CONF_FILE"
  58. }
  59. swan_xappend() {
  60. xappend "$STRONGSWAN_VAR_CONF_FILE" "$@"
  61. }
  62. swan_xappend0() {
  63. swan_xappend "$@"
  64. }
  65. swan_xappend1() {
  66. swan_xappend " ""$@"
  67. }
  68. swan_xappend2() {
  69. swan_xappend " ""$@"
  70. }
  71. swan_xappend3() {
  72. swan_xappend " ""$@"
  73. }
  74. swan_xappend4() {
  75. swan_xappend " ""$@"
  76. }
  77. swanctl_reset() {
  78. file_reset "$SWANCTL_VAR_CONF_FILE"
  79. }
  80. swanctl_xappend() {
  81. xappend "$SWANCTL_VAR_CONF_FILE" "$@"
  82. }
  83. swanctl_xappend0() {
  84. swanctl_xappend "$@"
  85. }
  86. swanctl_xappend1() {
  87. swanctl_xappend " ""$@"
  88. }
  89. swanctl_xappend2() {
  90. swanctl_xappend " ""$@"
  91. }
  92. swanctl_xappend3() {
  93. swanctl_xappend " ""$@"
  94. }
  95. swanctl_xappend4() {
  96. swanctl_xappend " ""$@"
  97. }
  98. warning() {
  99. echo "WARNING: $@" >&2
  100. }
  101. fatal() {
  102. echo "ERROR: $@" >&2
  103. CONFIG_FAIL=1
  104. }
  105. append_var() {
  106. local var="$2" value="$1" delim="${3:- }"
  107. append "$var" "$value" "$delim"
  108. }
  109. is_aead() {
  110. local cipher="$1"
  111. case "$cipher" in
  112. aes*gcm*|aes*ccm*|aes*gmac*)
  113. return 0 ;;
  114. chacha20poly1305)
  115. return 0 ;;
  116. esac
  117. return 1
  118. }
  119. add_esp_proposal() {
  120. local encryption_algorithm
  121. local hash_algorithm
  122. local dh_group
  123. config_get encryption_algorithm "$1" encryption_algorithm
  124. config_get hash_algorithm "$1" hash_algorithm
  125. config_get dh_group "$1" dh_group
  126. # check for AEAD and clobber hash_algorithm if set
  127. if is_aead "$encryption_algorithm" && [ -n "$hash_algorithm" ]; then
  128. fatal "Can't have $hash_algorithm with $encryption_algorithm"
  129. hash_algorithm=
  130. fi
  131. [ -n "$encryption_algorithm" ] && \
  132. crypto="${crypto:+${crypto},}${encryption_algorithm}${hash_algorithm:+-${hash_algorithm}}${dh_group:+-${dh_group}}"
  133. }
  134. parse_esp_proposal() {
  135. local conf="$1"
  136. local var="$2"
  137. local crypto=""
  138. config_list_foreach "$conf" crypto_proposal add_esp_proposal
  139. export -n "$var=$crypto"
  140. }
  141. add_ike_proposal() {
  142. local encryption_algorithm
  143. local hash_algorithm
  144. local dh_group
  145. local prf_algorithm
  146. config_get encryption_algorithm "$1" encryption_algorithm
  147. config_get hash_algorithm "$1" hash_algorithm
  148. config_get dh_group "$1" dh_group
  149. config_get prf_algorithm "$1" prf_algorithm
  150. # check for AEAD and clobber hash_algorithm if set
  151. if is_aead "$encryption_algorithm" && [ -n "$hash_algorithm" ]; then
  152. fatal "Can't have $hash_algorithm with $encryption_algorithm"
  153. hash_algorithm=
  154. fi
  155. [ -n "$encryption_algorithm" ] && \
  156. crypto="${crypto:+${crypto},}${encryption_algorithm}${hash_algorithm:+-${hash_algorithm}}${prf_algorithm:+-${prf_algorithm}}${dh_group:+-${dh_group}}"
  157. }
  158. parse_ike_proposal() {
  159. local conf="$1"
  160. local var="$2"
  161. local crypto=""
  162. config_list_foreach "$conf" crypto_proposal add_ike_proposal
  163. export -n "$var=$crypto"
  164. }
  165. config_child() {
  166. # Generic ipsec conn section shared by tunnel and transport
  167. local config_name="$1"
  168. local mode="$2"
  169. local hw_offload
  170. local interface
  171. local ipcomp
  172. local priority
  173. local local_subnet
  174. local local_nat
  175. local updown
  176. local firewall
  177. local remote_subnet
  178. local lifetime
  179. local dpdaction
  180. local closeaction
  181. local startaction
  182. local if_id
  183. local rekeytime
  184. local rekeybytes
  185. local lifebytes
  186. local rekeypackets
  187. local lifepackets
  188. config_get startaction "$1" startaction "route"
  189. config_get local_nat "$1" local_nat ""
  190. config_get updown "$1" updown ""
  191. config_get firewall "$1" firewall ""
  192. config_get lifetime "$1" lifetime ""
  193. config_get dpdaction "$1" dpdaction "none"
  194. config_get closeaction "$1" closeaction "none"
  195. config_get if_id "$1" if_id ""
  196. config_get rekeytime "$1" rekeytime ""
  197. config_get_bool ipcomp "$1" ipcomp 0
  198. config_get interface "$1" interface ""
  199. config_get hw_offload "$1" hw_offload ""
  200. config_get priority "$1" priority ""
  201. config_get rekeybytes "$1" rekeybytes ""
  202. config_get lifebytes "$1" lifebytes ""
  203. config_get rekeypackets "$1" rekeypackets ""
  204. config_get lifepackets "$1" lifepackets ""
  205. config_list_foreach "$1" local_subnet append_var local_subnet ","
  206. config_list_foreach "$1" remote_subnet append_var remote_subnet ","
  207. local esp_proposal
  208. parse_esp_proposal "$1" esp_proposal
  209. # translate from ipsec to swanctl
  210. case "$startaction" in
  211. add)
  212. startaction="none" ;;
  213. route)
  214. startaction="trap" ;;
  215. start|none|trap)
  216. # already using new syntax
  217. ;;
  218. *)
  219. fatal "Startaction $startaction unknown"
  220. startaction=
  221. ;;
  222. esac
  223. case "$closeaction" in
  224. none|clear)
  225. closeaction="none" ;;
  226. hold)
  227. closeaction="trap" ;;
  228. restart)
  229. closeaction="start" ;;
  230. trap|start)
  231. # already using new syntax
  232. ;;
  233. *)
  234. fatal "Closeaction $closeaction unknown"
  235. closeaction=
  236. ;;
  237. esac
  238. [ -n "$closeaction" -a "$closeaction" != "none" ] && warning "Closeaction $closeaction can cause instability"
  239. case "$dpdaction" in
  240. none)
  241. dpddelay="0s"
  242. dpdaction=
  243. ;;
  244. clear)
  245. ;;
  246. hold)
  247. dpdaction="trap" ;;
  248. restart)
  249. dpdaction="start" ;;
  250. trap|start)
  251. # already using new syntax
  252. ;;
  253. *)
  254. fatal "Dpdaction $dpdaction unknown"
  255. dpdaction=
  256. ;;
  257. esac
  258. case "$hw_offload" in
  259. yes|no|auto|"")
  260. ;;
  261. *)
  262. fatal "hw_offload value $hw_offload invalid"
  263. hw_offload=""
  264. ;;
  265. esac
  266. [ -n "$local_nat" ] && local_subnet="$local_nat"
  267. swanctl_xappend3 "$config_name {"
  268. [ -n "$local_subnet" ] && swanctl_xappend4 "local_ts = $local_subnet"
  269. [ -n "$remote_subnet" ] && swanctl_xappend4 "remote_ts = $remote_subnet"
  270. [ -n "$hw_offload" ] && swanctl_append4 "hw_offload = $hw_offload"
  271. [ $ipcomp -eq 1 ] && swanctl_xappend4 "ipcomp = 1"
  272. [ -n "$interface" ] && swanctl_append4 "interface = $interface"
  273. [ -n "$priority" ] && swanctl_append4 "priority = $priority"
  274. [ -n "$if_id" ] && { swanctl_xappend4 "if_id_in = $if_id" ; swanctl_xappend4 "if_id_out = $if_id" ; }
  275. [ -n "$startaction" -a "$startaction" != "none" ] && swanctl_xappend4 "start_action = $startaction"
  276. [ -n "$closeaction" -a "$closeaction" != "none" ] && swanctl_xappend4 "close_action = $closeaction"
  277. swanctl_xappend4 "esp_proposals = $esp_proposal"
  278. swanctl_xappend4 "mode = $mode"
  279. if [ -n "$lifetime" ]; then
  280. swanctl_xappend4 "life_time = $lifetime"
  281. elif [ -n "$rekeytime" ]; then
  282. swanctl_xappend4 "life_time = $(seconds2time $(((110 * $(time2seconds $rekeytime)) / 100)))"
  283. fi
  284. [ -n "$rekeytime" ] && swanctl_xappend4 "rekey_time = $rekeytime"
  285. if [ -n "$lifebytes" ]; then
  286. swanctl_xappend4 "life_bytes = $lifebytes"
  287. elif [ -n "$rekeybytes" ]; then
  288. swanctl_xappend4 "life_bytes = $(((110 * rekeybytes) / 100))"
  289. fi
  290. [ -n "$rekeybytes" ] && swanctl_xappend4 "rekey_bytes = $rekeybytes"
  291. if [ -n "$lifepackets" ]; then
  292. swanctl_xappend4 "life_packets = $lifepackets"
  293. elif [ -n "$rekeypackets" ]; then
  294. swanctl_xappend4 "life_packets = $(((110 * rekeypackets) / 100))"
  295. fi
  296. [ -n "$rekeypackets" ] && swanctl_xappend4 "rekey_packets = $rekeypackets"
  297. [ -n "$inactivity" ] && swanctl_xappend4 "inactivity = $inactivity"
  298. [ -n "$updown" ] && swanctl_xappend4 "updown = $updown"
  299. [ -n "$dpdaction" ] && swanctl_xappend4 "dpd_action = $dpdaction"
  300. swanctl_xappend3 "}"
  301. }
  302. config_tunnel() {
  303. config_child "$1" "tunnel"
  304. }
  305. config_transport() {
  306. config_child "$1" "transport"
  307. }
  308. config_connection() {
  309. local config_name="$1"
  310. local enabled
  311. local gateway
  312. local local_gateway
  313. local local_sourceip
  314. local local_ip
  315. local remote_gateway
  316. local pre_shared_key
  317. local auth_method
  318. local keyingtries
  319. local dpddelay
  320. local inactivity
  321. local keyexchange
  322. local fragmentation
  323. local mobike
  324. local local_cert
  325. local local_key
  326. local ca_cert
  327. local rekeytime
  328. config_get_bool enabled "$1" enabled 0
  329. [ $enabled -eq 0 ] && return
  330. config_get gateway "$1" gateway
  331. config_get pre_shared_key "$1" pre_shared_key
  332. config_get auth_method "$1" authentication_method
  333. config_get local_identifier "$1" local_identifier ""
  334. config_get remote_identifier "$1" remote_identifier ""
  335. config_get local_ip "$1" local_ip "%any"
  336. config_get keyingtries "$1" keyingtries "3"
  337. config_get dpddelay "$1" dpddelay "30s"
  338. config_get inactivity "$1" inactivity
  339. config_get keyexchange "$1" keyexchange "ikev2"
  340. config_get fragmentation "$1" fragmentation "yes"
  341. config_get_bool mobike "$1" mobike 1
  342. config_get local_cert "$1" local_cert ""
  343. config_get local_key "$1" local_key ""
  344. config_get ca_cert "$1" ca_cert ""
  345. config_get rekeytime "$1" rekeytime
  346. config_get overtime "$1" overtime
  347. config_list_foreach "$1" local_sourceip append_var local_sourceip ","
  348. case "$fragmentation" in
  349. 0)
  350. fragmentation="no" ;;
  351. 1)
  352. fragmentation="yes" ;;
  353. yes|accept|force|no)
  354. # already using new syntax
  355. ;;
  356. *)
  357. fatal "Fragmentation $fragmentation not supported"
  358. fragmentation=
  359. ;;
  360. esac
  361. [ "$gateway" = "any" ] && remote_gateway="%any" || remote_gateway="$gateway"
  362. local ipdest
  363. [ "$remote_gateway" = "%any" ] && ipdest="1.1.1.1" || ipdest="$remote_gateway"
  364. local_gateway=`ip -o route get $ipdest | awk '/ src / { gsub(/^.* src /,""); gsub(/ .*$/, ""); print $0}'`
  365. if [ -n "$local_key" ]; then
  366. [ "$(dirname "$local_key")" != "." ] && \
  367. fatal "local_key $local_key can't be pathname"
  368. [ -f "/etc/swanctl/private/$local_key" ] || \
  369. fatal "local_key $local_key not found"
  370. fi
  371. local ike_proposal
  372. parse_ike_proposal "$1" ike_proposal
  373. [ -n "$firewall" ] && fatal "Firewall not supported"
  374. if [ "$auth_method" = pubkey ]; then
  375. if [ -n "$ca_cert" ]; then
  376. [ "$(dirname "$ca_cert")" != "." ] && \
  377. fatal "ca_cert $ca_cert can't be pathname"
  378. [ -f "/etc/swanctl/x509ca/$ca_cert" ] || \
  379. fatal "ca_cert $ca_cert not found"
  380. fi
  381. if [ -n "$local_cert" ]; then
  382. [ "$(dirname "$local_cert")" != "." ] && \
  383. fatal "local_cert $local_cert can't be pathname"
  384. [ -f "/etc/swanctl/x509/$local_cert" ] || \
  385. fatal "local_cert $local_cert not found"
  386. fi
  387. fi
  388. swanctl_xappend0 "# config for $config_name"
  389. swanctl_xappend0 "connections {"
  390. swanctl_xappend1 "$config_name {"
  391. swanctl_xappend2 "local_addrs = $local_ip"
  392. swanctl_xappend2 "remote_addrs = $remote_gateway"
  393. [ -n "$local_sourceip" ] && swanctl_xappend2 "vips = $local_sourceip"
  394. [ -n "$fragmentation" ] && swanctl_xappend2 "fragmentation = $fragmentation"
  395. swanctl_xappend2 "local {"
  396. swanctl_xappend3 "auth = $auth_method"
  397. [ -n "$local_identifier" ] && swanctl_xappend3 "id = \"$local_identifier\""
  398. [ "$auth_method" = pubkey ] && [ -n "$local_cert" ] && \
  399. swanctl_xappend3 "certs = $local_cert"
  400. swanctl_xappend2 "}"
  401. swanctl_xappend2 "remote {"
  402. swanctl_xappend3 "auth = $auth_method"
  403. [ -n "$remote_identifier" ] && swanctl_xappend3 "id = \"$remote_identifier\""
  404. swanctl_xappend2 "}"
  405. swanctl_xappend2 "children {"
  406. config_list_foreach "$1" tunnel config_tunnel
  407. config_list_foreach "$1" transport config_transport
  408. swanctl_xappend2 "}"
  409. case "$keyexchange" in
  410. ike)
  411. ;;
  412. ikev1)
  413. swanctl_xappend2 "version = 1" ;;
  414. ikev2)
  415. swanctl_xappend2 "version = 2" ;;
  416. *)
  417. fatal "Keyexchange $keyexchange not supported"
  418. keyexchange=
  419. ;;
  420. esac
  421. [ $mobike -eq 1 ] && swanctl_xappend2 "mobike = yes" || swanctl_xappend2 "mobike = no"
  422. if [ -n "$rekeytime" ]; then
  423. swanctl_xappend2 "rekey_time = $rekeytime"
  424. if [ -z "$overtime" ]; then
  425. overtime=$(seconds2time $(($(time2seconds $rekeytime) / 10)))
  426. fi
  427. fi
  428. [ -n "$overtime" ] && swanctl_xappend2 "over_time = $overtime"
  429. swanctl_xappend2 "proposals = $ike_proposal"
  430. [ -n "$dpddelay" ] && swanctl_xappend2 "dpd_delay = $dpddelay"
  431. [ "$keyingtries" = "%forever" ] && swanctl_xappend2 "keyingtries = 0" || swanctl_xappend2 "keyingtries = $keyingtries"
  432. swanctl_xappend1 "}"
  433. swanctl_xappend0 "}"
  434. if [ "$auth_method" = pubkey ]; then
  435. swanctl_xappend0 ""
  436. if [ -n "$ca_cert" ]; then
  437. swanctl_xappend0 "authorities {"
  438. swanctl_xappend1 "$config_name {"
  439. swanctl_xappend2 "cacert = $ca_cert"
  440. swanctl_xappend1 "}"
  441. swanctl_xappend0 "}"
  442. fi
  443. elif [ "$auth_method" = psk ]; then
  444. swanctl_xappend0 ""
  445. swanctl_xappend0 "secrets {"
  446. swanctl_xappend1 "ike {"
  447. swanctl_xappend2 "secret = $pre_shared_key"
  448. if [ -n "$local_id" ]; then
  449. swanctl_xappend2 "id1 = $local_id"
  450. if [ -n "$remote_id" ]; then
  451. swanctl_xappend2 "id2 = $remote_id"
  452. fi
  453. fi
  454. swanctl_xappend1 "}"
  455. swanctl_xappend0 "}"
  456. else
  457. fatal "AuthenticationMode $auth_mode not supported"
  458. fi
  459. swanctl_xappend0 ""
  460. }
  461. do_preamble() {
  462. swanctl_xappend0 "# generated by /etc/init.d/swanctl"
  463. }
  464. config_ipsec() {
  465. local rtinstall_enabled
  466. local routing_table
  467. local routing_table_id
  468. local interface
  469. local interface_list
  470. config_get debug "$1" debug 0
  471. config_get_bool rtinstall_enabled "$1" rtinstall_enabled 1
  472. [ $rtinstall_enabled -eq 1 ] && install_routes=yes || install_routes=no
  473. # prepare extra charon config option ignore_routing_tables
  474. for routing_table in $(config_get "$1" "ignore_routing_tables"); do
  475. if [ "$routing_table" -ge 0 ] 2>/dev/null; then
  476. routing_table_id=$routing_table
  477. else
  478. routing_table_id=$(sed -n '/[ \t]*[0-9]\+[ \t]\+'$routing_table'[ \t]*$/s/[ \t]*\([0-9]\+\).*/\1/p' /etc/iproute2/rt_tables)
  479. fi
  480. [ -n "$routing_table_id" ] && append routing_tables_ignored "$routing_table_id"
  481. done
  482. config_list_foreach "$1" interface append_var interface_list
  483. if [ -z "$interface_list" ]; then
  484. WAIT_FOR_INTF=0
  485. else
  486. for interface in $interface_list; do
  487. network_get_device device $interface
  488. [ -n "$device" ] && append device_list "$device" ","
  489. done
  490. [ -n "$device_list" ] && WAIT_FOR_INTF=0 || WAIT_FOR_INTF=1
  491. fi
  492. }
  493. do_postamble() {
  494. swan_xappend0 "# generated by /etc/init.d/swanctl"
  495. swan_xappend0 "charon {"
  496. swan_xappend1 "install_routes = $install_routes"
  497. [ -n "$routing_tables_ignored" ] && swan_xappend1 "ignore_routing_tables = $routing_tables_ignored"
  498. [ -n "$device_list" ] && swan_xappend1 "interfaces_use = $device_list"
  499. swan_xappend1 "start-scripts {"
  500. swan_xappend2 "load-all = /usr/sbin/swanctl --load-all --noprompt"
  501. swan_xappend1 "}"
  502. swan_xappend1 "syslog {"
  503. swan_xappend2 "identifier = ipsec"
  504. swan_xappend2 "daemon {"
  505. swan_xappend3 "default = $debug"
  506. swan_xappend2 "}"
  507. swan_xappend1 "}"
  508. swan_xappend0 "}"
  509. }
  510. prepare_env() {
  511. mkdir -p /var/ipsec /var/swanctl
  512. swan_reset
  513. swanctl_reset
  514. do_preamble
  515. # needed by do_postamble
  516. local debug install_routes routing_tables_ignored device_list
  517. config_load ipsec
  518. config_foreach config_ipsec ipsec
  519. config_foreach config_connection remote
  520. do_postamble
  521. }
  522. service_running() {
  523. swanctl --stats > /dev/null 2>&1
  524. }
  525. reload_service() {
  526. running && {
  527. prepare_env
  528. [ $WAIT_FOR_INTF -eq 0 ] && {
  529. swanctl --load-all --noprompt
  530. return
  531. }
  532. }
  533. start
  534. }
  535. stop_service() {
  536. swan_reset
  537. swanctl_reset
  538. }
  539. service_triggers() {
  540. procd_add_reload_trigger "ipsec"
  541. config load "ipsec"
  542. }
  543. start_service() {
  544. prepare_env
  545. [ $WAIT_FOR_INTF -eq 1 ] && return
  546. if [ $CONFIG_FAIL -ne 0 ]; then
  547. procd_set_param error "Invalid configuration"
  548. return
  549. fi
  550. procd_open_instance
  551. procd_set_param command $PROG
  552. procd_set_param file $SWANCTL_CONF_FILE
  553. procd_append_param file /etc/swanctl/conf.d/*.conf
  554. procd_append_param file $STRONGSWAN_CONF_FILE
  555. procd_set_param respawn
  556. procd_close_instance
  557. }