blob: bbfa573d69a41c2613f2a8f32f7210595e04fea4 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001#!/bin/sh /etc/rc.common
2
3START=90
4STOP=10
5
6USE_PROCD=1
7PROG=/usr/lib/ipsec/starter
8
9. $IPKG_INSTROOT/lib/functions.sh
10. $IPKG_INSTROOT/lib/functions/network.sh
11
12IPSEC_SECRETS_FILE=/etc/ipsec.secrets
13IPSEC_CONN_FILE=/etc/ipsec.conf
14STRONGSWAN_CONF_FILE=/etc/strongswan.conf
15
16IPSEC_VAR_SECRETS_FILE=/var/ipsec/ipsec.secrets
17IPSEC_VAR_CONN_FILE=/var/ipsec/ipsec.conf
18STRONGSWAN_VAR_CONF_FILE=/var/ipsec/strongswan.conf
19
20WAIT_FOR_INTF=0
21
22file_reset() {
23 : > "$1"
24}
25
26xappend() {
27 local file="$1"
28 shift
29
30 echo "$@" >> "$file"
31}
32
33ipsec_reset() {
34 file_reset "$IPSEC_VAR_CONN_FILE"
35}
36
37ipsec_xappend() {
38 xappend "$IPSEC_VAR_CONN_FILE" "$@"
39}
40
41swan_reset() {
42 file_reset "$STRONGSWAN_VAR_CONF_FILE"
43}
44
45swan_xappend() {
46 xappend "$STRONGSWAN_VAR_CONF_FILE" "$@"
47}
48
49secret_reset() {
50 file_reset "$IPSEC_VAR_SECRETS_FILE"
51}
52
53secret_xappend() {
54 xappend "$IPSEC_VAR_SECRETS_FILE" "$@"
55}
56
57warning() {
58 echo "WARNING: $@" >&2
59}
60
61add_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
74set_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
96config_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
188config_tunnel() {
189 config_conn "$1"
190
191 # Specific for the tunnel part
192 ipsec_xappend " type=tunnel"
193}
194
195config_transport() {
196 config_conn "$1"
197
198 # Specific for the transport part
199 ipsec_xappend " type=transport"
200}
201
202config_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
243do_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
251config_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
310prepare_env() {
311 mkdir -p /var/ipsec
312 config_load ipsec
313 config_foreach config_ipsec ipsec
314 config_foreach config_remote remote
315}
316
317service_running() {
318 ipsec status > /dev/null 2>&1
319}
320
321reload_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
334stop_service() {
335 ipsec_reset
336 swan_reset
337 secret_reset
338}
339
340check_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
348service_triggers() {
349 procd_add_reload_trigger "ipsec"
350 config load "ipsec"
351 config_foreach check_ipsec_interface ipsec
352}
353
354start_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}