-
Notifications
You must be signed in to change notification settings - Fork 16
/
install.sh
executable file
·291 lines (256 loc) · 8.86 KB
/
install.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
#! /bin/bash
# This script sets up a full disc encrypted debian/ubuntu machine for
# unlocking during boot from the console, with a usbstick containing a key
# or from a SSH connection.
#
# Author: Martin van Beurden <[email protected]>
# crypto-usb-key.sh keyscript, based on http://wejn.org/how-to-make-passwordless-cryptsetup.html
#
set -e
KEYFILEPATH="$1"
if [ -z "$KEYFILEPATH" ]; then
KEYFILEPATH=".keyfile"
KEYFILE="$KEYFILEPATH"
if [ ! -f "$KEYFILEPATH" ]; then
echo "Generating key \"$KEYFILE\", this should go on your USB stick."
apt-get install -y sharutils
head -c 2880 /dev/urandom | uuencode -m - | head -n 65 | tail -n 64 > "$KEYFILE"
else
echo "Using existing key \"$KEYFILE\", this should go on your USB stick."
fi
elif [ ! -f "$KEYFILEPATH" ]; then
echo "Keyfile \"$KEYFILEPATH\" not found, exiting."
exit 1;
else
KEYFILE=$(basename $KEYFILEPATH)
fi
#Add key to the cryptvolume
echo "Getting first cryptodisk in /etc/crypttab"
lowestlinenr=9999
for diskid in $(blkid -t TYPE=crypto_LUKS -o value -s UUID); do
linenr=$(awk 'match($0,v){print NR; exit}' v=$diskid /etc/crypttab)
echo "Found $diskid on line $linenr"
if [ $linenr -lt $lowestlinenr ]; then
cryptUUID=$diskid
lowestlinenr=$linenr
fi
done
if [ -z "$cryptUUID" ]; then
echo "Unable to find a cryptodisk to use, exiting."
exit 1
fi
echo "Using cryptodisk $cryptUUID"
echo "Checking keyfile..."
if cryptsetup luksDump UUID=$cryptUUID --dump-master-key --batch-mode --key-file "$KEYFILEPATH" > /dev/null ; then
echo "Keyfile \"$KEYFILE\" already added to luks."
else
echo "Adding keyfile \"$KEYFILE\" to luks."
cryptsetup luksAddKey UUID=$cryptUUID "$KEYFILEPATH"
fi
#Add modules needed for usb reading
grep -q '^vfat$' /etc/initramfs-tools/modules || echo 'vfat' >> /etc/initramfs-tools/modules
grep -q '^fat$' /etc/initramfs-tools/modules || echo 'fat' >> /etc/initramfs-tools/modules
grep -q '^nls_cp437$' /etc/initramfs-tools/modules || echo 'nls_cp437' >> /etc/initramfs-tools/modules
grep -q '^nls_iso8859_1$' /etc/initramfs-tools/modules || echo 'nls_iso8859_1' >> /etc/initramfs-tools/modules
grep -q '^nls_utf8$' /etc/initramfs-tools/modules || echo 'nls_utf8' >> /etc/initramfs-tools/modules
grep -q '^nls_base$' /etc/initramfs-tools/modules || echo 'nls_base' >> /etc/initramfs-tools/modules
#Setup cryptkey
cp crypto-usb-key.sh /usr/local/sbin/
chmod a+x /usr/local/sbin/crypto-usb-key.sh
sed -i "/$cryptUUID/ s/$cryptUUID[ \t]*[^ \t]*/$cryptUUID $KEYFILE/g" /etc/crypttab
#remove any previous keyscript
sed -i "/$cryptUUID/ s/,keyscript=[^, \t]*//" /etc/crypttab
#add our keyscript
sed -i "/$cryptUUID/ s/\$/,keyscript=\/usr\/local\/sbin\/crypto-usb-key.sh/" /etc/crypttab
#Dropbear ssh unlock
apt-get install -y dropbear initramfs-tools busybox
#Add network drivers
ifaces=$(ip addr|egrep "^[0-9]*: "|egrep -v "^[0-9]*: lo:"|awk '{print $2}'|sed 's/:$//g')
for iface in $ifaces; do
if [ -f /sys/class/net/$iface/device/uevent ]; then
echo "Found interface $iface"
ifacemod="$(grep DRIVER /sys/class/net/$iface/device/uevent |awk -F'=' '{print $2}')"
grep -q "^$ifacemod$" /etc/initramfs-tools/modules || echo "$ifacemod" >> /etc/initramfs-tools/modules
fi
done
#explicitely enable dropbear (=default behavior), won't touch existing setting if any
(grep -qs '^DROPBEAR=' /etc/initramfs-tools/conf.d/dropbear || \
grep '^DROPBEAR=' /etc/initramfs-tools/initramfs.conf || \
echo 'DROPBEAR=y' \
) >> /etc/initramfs-tools/conf.d/dropbear
#explicitely set ip to dhcp (=default behavior), won't touch existing setting if any
(grep -qs '^IP=' /etc/initramfs-tools/conf.d/dropbear || \
grep '^IP=' /etc/initramfs-tools/initramfs.conf || \
echo 'IP=dhcp' \
) >> /etc/initramfs-tools/conf.d/dropbear
#disallow password logins (=non-default behavior), set port to 22 (=default behavior), won't touch existing setting if any
(grep -qs 'PKGOPTION_dropbear_OPTION=' /etc/initramfs-tools/conf.d/dropbear || \
grep 'PKGOPTION_dropbear_OPTION=' /etc/initramfs-tools/initramfs.conf || \
echo 'export PKGOPTION_dropbear_OPTION="-s -p 22"' \
) >> /etc/initramfs-tools/conf.d/dropbear
# Generate public-private key pair needed to login to dropbear as root
if [ ! -f /etc/dropbear-initramfs/id_rsa ]; then
ssh-keygen -t rsa -N '' -f /etc/dropbear-initramfs/id_rsa
cat /etc/dropbear-initramfs/id_rsa/id_rsa.pub >>/etc/dropbear-initramfs/authorized_keys
chmod 600 /etc/dropbear-initramfs/authorized_keys
fi
#Write initramfs scripts
#
#Network won't be reconfigured after dropbear has initialized it in initramfs, reset it
#
cat <<EOF >/etc/initramfs-tools/scripts/local-bottom/reset_network
#!/bin/sh
#
# Initramfs script to reset all network devices after initramfs is done.
#
# Author: Martin van Beurden, https://martinvanbeurden.nl
#
# Usage:
# - Copy this script to /etc/initramfs-tools/scripts/local-bottom/reset_network
# - chmod +x /etc/initramfs-tools/scripts/local-bottom/reset_network
# - update-initramfs -u -k -all
#
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case \$1 in
prereqs)
prereqs
exit 0
;;
esac
#
# Begin real processing
#
ifaces=\$(ip addr|egrep "^[0-9]*: "|egrep -v "^[0-9]*: lo:"|awk '{print \$2}'|sed 's/:$//g')
for iface in \$ifaces; do
echo "Flushing network interface \$iface"
ip addr flush \$iface
done
EOF
chmod +x /etc/initramfs-tools/scripts/local-bottom/reset_network
#
#Just an extra, kills the dropbear connecton when done so the client
#knows immediately it has been disconnected.
#
cat << EOF>/etc/initramfs-tools/scripts/local-bottom/kill_dropbear_connections
#!/bin/sh
# Initramfs script to kill all dropbear clientconnections after initramfs is done.
#
# Adopted from openwrt
# Author: Martin van Beurden, https://martinvanbeurden.nl
#
# Usage:
# - Copy this script to /etc/initramfs-tools/scripts/local-bottom/kill_dropbear_connections
# - chmod +x /etc/initramfs-tools/scripts/local-bottom/kill_dropbear_connections
# - update-initramfs -u -k -all
#
PREREQ=""
prereqs()
{
echo "$PREREQ"
}
case \$1 in
prereqs)
prereqs
exit 0
;;
esac
#
# Begin real processing
#
NAME=dropbear
PROG=/sbin/dropbear
# get all server pids that should be ignored
ignore=""
for server in \`cat /var/run/\${NAME}*.pid\`
do
ignore="\${ignore} \${server}"
done
# get all running pids and kill client connections
for pid in \`pidof "\${NAME}"\`
do
# check if correct program, otherwise process next pid
grep -F -q -e "\${PROG}" "/proc/\${pid}/cmdline" || {
continue
}
# check if pid should be ignored (servers)
skip=0
for server in \${ignore}
do
if [ "\${pid}" == "\${server}" ]
then
skip=1
break
fi
done
[ "\${skip}" -ne 0 ] && continue
# kill process
echo "\$0: Killing ${pid}..."
kill \${pid}
done
EOF
chmod +x /etc/initramfs-tools/scripts/local-bottom/kill_dropbear_connections
#
#Add an unlock script and autostart it because I keep forgetting the command I'm supposed to type
#
cat << DONE > /etc/initramfs-tools/hooks/crypt_unlock.sh
#!/bin/sh
PREREQ="dropbear"
prereqs() {
echo "\$PREREQ"
}
case "\$1" in
prereqs)
prereqs
exit 0
;;
esac
. "\${CONFDIR}/initramfs.conf"
. /usr/share/initramfs-tools/hook-functions
if [ "\${DROPBEAR}" != "n" ] && [ -r "/etc/crypttab" ] ; then
#run unlock on ssh login
echo unlock>>"\${DESTDIR}/etc/profile"
#write the unlock script
cat > "\${DESTDIR}/bin/unlock" << EOF
#!/bin/sh
# Read passphrase
read_pass()
{
# Disable echo.
stty -echo
# Set up trap to ensure echo is enabled before exiting if the script
# is terminated while echo is disabled.
trap 'stty echo' EXIT SIGINT
# Read passphrase.
read "\\\$@"
# Enable echo.
stty echo
trap - EXIT SIGINT
# Print a newline because the newline entered by the user after
# entering the passcode is not echoed. This ensures that the
# next line of output begins at a new line.
echo
}
printf "Enter passphrase: "
read_pass password
echo "\\\$password" >/lib/cryptsetup/passfifo
EOF
chmod +x "\${DESTDIR}/bin/unlock"
echo On successful unlock this ssh-session will disconnect. >> \${DESTDIR}/etc/motd
echo Run \"unlock\" to get passphrase prompt back if you end up in the shell. >> \${DESTDIR}/etc/motd
fi
DONE
chmod +x /etc/initramfs-tools/hooks/crypt_unlock.sh
update-initramfs -u -k $(uname -r)
echo "************************************************************************"
echo "DONE!"
echo
echo "Copy /etc/dropbead-initramfs/id_rsa to your local machine."
echo "This is the private key you need to log into dropbear (no password, root@machinename)."
echo "A better option is to add your own public key to /etc/dropbear-initramfs/authorized_keys and rerun update-initramfs -u -k \`uname -r\`"
echo
echo "Make sure you have a safe boot option before rebooting."
echo "************************************************************************"