01.LUKS 패키지 설치
# LUKS
apt -y install cryptsetup
apt -y install cryptsetup-initramfs
apt -y install systemd-cryptsetup
# iSCSI
apt -y install targetcli-fb
# Tang/Clevis
apt -y install tang
apt -y install clevis
apt -y install clevis-luks
apt -y install clevis-dracut
# TPM 2.0
apt -y install systemd
apt -y install tpm2-tools
02.필요한 경우 C/C++ 개발도구 설치
apt -y install build-essential
apt -y install autoconf automake cmake
apt -y install libmicrohttpd-dev
apt -y install libjansson-dev
apt -y install libgnutls28-dev
apt -y install uuid-dev
apt -y install samba
apt -y install ntfs-3g
03.LUKS 키 생성
mkdir -p /etc/cryptsetup-keys.d
chmod 700 /etc/cryptsetup-keys.d
# 4096비트 키 생성
dd if=/dev/urandom of=/etc/cryptsetup-keys.d/secure_ntfs.key bs=512 count=8
chmod 600 /etc/cryptsetup-keys.d/secure_ntfs.key
chown root:root /etc/cryptsetup-keys.d/secure_ntfs.key
ls -l /etc/cryptsetup-keys.d/secure_ntfs.key
04.파티션 초기화 (파티션은 미리 생성되어 있어야 함)
wipefs --force -a /dev/sda4
dd if=/dev/zero of=/dev/sda4 bs=1M count=10
05.LUKS로 파티션 초기화 후 확인
cryptsetup luksFormat \
--batch-mode \
--type luks2 \
--cipher aes-xts-plain64 \
--key-size 512 \
--hash sha256 \
/dev/sda4 /etc/cryptsetup-keys.d/secure_ntfs.key
cryptsetup luksDump /dev/sda4
06.LUKS header 백업
mkdir -p /root/luks-backup
cryptsetup luksHeaderBackup /dev/sda4 --header-backup-file /root/luks-backup/header.img
cryptsetup luksDump /dev/sda4 > /root/luks-backup/luks_dump.txt
blkid > /root/luks-backup/blkid.txt
lsblk -f > /root/luks-backup/lsblk.txt
cp /etc/crypttab /root/luks-backup/
cp /etc/fstab /root/luks-backup/
cp /etc/cryptsetup-keys.d/secure_ntfs.key /root/luks-backup/
06-1.복원
cryptsetup luksHeaderRestore /dev/sda4 --header-backup-file /root/luks-backup/header.img
07.LUKS 볼륨 열기
cryptsetup open /dev/sda4 secure_ntfs \
--key-file /etc/cryptsetup-keys.d/secure_ntfs.key
ls -l /dev/mapper/secure_ntfs
lsblk -f
7-1.LUKS 볼륨 닫기
cryptsetup close secure_ntfs
08.파티션 포맷
mkfs.ntfs -f -L SECURE_NTFS /dev/mapper/secure_ntfs
lsblk -f /dev/sda4
09.마운트
mkdir -p /mnt/secure_ntfs
mount /dev/mapper/secure_ntfs /mnt/secure_ntfs
df -hT /mnt/secure_ntfs
10.LUKS 볼륨 닫기 (필요한 경우만)
umount /mnt/secure_ntfs
cryptsetup close secure_ntfs
11.자동 마운트 설정
1) UUID 확인
blkid /dev/sda4
blkid /dev/mapper/secure_ntfs
2) /etc/crypttab 작성
vi /etc/crypttab (UUID는 "blkid /dev/sda4"에 포함된 UUID)
secure_ntfs UUID=8d9c74cb-a4ed-4657-89de-d4017e2fcea5 /etc/cryptsetup-keys.d/secure_ntfs.key luks,nofail
3) /etc/fstab에 추가
vi /etc/fstab
/dev/mapper/secure_ntfs /mnt/secure_ntfs ntfs3 defaults,nofail 0 0
4) 적용
systemctl daemon-reexec
systemctl daemon-reload
#update-initramfs -u
cryptdisks_start secure_ntfs 2>/dev/null || true
mount -a
#!/usr/bin/env bash
set -euo pipefail
###########################################################
#
# LUKS 암호화 스크립트
#
# by hasu0707@gmail.com
#
###########################################################
usage() {
cat <<'EOF'
Usage:
./encrypt_disk.sh --name <crypt_name> --fs <ext4|ntfs> [--mount <mount_point>] [-f] <device>
Example:
./encrypt_disk.sh --name secure_ntfs --fs ntfs /dev/sda4
./encrypt_disk.sh -f --name secure_ext4 --fs ext4 --mount /secure /dev/sdb1
Options:
--name cryptsetup mapper name
--fs filesystem type: ext4 or ntfs
--mount mount point, default: /mnt/<crypt_name>
-f force mode, skip confirmation
-h show this help
EOF
}
die() {
echo "ERROR: $*" >&2
exit 1
}
info() {
echo "INFO: $*"
}
require_root() {
# root 권한이 아니면 디스크 초기화, LUKS 생성, fstab 수정 등이 불가능하므로 중단
[[ "${EUID}" -eq 0 ]] || die "This script must be run as root."
}
parse_args() {
FORCE=0
CRYPT_NAME=""
FS_TYPE=""
MOUNT_POINT=""
DEVICE=""
# 명령행 파라미터 파싱
while [[ $# -gt 0 ]]; do
case "$1" in
--name)
CRYPT_NAME="${2:-}"
shift 2
;;
--fs)
FS_TYPE="${2:-}"
shift 2
;;
--mount)
MOUNT_POINT="${2:-}"
shift 2
;;
-f|--force)
FORCE=1
shift
;;
-h|--help)
usage
exit 0
;;
-*)
die "Unknown option: $1"
;;
*)
DEVICE="$1"
shift
;;
esac
done
[[ -n "$CRYPT_NAME" ]] || die "--name is required."
[[ -n "$FS_TYPE" ]] || die "--fs is required."
[[ -n "$DEVICE" ]] || die "Device is required."
[[ -b "$DEVICE" ]] || die "Device does not exist or is not a block device: $DEVICE"
[[ "$FS_TYPE" == "ext4" || "$FS_TYPE" == "ntfs" ]] || die "--fs must be ext4 or ntfs."
# 마운트 경로가 지정되지 않으면 cryptsetup name 기준으로 기본 경로 설정
if [[ -z "$MOUNT_POINT" ]]; then
MOUNT_POINT="/mnt/$CRYPT_NAME"
fi
}
check_command() {
local cmd="$1"
# 명령어 존재 여부 검사
command -v "$cmd" >/dev/null 2>&1 || die "Required command not found: $cmd"
}
check_package() {
local pkg="$1"
# dpkg 기준 패키지 설치 상태 검사
dpkg-query -W -f='${Status}' "$pkg" 2>/dev/null | grep -q "install ok installed" \
|| die "Required package is not installed: $pkg"
}
check_requirements() {
# 공통 필수 명령어 검사
check_command wipefs
check_command dd
check_command blkid
check_command lsblk
check_command findmnt
check_command mount
check_command umount
check_command cryptsetup
check_command systemctl
check_command systemd-cryptsetup
# 공통 필수 패키지 검사
check_package util-linux
check_package cryptsetup
check_package cryptsetup-initramfs
check_package systemd
# 파일시스템별 필수 명령어 및 패키지 검사
case "$FS_TYPE" in
ext4)
check_command mkfs.ext4
check_package e2fsprogs
;;
ntfs)
check_command mkfs.ntfs
check_command ntfs-3g
check_package ntfs-3g
;;
esac
}
confirm_execution() {
# -f 옵션이 없는 경우 대문자 YES 입력 시에만 실행
if [[ "$FORCE" -eq 1 ]]; then
return
fi
echo "WARNING: This operation will permanently erase all data on: $DEVICE"
echo "Type YES to continue:"
read -r answer
[[ "$answer" == "YES" ]] || die "Confirmation failed. Aborted."
}
unmount_node() {
local node="$1"
local targets
# 특정 블록 디바이스가 마운트된 위치 조회
mapfile -t targets < <(findmnt -rn -S "$node" -o TARGET 2>/dev/null || true)
for target in "${targets[@]}"; do
info "Unmounting $target"
umount "$target" || die "Failed to unmount: $target"
done
}
unmount_related_devices() {
local nodes
# 파티션 또는 디스크 하위 디바이스를 역순으로 조회하여 하위부터 언마운트
mapfile -t nodes < <(lsblk -nrpo NAME "$DEVICE" | tac)
for node in "${nodes[@]}"; do
unmount_node "$node"
done
}
close_existing_luks() {
# 동일한 mapper name이 열려 있으면 우선 언마운트 후 close
if [[ -e "/dev/mapper/$CRYPT_NAME" ]]; then
unmount_node "/dev/mapper/$CRYPT_NAME"
info "Closing existing mapper: $CRYPT_NAME"
cryptsetup close "$CRYPT_NAME" || die "Failed to close mapper: $CRYPT_NAME"
fi
# 지정 디바이스 하위에 열린 crypt 타입 매핑이 있으면 모두 close
while read -r name type; do
if [[ "$type" == "crypt" ]]; then
local mapper_name
mapper_name="$(basename "$name")"
unmount_node "$name"
info "Closing existing LUKS mapper: $mapper_name"
cryptsetup close "$mapper_name" || die "Failed to close mapper: $mapper_name"
fi
done < <(lsblk -nrpo NAME,TYPE "$DEVICE")
}
wipe_device() {
# 요구사항에 따라 wipefs와 dd를 모두 수행하여 기존 시그니처와 헤더를 제거
info "Wiping filesystem signatures on $DEVICE"
wipefs -a "$DEVICE" || die "wipefs failed."
info "Overwriting the beginning of $DEVICE with zeroes"
dd if=/dev/zero of="$DEVICE" bs=1M count=64 conv=fsync status=progress \
|| die "dd wipe failed."
}
create_luks_container() {
# LUKS UUID를 알기 전에는 임시 키 파일 생성
TMP_KEY="$(mktemp /root/luks-key.XXXXXX)"
chmod 600 "$TMP_KEY"
# 4096바이트 키 파일 생성
info "Generating 4096-byte key file"
dd if=/dev/urandom of="$TMP_KEY" bs=4096 count=1 status=none
chmod 400 "$TMP_KEY"
# 키 파일을 이용해 LUKS 포맷
info "Formatting $DEVICE as LUKS"
cryptsetup luksFormat "$DEVICE" "$TMP_KEY" --batch-mode \
|| die "cryptsetup luksFormat failed."
# 최종 LUKS UUID 조회
LUKS_UUID="$(cryptsetup luksUUID "$DEVICE")"
[[ -n "$LUKS_UUID" ]] || die "Failed to get LUKS UUID."
# 요구사항에 맞게 LUKS UUID 기반 키 파일 경로 생성
KEY_FILE="/etc/cryptsetup-keys.d/${LUKS_UUID}.key"
install -d -m 700 /etc/cryptsetup-keys.d
mv "$TMP_KEY" "$KEY_FILE"
chmod 400 "$KEY_FILE"
# 생성한 LUKS 컨테이너 오픈
info "Opening LUKS container as $CRYPT_NAME"
cryptsetup open "$DEVICE" "$CRYPT_NAME" --key-file "$KEY_FILE" \
|| die "cryptsetup open failed."
}
create_filesystem() {
local mapper="/dev/mapper/$CRYPT_NAME"
# 선택한 파일시스템 타입에 따라 내부 파일시스템 생성
case "$FS_TYPE" in
ext4)
info "Creating ext4 filesystem"
mkfs.ext4 -F "$mapper" || die "mkfs.ext4 failed."
FSTAB_TYPE="ext4"
FSTAB_OPTIONS="defaults,nofail"
FSTAB_PASS="2"
;;
ntfs)
info "Creating NTFS filesystem"
mkfs.ntfs -F -Q "$mapper" || die "mkfs.ntfs failed."
FSTAB_TYPE="ntfs-3g"
FSTAB_OPTIONS="defaults,nofail,uid=0,gid=0,umask=022"
FSTAB_PASS="0"
;;
esac
# fstab에는 내부 파일시스템 UUID를 사용
FS_UUID="$(blkid -s UUID -o value "$mapper")"
[[ -n "$FS_UUID" ]] || die "Failed to get filesystem UUID."
}
create_backup() {
BACKUP_DIR="/var/backup/cryptsetup/$LUKS_UUID"
install -d -m 700 "$BACKUP_DIR"
info "Creating backup files in $BACKUP_DIR"
# LUKS 헤더 백업
cryptsetup luksHeaderBackup "$DEVICE" \
--header-backup-file "$BACKUP_DIR/luksHeader"
# LUKS 정보 및 시스템 블록 디바이스 정보 백업
cryptsetup luksDump "$DEVICE" > "$BACKUP_DIR/luksDump"
blkid > "$BACKUP_DIR/blkid.txt"
lsblk -f > "$BACKUP_DIR/lsblk.txt"
# 변경 전 설정 파일 백업
cp -a /etc/crypttab "$BACKUP_DIR/crypttab.before" 2>/dev/null || true
cp -a /etc/fstab "$BACKUP_DIR/fstab.before" 2>/dev/null || true
}
update_crypttab() {
local line
line="${CRYPT_NAME} UUID=${LUKS_UUID} ${KEY_FILE} luks"
info "Updating /etc/crypttab"
touch /etc/crypttab
# 동일 mapper name 또는 동일 LUKS UUID가 있으면 중복 방지를 위해 제거
sed -i.bak \
-e "/^${CRYPT_NAME}[[:space:]]/d" \
-e "/UUID=${LUKS_UUID}[[:space:]]/d" \
/etc/crypttab
echo "$line" >> /etc/crypttab
}
update_fstab() {
local line
line="UUID=${FS_UUID} ${MOUNT_POINT} ${FSTAB_TYPE} ${FSTAB_OPTIONS} 0 ${FSTAB_PASS}"
info "Updating /etc/fstab"
install -d -m 755 "$MOUNT_POINT"
touch /etc/fstab
# 동일 마운트포인트 또는 동일 파일시스템 UUID가 있으면 중복 방지를 위해 제거
sed -i.bak \
-e "\|[[:space:]]${MOUNT_POINT}[[:space:]]|d" \
-e "/^UUID=${FS_UUID}[[:space:]]/d" \
/etc/fstab
echo "$line" >> /etc/fstab
}
backup_final_configs() {
# 변경 완료 후 최종 설정 파일 백업
cp -a /etc/crypttab "$BACKUP_DIR/crypttab"
cp -a /etc/fstab "$BACKUP_DIR/fstab"
}
reload_systemd() {
# crypttab/fstab 변경 후 systemd generator 결과를 즉시 반영하도록 daemon reload
info "Reloading systemd daemon"
systemctl daemon-reload || die "systemctl daemon-reload failed."
}
mount_volume() {
# fstab 기준으로 마운트 테스트
info "Mounting $MOUNT_POINT"
mount "$MOUNT_POINT" || die "Failed to mount: $MOUNT_POINT"
}
update_initramfs_if_available() {
# cryptsetup-initramfs가 설치된 환경에서 부팅 초기 단계 반영
if command -v update-initramfs >/dev/null 2>&1; then
info "Updating initramfs"
update-initramfs -u || die "update-initramfs failed."
fi
}
main() {
if [[ $# -eq 0 ]]; then
usage
exit 1
fi
parse_args "$@"
require_root
check_requirements
confirm_execution
info "Target device: $DEVICE"
info "Mapper name: $CRYPT_NAME"
info "Filesystem: $FS_TYPE"
info "Mount point: $MOUNT_POINT"
unmount_related_devices
close_existing_luks
wipe_device
create_luks_container
create_filesystem
create_backup
update_crypttab
update_fstab
backup_final_configs
reload_systemd
mount_volume
update_initramfs_if_available
info "Encryption completed successfully."
info "LUKS UUID: $LUKS_UUID"
info "Filesystem UUID: $FS_UUID"
info "Key file: $KEY_FILE"
info "Backup directory: $BACKUP_DIR"
info "Mount point: $MOUNT_POINT"
}
main "$@"