Skip to content

Instantly share code, notes, and snippets.

@pepa65
Created August 9, 2016 08:12
Show Gist options
  • Save pepa65/8dad347b993667de3b9b6235189831a8 to your computer and use it in GitHub Desktop.
Save pepa65/8dad347b993667de3b9b6235189831a8 to your computer and use it in GitHub Desktop.
Unlocking LUKS encrypted root filesystems on boot remotely through dropbear ssh for Ubuntu 16.04 and 14.04
#!/bin/bash
## Unlocking LUKS with cryptsetup by entering a password through ssh
#### For Ubuntu 16.04.1 and friends or Ubuntu 14.04.5
### Areas of modification:
## 1. Start networking early: /etc/default/grub
## 2. Install dropbear
## 3. Modify initramfs: /etc/initramfs-tools
## a. Add ssh-keys: /etc/initramfs-tools/root/.ssh/authorized_keys
## b. Add files for unlocking: .profile, unlock & lib: /etc/initramfs-tools/scripts/init-premount
## c. Enable: /etc/initramfs-tools/modules /etc/initramfs-tools/initramfs.conf
## 4. Rebuild initramfs
### Initial settings
## Choose port and IP-address
## (IP-address reachable from the router; router WAN IP known [fixed/DDNS])
## (Port and IP-address need to be forwarded from the WAN port on the router!)
p=2222
i=192.168.3.9
## Network device (if not filled in will attempt to find)
n=
## Ubuntu edition (1: Ubuntu 16.04.1, 0: Ubuntu 14.04.5)
u=1
((u)) && e='Ubuntu 16.04.1' || e='Ubuntu 14.04.5'
## Find network device
s=/sys/devices/*/*/*/net
[[ $s = '/sys/devices/*/*/*/net' ]] && s=/sys/devices/*/*/net
[[ -z $n ]] && n=$(ls $s |grep '^[^w/]')
[[ -z $n ]] && echo "No suitable network devices found" && exit 1
(($(wc -l <<<"$n")>1)) && echo "Select network device by number:" && n=$(select d in $n; do echo $d; break; done)
echo "$e will ask for unlock by ssh to $i port $p on network device $n"
read -p 'OK (Enter) or Ctrl-C to stop '
### 1. Start networking early: /etc/default/grub
## Add ip= kernel parameter to GRUB_CMDLINE_LINUX in /etc/default/grub
## (ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>)
### Ubuntu 16.04.1: dhcp; Ubuntu 14.04.5: set IP address
((u)) && s='ip=dhcp' || s="ip=$i:::::$n:none"
f=/etc/default/grub
sed -i "s@^GRUB_CMDLINE_LINUX=\"\([^\"]\)@GRUB_CMDLINE_LINUX=\"$s,\1@" "$f"
sed -i "s@^GRUB_CMDLINE_LINUX=\"\"@GRUB_CMDLINE_LINUX=\"$s\"@" "$f"
update-grub
## 2. Install dropbear
## (If apt never ran before, do 'apt update' first)
((u)) && apt install dropbear-initramfs || apt install dropbear
## No dropbear in normal runlevels
! ((u)) && update-rc.d -f dropbear remove
## 3. Modify initramfs
## 3a. Add ssh-keys
## Make additional directories
mkdir -p /etc/initramfs-tools/root/.ssh
echo "Paste the contents of the client's ~/.ssh/id_rsa.pub:"
read -e && echo $REPLY >>/etc/initramfs-tools/root/.ssh/authorized_keys
## 3b. Add files for unlocking
## Create the needed files at the end of starting dropbear
f=/etc/initramfs-tools/scripts/init-premount/dropbear
if ! ((u))
then
cp /usr/share/initramfs-tools/scripts/init-premount/dropbear "$f"
sed -i "s@^/sbin/dropbear@/sbin/dropbear -p $p -s@' "$f"
fi
cat <<\END >>"$f"
cat <<\EOF >"$DESTDIR/bin/unlock"
#!/bin/sh
if PATH=/lib/unlock:/bin:/sbin /scripts/local-top/cryptroot
then
kill `ps |grep cryptroot |grep -v 'grep' |awk '{print $1}'`
exit 0
fi
exit 1
EOF
chmod 755 "$DESTDIR/bin/unlock"
mkdir -p "$DESTDIR/lib/unlock"
cat <<\EOF >"$DESTDIR/lib/unlock/plymouth"
#!/bin/sh
[ "$1" == "--ping" ] && exit 1
/bin/plymouth "$@"
EOF
chmod 755 "$DESTDIR/lib/unlock/plymouth"
END
((u)) && f=/etc/initramfs-tools/root/.profile
cat <<\EOF >>"$f"
trap "p=`ps |grep ' -sh ' |grep -v 'grep' |awk '{print $1}'`; [ -z $p ] || kill -9 $p" 1 2 3 4 6 8 9 11 13 14 15
/bin/unlock
exit 0
EOF
## 3c. Enable
## Add the network driver to /etc/initramfs-tools/modules
echo $(d=$(readlink /sys/class/net/$n/device/driver/module); echo ${d##*/}) >>"/etc/initramfs-tools/modules"
f=/etc/initramfs-tools/initramfs.conf
sed -i "s@^DEVICE=@DEVICE=$n@" "$f"
((u)) && echo -e "DROPBEAR=y\nDROPBEAR_OPTIONS='-p $p -s'" >>"$f"
## 4. Rebuild initramfs
update-initramfs -u
@BinaryShrub
Copy link

Thanks for the post! Couple of problems:

  • without defining n the script didnt work for me on 16.04 I got an ls /sys/devices///net issue
  • line 111 and 112 didnt work for me, I had to do it manually.

Other than that, I can verify that this worked for me on 16.04.1 with LUKS on LVM on RAID5

@GGerikP
Copy link

GGerikP commented May 8, 2018

Thanks for this. You've got a typo on line 72: an imbalance of the quotation marks. The first is a double quote and the second is a single quote after the @ symbol.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment