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.

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