Difference between revisions of "Remote disk unlocking"

From NixOS Wiki
Jump to: navigation, search
m (Wording: theses -> these)
m (rollback unauthorized mass edits)
Tag: Rollback
 
(18 intermediate revisions by 7 users not shown)
Line 1: Line 1:
= Unlocking your LUKS via SSH and Tor =
+
If you want to unlock your computer remotely via SSH or even through Tor, and you are facing the problem, that you can’t reach your computer before your computer is unlocked. Tor will help you to reach your computer, even during the boot process.
  
If you want to unlock your computer remotely, and you are facing the problem, that you can’t reach your computer before your computer is unlocked, Tor will help you to reach your computer, even during the boot process.
+
== Setup ==
  
== SSH in initrd ==
+
Generate host key for the SSH daemon which will run in initrd during boot
  
=== Prepare SSH host keys ===
+
<syntaxhighlight lang="bash">
 +
# ssh-keygen -t rsa -N "" -f /etc/secrets/initrd/ssh_host_rsa_key
 +
</syntaxhighlight>
  
It is very important that you create your SSH host keys upfront, otherwise you end up connecting to a server on the internet and typing in your disk encryption password without authenticating the machine on the remote end!
+
Enable SSH daemon in initrd
  
To create a hostkey run
+
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
 +
boot.kernelParams = [ "ip=dhcp" ];
 +
boot.initrd = {
 +
  availableKernelModules = [ "r8169" ];
 +
  systemd.users.root.shell = "/bin/cryptsetup-askpass";
 +
  network = {
 +
    enable = true;
 +
    ssh = {
 +
      enable = true;
 +
      port = 22;
 +
      authorizedKeys = [ "ssh-rsa AAAAyourpublic-key-here..." ];
 +
      hostKeys = [ "/etc/secrets/initrd/ssh_host_rsa_key" ];
 +
    };
 +
  };
 +
};
 +
</nowiki>}}
  
<pre>ssh-keygen -t rsa -N "" -f /etc/secrets/initrd/ssh_host_rsa_key</pre>
+
Adapt following parts according to your setup
  
or
+
* '''authorizedKeys''': Add the SSH public keys for the users which should be able to authenticate to the SSH daemon to the <code>authorizedKeys</code> option.
 +
* '''availableKernelModules''': Most likely your network card is not working without its kernel module being part of the initrd, so you have to find out which module is used for your network. Use <code>lspci -v | grep -iA8 'network\|ethernet'</code> for that.
 +
* '''kernelParams''': Instead of using DHCP you could also configure a static IP, for example with kernel parameter <code>boot.kernelParams = [ "ip=10.25.0.2::10.25.0.1:255.255.255.0:myhost::none" ];</code>, where <code>10.25.0.2</code> is the client IP, <code>10.25.0.1</code> is the gateway IP. See [https://www.kernel.org/doc/Documentation/filesystems/nfs/nfsroot.txt the kernel documentation] for more information on the <code>ip=</code> parameter. When using DHCP, make sure your computer is always attached to the network and is able to get an IP adress, or the boot process will hang.
  
<pre>ssh-keygen -t ed25519 -N "" -f /etc/secrets/initrd/ssh_host_ed25519_key</pre>
 
  
==== Known hosts ====
+
The <code>shell</code> option is necessary to get a password prompt instead of a shell.
 +
If you omit it, you will get dropped into <code>/bin/ash</code>, and you will have to manually run <code>cryptsetup-askpass</code> to enter the password. Alternatively, the <code>shell</code> option can be set to <code>/bin/conspy</code> for passwords which expect stdin. This binary included by default, and provided by busybox.
  
It’s a good idea to add the host key (which got printed during creation) to your known_hosts file e.g. <code>~/.ssh/known_hosts</code> or <code>services.openssh.knownHosts</code>.
+
== Usage ==
  
=== Set up SSH in initrd ===
+
After reboot, connect to the initrd SSH daemon using
  
Setting up ssh is very easy.
+
<syntaxhighlight lang="bash">
 +
# ssh root@10.25.0.2
 +
</syntaxhighlight>
  
<pre># ssh setup
+
Where <code>10.25.0.2</code> is the IP which is acquired via DHCP or configured via the kernel parameter.
boot.initrd.network.enable = true;
+
 
boot.initrd.network.ssh = {
+
== Tips and tricks ==
   enable = true;
+
 
   port = 22;
+
=== Bcachefs unlocking ===
  authorizedKeys = [ &quot;ssh-rsa AAAAyourpublic-key-here....&quot; ];
+
 
  hostKeys = [ "/etc/secrets/initrd/ssh_host_rsa_key" "/etc/secrets/initrd/ssh_host_ed25519_key" ];
+
Unlocking encrypted Bcachefs root filesystems is [https://github.com/NixOS/nixpkgs/issues/291529 not yet supported]. As a workaround, following script can be used as SSH shell, to unlock the disk <code>/dev/vda2</code>.
 +
 
 +
{{file|/etc/nixos/configuration.nix|nix|<nowiki>
 +
boot.initrd.systemd = let
 +
   askPass = pkgs.writeShellScriptBin "bcachefs-askpass" ''
 +
    keyctl link @u @s
 +
    mkdir /sysroot
 +
    until bcachefs mount /dev/vda2 /sysroot
 +
    do
 +
      sleep  1
 +
    done
 +
  '';
 +
   in {
 +
    enable = true;
 +
    initrdBin = with pkgs; [ keyutils ];
 +
    storePaths = ["${askPass}/bin/bcachefs-askpass"];
 +
    users.root.shell = "${askPass}/bin/bcachefs-askpass";
 +
  };
 
};
 
};
</pre>
+
</nowiki>}}
  
Most likely your network card is not working without its kernel module being part of the initrd, so you have to find out which module is used for your network. Use <code>lspci -v</code> for that.
+
Using systemd in initrd automatically continues the boot process after the target <code>/sysroot</code> is mounted.
  
<pre>boot.initrd.availableKernelModules = [ &quot;r8169&quot; ];</pre>
+
=== Tor in initrd ===
  
== Tor in initrd ==
+
An example with an ssh server listening at a tor hidden service address can be found at [https://cgit.euer.krebsco.de/stockholm/tree/krebs/2configs/tor/initrd.nix?id=9919cb25912dfcc50881239f95494dd2f8e7b858 krebs/2configs/tor/initrd.nix in stockholm]
  
=== Prepare the Onion ID ===
+
==== Prepare the Onion ID ====
  
 
You need 3 files to create an onion id (a.k.a. tor hidden service).
 
You need 3 files to create an onion id (a.k.a. tor hidden service).
Line 70: Line 108:
 
Hit <code>Ctrl-C</code> and the files you need, should be in <code>/home/tony/tor/onion</code>.
 
Hit <code>Ctrl-C</code> and the files you need, should be in <code>/home/tony/tor/onion</code>.
  
=== Setup Tor ===
+
==== Setup Tor ====
  
 
Now that you have your 3 files, you have to script a bit, but it’s not too complicated.
 
Now that you have your 3 files, you have to script a bit, but it’s not too complicated.
  
<pre># copy your onion folder
+
<syntaxhighlight lang="nix"># copy your onion folder
 
boot.initrd.secrets = {
 
boot.initrd.secrets = {
   &quot;/etc/tor/onion/bootup&quot; = /home/tony/tor/onion; # maybe find a better spot to store this.
+
   "/etc/tor/onion/bootup"; = /home/tony/tor/onion; # maybe find a better spot to store this.
 
};
 
};
  
Line 86: Line 124:
 
# start tor during boot process
 
# start tor during boot process
 
boot.initrd.network.postCommands = let
 
boot.initrd.network.postCommands = let
   torRc = (pkgs.writeText &quot;tor.rc&quot; ''
+
   torRc = (pkgs.writeText "tor.rc" ''
 
     DataDirectory /etc/tor
 
     DataDirectory /etc/tor
 
     SOCKSPort 127.0.0.1:9050 IsolateDestAddr
 
     SOCKSPort 127.0.0.1:9050 IsolateDestAddr
Line 94: Line 132:
 
   '');
 
   '');
 
in ''
 
in ''
   echo &quot;tor: preparing onion folder&quot;
+
   echo "tor: preparing onion folder"
 
   # have to do this otherwise tor does not want to start
 
   # have to do this otherwise tor does not want to start
 
   chmod -R 700 /etc/tor
 
   chmod -R 700 /etc/tor
  
   echo &quot;make sure localhost is up&quot;
+
   echo "make sure localhost is up"
 
   ip a a 127.0.0.1/8 dev lo
 
   ip a a 127.0.0.1/8 dev lo
 
   ip link set lo up
 
   ip link set lo up
  
   echo &quot;tor: starting tor&quot;
+
   echo "tor: starting tor"
 
   tor -f ${torRc} --verify-config
 
   tor -f ${torRc} --verify-config
   tor -f ${torRc} &amp;
+
   tor -f ${torRc} &
'';</pre>
+
'';</syntaxhighlight>
 
That was it. Tor should be running during your boot process.
 
That was it. Tor should be running during your boot process.
  
=== Setup haveged ===
+
==== Setup haveged ====
  
 
If your system doesn't gather enough entropy the startup time of tor is rather long (2:42 vs 0:06 on a RPi 4b). Counter it by starting <code>haveged</code>.
 
If your system doesn't gather enough entropy the startup time of tor is rather long (2:42 vs 0:06 on a RPi 4b). Counter it by starting <code>haveged</code>.
Line 117: Line 155:
 
</pre>
 
</pre>
  
Then use this snippet before <code>echo &quot;tor: starting tor&quot;</code> in your <code>boot.initrd.network.postCommands</code>.
+
Then use this snippet before <code>echo "tor: starting tor"</code> in your <code>boot.initrd.network.postCommands</code>.
 
<pre>
 
<pre>
 
       echo "haveged: starting haveged"
 
       echo "haveged: starting haveged"
Line 123: Line 161:
 
</pre>
 
</pre>
  
=== Setup ntpdate ===
+
==== Setup ntpdate ====
  
 
If your system doesn't utilize a RTC you've to ensure time is correctly set before startup of tor.
 
If your system doesn't utilize a RTC you've to ensure time is correctly set before startup of tor.
Line 132: Line 170:
 
</pre>
 
</pre>
  
Then use this snippet before <code>echo &quot;tor: starting tor&quot;</code> in your <code>boot.initrd.network.postCommands</code>.
+
Then use this snippet before <code>echo "tor: starting tor"</code> in your <code>boot.initrd.network.postCommands</code>.
 
<pre>
 
<pre>
 
       echo "ntp: starting ntpdate"
 
       echo "ntp: starting ntpdate"
Line 140: Line 178:
 
</pre>
 
</pre>
  
== Unlock your LUKS via SSH and Tor ==
+
==== Usage ====
  
 
When your computer boots, and asks for the LUKS password. Now you can unlock your encrypted Hard drive using:
 
When your computer boots, and asks for the LUKS password. Now you can unlock your encrypted Hard drive using:
  
<pre>torify ssh root@&lt;onion.id&gt;.onion -p 22 'echo &quot;my-secret-password&quot; &gt; /crypt-ramfs/passphrase'</pre>
+
<pre>torify ssh root@<onion.id>.onion -p 22 'my-secret-password'</pre>
 
 
== Example ==
 
An example with an ssh server listening at a tor hidden service address can be found at [https://cgit.euer.krebsco.de/stockholm/tree/krebs/2configs/tor/initrd.nix?id=9919cb25912dfcc50881239f95494dd2f8e7b858 krebs/2configs/tor/initrd.nix in stockholm]
 

Latest revision as of 11:01, 6 April 2024

If you want to unlock your computer remotely via SSH or even through Tor, and you are facing the problem, that you can’t reach your computer before your computer is unlocked. Tor will help you to reach your computer, even during the boot process.

Setup

Generate host key for the SSH daemon which will run in initrd during boot

# ssh-keygen -t rsa -N "" -f /etc/secrets/initrd/ssh_host_rsa_key

Enable SSH daemon in initrd

Breeze-text-x-plain.png
/etc/nixos/configuration.nix
boot.kernelParams = [ "ip=dhcp" ];
boot.initrd = {
  availableKernelModules = [ "r8169" ];
  systemd.users.root.shell = "/bin/cryptsetup-askpass";
  network = {
    enable = true;
    ssh = {
      enable = true;
      port = 22;
      authorizedKeys = [ "ssh-rsa AAAAyourpublic-key-here..." ];
      hostKeys = [ "/etc/secrets/initrd/ssh_host_rsa_key" ];
    };
  };
};


Adapt following parts according to your setup

  • authorizedKeys: Add the SSH public keys for the users which should be able to authenticate to the SSH daemon to the authorizedKeys option.
  • availableKernelModules: Most likely your network card is not working without its kernel module being part of the initrd, so you have to find out which module is used for your network. Use lspci -v | grep -iA8 'network\|ethernet' for that.
  • kernelParams: Instead of using DHCP you could also configure a static IP, for example with kernel parameter boot.kernelParams = [ "ip=10.25.0.2::10.25.0.1:255.255.255.0:myhost::none" ];, where 10.25.0.2 is the client IP, 10.25.0.1 is the gateway IP. See the kernel documentation for more information on the ip= parameter. When using DHCP, make sure your computer is always attached to the network and is able to get an IP adress, or the boot process will hang.


The shell option is necessary to get a password prompt instead of a shell. If you omit it, you will get dropped into /bin/ash, and you will have to manually run cryptsetup-askpass to enter the password. Alternatively, the shell option can be set to /bin/conspy for passwords which expect stdin. This binary included by default, and provided by busybox.

Usage

After reboot, connect to the initrd SSH daemon using

# ssh root@10.25.0.2

Where 10.25.0.2 is the IP which is acquired via DHCP or configured via the kernel parameter.

Tips and tricks

Bcachefs unlocking

Unlocking encrypted Bcachefs root filesystems is not yet supported. As a workaround, following script can be used as SSH shell, to unlock the disk /dev/vda2.

Breeze-text-x-plain.png
/etc/nixos/configuration.nix
boot.initrd.systemd = let
  askPass = pkgs.writeShellScriptBin "bcachefs-askpass" ''
    keyctl link @u @s
    mkdir /sysroot
    until bcachefs mount /dev/vda2 /sysroot
    do
      sleep  1
    done
  '';
  in {
    enable = true;
    initrdBin = with pkgs; [ keyutils ];
    storePaths = ["${askPass}/bin/bcachefs-askpass"];
    users.root.shell = "${askPass}/bin/bcachefs-askpass";
  };
};


Using systemd in initrd automatically continues the boot process after the target /sysroot is mounted.

Tor in initrd

An example with an ssh server listening at a tor hidden service address can be found at krebs/2configs/tor/initrd.nix in stockholm

Prepare the Onion ID

You need 3 files to create an onion id (a.k.a. tor hidden service).

  • hostname
  • hs_ed25519_public_key
  • hs_ed25519_secret_key

To create these files, you have to run tor once, with a dummy configuration.

DataDirectory /tmp/my-dummy.tor/
SOCKSPort 127.0.0.1:10050 IsolateDestAddr
SOCKSPort 127.0.0.1:10063
HiddenServiceDir /home/tony/tor/onion
HiddenServicePort 1234 127.0.0.1:1234

Let’s asume you created this file in /home/tony/tor/tor.rc.

Verify that everything is tor.rc awesome, by running tor -f /home/tony/tor/tor.rc --verify-config. If you don’t see any errors, just run tor -f /home/tony/tor/tor.rc.

You will get some output like this.

May 21 18:38:39.000 [notice] Bootstrapped 80% (ap_conn): Connecting to a relay to build circuits
May 21 18:38:39.000 [notice] Bootstrapped 85% (ap_conn_done): Connected to a relay to build circuits
May 21 18:38:39.000 [notice] Bootstrapped 89% (ap_handshake): Finishing handshake with a relay to build circuits
May 21 18:38:39.000 [notice] Bootstrapped 90% (ap_handshake_done): Handshake finished with a relay to build circuits
May 21 18:38:39.000 [notice] Bootstrapped 95% (circuit_create): Establishing a Tor circuit
May 21 18:38:40.000 [notice] Bootstrapped 100% (done): Done

Hit Ctrl-C and the files you need, should be in /home/tony/tor/onion.

Setup Tor

Now that you have your 3 files, you have to script a bit, but it’s not too complicated.

# copy your onion folder
boot.initrd.secrets = {
  "/etc/tor/onion/bootup"; = /home/tony/tor/onion; # maybe find a better spot to store this.
};

# copy tor to you initrd
boot.initrd.extraUtilsCommands = ''
  copy_bin_and_libs ${pkgs.tor}/bin/tor
'';

# start tor during boot process
boot.initrd.network.postCommands = let
  torRc = (pkgs.writeText "tor.rc" ''
    DataDirectory /etc/tor
    SOCKSPort 127.0.0.1:9050 IsolateDestAddr
    SOCKSPort 127.0.0.1:9063
    HiddenServiceDir /etc/tor/onion/bootup
    HiddenServicePort 22 127.0.0.1:22
  '');
in ''
  echo "tor: preparing onion folder"
  # have to do this otherwise tor does not want to start
  chmod -R 700 /etc/tor

  echo "make sure localhost is up"
  ip a a 127.0.0.1/8 dev lo
  ip link set lo up

  echo "tor: starting tor"
  tor -f ${torRc} --verify-config
  tor -f ${torRc} &
'';

That was it. Tor should be running during your boot process.

Setup haveged

If your system doesn't gather enough entropy the startup time of tor is rather long (2:42 vs 0:06 on a RPi 4b). Counter it by starting haveged.

Append in your boot.initrd.extraUtilsCommands.

  copy_bin_and_libs ${pkgs.haveged}/bin/haveged

Then use this snippet before echo "tor: starting tor" in your boot.initrd.network.postCommands.

      echo "haveged: starting haveged"
      haveged -F &

Setup ntpdate

If your system doesn't utilize a RTC you've to ensure time is correctly set before startup of tor.

Append in your boot.initrd.extraUtilsCommands.

  copy_bin_and_libs ${pkgs.ntp}/bin/ntpdate

Then use this snippet before echo "tor: starting tor" in your boot.initrd.network.postCommands.

      echo "ntp: starting ntpdate"
      echo "ntp   123/tcp" >> /etc/services
      echo "ntp   123/udp" >> /etc/services
      ntpdate w.x.y.z # pick one IP from https://www.ntppool.org/

Usage

When your computer boots, and asks for the LUKS password. Now you can unlock your encrypted Hard drive using:

torify ssh root@<onion.id>.onion -p 22 'my-secret-password'