LUKS 기본 작업 설명

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 "$@"
위로 스크롤