Repository navigation
Expand file tree
/
Copy pathInstallPiStrong
More file actions
executable file
·586 lines (540 loc) · 18.2 KB
/
Copy pathInstallPiStrong
File metadata and controls
executable file
·586 lines (540 loc) · 18.2 KB
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
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
#!/bin/bash
#
# Installation tool for pistrong
# Performs the following tasks
# Ensures required packages are installed
# On Raspbian these are: Apt-get install libgmp10 libgmp-dev libsystemd-dev libssl-dev
# Checks for availability of apt version of strongSwan
# If it exists, gives user an option which strongSwan to install (latest or distro-provided)
# If latest:
# Creates a work directory: $PISTRONGOOT/piStrong (defaults to /root/piStrong)
# Downloads and bunzip2 the current released strongswan bits
# Builds strongswan
# Installs into the system
# If apt distro-provided:
# Installs the correct packages
#
# Use pistrong to manage users and certificates for your strongSwan VPN
# Start and stop the VPN via: 'sudo pistrong service start' and 'sudo pistrong service stop' ...
# ...or 'sudo systemctl start strongswan' and 'sudo systemctl stop strongswan'
#
function get_wssver() {
# Broke when strongswan website/download page updated. Sigh
#vs1=$(curl -s -L https://www.strongswan.org/download.html | grep 'Current Release' | head -1)
#s1=${vs1##<h4>Current Release*normal\">}
#wssver=${s1%%<*}
#echo $wssver
#return 1
#
# String returned now (5/2023) in vs1 starts with these 2 lines, grab 2nd line with version:
# <h4 class="has-text-primary">Current Release</h4>
# <p>Version: <strong class="has-text-primary">5.9.10</strong></p>
vs1=$(curl -s -L https://www.strongswan.org/download.html | sed -n '/Current Release/,/Version:/p' | head -2 | grep -v Current)
s1=${vs1##*primary\"\>}
wssver=${s1%%<*}
echo $wssver
return 1
}
function get_osdistro() {
[ "$osdistro" != "" ] && return
if [ -f "/etc/os-release" ]
then
osdistro=$(grep ^ID= /etc/os-release | (IFS='='; read a b ; echo $b))
oslike=$(grep ^ID_LIKE= /etc/os-release | (IFS='='; read a b ; echo $b))
else
osdistro="unknown"
fi
osdistro=${osdistro%\"}
osdistro=${osdistro#\"}
[ "$oslike" == "ubuntu" ] && osdistro="ubuntu"
declare -x osdistro
}
function get_aptssver() {
read cand aptssver <<< $(apt policy strongswan-swanctl 2> /dev/null | grep Candidate)
echo "$aptssver"
return
}
function askyn() {
local ans
echo -n "$1" '[y/n]? ' ; read $2 ans
case "$ans" in
y*|Y*) return 0 ;;
*) return 1 ;;
esac
}
function askin() {
local ans sw=""
# sw="-n 1"
echo -n "$1 "; read $sw ans
}
function askinall() {
# Asks only if started with 'allx'
[ "$cmd" == "allx" ] && askin "$1"
}
function ispkginstalled() {
#
# $1 has package name
#
iver=$(apt-cache policy $1 | grep Installed:)
if [ "$iver" == "" ]
then
return 1
else
[[ "$iver" =~ "(none)" ]] && return 1 || return 0
fi
return
}
function do_cleanupwebinstall() {
[ "$PISTRONGROOT" == "" ] && PISTRONGROOT="/root"
[ ! -d "$PISTRONGROOT" ] && return
PSDIR="$PISTRONGROOT/piStrong"
[ ! -d "$PSDIR" ] && return
gotoBuildDir
[ ! -d "$PSBDIR" ] && return
echo "** We must remove the existing strongSwan Web install"
echo " Any existing CA and user/device certs and keys will be preserved"
if askyn "Continue"
then
[ -f $PISTRONGROOT/pistrong-uninstall.log ] && rm -f $PISTRONGROOT/pistrong-uninstall.log
echo "> Removing existing strongSwan Web install"
echo "* Uninstall log will be in $PISTRONGROOT/pistrong-uninstall.log"
make uninstall > $PISTRONGROOT/pistrong-uninstall.log 2>&1
cd $PISTRONGROOT
rm -rf piStrong
else
echo "** Cannot continue apt install until web install is removed"
exit
fi
}
function do_cleanupaptinstall() {
local c1=1
ispkginstalled strongswan && c1=0
ispkginstalled strongswan-swanctl && c1=0
if [ $c1 -eq 1 ]
then
return
fi
echo "** We must remove your existing apt install of strongSwan"
echo " Any existing CA and user/device certs and keys will be preserved"
if ! askyn "Continue"
then
echo "** Cannot do the web install until the apt install is removed"
exit
fi
apt-get --yes remove strongswan strongswan-swanctl strongswan-pki charon-systemd libstrongswan libstrongswan-extra-plugins libstrongswan-standard-plugins strongswan-libcharon libcharon-extra-plugins strongswan-charon strongswan-starter
}
function do_wrapup() {
echo $"
> pistrong/strongSwan Installation complete
** Required Post-installation Steps:
* If this system will be a VPN Server:
* Configure your CA. Use /usr/local/bin/makeMyCA to fully configure a CA that supports Android, iOS/MacOS, Linux, and Windows VPN Clients
* Configure iptables. See https://github.com/gitbls/pistrong/blob/master/README.md#firewall-considerations
* Configure email settings via pistrong if you intend to email certs (See 'Sending email' in the README)
* Configure strongSwan service to automatically start if desired
* Add user Certs (See pistrong help and pistrong add --help for command details)
* Add port forwards on your router to this system for UDP ports 500 and 4500
* If this system will be a VPN Client:
* Once you receive the VPN Cert Pack from the VPN Server manager,
install it into strongSwan using the 'sudo pistrong client install' command
* Then:
'sudo pistrong service start' or 'sudo systemctl start strongswan' to start the strongSwan VPN
'sudo pistrong service enable' or 'sudo systemctl enable strongswan' to enable strongSwan to restart after each reboot
* Reboot the system and make sure everything works
"
}
function do_pistrong_download() {
#
# Download the pistrong bits from GitHub
#
echo "> Downloading pistrong scripts from github"
for f in pistrong InstallPiStrong makeMyCA makeTunnel
do
if [ ! -x /usr/local/bin/$f ]
then
echo "* Downloading $f"
# cp /l/work/pistrong/$f /usr/local/bin
curl -L https://raw.githubusercontent.com/gitbls/pistrong/master/$f -o /usr/local/bin/$f
chmod 755 /usr/local/bin/$f
fi
done
}
function get_servicename() {
for sn in strongswan strongswan-swanctl
do
if [ "$(systemctl list-unit-files --no-pager --no-legend $sn.service)" != "" ]
then
echo "$sn"
return
fi
done
echo "unknown"
return
}
function do_install_prereqs() {
case "$osdistro" in
ubuntu|debian|raspbian|raspios)
local pkgs=""
[ "$(which curl)" == "" ] && pkgs="curl"
[ "$(which zip)" == "" ] && pkgs="$pkgs zip"
[ "$(which unzip)" == "" ] && pkgs="$pkgs unzip"
[ "$(which iptables)" == "" ] && pkgs="$pkgs iptables"
[ "$(which dig)" == "" ] && pkgs="$pkgs bind9-dnsutils"
if [ "$pkgs" != "" ]
then
echo ""
#echo "% pistrong requires 'curl', 'unzip', 'zip', 'bind9-dnsutils', and 'iptables'"
echo " Doing 'apt update' and 'apt install' of prerequisite package(s): $pkgs"
apt-get update && apt-get install --yes $pkgs --no-install-recommends
fi
;;
*)
echo "? Cannot install prerequisite packages; Unknown distro '$os'"
;;
esac
}
function gotoBuildDir() {
for d in $PSDIR/strongswan-*
do
# Found it. Get ssver
IFS="-" read fn webssver <<< $d
break
done
PSBDIR="$PISTRONGROOT/piStrong/strongswan-$webssver"
cd $PSBDIR
return 0
}
function check_hostname() {
if [ "$(hostname)" == "raspberrypi" ]
then
echo ""
echo "%%% Your hostname is still 'raspberrypi'"
echo " We STRONGLY encourage you to change it via sudo raspi-config Network Options before continuing"
if askyn "Press y to exit and correct hostname, n to continue"
then
exit 1
fi
fi
}
function web_do_prereqs() {
get_osdistro
case "$osdistro" in
# opensuse*)
# echo "I'll try to install the required packages"
# zypper in make gcc gmp-devel systemd-devel libopenssl-1_1-devel python3-pexpect zip
# echo "Check above to ensure everything got installed"
# ;;
# centos|rhel|fedora)
# echo "I'll try to install the required packages, but this is incomplete"
# yum install gcc gmp-devel.x86_64 systemd-devel.x86_x64 openssl-devel.x86_64 zip
# echo "Check above to ensure everything got installed"
# echo "** You'll need to install python3 and pexpect if they are not already installed"
# ;;
ubuntu|debian|raspbian|raspios)
echo ""
echo "Ensuring that required packages 'make gcc libgmp10 libgmp-dev libsystemd-dev libssl-devpkg-config' are installed"
apt-get install --yes make gcc pkg-config libgmp10 libgmp-dev libsystemd-dev libssl-dev python3-pexpect
;;
*) echo "% Pre-reqs unknown for distro $osdistro"
esac
}
function web_dodownload() {
cd $PISTRONGROOT
webssver=$(get_wssver)
# webssver="5.6.3" # If you want a specific version (and it's still available, of course)
echo ""
echo "Using Strongswan version $webssver"
echo ""
echo "** The strongSwan download and build process can take about 10 minutes on an RPi4 on SSD"
echo " or close to an hour (RPi0W)."
echo ""
[ ! -d piStrong ] && mkdir piStrong
cd ./piStrong
[ -d strongswan-$webssver ] && rm -rf strongswan-$webssver
#
# Make sure no older versions are there with the same name pattern
#
oldssver=""
for d in $PSDIR/strongswan-*.*.*
do
if [ -d $d ]
then
IFS="-" read fn oldssver <<< $d
break
fi
done
if [ "$oldssver" != "" ]
then
echo ""
echo "% The directory '$PSDIR/strongswan-$oldssver' exists"
echo "% You must rename or delete all directories named '$PSDIR/strongswan-xx.xx.xx' before continuing"
exit
fi
if [ ! -f strongswan-$webssver.tar.bz2 ]
then
curl -L https://download.strongswan.org/strongswan-$webssver.tar.bz2 -o strongswan-$webssver.tar.bz2
ests=$?
[ $ests -ne 0 ] && echo "% Error downloading strongSwan tarball; Please try again" && exit
else
echo ""
echo "Using found strongSwan tar archive strongswan-$webssver.tar.bz2"
fi
# askinall "Press Enter to unpack the sources: "
echo ""
[ -f pistrong-untar.log ] && rm -f pistrong-untar.log
echo "** $(date +'%Y-%m-%d %H:%M:%S') Unpacking source archive [Log: $PSDIR/pistrong-untar.log]"
tar -xjvf strongswan-$webssver.tar.bz2 > pistrong-untar.log 2>&1
ests=$?
[ $ests -eq 0 ] && sts="No errors" || sts="review $PSDIR/pistrong-untar.log"
echo " tar exit status: $ests ($sts)"
}
function web_dopreconf() {
gotoBuildDir
askinall "Press Enter to start pre-make configuration: "
echo ""
echo "** $(date +'%Y-%m-%d %H:%M:%S') Performing pre-make configuration [Log: $PSBDIR/pistrong-configure.log]"
./configure --prefix= --enable-eap-mschapv2 --enable-eap-identity --enable-openssl --enable-eap-md5 --enable-eap-tls --enable-eap-dynamic --enable-systemd --enable-swanctl --disable-charon --disable-stroke --disable-scepclient --enable-counters > pistrong-configure.log 2>&1
ests=$?
[ $ests -eq 0 ] && sts="No errors" || sts="review $PSBDIR/pistrong-configure.log"
echo " Config exit status: $ests ($sts)"
}
function web_domake() {
gotoBuildDir
askinall "Press Enter to start make: "
echo ""
echo "** $(date +'%Y-%m-%d %H:%M:%S') Performing make [Log: $PSBDIR/pistrong-make.log]"
make > pistrong-make.log 2>&1
ests=$?
[ $ests -eq 0 ] && sts="No errors" || sts="review $PSBDIR/pistrong-make.log"
echo " Make exit status: $ests ($sts)"
}
function web_doinstall() {
gotoBuildDir
askinall "Press Enter to start install: "
echo ""
echo "** $(date +'%Y-%m-%d %H:%M:%S') Performing install [Log: $PSBDIR/pistrong-install.log]"
make install > pistrong-install.log 2>&1
ests=$?
[ $ests -eq 0 ] && sts="No errors" || sts="review $PSBDIR/pistrong-install.log"
echo " Install exit status: $ests ($sts)"
}
function web_doall() {
do_pistrong_download
web_do_prereqs
web_dodownload
web_dopreconf
web_domake
web_doinstall
do_post_config web
do_wrapup
}
function do_web_install() {
[ "$PISTRONGROOT" == "" ] && PISTRONGROOT="/root"
[ ! -d "$PISTRONGROOT" ] && echo "? PISTRONGROOT directory '$PISTRONGROOT' does not exist" && exit
PSDIR="$PISTRONGROOT/piStrong"
case "$1" in
"prereq") web_doprereqs ;;
"download") web_dodownload ;;
"preconf") web_dopreconf ;;
"make") web_domake ;;
"install") web_doinstall ;;
"postconf"|"post-configure") do_post_config web ;;
"all"|"allx") web_doall ;;
*) echo "? Invalid command" ;
echo "? Commands: prereq|download|preconf|make|install|postconf|all" ;
exit 1
;;
esac
}
function do_apt_install() {
echo "> Installing strongSwan from apt"
echo "* Installing packages 'strongswan-swanctl strongswan-pki charon-systemd libcharon-extauth-plugins libcharon-extra-plugins libstrongswan-extra-plugins libstrongswan-standard-plugins python3-pexpect'"
apt-get --yes install strongswan-swanctl strongswan-pki charon-systemd libcharon-extauth-plugins libcharon-extra-plugins libstrongswan-extra-plugins libstrongswan-standard-plugins python3-pexpect # iptables installed earlier
}
function do_post_config() {
echo ""
echo "> Creating /etc/swanctl/pistrong directories..."
[ ! -d /etc/swanctl/conf.d ] && mkdir /etc/swanctl/conf.d
[ ! -d /etc/swanctl/pistrong ] && mkdir -p /etc/swanctl/pistrong/{client-assets,server-assets,VPNClients,backup}
chmod 700 /etc/swanctl/pistrong/{client-assets,server-assets}
[ ! -d "/etc/swanctl/p12" ] && mkdir /etc/swanctl/p12 && chmod 750 /etc/swanctl/p12
#
# If /etc/swanctl/conf.d/*.conf files exist, sed them to make sure _updown is invoked from the correct location
case "$1" in
apt)
oldupdown="/libexec/ipsec/_updown"
newupdown="/usr/lib/ipsec/_updown"
;;
web)
oldupdown="/usr/lib/ipsec/_updown"
newupdown="/libexec/ipsec/_updown"
;;
esac
for f in /etc/swanctl/conf.d/*.conf
do
if [ "$f" != "/etc/swanctl/conf.d/*.conf" ]
then
echo "* Editing $f to ensure $oldupdown is changed to $newupdown"
sed -i "s#$oldupdown#$newupdown#" $f
fi
done
echo ""
echo " If this system will be a VPN Server AND you want remote VPN clients to access your LAN"
echo " then IPV4 forwarding should be enabled"
echo ""
fserver=1
if askyn "Enable IPV4 forwarding"
then
fserver=0
fi
sysctl92="/etc/sysctl.d/92-pistrong.conf"
sysctl92d="/etc/sysctl.d/.92-pistrong.conf"
if [ $fserver -eq 0 ]
then
if [ ! -f $sysctl92 ]
then
echo "* Creating $sysctl92 to set net.ipv4.ip_forward=1"
echo "net.ipv4.ip_forward=1" > $sysctl92 && sysctl -p $sysctl92 > /dev/null
fi
else
# Write it on VPN clients as well...but hidden so not executed
[ ! -f $sysctl92d ] && echo "net.ipv4.ip_forward=1" > $sysctl92d
fi
# Change IKE logging to eliminate keep-alive message logging
if [ ! -f /etc/strongswan.d/charon-systemd.conf-pistrong-orig ]
then
mv /etc/strongswan.d/charon-systemd.conf /etc/strongswan.d/charon-systemd.conf-pistrong-orig
cat >> /etc/strongswan.d/charon-systemd.conf <<EOF
charon-systemd {
#
# Section to configure native systemd journal logger, very similar to the
# syslog logger as described in LOGGER CONFIGURATION in strongswan.conf(5).
# See https://wiki.strongswan.org/projects/strongswan/wiki/Loggerconfiguration
#
journal {
# Loglevel for a specific subsystem.
# <subsystem> = <default>
# Default loglevel.
# default = 1
# ** pistrong set {ENC,IKE,NET}=0 to turn off frequently irrelevant message logging
# ** comment out these lines to re-enable keep-alive message logging
enc = 0
ike = 0
net = 0
}
}
EOF
fi
sn=$(get_servicename)
if [ "$sn" == "unknown" ]
then
echo "% Could not find the strongSwan systemd service"
echo " Set it with 'sudo pistrong config --service servicename.service'"
fi
pistrong config --service $sn.service
systemctl stop $sn > /dev/null 2>&1
}
#
# Main
#
function main() {
cmd="${1,,}"
[ "$cmd" == "" ] && cmd="all"
get_osdistro
check_hostname
echo "** Installer for strongSwan/pistrong Management Tool **"
echo ""
do_install_prereqs
echo ""
webssver=$(get_wssver)
if [ "$cmd" != "all" ]
then
do_cleanupaptinstall
do_web_install "$cmd"
exit
fi
if [ "$(which apt)" != "" ]
then
echo "> Identifying strongSwan version numbers on Web and in apt"
aptver=$(get_aptssver)
IFS="." read vmaj vmin vmisc <<< $aptver
vok=1
# Minimum required version of strongSwan is 5.8.0
# I had issues with 5.7.2 and iOS so disallowing older versions to avoid confusion
# Debian Bullseye will solve this issue with a much newer strongSwan apt package
if [ $vmaj -eq 5 ]
then
if [ $vmin -gt 8 ]
then
vok=0
fi
else
[ $vmaj -gt 5 ] && vok=0
fi
if [ $vok -eq 0 -o "$PSAPTOK" != "" ]
then
echo $"
strongSwan can be installed one of two ways:
apt: Version $aptver
Uses the standard apt package mechanism
Slightly older version of strongSwan, quick install
web: Version $webssver
Download, build, and install from strongswan.org
Latest released version of strongSwan, longer install (10-15 mins on Pi4)
See the github README for further information"
echo -n "Select A:apt W:website: " ; read ans
case "${ans,,}" in
a*|A*) echo ""
[ "$(which make)" == "" ] && echo "Installing make..." && apt-get install make
do_cleanupwebinstall
do_pistrong_download
do_apt_install
do_post_config apt
do_wrapup
exit
;;
w*|W*) echo ""
do_cleanupaptinstall
do_web_install "$cmd"
exit
;;
*) echo ""
exit
;;
esac
else
echo $"
% The version of strongSwan in apt is less than the minimum required version (5.8.0)
You can still install the web version ($webssver)
"
if askyn "Do you want to continue and install the web version"
then
do_cleanupaptinstall
do_web_install "$cmd"
exit
else
echo ""
exit
fi
fi
fi
echo "% strongSwan not found in apt"
if askyn "Do you want to install the latest version from the web"
then
do_cleanupaptinstall
do_web_install "$cmd"
fi
exit
}
if [[ $EUID -ne 0 ]]
then
if [[ $(dpkg-query -s sudo 2>/dev/null) ]]
then
sudo $0 $1 $2 $3 $4
exit
else
echo "? Please install sudo or run as root: $0 $1 $2"
exit 1
fi
fi
main "$@"