summaryrefslogtreecommitdiffstats
path: root/net/ipsec-tools/files/racoon.init
blob: 6520d5bdeb9e3772d36a567d00849218a2b18044 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
#!/bin/sh /etc/rc.common
#
# Copyright (C) 2015 Vitaly Protsko <villy@sft.ru>

#set -vx

USE_PROCD=1

START=60
STOP=40

let connWait=2/2
confDir=/var/racoon
confExtZone=
confIntZone=
confPort=
confNATPort=
confIPMode=

confPh1ID=0

log="logger -t init.d/racoon[$$] "

. /etc/racoon/functions.sh

setup_load() {
  config_get confExtZone "$1" ext_zone wan
  config_get confIntZone "$1" int_zone lan
  config_get confPort    "$1" port 500
  config_get confNATPort "$1" natt_port 4500
  config_get confIPMode  "$1" ipversion ""

  case X$confIPMode in
    X4|X6) ;;
    *) unset confIPMode ;;
  esac
}

write_header() {
  echo "
# autogenerated, don't edit, look at /etc/config/racoon
#
path certificate \"$confDir/cert\";
path script \"/etc/racoon\";
path pre_shared_key \"$confDir/psk.txt\";
path pidfile \"$confDir/racoon.pid\";
padding { maximum_length 20; randomize off; strict_check off; exclusive_tail off; }
timer { counter 5; interval 20 sec; persend 1; phase1 30 sec; phase2 15 sec; }
"
}

setup_conf() {
  local conf=$confDir/racoon.conf
  local peerconf=$confDir/peers.txt
  local pskconf=$confDir/psk.txt
  local item
  local data

  data="$(get_zoneiplist $confExtZone)"
  if [ "X$data" = X ]; then
    $log "No IP addresses found for zone $confExtZone, exitng"
    errno=2; return 2
  fi

  write_header > $conf
  echo -n > $peerconf
  echo -n > $pskconf
  chmod 0600 $conf $peerconf $pskconf

  echo "listen {" >> $conf
  for item in $data ; do
    echo "  isakmp $item [$confPort]; isakmp_natt $item [$confNATPort];" >> $conf
  done
  echo "}" >> $conf

  config_get_bool item "$1" debug 0
  data=warning
  test $item -ne 0 && data=debug
  echo "log $data;" >> $conf

  setup_fw add
}

setup_p1() {
  local conf=$confDir/racoon.conf
  local data

  echo "  proposal {" >> $conf
  config_get data "$1" lifetime 28800
  echo "    lifetime time $data sec;" >> $conf

  config_get data "$1" enc_alg
  test -n "$data" && echo "    encryption_algorithm $data;" >> $conf

  config_get data "$1" hash_alg
  test -n "$data" && echo "    hash_algorithm $data;" >> $conf

  config_get data "$1" auth_method
  test -n "$data" && echo "    authentication_method $data;" >> $conf

  config_get data "$1" dh_group 2
  echo -e "    dh_group $data;\n  }" >> $conf
}

setup_fw() {
  local cmd=/usr/sbin/iptables
  local mode

  case "$1" in
    add|up|1) mode=A ;;
    del|down|0) mode=D ;;
    *) return 3 ;;
  esac

  $cmd -$mode input_${confExtZone}_rule -p AH -j ACCEPT
  $cmd -$mode input_${confExtZone}_rule -p ESP -j ACCEPT
  $cmd -$mode input_${confExtZone}_rule -p UDP --dport $confPort -j ACCEPT
  $cmd -$mode input_${confExtZone}_rule -p UDP --dport $confNATPort -j ACCEPT
}

setup_sa() {
  local conf=$confDir/racoon.conf
  local remote="${2/ *}"
  local client="${2#* }"
  local locnet
  local remnet
  local p2
  local data

  test "$2" = "$client" && unset client

  if [ -z "$client" ]; then
    config_get locnet "$1" local_net
    config_get remnet "$1" remote_net
    if [ -z "$locnet" ] || [ -z "$remnet" ]; then
      $log "Remote and local networks for $1 must be configured ($2)"
      errno=4; return 4
    fi

    if [ "$remote" = "anonymous" ]; then
      echo "sainfo anonymous {" >> $conf
     else
      echo "sainfo address $locnet any address $remnet any {" >> $conf
    fi
  else
    echo "sainfo anonymous {" >> $conf
  fi

  config_get p2 "$1" p2_proposal
  if [ -z "$p2" ]; then
    $log "Phase2 proposal must be configured in $1 sainfo"
    errno=5; return 5
  fi

  echo "  remoteid $confPh1ID;" >> $conf

  config_get data "$p2" pfs_group
  test -n "$data" && echo "  pfs_group $data;" >> $conf
  config_get data "$p2" lifetime 14400
  test -n "$data" && echo "  lifetime time $data sec;" >> $conf
  config_get data "$p2" enc_alg
  test -n "$data" && echo "  encryption_algorithm $data;" >> $conf
  config_get data "$p2" auth_alg
  test -n "$data" && echo "  authentication_algorithm $data;" >> $conf

  echo -e "  compression_algorithm deflate;\n}" >> $conf

  if [ "$remote" = "anonymous" ]; then
    echo -e "mode_cfg {\n  auth_source system;\n  conf_source local;" >> $conf

    config_get data "$1" dns4
    test -n "$data" && echo "  dns4 $data;" >> $conf
    config_get data "$1" defdomain
    test -n "$data" && echo "  default_domain \"$data\";" >> $conf

    data=${remnet%/*}
    let "data=${data##*.}+1"
    echo "  network4 ${remnet%.*}.$data;" >> $conf

    let "data=255<<(24-${remnet#*/}+8)&255"
    echo "  netmask4 255.255.255.$data;" >> $conf

    echo -e "  split_network include $locnet;\n}" >> $conf

  elif [ -z "$client" ]; then
    manage_sa add $locnet $remnet $remote
    test $? -gt 0 -o $errno -gt 0 && return $errno

    manage_fw add $confIntZone $confExtZone $remnet
  fi
}

setup_tunnel() {
  local conf=$confDir/racoon.conf
  local peerconf=$confDir/peers.txt
  local data
  local remote
  local xauth

  config_get_bool data "$1" enabled 0
  test "$data" = "0" && return 0

  config_get remote "$1" remote
  if [ "$remote" = "anonymous" ]; then
    echo -e "remote anonymous {\n  generate_policy on;" >> $conf
  else
    data=$(nslookup "$remote" | awk 'NR == 5 {print $3}')
    test -n "$data" && remote="$data"
    echo -e "remote \"$1\" {\n  remote_address $remote;" >> $conf
    echo "$data" >> $peerconf
  fi

  config_get data "$1" pre_shared_key ""
  if [ -n "$data" ]; then
    if [ "$remote" != "anonymous" ]; then
      echo "$remote $data" >> $confDir/psk.txt
    else
      echo "* $data" >> $confDir/psk.txt
    fi
  fi

  let confPh1ID=$confPh1ID+1
  echo "  ph1id $confPh1ID;" >> $conf

  config_get xauth "$1" username ""

  config_get data "$1" certificate ""
  if [ -n "$data" ]; then
    echo -en "  verify_cert on;\n  my_identifier asn1dn;\n  certificate_type x509 " >> $conf
    echo -en "\"$data.crt\" \"$data.key\";\n  send_cr off;\n  peers_identifier " >> $conf
  else
    config_get data "$1" my_id_type ""
    if [ -n "$data" ]; then
      echo -n "  my_identifier $data" >> $conf
      config_get data "$1" my_id ""
      if [ -n "$data" ]; then
	echo " \"$data\";" >> $conf
      elif [ -n "$xauth" ]; then
	echo " \"$xauth\";" >> $conf
      else
	echo ";" >> $conf
      fi
    elif [ -n "$xauth" ]; then
      echo "  my_identifier user_fqdn \"$xauth\";" >> $conf
    fi
    echo -n "  peers_identifier " >> $conf
  fi

  if [ "$remote" = "anonymous" ]; then
    echo "user_fqdn;" >> $conf
  else
    config_get data "$1" peer_id_type "asn1dn"
    echo -n "$data" >> $conf

    config_get data "$1" peer_id ""
    test -n "$data" && echo -n " \"$data\"" >> $conf

    echo ";" >> $conf
  fi

  if [ -n "$xauth" ]; then
    config_get data "$1" password
    if [ -z "$data" ]; then
      $log "Password must be given in $1 tunnel"
      errno=7; return 7
    fi
    echo "$xauth $data" >> $confDir/psk.txt

    echo "  xauth_login \"$xauth\";" >> $conf
    echo -e "  script \"p1client-up\" phase1_up;\n  script \"p1client-down\" phase1_down;" >> $conf
  fi

  config_get data "$1" exchange_mode
  if [ -z "$data" ]; then
    data=main
    test -n "$xauth" && data="${data},aggressive"
  fi
  echo -e "  exchange_mode $data;\n  nat_traversal on;\n  support_proxy on;" >> $conf

  config_get data "$1" prop_check "obey"
  test -n "$data" && echo "  proposal_check $data;" >> $conf

  config_get_bool data "$1" weak_p1check 1
  if [ $data -eq 0 ]; then data=off; else data=on; fi
  echo "  weak_phase1_check $data;" >> $conf

  config_get_bool data "$1" verify_id 1
  if [ $data -eq 0 ]; then data=off; else data=on; fi
  echo "  verify_identifier $data;" >> $conf

  config_get data "$1" dpd_delay ""
  test -n "$data" && echo "  dpd_delay $data;" >> $conf

  unset data
  test -n "$xauth" && data="on"
  config_get data "$1" mode_cfg "$data"
  test -n "$data" && echo "  mode_cfg $data;" >> $conf

  config_get_bool data "$1" init 0
  if [ $data -eq 0 ]; then data=off; else data=on; fi
  echo "  initial_contact $data;" >> $conf


  config_list_foreach "$1" p1_proposal setup_p1
  echo "}" >> $conf

  config_list_foreach "$1" sainfo setup_sa "$remote $xauth"
}

setup_cert() {
  local item
  local data

  for item in key crt ; do
    config_get data "$1" $item ""
    test -z "$data" && continue

    echo "$data" |\
    sed 's/-\+[A-Z ]\+-\+/\n&\n/g' | sed 's/.\{50,50\}/&\n/g' | sed '/^$/d'\
    > $confDir/cert/$1.$item

    chmod 600 $confDir/cert/$1.$item
  done

  if [ -s $confDir/cert/$1.crt ]; then
    data=$(openssl x509 -noout -hash -in $confDir/cert/$1.crt)
    ln -sf $confDir/cert/$1.crt $confDir/cert/$data.0
  fi
}

destroy_sa() {
  local locnet
  local remnet

  config_get locnet "$1" local_net
  config_get remnet "$1" remote_net
  if [ -z "$locnet" ] || [ -z "$remnet" ]; then
    $log "Remote and local networks for $1 must be configured"
    errno=4; return 4
  fi

  manage_sa del $locnet $remnet $2
  manage_fw del $confIntZone $confExtZone $remnet
}

destroy_tunnel() {
  local data

  config_get_bool data "$1" enabled 0
  test "$data" = "0" && return 0

  config_get remote "$1" remote
  data=$(nslookup "$remote" | awk 'NR == 5 {print $3}')
  test -n "$data" && remote="$data"

  config_get data "$1" username ""
  if [ -z "$data" ]; then
    config_list_foreach "$1" sainfo destroy_sa $remote
  fi
}

destroy_conf() {
  setup_fw del
}

check_software() {
  local item

  for item in /usr/sbin/setkey /usr/bin/openssl /usr/sbin/ip ; do
    if [ ! -x $item ]; then
      $log "Needed program $item not found, exiting"
      errno=9; return 9
    fi
  done
}

cleanup_conf() {
  config_load racoon
  config_foreach setup_load racoon
  config_foreach destroy_conf racoon
  config_foreach destroy_tunnel tunnel

  /usr/sbin/setkey -P -F
  /usr/sbin/setkey -F
}

check_dir() {
  local item

  for item in $confDir $confDir/cert ; do
    if [ ! -d $item ]; then
      mkdir -m 0700 -p $item
    fi
  done
}

wait4wanzone() {
  local item=$connWait
  local data

  data="$(get_zoneiplist $confExtZone)"
  while [ $item -gt 0 ]; do
    test -n "$data" && break
    sleep 2
    let "item=$item-1"
    data="$(get_zoneiplist $confExtZone)"
  done

  test -z "$data" && return 10
}

start_service() {
  check_software
  test $? -gt 0 -o $errno -gt 0 && exit $errno

  check_dir

  config_load racoon
  config_foreach setup_load racoon

  config_foreach wait4wanzone racoon
  if [ $? -gt 0 ] || [ $errno -gt 0 ]; then
    $log "No active interfaces in $confExtZone zone found, exiting"
    exit $errno
  fi

  config_foreach setup_conf racoon
  test $? -gt 0 -o $errno -gt 0 && exit $errno

  config_foreach setup_tunnel tunnel
  test $? -gt 0 -o $errno -gt 0 && exit $errno

  config_foreach setup_cert certificate

  procd_open_instance
  procd_set_param command /usr/sbin/racoon
  test -n "$confIPMode" && procd_append_param command -$confIPMode
  procd_append_param command -F -f $confDir/racoon.conf
  procd_set_param file $confDir/racoon.conf
  procd_close_instance

  if [ -x /etc/racoon/vpnctl ]; then
    let connWait=$connWait*2+2
    ( sleep $connWait; /etc/racoon/vpnctl up ) &
  fi
}

service_triggers() {
  local item
  local data

  procd_add_reload_trigger "racoon" "network"

  config_load racoon
  config_foreach setup_load racoon

  data=$(get_zoneiflist $confExtZone)
  if [ $? -gt 0 ] || [ $errno -gt 0 ] || [ -z "$data" ]; then
    $log "Can not find interfaces for $confExtZone zone"
  else
    for item in $data ; do
      procd_add_reload_interface_trigger $item
    done
  fi
}

stop_service() {
  cleanup_conf
  procd_kill racoon 
}

trap "cleanup_conf" 1 2 3 4 5 6 7 8 9 10


# EOF /etc/init.d/racoon