├── 60dropbear-sshd ├── auth.c ├── console_peek.sh └── module-setup.sh ├── COPYING └── README.md /60dropbear-sshd/auth.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | // Based on: 10 | // https://bugzilla.redhat.com/show_bug.cgi?id=524727 11 | // http://roosbertl.blogspot.de/2012/12/centos6-disk-encryption-with-remote.html 12 | 13 | const char *prompt="Passphrase: "; 14 | 15 | int main (int argc, const char * argv[]) { 16 | char *passphrase; 17 | int i; 18 | 19 | int fd = open("/dev/console", O_RDONLY); 20 | if (fd < 0) return 2; 21 | 22 | passphrase = getpass(prompt); 23 | 24 | for (const char * str = passphrase; *str; ++str) ioctl(fd, TIOCSTI, str); 25 | ioctl(fd, TIOCSTI, "\r"); 26 | 27 | // clear string immediately 28 | int len = strlen(passphrase); 29 | for (i=0;i/dev/null 2>&1\ 58 | || { dfatal "dropbearconvert failed"; rm -rf "$tmp"; return 255; } 59 | } 60 | 61 | local key_fp=$(ssh-keygen -l -f "${dropbear_rsa_key}".pub) 62 | local key_bb=$(ssh-keygen -B -f "${dropbear_rsa_key}".pub) 63 | dinfo "Boot SSH key parameters:" 64 | dinfo " fingerprint: ${key_fp}" 65 | dinfo " bubblebabble: ${key_bb}" 66 | inst "${dropbear_rsa_key}" /etc/dropbear/host_key 67 | 68 | [[ -z "${dropbear_acl}" ]] && dropbear_acl=/root/.ssh/authorized_keys 69 | inst "${dropbear_acl}" /root/.ssh/authorized_keys 70 | 71 | # glibc needs only /etc/passwd with "root" entry (no group or shadow), which 72 | # should be provided by 99base; /bin/sh will be run regardless of /etc/shells presence. 73 | # It can do without nsswitch.conf, resolv.conf or whatever other stuff it usually has. 74 | 75 | # Helper to safely send password to cryptsetup on /dev/console without echoing it. 76 | # Yeah, dracut modules shouldn't compile stuff, but I'm not packaging that separately. 77 | gcc -std=gnu99 -O2 -Wall "$moddir"/auth.c -o "$tmp"/auth 78 | inst "$tmp"/auth /bin/console_auth 79 | 80 | # Generate hooks right here, with parameters baked-in 81 | [[ -z "${dropbear_port}" ]] && dropbear_port=2222 82 | cat >"$tmp"/sshd_run.sh </dev/null || { 86 | info 'sshd port: ${dropbear_port}' 87 | info 'sshd key fingerprint: ${key_fp}' 88 | info 'sshd key bubblebabble: ${key_bb}' 89 | /sbin/dropbear -E -m -s -j -k -p ${dropbear_port}\ 90 | -r /etc/dropbear/host_key -d - -P /tmp/dropbear.pid 91 | [ \$? -gt 0 ] && info 'Dropbear sshd failed to start' 92 | } 93 | EOF 94 | cat >"$tmp"/sshd_kill.sh </dev/null 99 | pkill -P \${main_pid} 100 | kill \${main_pid} 2>/dev/null 101 | kill -CONT \${main_pid} 2>/dev/null 102 | EOF 103 | chmod +x "$tmp"/sshd_{run,kill}.sh 104 | inst_hook initqueue 20 "$tmp"/sshd_run.sh 105 | inst_hook cleanup 05 "$tmp"/sshd_kill.sh 106 | 107 | rm -rf "$tmp" 108 | return 0 109 | } 110 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Except for separate parts that are copy-pasted from open nets 2 | (see links in comments) and can be under any license... 3 | 4 | 5 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 6 | Version 2, December 2004 7 | 8 | Copyright (C) 2012 Mike Kazantsev 9 | 10 | Everyone is permitted to copy and distribute verbatim or modified 11 | copies of this license document, and changing it is allowed as long 12 | as the name is changed. 13 | 14 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 15 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 16 | 17 | 0. You just DO WHAT THE FUCK YOU WANT TO. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | dracut-crypt-sshd 2 | -------------------- 3 | 4 | **Deprecation notice**: there is a much improved and generalized version of this 5 | module, maintained at [dracut-crypt-ssh/dracut-crypt-ssh](https://github.com/dracut-crypt-ssh/dracut-crypt-ssh/). 6 | This project here is mostly for historical reasons. 7 | 8 | [Dracut initramfs](https://dracut.wiki.kernel.org/index.php/Main_Page) module 9 | to start [Dropbear sshd](https://matt.ucc.asn.au/dropbear/dropbear.html) 10 | on early boot to enter encryption passphrase from across the internets or just 11 | connect and debug whatever stuff there. 12 | 13 | Idea is to use the thing on remote VDS servers, where full-disk encryption is 14 | still desirable (if only to avoid data leaks when disks will be decomissioned 15 | and sold by VDS vendor) but rather problematic due to lack of KVM or whatever 16 | direct console access. 17 | 18 | Authenticates users strictly by provided authorized_keys ("dropbear_acl" option) file. 19 | 20 | See dropbear(8) manpage for full list of supported restrictions there (which are 21 | fairly similar to openssh). 22 | 23 | 24 | ### Obligatory warning 25 | 26 | Please think about your 27 | [threat model](https://en.wikipedia.org/wiki/Threat_model) first, 28 | and security/usability trade-off second. 29 | 30 | This module is very unlikely to help at all against malicious hosting provider 31 | or whatever three-letter-agency that will coerce it into cooperation, should it 32 | take interest in your poor machine - they can just extract keys from RAM image 33 | (especially if it's a virtualized container), backdoor kernel/initramfs and 34 | force a reboot, or do whatever else to get encryption keys via hardware/backdoor. 35 | 36 | It can help, as mentioned, against attacks on the data after you're done with it 37 | completely (i.e. shut the machine/container in question down for good), or 38 | against rather clumsy and incompetent "power off first and think second" 39 | attacks. 40 | 41 | If this benefit is worth the hassle of this extra ssh'ing, some maintenance 42 | overhead and the possibility of loosing the LUKS key/header (and all access to 43 | data with it), only then (I think) this module might be useful to you. 44 | 45 | Please also check out "Bad Things" section below before use. 46 | 47 | 48 | ### Usage 49 | 50 | First of all, it needs dropbear (at least its sshd, I tested only version built 51 | without pam support, both static and shared should work) and gcc installed (to 52 | build auth.c tool). 53 | 54 | - Copy or symlink `60dropbear-sshd` into `/usr/lib/dracut/modules.d/`. 55 | 56 | - Add `dracutmodules+="dropbear-sshd"` to dracut.conf 57 | (will pull in "network" module as dependency). 58 | 59 | - Check out supported dracut.conf options below. 60 | With no extra options, ad-hoc server rsa key will be generated (and its 61 | fingerprint/bbcode will be printed to dracut log), 62 | `/root/.ssh/authorized_keys` will be used for ACL. 63 | 64 | - See dracut.cmdline(7) manpage for info on how to setup "network" module 65 | (otherwise sshd is kinda useless). 66 | 67 | Simpliest way might be just passing `ip=dhcp rd.neednet=1` on cmdline, if dhcp 68 | can assign predictable ip and pass proper routes. 69 | 70 | Example of luks (uuid starts with "7a476ea0") + lvm (vg named "lvmcrypt", with lv 71 | there having fs with "root" label) + static-net (see manpage above for syntax) 72 | grub.cfg entry (wrapped for readability): 73 | 74 | menuentry "My Linux" { 75 | linux /vmlinuz ro root=LABEL=root 76 | rd.luks.uuid=7a476ea0 rd.lvm.vg=lvmcrypt rd.neednet=1 77 | ip=88.195.61.177::88.195.61.161:255.255.255.224:myhost:enp0s9:off 78 | initrd /dracut.xz 79 | } 80 | 81 | - Run dracut to build initramfs with the thing. 82 | 83 | 84 | On boot, sshd will be started with: 85 | 86 | - Port: ${dropbear_port} (dracut.conf) or 2222 (default). 87 | 88 | - User (to allow login as-): root 89 | 90 | - Host key: ${dropbear_rsa_key} (dracut.conf) or generated 91 | (fingerprint echoed during generation and to console on sshd start). 92 | DSA keys are not supported (and shouldn't generally be used with ssh). 93 | 94 | - Client key(s): ${dropbear_acl} (dracut.conf) or `/root/.ssh/authorized_keys` 95 | 96 | - Password auth and port forwarding explicitly disabled. 97 | 98 | Dropbear should echo a few info messages on start (unless rd.quiet or similar 99 | options are used) and print host ssh key fingerprint to console, as well as any 100 | logging (e.g. errors, if any) messages. 101 | 102 | Do check the fingerprints either by writing them down on key generation, console 103 | or through network perspectives at least. 104 | 105 | 106 | To login: 107 | 108 | % ssh -p2222 root@some.remote.host.tld 109 | 110 | Shell is /bin/sh, which should be 111 | [dash](http://gondor.apana.org.au/~herbert/dash/) in most dracut builds, but can 112 | probably be replaced with ash (busybox) or bash (heavy) using appropriate modules. 113 | 114 | 115 | Once inside: 116 | 117 | ```console 118 | 119 | % console_peek # to see what's on the console (e.g. which dev prompt is for) 120 | ... 121 | % console_auth # queries passphrase and sends it to console 122 | Passphrase: 123 | % 124 | ``` 125 | 126 | Boot should continue after last command, which should send entered passphrase to 127 | cryptsetup, waiting for it on the console, assuming its correctness. 128 | 129 | sshd should be killed during dracut "cleanup" phase, once main os init is about to run. 130 | Connection won't be closed, but nothing should work there, as initramfs gets destroyed. 131 | 132 | 133 | ### dracut.conf parameters 134 | 135 | - dropbear_port 136 | 137 | - dropbear_rsa_key 138 | 139 | - dropbear_acl 140 | 141 | See above. 142 | 143 | 144 | ### Common issues and non-issues 145 | 146 | - `Dropbear sshd failed to start` 147 | 148 | Only means what it says, see output of dropbear *before* it died - it should 149 | print some specific errors which led to it exiting like that. 150 | 151 | - `Failed reading '-', disabling DSS` 152 | 153 | Will *always* be printed and should be ignored - DSA keys are not generated/used 154 | in these scripts, and probably shouldn't be. 155 | 156 | - Host hangs in initramfs, but can't be pinged (e.g. `ping my.host.tld`) from outside. 157 | 158 | Either no network configuration parameters were passed to dracut, or it failed 159 | to configure at least one IP address. 160 | 161 | Don't forget `rd.neednet=1` on cmdline, as dracut will ignore specified network 162 | settings without nfs (or whatever net-) root otherwise. 163 | 164 | Read up dracut.cmdline(7), "Network" section and/or see why/if dracut failed to 165 | configure net as requested with `rd.debug`. 166 | See also "Debugging tips" section below. 167 | 168 | - Host pings, but ssh can't connect. 169 | 170 | Try `nc -v `, or "ncat" instead of "nc" there. 171 | "ncat" can be found in "nmap" package, "nc" usually comes pre-installed. 172 | 173 | If it hangs without printing "Connected to ..." line - can be some firewall 174 | before host or dropbear failed to start/listen. 175 | 176 | If there's no "SSH-2.0-dropbear_..." after "Connected to ..." line - some issue 177 | with dropbear. 178 | 179 | - `lastlog_perform_login: Couldn't stat /var/log/lastlog: No such file or directory` 180 | 181 | Pops up when logging in, can be safely ignored. 182 | 183 | 184 | ### Debugging tips 185 | 186 | If (or rather "when") something goes wrong and you can't access just-booted 187 | machine over network and can't get to console (hence sshd in initramfs), don't 188 | panic - it's fixable if machine can be rebooted into some rescue system 189 | remotely. 190 | 191 | Usually it's some dhcp+tftp netboot thing from co-located machine (good idea to 192 | setup/test in advance) plus whoever is there occasionally pushing the power 193 | button, or maybe some fancy hw/interface for that (e.g. hetzner "rescue" interface). 194 | 195 | To see what was going on during initramfs, open 196 | "modules.d/99base/rdsosreport.sh" in dracut, append this (to the end): 197 | 198 | set -x 199 | netstat -lnp 200 | netstat -np 201 | netstat -s 202 | netstat -i 203 | ip addr 204 | ip ro 205 | set +x 206 | 207 | exec >/dev/null 2>&1 208 | mkdir /tmp/myboot 209 | mount /dev/sda2 /tmp/myboot 210 | cp /run/initramfs/rdsosreport.txt /tmp/myboot/ 211 | umount /tmp/myboot 212 | rmdir /tmp/myboot 213 | 214 | Be sure to replace `/dev/sda2` with whatever device is used for /boot, rebuild 215 | dracut and add `rd.debug` to cmdline (e.g. in grub.cfg's "linux" line). 216 | 217 | Upon next reboot, *wait* for at least a minute, since dracut should give up on 218 | trying to boot the system first, then it will store full log of all the stuff 219 | modules run ("set -x") and their output in "/boot/rdsosreport.txt". 220 | 221 | Naturally, to access that, +1 reboot into some "rescue" system might be needed. 222 | 223 | In case of network-related issues - e.g. if "rdsosreport.txt" file gets created 224 | with "rd.debug", but host can't be pinged/connected-to for whatever reason - 225 | either enable "debug" dracut module or add `dracut_install netstat ip` line to 226 | `install()` section of "modules.d/60dropbear-sshd/module-setup.sh" and check 227 | "rdsosreport.txt" or console output for whatever netstat + ip commands above 228 | (for "rdsosreport.sh") show - there can be no default route, whatever interface 229 | naming mixup, no traffic (e.g. unrelated connection issue), etc. 230 | 231 | 232 | ### Bad Things 233 | 234 | - Has quite a few rather unnecessary assumptions about environment baked-in 235 | (e.g. `/lib/libnss_files.so.2` path), and does `gcc -std=gnu99 -O2 -Wall 236 | "$moddir"/auth.c -o "${tmp_file}"` for that "console_auth" binary on dracut 237 | run. 238 | 239 | Better way to handle these and compile whatever binaries would be allowing for 240 | proper `./configure && make && make install` process, which I don't know 241 | enough about to support. 242 | 243 | Luckily, there are people that do, check out these links for better integrated 244 | versions of a similar thing: 245 | 246 | * https://github.com/dracut-crypt-ssh/dracut-crypt-ssh/ 247 | * https://github.com/artem-sidorenko/dracut-earlyssh/ 248 | * https://github.com/haraldh/dracut/pull/43 249 | * https://github.com/mdcurtis/dracut-earlyssh 250 | * https://github.com/philfry/dracut-earlyssh 251 | 252 | - Only tested with customized source-based distro 253 | ([Exherbo](http://exherbo.org/)), no idea how easy it is to use with generic 254 | debian or ubuntu. 255 | 256 | - `check()` in module_setup.sh should probably not be empty no-op. 257 | 258 | - Should probably have `set -e` or something alike (dracut-specific?) in install(). 259 | 260 | - No idea how to sanely run `ssh-keygen` (openssh) from a script, maybe use 261 | openssl instead? 262 | 263 | 264 | ### Based on code, examples and ideas from 265 | 266 | - https://bugzilla.redhat.com/show_bug.cgi?id=524727 267 | - http://roosbertl.blogspot.de/2012/12/centos6-disk-encryption-with-remote.html 268 | - https://bitbucket.org/bmearns/dracut-crypt-wait 269 | --------------------------------------------------------------------------------