Linux – Load dm-crypt on Ubuntu Server 18.04 LTS in Windows Subsystem for Linux 1 or 2

dm-cryptubuntu 18.04windows-subsystem-for-linux

I'm using Windows Subsystem for Linux (WSL1) on my Windows 10 system and tried to delete all data from a USB device and overwrite it with pseudorandom numbers following this tutorial (found it only in German, but is not really important for this question), but could not load a needed kernel module.

When trying to load dm-crypt I get

$ sudo modprobe dm-crypt
modprobe: ERROR: ../libkmod/libkmod.c:586 kmod_search_moddep() could not open moddep file '/lib/modules/4.4.0-18362-Microsoft/modules.dep.bin'
modprobe: FATAL: Module dm-crypt not found in directory /lib/modules/4.4.0-18362-Microsoft

I assume my Ubuntu version is simply missing module dm-crypt.

Now my question: Does WSL support the kernel subsystem dm-crypt in general?

I'm using WSL1 with 64 bit Ubuntu 18.04 LTS.

Update:
I tried again with WSL2 and Ubuntu 18.04 LTS but got the same error message:

$ sudo modprobe dm-crypt
modprobe: ERROR: ../libkmod/libkmod.c:586 kmod_search_moddep() could not open moddep file '/lib/modules/4.4.0-19013-Microsoft/modules.dep.bin'
modprobe: FATAL: Module dm-crypt not found in directory /lib/modules/4.4.0-19013-Microsoft

Best Answer

I can't vouch for WSL1, but it appears that WSL2 supports it since it is running the full Linux kernel. In fact I have just tried to load the dm-crypt module and succeeded.

dm-crypt module loaded

You'll have to enable WSL2 first. As at this writing, it's only available to Windows Insiders: https://docs.microsoft.com/en-us/windows/wsl/wsl2-install

Then you'll have to compile your own custom kernel to get dm-crypt support: https://github.com/microsoft/WSL2-Linux-Kernel/blob/master/README-Microsoft.WSL2

Install git and some compilers:

$ sudo apt install build-essential flex bison libssl-dev libelf-dev libncurses5-dev git

Clone the Microsoft WSL2 kernel:

$ git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
$ cd WSL2-Linux-Kernel

You'll have to select the cryptographic features. I used the menu:

$ export KCONFIG_CONFIG=Microsoft/config-wsl
$ make menuconfig
[*] Enable loadable module support

Device Drivers --->
[*] Multiple devices driver support (RAID and LVM) --->
    <*> Device mapper support
    <M>   Crypt target support    

General setup  --->
    [*] Initial RAM filesystem and RAM disk (initramfs/initrd) support

Device Drivers --->
    [*] Block Devices ---> 
        <*> Loopback device support 

File systems ---> 
     <*> FUSE (Filesystem in Userspace) support 

And whatever algorithms you want...

[*] Cryptographic API ---> 
    <*> XTS support
    <*> SHA224 and SHA256 digest algorithm
    <*> AES cipher algorithms
    <*> AES cipher algorithms (x86_64)
    <*> User-space interface for hash algorithms
    <*> User-space interface for symmetric key cipher algorithms
    <*> RIPEMD-160 digest algorithm 
    <*> SHA384 and SHA512 digest algorithms 
    <*> Whirlpool digest algorithms 
    <*> LRW support 
    <*> Serpent cipher algorithm 
    <*> Twofish cipher algorithm

For what you want to do, you'll have to select "XTS Support" under "Cryptographic API".

Save your config and then compile the kernel:

$ sudo make && make modules_install

Then copy the new image to your windows host. My image file was called bzImage:

$ cp arch/x86_64/boot/bzImage /mnt/c/Users/your-user-name/

Create a file on your Windows host's "Users\your-user-name" folder called ".wslconfig" (note the dot . in-front). I used Notepad++. Put the following lines in it:

[wsl2]
kernel=C:\\Users\\your-user-name\\bzImage
swap=0
localhostForwarding=true

Exit your WSL2 instance, and reboot your WSL2 instance (use Powershell):

> wsl --shutdown

Open you WSL2 bash session again and try to load the dm-crypt module:

$ sudo modprobe -v dm_crypt

insmod /lib/modules/4.19.81-microsoft-standard/kernel/drivers/md/dm-crypt.ko

UPDATE 1:

Regarding the access to block devices, well... as of this writing, it seems Microsoft is still working on it: https://github.com/Microsoft/WSL/issues/689

Hope that helps :)

UPDATE 2:

You could get around the block device limitation on WSL2 by serving your host's USB drive to WSL2 via the USB/IP or iSCSI protocol. I tried USP/IP, but I had too much trouble with it since my USB device was classified as a "hub". So I tried the iSCSI method by creating an iSCSI target on my Windows host, and then connected to it from my WSL2 instance.

I used the "iSCSIConsole" application on TalAloni's github repository: https://github.com/TalAloni/iSCSIConsole to create the target.

You'll have to run it with administrator privileges in order to attach a physical disk such as a USB drive. You also may have to allow it through the Windows host firewall to get it to communicate with the WSL2 instance. I attached my USB thumb drive with the default iSCSI target name of "iqn.1991-05.com.microsoft:target1".

Adding an iSCSI Target

Selecting a Physical Disk

After you got that running, you can connect to it from your WSL2 instance.

First, you must make sure you have the iSCSI driver modules loaded for your custom WSL2 kernel. I enabled it in the kernel configuration menu, then recompiled:

$ KCONFIG_CONFIG=Microsoft/config-wsl make menuconfig
[*] Networking support  --->
   Networking options  --->
      [*] TCP/IP networking 

Device Drivers  --->
  SCSI device support  --->
     <*> SCSI device support --->
     <*> SCSI disk support
     <*> SCSI generic support
     SCSI Transports --->
       <M> iSCSI Transport Attributes
     [*] SCSI low-level drivers  --->
       <M> iSCSI Initiator over TCP/IP     
$ sudo make && make modules_install

Once you have your new kernel and modules installed, load the iscsi modules:

$ sudo modprobe libiscsi
$ sudo modprobe scsi_transport_iscsi
$ sudo modprobe iscsi_tcp
$ sudo modprobe libiscsi_tcp

Then I set up a client/initiator on my WSL2 instance. We're going to use open-iscsi, but it requires systemd, and systemd is not enabled on WSL2 by default. But it is very easy to do. Here is a very short guide on how to do that: https://forum.snapcraft.io/t/running-snaps-on-wsl2-insiders-only-for-now/13033. You can skip the snap parts.

Then install open-iscsi:

$ sudo apt install open-iscsi

Edit the "/etc/iscsi/iscsid.conf" and change change "node.startup" to "automatic". Setting it to automatic will cause your WSL sessions to start up very slowly next time you reboot, since your "host" IP changes and it will not be able to reconnect.

Start the iscsi initiator:

$ sudo /etc/init.d/open-iscsi start

Then connect to the target and list the storage devices:

$ export WSLHOSTIP=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}')
$ sudo iscsiadm -m discovery -t st -p $WSLHOSTIP

172.26.240.1:3260,-1 iqn.1991-05.com.microsoft:target1

$ sudo iscsiadm -m node

172.26.240.1:3260,-1 iqn.1991-05.com.microsoft:target1

Now we can connect:

$ sudo iscsiadm -m node --targetname "iqn.1991-05.com.microsoft:target1" --portal "$WSLHOSTIP:3260" --login

Logging in to [iface: default, target: iqn.1991-05.com.microsoft:target1, portal: 172.26.240.1,3260] (multiple)
Login to [iface: default, target: iqn.1991-05.com.microsoft:target1, portal: 172.26.240.1,3260] successful.

My USB drive was then listed as /dev/sdb.

$ ls /dev/sd*

/dev/sda  /dev/sdb

$ sudo fdisk -l /dev/sdb

Disk /dev/sdb: 30 GiB, 32212254720 bytes, 62914560 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x3958509f

Device     Boot Start      End  Sectors Size Id Type
/dev/sdb1  *     2048 62914559 62912512  30G  b W95 FAT32

Now you can do your drive encryption...

$ sudo modprobe dm_crypt
$ sudo cryptsetup -d /dev/urandom -c aes-xts-plain create delete /dev/sdb  && shred -vzn 0 /dev/mapper/delete && sync && sleep 4 && cryptsetup remove delete

shred: /dev/mapper/delete: pass 1/1 (000000)...
shred: /dev/mapper/delete: pass 1/1 (000000)...32MiB/30GiB 0%
shred: /dev/mapper/delete: pass 1/1 (000000)...62MiB/30GiB 0%
shred: /dev/mapper/delete: pass 1/1 (000000)...90MiB/30GiB 0%
shred: /dev/mapper/delete: pass 1/1 (000000)...108MiB/30GiB 0%
shred: /dev/mapper/delete: pass 1/1 (000000)...137MiB/30GiB 0%
shred: /dev/mapper/delete: pass 1/1 (000000)...149MiB/30GiB 0%
...
Related Question