-
Notifications
You must be signed in to change notification settings - Fork 0
/
dropbear
388 lines (329 loc) · 12.5 KB
/
dropbear
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
#!/bin/sh
# add dropbear to the initrd to be able to mount crypto partitions from remote
PREREQ=""
prereqs()
{
echo "${PREREQ}"
}
case "${1}" in
prereqs)
prereqs
exit 0
;;
esac
# Begin real processing below this line
# Original copyright Wulf Coulmann
# 2010-2014 (c) Matthias Bücher
# GNU GPL
# http://www.gnu.org/licenses/gpl.html
#
# Download me here: http://gpl.coulmann.de/dropbear -or- https://github.com/maddes-b/luks-setup-via-ssh
# get infos about this script here:
# http://gpl.coulmann.de/ssh_luks_unlock.html
#
# version 1.0.2 by Matthias "Maddes" Bücher
#
# Read the script completely and thoroughly.
# Search for "CHECK HERE" to find the most important configuration stuff.
#
# The following Debian releases were tested:
# 4.0r9 with version 1.0.2 (incl. DHCP, mdadm, lvm)
# 5.0.8 with version 1.0.1 (incl. DHCP)
# 6.0.2 with version 1.0.1 (incl. DHCP)
# 4.0r7 with version 0.8a
# 5.0.0 with version 0.8a (incl. DHCP)
#
# To test this hook script use: mkinitramfs -o /tmp/initrd-dropbear-test
# With the -k option you can also investigate the temporary directory used to make the image
#
# Changelog 1.0.2 - "after life"
# - corrected prereqs for cryptroot_block that it is executed at last but before cryptroot, so mdadm and lvm work too
#
# Changelog 1.0.1 - "final, over and out"
# - check for Debian-based OS
# - allow full script to run for Debian up to 5.0 "Lenny"
# - added solution for 6.0 "Squeeze" (scripts: unlock, rm_dropbear), so users do not get logged out during upgrade
# - marked all interesting config stuff with CHECK HERE
# - adopted copying DropBear stuff from Debian 6.0 "Squeeze" to get rid of possible exposure of SSH private data
# use separate config and keys from /etc/initramfs-tools/etc/dropbear if available
#
# Changelog 1.0
# - This initrd hook is deprecated since Debian 6.0 "Squeeze". It will not be maintaind anymore.
# Debian has its native solution now, see /usr/share/doc/cryptsetup/README.remote.gz
#
# Changelog 0.9.1:
# - add /lib/libnsl.so.1 (thanks Gijs)
#
# Changelog 0.9a:
# - further code clean-up
#
# Changelog 0.9:
# - added quotes to ${INPUT}
#
# Changelog 0.8a:
# - changes from german c't magazine, 12/2008, S.188, article "Fernverschluesselt: Verschluesselte Root-Partition fuer Linux-Systeme":
# - /usr/bin creation
# - copy urandom seed
# - copy only root password from /etc/shadow
# - use more significant marker __EOF
# - changes from Maddes.net, 2009-02-18:
# - merged c't changes into version 0.8
# - added mkdir commands to make it work with Debian 4.0
# - added commands for DHCP to make it work with Debian 5.0
# - default to DHCP
# - explicitly stated variables ${}
# - added comments about disabling passwort logins for ssh and empty /etc/shadow
# - fixed typos
# - tested functionality with Debian 4.0r7 and 5.0r0
# check for Debian-based OS and its Debian version
[ ! -f '/etc/debian_version' ] && {
echo "ERROR: initrd hook ${0} is intended for Debian and its derivates only."
exit 72
}
VERSIONBYNAME=0
[ -f '/etc/issue' ] && grep -q -F -e 'Ubuntu' /etc/issue && VERSIONBYNAME=1
[ ${VERSIONBYNAME} -eq 0 ] && DEBVERSION=`cut -f 1 -d '.' /etc/debian_version`
[ ${VERSIONBYNAME} -ne 0 ] && {
DEBRELEASE=`cut -f 1 -d '/' /etc/debian_version`
DEBVERSION=99 ; # Debian version unsupported (like squeeze) or untested (like sarge, woody, potato, slink, hamm)
[ "${DEBRELEASE}" = "etch" ] && DEBVERSION=4
[ "${DEBRELEASE}" = "lenny" ] && DEBVERSION=5
}
# script for Debian 4/5 and also 6
# make sure to exit dropbear at the end of the InitRD startup process
[ -d "${DESTDIR}/scripts/local-bottom/" ] || mkdir -p "${DESTDIR}/scripts/local-bottom/"
cat > "${DESTDIR}/scripts/local-bottom/rm_dropbear" << '__EOF'
#!/bin/sh
PREREQ=""
prereqs()
{
echo ""
}
case "${1}" in
prereqs)
prereqs
exit 0
;;
esac
# Begin real processing below this line
# kill dropbear ssh server
killall dropbear
__EOF
chmod 700 "${DESTDIR}/scripts/local-bottom/rm_dropbear"
[ "${DEBVERSION}" -ge 6 ] && {
printf '\a'
echo "WARN: initrd hook ${0} is deprecated since Debian 6.0 \"Squeeze\"."
echo ' It still works for Debian 6.0, so it can be used as a temporary solution'
echo ' during an upgrade.'
echo ' '
echo ' Debian has its native solution now, see /usr/share/doc/cryptsetup/README.remote.gz'
echo ' and https://www.maddes.net/software/luks.htm.'
echo " Please deactivate ${0} by removing it and re-create the initrd again."
echo ' '
echo ' If you are currently upgrading to 6.0, then before upgrading kernel and udev'
echo ' make sure to clean up /etc/initramfs/hooks/ and /etc/initramfs/scripts/'
echo ' from old cryptroot and udev stuff. Maybe add new hooks and scripts for unlocking'
echo ' encrypted root remotely, see https://www.maddes.net/software/luks.htm.'
echo ' Then re-create the initrd again.'
echo ' DO NOT REBOOT UNTIL YOU ARE SURE THAT YOU HAVE DONE ALL COMPLETELY.'
[ -d "${DESTDIR}/usr/bin/" ] || mkdir -p "${DESTDIR}/usr/bin/"
cat > "${DESTDIR}/usr/bin/unlock" << '__EOF'
#!/bin/sh
/lib/cryptsetup/askpass "Enter volume password: " > /lib/cryptsetup/passfifo
__EOF
chmod 700 "${DESTDIR}/usr/bin/unlock"
exit 0
}
# load the prepared functions of Debian's initramfs environment
. "${CONFDIR}/initramfs.conf"
. /usr/share/initramfs-tools/hook-functions
#
if [ -e /etc/initramfs-tools/conf.d/dropbear ]; then
. /etc/initramfs-tools/conf.d/dropbear
fi
# Install dropbear if explicitly enabled, or in case of a cryptroot setup if not explicitly disabled
if [ "${DROPBEAR}" = "y" ] || ( [ "${DROPBEAR}" != "n" ] && [ -r "/etc/crypttab" ] ); then
true # do nothing
else
exit 0
fi
# build the directories
DIRS='/usr/sbin/ /usr/bin/ /proc/ /root/.ssh/ /var/ /var/lib/ /var/lib/urandom/ /var/run/'
for now in ${DIRS} ; do
if [ ! -d "${DESTDIR}${now}" ] ; then
mkdir -p "${DESTDIR}${now}"
fi
done
# copy the main ssh-daemon including libaries
copy_exec /usr/sbin/dropbear /usr/sbin/
copy_exec /usr/bin/passwd /usr/bin/
copy_exec /bin/login /bin/
copy_exec /sbin/dhclient /sbin/
copy_exec /sbin/dhclient-script /sbin/
cp -pr /etc/dhcp3/ "${DESTDIR}/etc/"
cp -pr /var/lib/dhcp3 "${DESTDIR}/var/lib/"
# some libraries are not autoincluded by copy_exec
cp /lib/libnss_* "${DESTDIR}/lib/"
copy_exec /etc/ld.so.cache /etc/
copy_exec /lib/libnsl.so.1 /lib/
# copy ssh-daemon config and host key files
if [ -d /etc/initramfs-tools/etc/dropbear/ ]; then
cp -pr /etc/initramfs-tools/etc/dropbear "${DESTDIR}/etc/"
elif [ -d /etc/dropbear/ ]; then
cp -pr /etc/dropbear "${DESTDIR}/etc/"
echo "dropbear: WARNING: host keys of encrypted root exposed in initrd"
echo "dropbear: WARNING: If host keys of encrypted root should not be exposed (recommended), then create new host keys in /etc/initramfs-tools/etc/dropbear/"
else
echo "dropbear: ERROR: /etc/dropbear not found, neither directly or in /etc/initramfs-tools, remote unlocking of cryptroot via ssh won't work!"
fi
for keytype in 'dss' 'rsa'; do
if [ ! -f "${DESTDIR}/etc/dropbear/dropbear_${keytype}_host_key" ]; then
echo "dropbear: ERROR: ${keytype} host key not found, remote unlocking of cryptroot via ssh won't work!"
fi
done
# copy user config files
cp -pr /etc/passwd "${DESTDIR}/etc/" # quick and dirty, to keep file attributes
cp -pr /etc/shadow "${DESTDIR}/etc/" # quick and dirty, to keep file attributes
cp -pr /etc/group "${DESTDIR}/etc/"
# only have the root account with a changed shell and no password (all other users are left out)
echo "root:x:0:0:root:/root:/bin/sh" > "${DESTDIR}/etc/passwd"
echo "root:!:0:0:99999:7:::" > "${DESTDIR}/etc/shadow"
# CHECK HERE
# copy password of root account
# if password logins via ssh are forbidden (dropbear option -s)
# then do not copy /etc/shadow here, as the initrd is not encrypted
grep -G -e "^root" < /etc/shadow > "${DESTDIR}/etc/shadow"
# copy authorized_keys file for root
chmod go=-s "${DESTDIR}/root/.ssh/"
if [ -f /etc/initramfs-tools/root/.ssh/authorized_keys ]; then
cp -p /etc/initramfs-tools/root/.ssh/authorized_keys "${DESTDIR}/root/.ssh/"
echo "dropbear: INFO: make sure that the entries in /etc/initramfs-tools/root/.ssh/authorized_keys are complete."
elif [ -f /root/.ssh/authorized_keys ]; then
cp -p /root/.ssh/authorized_keys "${DESTDIR}/root/.ssh/"
fi
if [ ! -s "${DESTDIR}/root/.ssh/authorized_keys" ]; then
echo "dropbear: WARNING: no or empty authorized_keys file. it is recommended to use public key authorization and disable passwords."
fi
# copy misc config files
cp -pr /etc/nsswitch.conf "${DESTDIR}/etc/"
cp -pr /etc/localtime "${DESTDIR}/etc/"
cp -pr /var/lib/urandom/random-seed "${DESTDIR}/var/lib/urandom/"
# there is no bash in the created initrd, so create a link to sh for it
ln -s /bin/sh "${DESTDIR}/bin/bash"
# missing stuff for DHCP
# --> already inside busybox and working
ln -s /bin/busybox "${DESTDIR}/bin/hostname"
ln -s /bin/busybox "${DESTDIR}/bin/ifconfig"
ln -s /bin/busybox "${DESTDIR}/bin/mv"
ln -s /bin/busybox "${DESTDIR}/bin/rm"
ln -s /bin/busybox "${DESTDIR}/bin/route"
# --> extras where busybox is not compatible/working
copy_exec /bin/chmod /bin/
copy_exec /bin/chown /bin/
copy_exec /bin/run-parts /bin/
# --> libraries
copy_exec /lib/libncurses.so.5 /lib/
# the blocker script to request input action before running cryptroot
# this let us run cryptroot on the local terminal and also inside ssh
# dirty but effective
[ -d "${DESTDIR}/scripts/local-top/" ] || mkdir -p "${DESTDIR}/scripts/local-top/"
cat > "${DESTDIR}/scripts/local-top/cryptroot_block" << '__EOF'
#!/bin/sh
PREREQ='network_ssh'
#
# Standard initramfs preamble
#
prereqs()
{
# Make sure that cryptroot_block is run last in local-top, but before cryptroot
PREREQ='network_ssh'
for REQ in /scripts/local-top/*
do
SCRIPT=$(basename ${REQ})
if [ "${SCRIPT}" != 'cryptroot' -a "${SCRIPT}" != 'cryptroot_block' ]; then
PREREQ="${PREREQ} ${SCRIPT}"
fi
done
echo "${PREREQ}"
}
case "${1}" in
prereqs)
prereqs
exit 0
;;
esac
# Begin real processing below this line
echo Type "ok" and press enter to put in passphrase:
INPUT='wait'
while [ "${INPUT}" != 'ok' ] ; do
read INPUT
done
__EOF
chmod 700 "${DESTDIR}/scripts/local-top/cryptroot_block"
[ -d "${DESTDIR}/scripts/local-top/" ] || mkdir -p "${DESTDIR}/scripts/local-top/"
cat > "${DESTDIR}/scripts/local-top/network_ssh" << '__EOF'
#!/bin/sh
# start network and ssh server
PREREQ=""
prereqs()
{
echo "${PREREQ}"
}
case "${1}" in
prereqs)
prereqs
exit 0
;;
esac
# Begin real processing below this line
# build up helpful environment
[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir --mode=0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
mount -t sysfs -o nodev,noexec,nosuid none /sys
mount -t proc -o nodev,noexec,nosuid none /proc
mkdir /dev/pts
mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts
# CHECK HERE
# network setup: edit ip address, mask and gateway to the server's needs
#ifconfig eth0 192.168.1.10 netmask 255.255.255.0
#route add default gw 192.168.1.100
# to configure via dhcp make sure to include dhclient or pump in
# /etc/initramfs-tools/hooks/dropbear via
# copy_exec /sbin/dhclient /sbin/
ifconfig eth0 up
/sbin/dhclient eth0
# CHECK HERE
# for debugging the ssh server force it to the foreground
# /usr/sbin/dropbear -E -F -b /etc/dropbear/banner
# for more debugging run it with strace
# therefore include strace and nc at top of
# /etc/initramfs-tools/hooks/dropbear via
# copy_exec /usr/bin/strace
# copy_exec /bin/nc
# then start nc on another host and run
# strace -f /usr/sbin/dropbear -E -F 2>&1 | /bin/nc -vv <ip of other host> <nc port of other host>
# e.g.:
# strace -f /usr/sbin/dropbear -E -F 2>&1 | /bin/nc -vv 192.168.1.2 8888
# CHECK HERE
# to forbid password logins via ssh use -s
# then also empty /etc/shadow above, as the initrd is not encrypted
/usr/sbin/dropbear -b /etc/dropbear/banner
__EOF
chmod 700 "${DESTDIR}/scripts/local-top/network_ssh"
[ -d "${DESTDIR}/etc/dropbear/" ] || mkdir -p "${DESTDIR}/etc/dropbear/"
cat > "${DESTDIR}/etc/dropbear/banner" << '__EOF'
To unlock root-partition run
unlock
__EOF
# script to unlock luks via ssh
# dirty but effective
[ -d "${DESTDIR}/usr/bin/" ] || mkdir -p "${DESTDIR}/usr/bin/"
cat > "${DESTDIR}/usr/bin/unlock" << '__EOF'
#!/bin/sh
/bin/sh /scripts/local-top/cryptroot && mv /scripts/local-top/cryptroot /root && kill `ps | grep -F -e 'cryptroot_block' | grep -v -F -e 'grep' | awk '{ print $1 }'`
__EOF
chmod 700 "${DESTDIR}/usr/bin/unlock"