ZFS on LUKS: mudanças entre as edições

De Área31 Hackerspace
Sem resumo de edição
Sem resumo de edição
Linha 11: Linha 11:
Pelo visto você é um bom menino (ou menine kekekeke), que criptografou seu disco certinho, e seguiu as boas práticas recomendadas pelo área31 hackerspace lendo os artigos [[HackForge]] e  aprendeu até a criar seu próprio [[Storage_criptografado_em_roteador_residencial|storage criptografado em roteador residencial]]. Aprendeu inclusive a [[Desbloqueio_de_LUKS_com_um_dispositivo_USB_no_Boot|desbloquear seu LUKS durante o boot usando um device USB]]. Logo, agora vc quer um espelho de discos semelhante ao RAID-1, só que usando ZFS on Linux. Então se divirta :D
Pelo visto você é um bom menino (ou menine kekekeke), que criptografou seu disco certinho, e seguiu as boas práticas recomendadas pelo área31 hackerspace lendo os artigos [[HackForge]] e  aprendeu até a criar seu próprio [[Storage_criptografado_em_roteador_residencial|storage criptografado em roteador residencial]]. Aprendeu inclusive a [[Desbloqueio_de_LUKS_com_um_dispositivo_USB_no_Boot|desbloquear seu LUKS durante o boot usando um device USB]]. Logo, agora vc quer um espelho de discos semelhante ao RAID-1, só que usando ZFS on Linux. Então se divirta :D


"É fundamental reconhecer que, embora indesejado, o acesso não autorizado aos seus arquivos é uma possibilidade real. Muitas pessoas acreditam na inviolabilidade de seus dados, confiando nas promessas de segurança feitas por empresas, ou na suposta eficácia de seus sistemas operacionais e softwares de proteção. No entanto, é um equívoco comum subestimar que, com a motivação correta e acesso físico, qualquer zé mané da esquina com conhecimentos básicos, ou em um cenário mais extremo, entidades governamentais (sim, agentes do '''ESTADO'''), podem acessar ou comprometer seus dados. Portanto, a implementação de criptografia em nível de sistema de arquivos em seus sistemas não é apenas recomendada, mas essencial. A mensagem aqui é clara: não negligencie a segurança dos seus dados. Priorize a criptografia abrangente para garantir sua proteção."
É fundamental reconhecer que, embora indesejado, o acesso não autorizado aos seus arquivos é uma possibilidade real. Muitas pessoas acreditam na inviolabilidade de seus dados, confiando nas promessas de segurança feitas por empresas, ou na suposta eficácia de seus sistemas operacionais e softwares de proteção. No entanto, é um equívoco comum subestimar que, com a motivação correta e acesso físico, qualquer zé mané da esquina com conhecimentos básicos, ou em um cenário mais extremo, entidades governamentais (sim, agentes do '''ESTADO'''), podem acessar ou comprometer seus dados. Portanto, a implementação de criptografia em nível de sistema de arquivos em seus sistemas não é apenas recomendada, mas essencial. A mensagem aqui é clara: não negligencie a segurança dos seus dados. Priorize a criptografia abrangente para garantir sua proteção, ou seja, CRIPTOGRAFE TUDO, estúpido!





Edição das 11h15min de 12 de novembro de 2023

Membro do hackerspace feliz por ter um mirror ZFS (semelhante ao RAID-1) criptografadinho com LUKS, com cache em NVME e tudoooo, chega a ser poético de tão bonito.
Autor: 
* Coffnix

"Home Network Defense"

Utilize criptografia pra tudo

Motivo

Pelo visto você é um bom menino (ou menine kekekeke), que criptografou seu disco certinho, e seguiu as boas práticas recomendadas pelo área31 hackerspace lendo os artigos HackForge e aprendeu até a criar seu próprio storage criptografado em roteador residencial. Aprendeu inclusive a desbloquear seu LUKS durante o boot usando um device USB. Logo, agora vc quer um espelho de discos semelhante ao RAID-1, só que usando ZFS on Linux. Então se divirta :D

É fundamental reconhecer que, embora indesejado, o acesso não autorizado aos seus arquivos é uma possibilidade real. Muitas pessoas acreditam na inviolabilidade de seus dados, confiando nas promessas de segurança feitas por empresas, ou na suposta eficácia de seus sistemas operacionais e softwares de proteção. No entanto, é um equívoco comum subestimar que, com a motivação correta e acesso físico, qualquer zé mané da esquina com conhecimentos básicos, ou em um cenário mais extremo, entidades governamentais (sim, agentes do ESTADO), podem acessar ou comprometer seus dados. Portanto, a implementação de criptografia em nível de sistema de arquivos em seus sistemas não é apenas recomendada, mas essencial. A mensagem aqui é clara: não negligencie a segurança dos seus dados. Priorize a criptografia abrangente para garantir sua proteção, ou seja, CRIPTOGRAFE TUDO, estúpido!


Requisitos

Aqui utilizamos OpenSUSE + ZFS on Linux, mas você tem liberdade de utilizar em qualquer distro, adapte somente os comandos e arquivos caso utilize outra distro.

Procedimento

Instale o ZFS

Configure o repositório "Filesystem Tools" criando o arquivo abaixo:

   /etc/zypp/repos.d/repo-filesystems.repo
[filesystems]
name=Filesystem tools and FUSE-related packages (openSUSE_Tumbleweed)
enabled=1
autorefresh=1
baseurl=https://download.opensuse.org/repositories/filesystems/openSUSE_Tumbleweed/
type=rpm-md
gpgcheck=1
gpgkey=https://download.opensuse.org/repositories/filesystems/openSUSE_Tumbleweed/repodata/repomd.xml.key

Agora atualize o cache e instale os pacotes necessários:

root # zypper refresh
root # zypper in zfs-kmp-default zfs-ueficert zfs

Adicione o ZFS ao boot:

root # systemctl enable zfs-import-cache
root # systemctl enable zfs-mount

Configure o LUKS

Agora configure crie o luks em cada disco. Lembre-se de alterar os ID dos devices de "ata-ST8000NE001-2M7101_WSD0SC28" e "ata-ST8000NE001-2M7101_WSD0SC30" para os seus:

root # mkdir -p /etc/area31/headerstore
root # cryptsetup luksFormat --force-password --type luks2 --cipher aes-xts-plain64 --hash sha512 --key-size 512 /dev/disk/by-id/ata-ST8000NE001-2M7101_WSD0SC28 --align-payload 8192 --header /etc/area31/headerstore/ata-ST8000NE001-2M7101_WSD0SC28.img
root # cryptsetup luksFormat --force-password --type luks2 --cipher aes-xts-plain64 --hash sha512 --key-size 512 /dev/disk/by-id/ata-ST8000NE001-2M7101_WSD0SC30 --align-payload 8192 --header /etc/area31/headerstore/ata-ST8000NE001-2M7101_WSD0SC30.img

Crie uma chave para desbloqueio do LUKS:

root # mkdir -p /opt/area31/keystore/keyfile ; dd if=/dev/urandom of=/opt/area31/keystore/keyfile bs=4096 count=1
root # chmod 400 /opt/area31/keystore/keyfile

Inclua a chave em ambos os discos:

root # cryptsetup luksAddKey /dev/disk/by-id/ata-ST8000NE001-2M7101_WSD0SC30 --header /etc/area31/headerstore/ata-ST8000NE001-2M7101_WSD0SC30.img /opt/area31/keystore/keyfile
root # cryptsetup luksAddKey /dev/disk/by-id/ata-ST8000NE001-2M7101_WSD0SC28 --header /etc/area31/headerstore/ata-ST8000NE001-2M7101_WSD0SC28.img /opt/area31/keystore/keyfile

Monte usando a chave:

root # cryptsetup luksOpen /dev/disk/by-id/ata -ST8000NE001-2M7101_WSD0SC30 --header /etc/area31/headerstore/ata-ST8000NE001-2M7101_WSD0SC30.img --key-file=/opt/area31/keystore/keyfile storage_disk1_luks
root # cryptsetup luksOpen  /dev/disk/by-id/ata-ST8000NE001-2M7101_WSD0SC28 --header /etc/area31/headerstore/ata-ST8000NE001-2M7101_WSD0SC28.img --key-file=/opt/area31/keystore/keyfile storage_disk2_luks

Configure o mirror ZFS

Crie um novo pool ZFS como mirror com 2 dispositivos LUKS montados previamente, com nome vdisk0 montado em /storage:

root # mkdir -p /storage ; chattr +i /storage
root # zpool create -f -o ashift=12 -m /storage vdisk0 mirror /dev/mapper/storage_disk1_luks /dev/mapper/storage_disk2_luks

Inicie o serviço ZFS para montar o pool sem precisar reiniciar:

root # systemctl start zfs-mount
root # systemctl start zfs-import-cache

Para desmontar /storage (se necessário):

root # zpool export vdisk0

Para remontar o /storage (se necessário):

root # zpool import vdisk0

Habilite o 'relatime' no pool ZFS para otimizar o acesso a tempos de leitura:

root # zfs set relatime=on vdisk0

Ativar a compressão lz4 para economizar espaço no pool ZFS:

root # zfs set compression=lz4 vdisk0

Ative a deduplication (IMPORTANTE!!!):

root # zfs set dedup=on vdisk0

Verifique se dedup está ativo:

root # zfs get dedup vdisk0

Para checar o status do ZFS:

root # zfs get all vdisk0
root # zpool status

Liste todos os datasets ZFS:

root # zfs list -o name,mountpoint,used,avail,refer

Ative cache em SSD ou NVME

Adicione um NVME ou SSD como cache ao pool ZFS. Basta criar uma partição comum do tipo 8e (Linux) entre 50GB e 100GB e depois adiciona-lo. Ex:

root # zpool add vdisk0 cache /dev/nvme0n1p7


Montagem automática do ZFS

Crie o config para o script:

root # mkdir -p /opt/area31/conf ; touch /opt/area31/conf/mount-luks-zfs.conf

Com o seguinte conteúdo:

   /opt/area31/bin/mount-luks-zfs.sh
DISK_ID_01="ata-ST8000NE001-2M7101_WSD0SC30"
DISK_ID_02="ata-ST8000NE001-2M7101_WSD0SC28"
LUKS_DISK_01="storage_disk1_luks"
LUKS_DISK_02="storage_disk2_luks"
LUKS_KEYFILE="/etc/area31/keystore/keyfile"
DIR_LUKS_HEADER="/etc/area31/headerstore"
DIR_ZFS="/storage"
ZFS_VDISK_01="vdisk0"

Agora crie o script para montagem automática do ZFS:

root # mkdir -p /opt/area31/bin ; touch /opt/area31/bin/mount-luks-zfs.sh ; chmod +x /opt/area31/bin/mount-luks-zfs.sh

Com o seguinte conteúdo:

   /opt/area31/bin/mount-luks-zfs.sh (bash source code)
#!/bin/bash

###########################################################################
# Verifica se o script já está em execução

SCRIPT_NAME="${0##*/}"

if [ "$(pgrep -cx "${SCRIPT_NAME}")" -gt 1 ]; then
    echo "O script já está em execução, aguarde 10 segundos para tentar novamente."
    sleep 10

    if [ "$(pgrep -cx "${SCRIPT_NAME}")" -gt 1 ]; then
        echo "O script já está em execução e não será executado novamente."
        exit 1
    fi
fi

###########################################################################
# Iniciando script

CNF="/opt/area31/conf/mount-luks-zfs.conf"

# Checa se existe o arquivo de CONF, caso não exista ele sai
if [ -f "${CNF}" ] && [ ! -z "${CNF}" ]; then
    source ${CNF}
else
    echo "${CNF} não encontrado."
    exit 1
fi

ERROR="0"

# Lista de variáveis para verificar
variables=("DIR_ZFS" "ZFS_VDISK_01" "DIR_LUKS_HEADER" "LUKS_KEYFILE" "LUKS_DISK_02" "LUKS_DISK_01" "DISK_ID_02" "DISK_ID_01")

# Função para verificar variável
check_variable() {
    local var_name="$1"

    # Usando indireção para pegar o valor da variável
    local actual_value="${!var_name}"

    # Verificar se a variável está definida e não está vazia
    if [[ -z "$actual_value" ]]; then
        echo "Erro: $var_name não está definido ou está vazio!"
        return 1
    fi
}

# Verificar todas as variáveis do CONF antes de iniciar o script
for var in "${variables[@]}"; do
    check_variable "$var" | |  exit 1
done

###########################################################################################################

check_pool_zfs_active(){
	CHECK_MOUNTED="$(mount | grep zfs | grep  "${DIR_ZFS}" | wc -l)"
	if [ "${CHECK_MOUNTED}" -ne 0 ]; then
		CHECK_NONE_ZFS="$(zpool status | grep 'no pools available' | wc -l 2> /dev/null)"
		if [ "${CHECK_NONE_ZFS}" -ne 0 ]; then
			ZFS_UMOUNTED="1"
		else
			ZFS_UMOUNTED="0"
		fi
	else
		echo -e "/storage desmontado e ZFS inativo"
		exit 0
	fi
}

umount_luks(){
	CHECK_LUKS_DISK_01="$(lsblk -o NAME,TYPE,MOUNTPOINT | grep -w 'crypt'  | grep ${LUKS_DISK_01} | wc -l)"
	CHECK_LUKS_DISK_02="$(lsblk -o NAME,TYPE,MOUNTPOINT | grep -w 'crypt'  | grep ${LUKS_DISK_02} | wc -l)"

	if [ "${CHECK_LUKS_DISK_01}" -ne 0 ]; then
		cryptsetup luksClose "${LUKS_DISK_01}"
		if [ "$?" -ne 0 ]; then
			echo -e "Erro ao desmontar o LUKS \"${LUKS_DISK_01}\""
			ERROR="1"
		else
			echo -e "Sucesso ao desmontar o LUKS \"${LUKS_DISK_01}\""
		fi
	else
		echo "LUKS \"${LUKS_DISK_01}\" desmontado."
	fi

	if [ "${CHECK_LUKS_DISK_02}" -ne 0 ]; then
		cryptsetup luksClose "${LUKS_DISK_02}"
		if [ "$?" -ne 0 ]; then
			echo -e "Erro ao tentar desmontar o LUKS \"${LUKS_DISK_02}\""
			ERROR="1"
		else
			echo -e "Sucesso ao desmontar o LUKS \"${LUKS_DISK_02}\""
		fi
	else
		echo "LUKS \"${LUKS_DISK_02}\" desmontado."
	fi
}


mount_zfs(){
	# Checa se o disco está montado
	CHECK_LUKS_DISK_01="$(lsblk -o NAME,TYPE,MOUNTPOINT | grep -w 'crypt'  | grep ${LUKS_DISK_01} | wc -l)"
	CHECK_LUKS_DISK_02="$(lsblk -o NAME,TYPE,MOUNTPOINT | grep -w 'crypt'  | grep ${LUKS_DISK_02} | wc -l)"

	# monte usando a chave do pendrive
	if [ "${CHECK_LUKS_DISK_01}" -eq 0 ]; then
		echo -e "Tentando montar o LUKS \"${LUKS_DISK_01}\" do dispositivo \"${DISK_ID_01}\"..."
		cryptsetup luksOpen "/dev/disk/by-id/${DISK_ID_01}" --header "${DIR_LUKS_HEADER}/${DISK_ID_01}.img" --key-file="${LUKS_KEYFILE}" "${LUKS_DISK_01}"
		if [ "$?" -ne 0 ]; then
			ERROR="1"
			exit 1
		else
			echo -e "Sucesso ao montar os dispositivos LUKS do dispositivo \"${DISK_ID_01}\"."
		fi
	fi

	if [ "${CHECK_LUKS_DISK_02}" -eq 0 ]; then
		echo -e "Tentando montar o LUKS \"${LUKS_DISK_02}\" do dispositivo \"${DISK_ID_02}\"..."
		cryptsetup luksOpen "/dev/disk/by-id/${DISK_ID_02}" --header "${DIR_LUKS_HEADER}/${DISK_ID_02}.img" --key-file="${LUKS_KEYFILE}" "${LUKS_DISK_02}"
		if [ "$?" -ne 0 ]; then
			ERROR="1"
			exit 1
		else
			echo -e "Sucesso ao montar os dispositivos LUKS do dispositivo \"${DISK_ID_02}\"."
		fi
	fi

	zfs get all "${ZFS_VDISK_01}" &> /dev/null
	if [ "$?" -eq 0 ]; then
		echo -e "ZFS inicializado. Caso deseje utilize $0 check ou $0 umount"
	else
		if [ "${ERROR}" -eq 0 ]; then
			echo -e "LUKS montado. Tentando inicializar o ZFS..."
			zpool import "${ZFS_VDISK_01}"
			if [ "$?" -ne 0 ]; then
				ERROR="1"
				exit 1
			else
				echo -e "Sucesso ao inicializar o ZFS.\n$(df -hT "${DIR_ZFS}")"
			fi
		fi
	fi
}


case "$1" in
	check)
		zfs get all "${ZFS_VDISK_01}"
		zpool status "${ZFS_VDISK_01}"
	;;
	umount)
		CHECK_MOUNTED="$(mount | grep zfs | grep "${DIR_ZFS}" | wc -l)"
		if [ "${CHECK_MOUNTED}" -eq 0 ]; then
			echo -e "ZFS desmontado. Tentando desmontar o LUKS..."
			umount_luks
		else
			zpool export "${ZFS_VDISK_01}"
			if [ "$?" -ne 0 ]; then
				echo -e "Erro ao tentar desmontar o ZFS \"${ZFS_VDISK_01}\""
			else
				umount_luks
			fi
		fi
	;;
	*)
		mount_zfs
	;;
esac


Configure o systemd

Caso queira que o ZFS seja montado automaticamente no processo de boot, crie o seguinte arquivo:

   /etc/systemd/system/mount-luks-zfs.service
[Unit]
Description=mount-luks-zfs
Wants=networking.service
After=networking.service

[Service]
Type=simple
RemainAfterExit=yes
ExecStart=/opt/area31/bin/mount-luks-zfs.sh
ExecStop=/opt/area31/bin/mount-luks-zfs.sh umount
ExecReload=/opt/area31/bin/mount-luks-zfs.sh
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target

Ative e inicie:

root # systemctl enable /etc/systemd/system/mount-luks-zfs.service
root # systemctl start mount-luks-zfs.service

Seja feliz! :D

Cookies nos ajudam a entregar nossos serviços. Ao usar nossos serviços, você concorda com o uso de cookies.