forked from coldhakca/tor-relay-bootstrap
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bootstrap.sh
executable file
·558 lines (485 loc) · 15.1 KB
/
bootstrap.sh
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
#!/bin/bash
#####################################################################
#
# bootstrap.sh
# -------------------
# Configures Debian / Ubuntu to be a set-and-forget Tor relay.
#
#####################################################################
PWD="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
set -e
INSTALL_PACKAGES=()
STOP_SERVICES=()
APT_SOURCES_FILE="/etc/apt/sources.list.d/torproject.list"
# check for root
function check_root () {
if [[ $EUID -ne 0 ]]; then
echo "This script must be run as root (use su / sudo)" 1>&2
exit 1
fi
}
# suggest user account
function suggest_user () {
ORIG_USER=$(logname)
if [ "$ORIG_USER" == "root" ]; then
echo "It appears that you have logged into this machine as root. If you would like to disable remote root access, create a user account and use su / sudo to run bootstrap.sh."
echo "Would you like to continue and allow remote root access? [y/n]"
read useroot
if [ "$useroot" != "y" ]; then
exit 1
fi
fi
}
# install mandatory packages used in add_tor_sources
function install_requirements() {
echo "== Updating software"
apt-get update
apt-get install -y lsb-release apt-transport-tor gpg dirmngr curl netcat
}
function uninstall_requirements() {
echo "== Removing software"
apt-get remove --purge -y apt-transport-tor dirmngr curl netcat
}
function uninstall_requirements() {
echo "== Removing software"
apt-get remove --purge -y apt-transport-tor dirmngr curl
}
# add official Tor repository and Debian onion service mirrors
function add_tor_sources() {
DISTRO=$(lsb_release -si)
SID=$(lsb_release -cs)
if [ "$DISTRO" == "Debian" -o "$DISTRO"=="Ubuntu" ]; then
echo "== Removing previous Tor sources"
rm -f $APT_SOURCES_FILE
echo "== Adding the official Tor repository"
echo "deb https://deb.torproject.org/torproject.org `lsb_release -cs` main" >> $APT_SOURCES_FILE
curl https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --import
gpg --export A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89 | apt-key add -
apt-get update
if [ "$DISTRO" == "Debian" ]; then
echo "== Switching to Debian's onion service mirrors"
echo "deb tor+http://vwakviie2ienjx6t.onion/debian `lsb_release -cs` main" >> $APT_SOURCES_FILE
if [ "$SID" != "sid" ]; then
echo "deb tor+http://vwakviie2ienjx6t.onion/debian `lsb_release -cs`-updates main">> $APT_SOURCES_FILE
echo "deb tor+http://sgvtcaew4bxjd7ln.onion/debian-security `lsb_release -cs`/updates main" >> $APT_SOURCES_FILE
fi
fi
else
echo "You do not appear to be running Debian or Ubuntu"
exit 1
fi
}
function remove_tor_sources() {
echo "== Removing previous Tor sources"
rm -f $APT_SOURCES_FILE
}
# install tor
function register_install_tor() {
echo "== Installing Tor"
INSTALL_PACKAGES+=("tor")
INSTALL_PACKAGES+=("deb.torproject.org-keyring")
STOP_SERVICES+=(tor)
}
function configure_tor() {
TEMPLATE=$1
NB_INSTANCES=$2
echo "== Configuring Tor"
sed -i -e 's/deb https\:\/\/deb\.torproject\.org\//deb tor\+http\:\/\/sdscoq7snqtznauu\.onion\//' $APT_SOURCES_FILE
create_instances $TEMPLATE $NB_INSTANCES
service tor restart
echo "== Waiting for Tor Socks5 service to be ready"
while ! echo -e 'PROTOCOLINFO\r\n' | nc 127.0.0.1 9050 | grep -qa tor; do
sleep 1
done
}
# create tor instance
function create_instance() {
TEMPLATE=$1
instance=$2
INSTANCE_NAME="${TEMPLATE}$((instance+1))"
echo "== Creating Tor Instance ${INSTANCE_NAME}"
tor-instance-create $INSTANCE_NAME
cp $PWD/etc/tor/torrc.$TEMPLATE /etc/tor/instances/$INSTANCE_NAME/torrc
orport=$((instance+9001))
dirport=$((instance+9030))
socksport=$((instance+9050))
sed -i "s/ORPort .*/ORPort ${orport}/" /etc/tor/instances/$INSTANCE_NAME/torrc
sed -i "s/DirPort .*/DirPort ${dirport}/" /etc/tor/instances/$INSTANCE_NAME/torrc
sed -i "s/SocksPort .*/SocksPort ${socksport}/" /etc/tor/instances/$INSTANCE_NAME/torrc
systemctl enable tor@${INSTANCE_NAME}
systemctl start tor@${INSTANCE_NAME}
systemctl mask tor@default
}
# create one or more tor instances
function create_instances() {
TEMPLATE=$1
NB_INSTANCES=$2
instance=0
while [ $instance -lt $NB_INSTANCES ]; do
create_instance $TEMPLATE $instance
instance=$((instance+1))
done
}
function register_install_firewall() {
echo "== Installing firewall"
INSTALL_PACKAGES+=("debconf-utils")
INSTALL_PACKAGES+=("iptables")
INSTALL_PACKAGES+=("iptables-persistent")
}
# configure firewall rules
function configure_firewall() {
#TODO: handle NB_INSTANCES
NB_INSTANCES=$1
echo "iptables-persistent iptables-persistent/autosave_v6 boolean true" | debconf-set-selections
echo "iptables-persistent iptables-persistent/autosave_v4 boolean true" | debconf-set-selections
cp $PWD/etc/iptables/rules.v4 /etc/iptables/rules.v4
cp $PWD/etc/iptables/rules.v6 /etc/iptables/rules.v6
#remove the COMMIT command from templates
sed -i '/COMMIT/d' /etc/iptables/rules.v4 /etc/iptables/rules.v6
# for each instance call instance_rules
instance=0
while [ $instance -lt $NB_INSTANCES ]; do
orport=$((instance+9001))
dirport=$((instance+9030))
echo "-A INPUT -p tcp --dport $orport -j ACCEPT" >> /etc/iptables/rules.v4
echo "-A INPUT -p tcp --dport $dirport -j ACCEPT" >> /etc/iptables/rules.v4
echo "-A INPUT -p tcp --dport $orport -j ACCEPT" >> /etc/iptables/rules.v6
echo "-A INPUT -p tcp --dport $dirport -j ACCEPT" >> /etc/iptables/rules.v6
instance=$((instance+1))
done
#re-add the COMMIT command at the end of config files
echo "COMMIT" >> /etc/iptables/rules.v4
echo "COMMIT" >> /etc/iptables/rules.v6
chmod 600 /etc/iptables/rules.v4
chmod 600 /etc/iptables/rules.v6
iptables-restore < /etc/iptables/rules.v4
ip6tables-restore < /etc/iptables/rules.v6
}
function register_install_f2b() {
echo "== Installing fail2ban"
INSTALL_PACKAGES+=("fail2ban")
}
function configure_f2b() {
return
}
function register_install_auto_update() {
echo "== Installing unattended upgrades"
INSTALL_PACKAGES+=("unattended-upgrades")
INSTALL_PACKAGES+=("apt-listchanges")
STOP_SERVICES+=("unattended-upgrades")
}
# configure automatic updates
function configure_auto_update() {
echo "== Configuring unattended upgrades"
cp $PWD/etc/apt/apt.conf.d/20auto-upgrades /etc/apt/apt.conf.d/20auto-upgrades
}
# install apparmor
function register_install_aa() {
echo "== Installing AppArmor"
INSTALL_PACKAGES+=("apparmor")
INSTALL_PACKAGES+=("apparmor-profiles")
INSTALL_PACKAGES+=("apparmor-utils")
}
# configure apparmor
function configure_aa() {
echo "== Configuring AppArmor"
sed -i.bak 's/GRUB_CMDLINE_LINUX="\(.*\)"/GRUB_CMDLINE_LINUX="\1 apparmor=1 security=apparmor"/' /etc/default/grub
update-grub
}
# install ntp
function register_install_ntp() {
echo "== Installing ntp"
INSTALL_PACKAGES+=("ntp")
}
# configure ntp
function configure_ntp() {
return
}
# install sshd
function register_install_sshd() {
echo "== Installing openssh-server"
INSTALL_PACKAGES+=("openssh-server")
}
# configure sshd
function configure_sshd() {
SSHD_CONFIG_FILE="/etc/ssh/sshd_config"
if [ -n "$ORIG_USER" ]; then
echo "== Configuring sshd"
# only allow the current user to SSH in
if ! grep -q "AllowUsers $ORIG_USER" $SSHD_CONFIG_FILE; then
echo "" >> $SSHD_CONFIG_FILE
echo "AllowUsers $ORIG_USER" >> $SSHD_CONFIG_FILE
echo " - SSH login restricted to user: $ORIG_USER"
fi
if grep -q "Accepted publickey for $ORIG_USER" /var/log/auth.log; then
# user has logged in with SSH keys so we can disable password authentication
sed -i '/^#\?PasswordAuthentication/c\PasswordAuthentication no' $SSHD_CONFIG_FILE
echo " - SSH password authentication disabled"
if [ $ORIG_USER == "root" ]; then
# user logged in as root directly (rather than using su/sudo) so make sure root login is enabled
sed -i '/^#\?PermitRootLogin/c\PermitRootLogin yes' $SSHD_CONFIG_FILE
fi
else
# user logged in with a password rather than keys
echo " - You do not appear to be using SSH key authentication. You should set this up manually now."
fi
service ssh reload
else
echo "== Could not configure sshd automatically. You will need to do this manually."
fi
}
# install unbound
function register_install_unbound() {
echo "== Installing Unbound"
INSTALL_PACKAGES+=("unbound")
STOP_SERVICES+=(unbound)
}
# configure unbound
function configure_unbound() {
echo "== Configuring Unbound"
cp $PWD/etc/unbound/unbound.conf /etc/unbound/unbound.conf
# set system to use only local DNS resolver
# chattr -i /etc/resolv.conf
sed -i 's/^nameserver/#nameserver/g' /etc/resolv.conf
if grep -q "127.0.0.1" /etc/resolv.conf; then
echo "nameserver 127.0.0.1" >> /etc/resolv.conf
fi
# chattr +i /etc/resolv.conf
}
# install tor-arm
function register_install_tor_arm() {
echo "== Installing Tor-Arm"
INSTALL_PACKAGES+=("tor-arm")
}
function configure_tor_arm() {
return
}
# install monit
function register_install_monit() {
if apt-cache search ^monit$ 2>&1 | grep -q monit; then
echo "== Installing monit"
INSTALL_PACKAGES+=("monit")
STOP_SERVICES=("monit")
fi
}
# configure monit
function configure_monit() {
if dpkg --get-selections monit | grep -q monit; then
echo "== Configuring monit"
cp $PWD/etc/monit/conf.d/tor-relay.conf /etc/monit/conf.d/tor-relay.conf
fi
}
# install pip for nyx
function register_install_pip() {
echo "== Installing pip"
INSTALL_PACKAGES+=("python-pip")
}
# pip install nyx
function pip_install_nyx() {
echo "== Pip Installing Nyx"
pip install nyx
}
function install_packages() {
apt-get install -y "${INSTALL_PACKAGES[@]}"
}
function uninstall_packages() {
apt-get remove --purge -y "${INSTALL_PACKAGES[@]}"
}
function stop_services() {
for i in "${STOP_SERVICES[@]}"
do
service $i stop || echo -n ""
done
}
function restart_services() {
for i in "${STOP_SERVICES[@]}"
do
service $i restart
done
}
# final instructions
function print_final() {
echo ""
echo "== Try SSHing into this server again in a new window, to confirm the firewall isn't broken"
echo ""
echo "== Edit /etc/tor/torrc"
echo " - Set Address, Nickname, Contact Info, and MyFamily for your Tor relay"
echo " - Optional: include a Bitcoin address in the 'ContactInfo' line"
echo " - This will enable you to receive donations from OnionTip.com"
echo " - Optional: limit the amount of data transferred by your Tor relay (to avoid additional hosting costs)"
echo " - Uncomment the lines beginning with '#AccountingMax' and '#AccountingStart'"
echo ""
echo "== If you are running Ubuntu (We do this automatically in Debian), consider having ${APT_SOURCES_FILE} update over HTTPS and/or HTTPS+Tor"
echo " see https://guardianproject.info/2014/10/16/reducing-metadata-leakage-from-software-updates/"
echo " for more details"
echo ""
echo "== REBOOT THIS SERVER"
}
function register_install_toronly() {
register_install_tor
}
function configure_toronly() {
NB_INSTANCES=$1
return
}
function register_install_minimal() {
register_install_toronly
register_install_f2b
register_install_firewall
}
function configure_minimal() {
NB_INSTANCES=$1
configure_toronly $NB_INSTANCES
configure_f2b
configure_firewall $NB_INSTANCES
}
function register_install_standard() {
register_install_minimal
register_install_auto_update
register_install_aa
register_install_ntp
register_install_sshd
register_install_unbound
}
function configure_standard() {
NB_INSTANCES=$1
configure_minimal $NB_INSTANCES
configure_auto_update
configure_aa
configure_ntp
configure_sshd
configure_unbound
}
function register_install_full() {
register_install_standard
register_install_tor_arm
register_install_monit
register_install_pip
}
function configure_full() {
NB_INSTANCES=$1
configure_standard $NB_INSTANCES
configure_tor_arm
configure_monit
pip_install_nyx
}
function standard_procedure() {
TEMPLATE=$1
NB_INSTANCES=$2
install_packages
stop_services
configure_tor $TEMPLATE $NB_INSTANCES
apt-get update #Reupdate packages with Tor network repos
}
function postinst_script() {
POSTINST_SCRIPT=$1
echo "== Running PostInst Script ${POSTINST_SCRIPT}"
bash $POSTINST_SCRIPT
}
function configure_full_cleanup() {
uninstall_requirements
remove_tor_sources
}
function standard_procedure_cleanup() {
INSTALL_PACKAGES=( "${INSTALL_PACKAGES[@]/openssh-server/}" )
INSTALL_PACKAGES=( "${INSTALL_PACKAGES[@]/apparmor-profiles/}" )
INSTALL_PACKAGES=( "${INSTALL_PACKAGES[@]/apparmor-utils/}" )
INSTALL_PACKAGES=( "${INSTALL_PACKAGES[@]/apparmor/}" )
INSTALL_PACKAGES=( "${INSTALL_PACKAGES[@]/iptables-persistent/}" )
INSTALL_PACKAGES=( "${INSTALL_PACKAGES[@]/iptables/}" )
INSTALL_PACKAGES=( "${INSTALL_PACKAGES[@]/gpg/}" )
for i in "${INSTALL_PACKAGES[@]}"
do
if [[ $i != "" && `dpkg -l | grep ${i} | wc -l` -eq "0" ]]; then
INSTALL_PACKAGES=( "${INSTALL_PACKAGES[@]/${i}/}" )
fi
done
uninstall_packages
stop_services
apt-get autoremove --purge
}
TEMPLATE="proxy"
NB_INSTANCES=1
INSTALL=""
while getopts "t:m:i:p:h" opt; do
case ${opt} in
h)
echo "Usage:"
echo " -h Display this help message."
echo " -t TEMPLATE Select TEMPLATE [proxy|relay|exit|bridge] to use."
echo " -i INSTALL Select INSTALL [toronly|minimal|standard|full|cleanup] profile."
echo " -m %d Configure multiple instances."
echo " -p POSTINST_SCRIPT Call a post installation script."
exit 0
;;
t)
TEMPLATE=$OPTARG
;;
m)
NB_INSTANCES=$OPTARG
;;
i)
INSTALL=$OPTARG
;;
p)
POSTINST_SCRIPT=$OPTARG
;;
*)
echo "Invalid Option: -$OPTARG" 1>&2
exit 1
;;
esac
done
shift $((OPTIND -1))
if [ -z "$INSTALL" ]; then
echo "Error: INSTALL option is mandatory"
exit 1
fi
check_root
suggest_user
case "$INSTALL" in
toronly)
install_requirements
add_tor_sources
register_install_toronly
standard_procedure $TEMPLATE $NB_INSTANCES
configure_toronly $NB_INSTANCES
postinst_script $POSTINST_SCRIPT
;;
minimal)
install_requirements
add_tor_sources
register_install_minimal
standard_procedure $TEMPLATE $NB_INSTANCES
configure_minimal $NB_INSTANCES
postinst_script $POSTINST_SCRIPT
;;
standard)
install_requirements
add_tor_sources
register_install_standard
standard_procedure $TEMPLATE $NB_INSTANCES
configure_standard $NB_INSTANCES
postinst_script $POSTINST_SCRIPT
;;
full)
install_requirements
add_tor_sources
register_install_full
standard_procedure $TEMPLATE $NB_INSTANCES
configure_full $NB_INSTANCES
postinst_script $POSTINST_SCRIPT
;;
cleanup)
register_install_full
standard_procedure_cleanup
configure_full_cleanup
exit 0
;;
*)
echo "Invalid Install: -$OPTARG" 1>&2
exit 1
;;
esac
restart_services
print_final