Self Contained Encrypted iSCSI Datastore in VMware ESXi
Hopefully the title made sense. Alternate title could be
- LUKS Encrypted iSCSI SAN in Debian
- LUKS Encrypted iSCSI Target in Debian
- How to share a volume via iSCSI in Debian
You get the idea.
This article is about creating an encrypted ESXi datastore out of existing storage you have in your ESXi server. But the first half is really just how to create an LUKS encrypted LUN in Debian and share it out via iSCSI, so if you just need that, ignore the rest.
The way we configure it will mean you need to enter a passphrase on boot, and from there the system will boot and automatically mount a LUN to be shared out via iSCSI
The reason for me wanting to do this is that I have three virtual machines which contain sensitive data, and really need to be encrypted. If I do full disk encryption on the virtual machines, it blows my Veeam backup sizes up a LOT. Veeam can no longer de-dupe or do changed block tracking. Because I replicate these virtual machines over the WAN to another system in a datacenter with my pathetic 40Mb/s upload speed, this really wasn't something I could give up. The other option is to setup vSphere encryption, but it's a big setup and requires KMS servers, a bunch of messing around with certificates.
I decided to use Debian for this as its what I am used to. I used to use Ubuntu but it took a turn for the worst with version 18, so I made the switch to Debian 9 which has been great. So far its almost 100% the same, but without the crap. So if you are using Ubuntu, these steps should work fine.
How to do it
First, create a virtual machine in ESXi for Debian 9. I gave it 6 vCPU's, 512MB of RAM, an 8GB Thin disk along with a VMXNET3 NIC. The RAM could be even lower, I suspect you would have no issues with 256MB. I added a few more CPU cores because when I was hitting the VM hard with some vMotion the CPU load did ramp up a little, and since I have dual E5-2680 V2's, it means I have 40 threads laying around. I suspect you could get away with 4 vCores with no issue
We will add a second drive to share out via iSCSI later on. So skip that for now
Once you have created the VM, attach the Debian 9 netinstall ISO and boot to it. Select the regular Install option, and not the Graphical install
Now just run through and select all the usual stuff like keyboard layout, timezone, hostname etc. Eventually you will get to the storage options. You want to select the option to use encrypted LVM
Move along selecting the default options and write the changes to LVM. When you reach the point of entering a passphrase, make sure its a good one!
Move along with the setup and write the changes to disk. When you get to the software selection page, unselect everything but standard system utilities
From there finish the setup using the default options, or whatever options you want.
As soon as it reboots, it's going to prompt for your encryption key which it will do from now on
Enter your passphrase, and then log in as root
You'll want to update the system first
apt update
apt dist-upgrade -y
apt autoremove
apt clean
From there we want to install tgt, open-vm-tools, htop, ufw, sudo and the openssh server
apt install openssh-server open-vm-tools htop sudo ufw -y
Then go ahead and add your user to the sudoers group
usermod -aG sudo usernameyouchoseoninstall
Now go ahead and reboot, and then connect to the VM via SSH.
Once you connect, we should render the root account useless since we won't need it anymore. Run the following to set the hash to an impossible value, meaning you can't login. If you do need to login, just reset it or access it via su
sudo usermod -p ! root
Now its all updated and you have the base configured, we can go ahead and add the additional virtual hard drive which will end up being shared out. Shut down the VM
sudo shutdown -h now
Now edit the VM, and add a thin disk of whatever size you want. Then power it back on, unlock it with your passphrase and SSH back in
Now run lsblk to see the location of your new drive you added. As you can see, mine is sdb. which makes the full location /dev/sdb
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 8G 0 disk
├─sda1 8:1 0 243M 0 part /boot
├─sda2 8:2 0 1K 0 part
└─sda5 8:5 0 7.8G 0 part
└─sda5_crypt 254:1 0 7.8G 0 crypt
├─iscsi--secure1--vg-root 254:2 0 5.8G 0 lvm /
└─iscsi--secure1--vg-swap_1 254:3 0 2G 0 lvm [SWAP]
sdb 8:16 0 400G 0 disk
sr0 11:0 1 1024M 0 rom
Now go ahead and create a volume group, you should see the confirmation output below. I name my volume group "fs-secure_iscsi"
sudo vgcreate fs-secure_iscsi /dev/sdb
Volume group "fs-secure_iscsi" successfully created
And now create a logical volume. I named mine "fs-secure_lun1" and told it to use 100% of the free space
sudo lvcreate -l 100%FREE -n fs-secure_lun1 fs-secure_iscsi
Logical volume "fs-secure_lun1" created.
If you run lvs, you should see it
sudo lvs
LV VG Attr LSize Pool Origin Data% Meta% Move Log Cpy%Sync Convert
root fs-secure-vg -wi-ao---- 6.76g
swap_1 fs-secure-vg -wi-ao---- 1.00g
fs-secure_lun1 fs-secure_iscsi -wi-a----- 400.00g
Now we want to encrypt that volume we just made, run the following. You can see the naming convention you need to use.
sudo cryptsetup -v -y luksFormat /dev/mapper/fs--secure_iscsi-fs--secure_lun1
If you are unsure, you can go to /dev/mapper and list the contents and you should see the volume name in full.
cd /dev/mapper
ls -al
total 0
drwxr-xr-x 2 root root 160 Apr 11 19:47 .
drwxr-xr-x 18 root root 3200 Apr 11 19:47 ..
crw------- 1 root root 10, 236 Apr 11 19:47 control
lrwxrwxrwx 1 root root 7 Apr 11 19:47 fs--secure_iscsi-fs--secure_lun1 -> ../dm-0
lrwxrwxrwx 1 root root 7 Apr 11 19:47 iscsi--secure1--vg-root -> ../dm-2
lrwxrwxrwx 1 root root 7 Apr 11 19:47 iscsi--secure1--vg-swap_1 -> ../dm-3
lrwxrwxrwx 1 root root 7 Apr 11 19:47 sda5_crypt -> ../dm-1
sean@iscsi-secure1:/dev/mapper$
After you run the above cryptsetup command it should give you a warning to type YES in caps, and enter the passphrase
WARNING!
========
This will overwrite data on /dev/mapper/fs--secure_iscsi-fs--secure_lun1 irrevocably.
Are you sure? (Type uppercase yes): YES
Enter passphrase:
Verify passphrase:
Command successful.
Now the volume is encrypted, but you can't actually see the encrypted volume anywhere. You now need to mount the volume which will give you a NEW volume which is encrypted. This will be what you share out via iSCSI
We won't mount it just yet, we will dive directly into auto-mounting the second volume on boot. This is perfectly secure as we still need to unlock the OS drive before this will ever take place
We will now generate a key for the auto-mount process to use. First create a folder somewhere
sudo mkdir /etc/luks-keys
Now generate random characters for the key file
sudo dd if=/dev/urandom of=/etc/luks-keys/disk_secret_key bs=512 count=8
Now its created, we need to add that keyfile to the encrypted volume. After entering the first line, it will prompt for your passphrase you set when creating it, and then add the keyfile
sudo cryptsetup -v luksAddKey /dev/mapper/fs--secure_iscsi-fs--secure_lun1 /etc/luks-keys/disk_secret_key
Enter any passphrase: passphrase
Key slot 0 unlocked.
Command successful.
Now we can verify the key works by actually mouting the volume
sudo cryptsetup -v luksOpen /dev/mapper/fs--secure_iscsi-fs--secure_lun1 iscsi_crypt --key-file=/etc/luks-keys/disk_secret_key
Key slot 1 unlocked.
Command successful.
After this, you will have a new device at /dev/mapper/iscsi_crypt. This is just temporary, we will now close it
sudo cryptsetup -v luksClose iscsi_crypt
Now we know the key works, we need to configure the volume to mount on boot. First we need to find the UUID of the volume, so run the following
sudo cryptsetup luksDump /dev/mapper/fs--secure_iscsi-fs--secure_lun1 | grep "UUID"
UUID: 2a2335bf-5662-343c-a468-fbe3454659c85
Make a note of the UUID. and open the file /etc/crypttab
sudo nano /etc/crypttab
Make a new line under the existing entry, and enter the following. Remember to change the UUID, and if you want the encrypted volume named something else, change the iscsi_crypt text.
iscsi_crypt UUID=2a2335bf-5662-343c-a468-fbe3454659c85 /etc/luks-keys/disk_secret_key luks
Save the file and exit nano
Now go ahead and reboot the system. When it comes back up go to /dev/mapper and see the contents. You should see your mounted volume listed.
cd /dev/mapper
ls -al
total 0
drwxr-xr-x 2 root root 160 Apr 11 19:47 .
drwxr-xr-x 18 root root 3200 Apr 11 19:47 ..
crw------- 1 root root 10, 236 Apr 11 19:47 control
lrwxrwxrwx 1 root root 7 Apr 11 19:47 fs--secure_iscsi-fs--secure_lun1 -> ../dm-0
lrwxrwxrwx 1 root root 7 Apr 11 20:16 iscsi_crypt -> ../dm-4
lrwxrwxrwx 1 root root 7 Apr 11 19:47 iscsi--secure1--vg-root -> ../dm-2
lrwxrwxrwx 1 root root 7 Apr 11 19:47 iscsi--secure1--vg-swap_1 -> ../dm-3
lrwxrwxrwx 1 root root 7 Apr 11 19:47 sda5_crypt -> ../dm-1
Now we can move on to
iSCSI Target Configuration
This part is actually very easy. We already installed tgt in the first few steps, so we just need to make the configuration.
Enter the following to make the config file. You can name it whatever you want
sudo nano /etc/tgt/conf.d/secure_iscsi.conf
In the file, we need to enter the configuration
<target iqn.2018-02.iscsi-secure1:lun1>
backing-store /dev/mapper/iscsi_crypt
initiator-address 10.0.50.14
incominguser username password12345
</target>
- The first line contains the target name. This is just the name of the iSCSI target, just enter an arbitrary date and name in the same format as I have done
- The next line is the backing for the iSCSI target, this should be the encrypted LUN we mounted.
- Next is a line for security, we can tell it to only accept connections from this address. If you want, you can remove the line. We can always come back and change this configuration
- The next line is for CHAP authentication. Enter a username and password here. But watch out, it must be a LEAST 12 characters for the password, and no more than 16! It also must not contain special characters
Now save the file and exit nano. Restart tgt to make the configuration take effect
sudo service tgt restart
Now its restarted, we can verify the LUN shows up
sudo tgtadm --mode target --op show
~~~snip~~~~
LUN: 1
Type: disk
SCSI ID: IET 00010001
SCSI SN: beaf11
Size: 429490 MB, Block size: 512
Online: Yes
Removable media: No
Prevent removal: No
Readonly: No
SWP: No
Thin-provisioning: No
Backing store type: rdwr
Backing store path: /dev/mapper/iscsi_crypt
Backing store flags:
Account information:
user
ACL information:
10.0.50.14
~~~snip~~~~
We are now completely finished configuring the Debian VM. I went ahead and set key based authentication for SSH and a few other security pieces, but those are up to you
Next we need to mount it in ESXi, if you are mounting it somewhere else, we are done!
Mounting the iSCSI LUN in ESXi
This will be done from ESXi 6.7, so if you are using a different version it may be a little different.
If your ESXi box has a single NIC, then you can just bind the software iSCSI initiator to your usual VMK port group. If you have multiple, you probably want to create a seperate iSCSI network.
I split off a single 1G NIC from my usual setup, and made a new vSwitch called "iSCSI vSwitch"
I then added a new VMK NIC for this traffic. You do not need to add any services to it. Make sure its using your new iSCSI vSwitch.
If this new iSCSI VMK will be on the same subnet or VLAN as your usual ESXi network, then select the default TCP/IP Stack when creating it. If not, you need to create a new TCP/IP stack via CLI for it, and configure the correct gateway
Now move over to port groups and create a port group for virtual machines on the same vSwitch. We are going to move the Debian VM to this port group so that iSCSI traffic is all on the same vSwitch, and does not have to go onto the physical network
Now just edit the VM and add it to this port group. Even though this vSwitch is backed by a 1G NIC in my case, I get well over 20Gb/s within ESXi because its all on the same vSwitch and never leaves the host.
Go over to storage, adapters and click on Configure iSCSI
Now make sure its enabled, enter the chap configuration (Make sure to enter credentials on the drop down arrow), make sure its bound the correct port, and then at the bottom enter the IP address of your Debian VM.
Once you have done that and clicked Save, it will automatically populate the target
Now just go into devices, and create a new datastore! It will show as degraded because it only has one path, you can ignore this.
Just be sure to make the Debian VM boot first, and set the VM's that reside on it to not automatically start. When you reboot your ESXi host they will show as orphaned because the storage is not available. After a few moments, it will show up in ESXi and you can start them as normal
Hopefully this was helpful!