远程解锁加密硬盘
Remotely unlocking an encrypted hard disk

原始链接: https://jyn.dev/remotely-unlocking-an-encrypted-hard-disk/

该项目详细介绍了如何在Linux系统完全启动*之前*建立持久连接,具体解决了断电时连接丢失的问题。作者由于经常旅行期间遇到频繁断电和动态IP地址,寻求一种超越标准BIOS设置和Tailscale配置的解决方案。 核心思想是将Tailscale和SSH服务器(Dropbear)直接嵌入到`initramfs`中——一个在早期启动期间加载到RAM中的最小操作系统。这允许在解密根分区*之前*进行SSH访问,即使IP地址变化或家庭断电也能实现远程访问。 主要挑战包括保护`initramfs`环境(防止shell访问,管理密钥过期)和配置网络。解决方案包括使用Tailscale ACL限制访问,禁用密钥过期,将SSH限制为密码提示以进行解密,并利用`systemd-network`实现早期以太网连接。 该过程涉及修改`mkinitcpio.conf`以包含必要的钩子,生成专用的SSH密钥,以及重建`initramfs`镜像。最终,这允许在主操作系统加载之前,通过`hostname-initrd`访问系统,从而提供可靠的远程访问解决方案。

一个黑客新闻的讨论强调了一种新的远程解锁加密硬盘的方法(链接至 jyn.dev),解决了全盘加密 (FDE) 用户长期存在的需求。目前,常见的 Linux 解决方案是使用 `dracut-sshd` (github.com/gsauthof/dracut-sshd)。 该讨论将此与现有的第三方 Windows 工具(如 WinMagic)相提并论,这些工具利用在线身份验证在验证用户身份*之后*安全地提供解密密钥。这种方法将密钥与本地可信平台模块 (TPM) 分开。 用户指出,这项技术通常应用于高安全行业的设备中,特别是处理敏感生物识别数据的设备,并且可能涉及启动一个单独的 Linux 镜像来解锁 Bitlocker 分区,然后再将控制权交还给 Windows。
相关文章

原文

Your mission, should you choose to accept it, is to sneak into the earliest parts of the boot process, swap the startup config without breaking anything, and leave without a trace.

Are you ready? Let's begin.

the setup

In which our heroes are introduced, and the scene is set.

For a very long time I had a beat-up old ThinkPad that couldn’t hold a charge for the life of it, especially when running Windows. It tended to die a lot when I was traveling, and I travel a lot. To save battery when I’m away from home, I often ssh back into my home desktop, both so I have persistent state even if my laptop battery dies, and so I get much faster builds that don’t kill the battery.

This has two small problems:

  1. Sometimes my home loses power and the desktop shuts off.
  2. Sometimes when the power comes back on it has a new public IP.

For a long time I solved 1. by enabling “Power On" after "Restore AC Power Loss” in the BIOS and 2. with tailscale. However, I recently installed Arch with an encrypted boot partition, which means that boot doesn’t finish until I type in the encryption password.

Well. Well. What if I Simply put tailscale in initramfs?

the plan

In which our intrepid heroes chart the challenges to come.

initramfs

Oh, right. If you weren’t aware, early boot in a Linux operating system is just running a full second operating system that happens to be very small, lol. That’s loaded from a compressed archive file in /boot and run from memory, with no access to persistent storage. This OS running from memory is called initramfs (initial RAM filesystem).

So when you see a screen like this: That’s actually a whole-ass OS, with an init PID and service management and everything. This is how, for example, systemd-analyze can show you stats about early boot — there’s another copy of systemd running in initramfs, and it passes its state off to the one in the main OS.

Well. That implies we can install things on it ^^.

constraints

There’s three parts to this:

  1. Networking in initramfs
  2. Tailscale in initramfs
  3. SSH in initramfs

We also want to make this as secure as possible, so there’s some more things to consider:

  • Putting tailscale in initramfs means that it has unencrypted keys lying around.
  • Tailscale keys expire (by default) after 90 days. At that point this will all break.
  • You really really don’t want people to get SSH access to your early boot environment.

We can solve this in a few ways:

  • Use Tailscale ACLs to only allow incoming connections to initramfs, not outgoing connections.
  • Set the key to never expire.
  • Set the SSH server to disallow all shells except the actual unlock command (systemd-tty-ask-password-agent).

tailscale ACLs

Some background about Tailscale’s ACLs (“access control lists”). Tailscale’s users are tied to their specific login method: you can, for example, add a passkey, but that passkey counts as a fully separate user than your original account. Tailscale also has “groups” of users, which are what they sound like, “auto groups”, which again are what they sound like, “hosts”, which are a machine connected to the network, and “tags”.

Tags are odd, I haven't seen anything like them before. They group hosts, not users, and when you add a tag to a host, that counts as its login method, rather than the host being tied to a user account.

A consequence of this is that the group autogroup:member does not include tagged machines, because tagged machines aren’t tied to a user account. (A second consequence is that you can’t remove all tags from a machine without logging out and logging back in to associate it with your user account.)

So we can write a policy like this:

{
    "tagOwners": {
    "tag:initrd": ["autogroup:admin"],
  },

      "acls": [
    {"action": "accept", "src": ["autogroup:member"], "dst": ["*:*"]},
  ],

    "tests": [
    {
      "src":    "100.76.34.8",       "accept": ["100.102.101.127:22", "100.101.55.73:10078"],     },
    {
      "src":  "100.102.101.127",       "deny": ["100.101.55.73:10078"],     },
  ],
}

This says “allow devices tied to a user account to access any other device, and allow no permissions at all for devices tied to a tag”.

selene here is my desktop, and selene-initrd is its initramfs.

systemd before boot

Because initramfs is just a (mostly) normal Linux system, that means it has its own init PID 1. On Arch, that PID is in fact just systemd. That means that we can add systemd services to initramfs! There's a whole collection of them in mkinitcpio-systemd-extras (mkinitcpio is the tool Arch uses to regenerate initramfs).

We need two services: an SSH server (I went with dropbear) and something to turn on networking, which this collection names sd-network.

the heist

In which our heroes execute their plan flawlessly, sneaking in without a sound.

If you follow these steps on an Arch system, you should end up with roughly the same setup as I have. Most of these commands assume you are running as root.

  • Setup early networking. (Note: these instructions are only for Ethernet connections. If you want WiFi in early boot, good luck and godspeed.)

    1. Add the following config in /etc/systemd/network-initramfs/10-wired.network:
    [Match]
    Type=ether
    
    [Network]
    DHCP=yes
    
    1. Register it in /etc/mkinitcpio.conf so it gets picked up by the sd-network hook:
    SD_NETWORK_CONFIG=/etc/systemd/network-initramfs
    

    All this rigamarole is necessary because the OS doesn't set the network interfaces to predictable names until late boot, so it needs some way to know which interface to use.

  • Last but not least, rebuild your initramfs: mkinitcpio -P.

Next time you reboot, you should be able to ssh into $(hostname)-initrd and get a prompt that looks like this:

the getaway

In which a moral is imparted, and our scene concluded.

The takeaway here is the same as in all my other posts: if you think something isn't possible to do with a computer, have you considered applying more violence?

联系我们 contact @ memedata.com