메뉴 건너뛰기

Hodol's Blog

우분투 VPS 에서 DM-Crypt를 이용하여 암호화 볼륨 생성하기

https://www.digitalocean.com/community/tutorials/how-to-use-dm-crypt-to-create-an-encrypted-volume-on-an-ubuntu-vps

목차

역자의 말 : TrueCrypt 프로젝트가 중단되면서 이를 대체할 암호화 모듈이 필요했습니다. 특히 파일 단위 암호화가 가능한 모듈이 필요했는데 - 파티션 단위나 디스크 단위는 너무 부담스럽잖아요 - 적당한 모듈을 검색하던 중 DM-Crypt를 이용하여 파일 단위 암호화 볼륨을 생성하고 사용하는 것에 대한 웹페이지를 찾게 되었습니다. 새로운 것도 배울 겸, 영어 공부도 할 겸, 겸사겸사 모드로 번역을 해보았습니다. 영어를 잘 하지 못해서 대부분 의역을 해버렸네요. 오역, 오탈자, 잘못된 부분 지적과 추가 설명 등 모두 환영합니다. 댓글로 남겨주시길 바랍니다. (광고 댓글 때문에, 댓글을 쓰더라도 바로 공개가 되지 않으니 이점 양해바랍니다.)

좋은 글 써주신 Justin Ellingwood 님께 감사드립니다.


소개

인터넷 접속이 가능한 컴퓨터에 저장된 데이터들의 보안은 중요한 사항이다. 비록 모든 스토리지 제공자가 데이터 보안에 신경을 써야하지만, 당신의 서버에서 실행 중인 소프트웨어의 결함이나 사회 공학적 기법 또는 많은 다른 실수들로 인해 허락되지 않은 데이터 접근이 발생하기도 한다. 간단히 말해, 감당하기 힘든 상황에 빠지는 것이 싫다면 암호화 기술과 데이터 보안 기술을 익혀둘 필요가 있다.

리눅스 시스템에서는 데이터를 암호화하는 많은 방법이 있다. 이들 중, 대부분의 암호화 방법들은 암호화된 파티션, 장치 또는 파일 시스템에 의존하고 있다. VPS 시스템을 다룬다면 이러한 (파티션, 장비, 파일시스템에 의존하는) 방식은 적당하지 않다. 하지만, 마치 암호화된 스토리지 장치처럼 작동하는 파일(*)을 생성하는 방법 같은 것도 있다.

(역주 : 앞으로 파일(*)은 암호화된 데이터가 저장되는 파일을 의미한다. 예를 들어, 단순 텍스트 '파일'인 a.txt파일(*) 안으로 복사하여 암호화 할 수 있다. 또한 혼동을 피하기 위해 a.txt같은 경우는 '파일'이라고 부르기 보다는 '데이터'로 언급하도록 노력하겠다.)

이 가이드에서는, dm-crypt 도구를 사용하여 중요한 자료를 암호화하여 저장할 수 있는 파일을 생성하는 방법을 살펴볼 것이다. 이 암호화된 파일(*)은 마치 보통 파티션처럼 시스템에 마운트를 될 수 있다. 여기서는 우분투 12.04 VPS 배포판을 기준으로 설명할 것이지만 다른 배포판에서도 비슷한 방법으로 작업할 수 있을 것이다.

기본 개념

dm-crypt는 Transparent Disk Encryption을 제공하는 커널 수준 암호화 방식이다. 이 말은, (앞으로 만들) 암호화된 파일(*)은 마운트되면 어떠한 추가적인 작업이 필요없이 즉시 이용가능하다는 뜻이다.

대부분의 암호화 방식은 데이터를 파티션 레벨에서 암호화하는데 우리는 파일(*)을 device mapping target으로 마운트하여 사용함으로써 이 문제를 우회하여 해결할 수 있다. 이 파일(*)은 loop device처럼 마운트될 것이다. 이렇게 하면, 마치 다른 파티션이나 물리적 장치처럼 이 마운트된 (가상)장치(*)에 데이터를 저장할 수 있다.

어떠한 암호화 작업을 하더라도 장단점을 고려할 필요가 있다. 무엇보다도 암호화에는 기능수행을 위한 overhead가 포함된다.(역주 : 저장 용량을 갉아먹는다.) 이 문제는 중요할 수도 그렇지 않을 수도 있다. 규모가 큰 암호화 작업을 시작하기 전에 작은 크기의 파일(*)로 먼저 테스트하기를 권장한다.

또 다른 고려사항은 복원이다. 암호화는, 그 본연의 목적에 따라, 데이터 복원을 어렵게 만든다. 만약 비밀번호를 잊어버린다면 당신은 데이터를 '효과적으로' 잃게 된다. 또한, LUKS 헤더 데이터가 덧씌어지거나 파손되어도 데이터를 잃게 된다. 시스템이 부팅하지 않은 상황에서 암호화된 데이터에 접근하려고 한다면, 아주 복잡한 과정을 거쳐야 한다.

데이터 암호화 작업을 결정할 때는 예기치 못한 일로 데이터를 잃을 수 있다는 것을 인지하고 있어야 한다. 암호화될 데이터들을 확실히 백업을 해 두어야 하며 dm-crypt는 이러한 작업에 관한 많은 정보를 다음 URL에서 제공한다.

https://code.google.com/p/cryptsetup/wiki/FrequentlyAskedQuestions#6._Backup_and_Data_Recovery
DM-crypt Tools 설치하기

리눅스 배포판에서 커널 수준의 기능이 있지만 (이 기능을 사용자가 다룰수 있게 해주는) 인터페이스(front-end) 도구는 기본적으로 설치되어 있지 않을 수도 있다. 이 가이드의 모든 명령들은 root의 권한으로 실행하도록 하자.

우리는 로컬 패키지 인덱스를 업데이트하고 dm-crypt 도구를 설치함으로써 준비를 마칠 수 있다.

# apt-get update
# apt-get install cryptsetup
(역주 : # yum install cryptsetup //Redhat 계열)
이 명령은 dm-crypt 볼륨 작업에 필요한 모든 의존패키지와 보조 유틸리티들을 설치할 것이다.
빈 Non-Sparse 파일 생성하기

암호화된 데이터를 저장하기 위해서 스토리지 장치처럼 작동하는 파일(*)을 만들어야한다. 우리는 빈 파일(*)을 생성하길 원하지만 그 파일(*)은, 생성될 때 (설정한) 전체 크기의 용량이 제대로 할당되지 않은 Sparse 파일이어서는 안된다. 이 작업을 수행하는데는 여러가지 방법 있다.

가장 쉽고 빠른 방법은 fallocate 명령을 사용하는 것이다. 이 명령으로 원하는 만큼의 디스크 용량을 파일(*)에 즉시 할당하고 입력한 파일명을 부여할 수 있다. 예를 들어, 512MB 파일(*)을 root의 홈 디렉토리에 생성하기 위해서는 다음과 같이 입력한다.

# fallocate -l 512M /root/test1
이 방법은 아주 빠르지만, block에 있던 기존의 찌꺼기 데이터(old, deleted)를 zero 데이터 또는 random 데이터로 덧 씌우지 않는다. 이는 아마 별로 바람직하지 않은 상황인게, 우리는 사람들이 암호화된 파일의 부분이 그곳에 기록된 암호화 데이터를 포함하고 있다고 말하는 것이 가능하기를 원치않기 때문이다.(역주 : 뭔 소리여....)

다른 방법으로는 흔한(ㅡ.ㅡ;) dd 명령어를 활용하는 것이다. 이 방법을 통해 /dev/zero 가상 장치를 생성할 파일(*)에 디스크 용량을 할당하는 작업에 제공함으로써 파일 전체에 zero로 기록할 수 있다. 다음과 같은 명령을 입력함으로써 앞서와 비슷한 빈 파일(*)을 생성할 수 있다.

# dd if=/dev/zero of=/root/test2 bs=1M count=512

아니면, 당신이 실제 기록된 암호화 데이터를 흉내내는 random데이터를 사용하고 싶다면 (random 데이터로 암호화 데이터를 위장을 하고 싶다면) 당신은 random 가상 장치 중 하나를 이용할 수 있다. 이는, 특히 큰 파일을 할당할 때, 시간이 많이 걸리는데, 암호화의 목적을 고려한다면 random 장치를 사용하는 것이 아마 가장 좋은 방법일 것이다.

# dd if=/dev/urandom of=/root/test3 bs=1M count=512

/dev/random 가상 장치를 사용하는 것이 보안상 가장 안전한 방법이지만 소모되는 시간 또한 증가한다.

# dd if=/dev/random of=/root/test4 bs=1M count=512
파일 안에 dm-crypt LUKS 컨테이너 생성하기

방금 생성한 빈 파일(*)을 포맷하기 전에, 파일 안에 LUKS 파티션을 생성해야 한다. LUKS 또는 Linux Unified Key Setup은 디스크 암호화의 한 표준이다. 이것은 다른 모든 데이터가 채워질 기초 레이어이다.

dm-crypt 도구는 아주 쉬운 방법으로 이 레이어를 생성한다. 다음 명령으로 컨테이너를 생성할 수 있다.

# cryptsetup -y luksFormat /root/test1
파일(*)의 내용이 덧씌워질 거라는 경고를 보게 되는데 두세번 확인하여 실수로 다른 파일에 내용을 덧씌우는 일이 없도록 하자. 확실하다면 "YES"(역주 : 대문자)를 입력하자.

다음엔 데이터를 복호하는데 필요한 비밀번호 설정을 해야 한다. 비밀번호를 잃어버리면 파일 안에 기록된 모든 파일을 잃게되는 것을 명심하라!!! 이 비밀번호는 잃어버리지 않고 확실히 기억할 수 있는 장소에 안전히 보관해두록 하자. -y 옵션은 우리가 비밀번호를 다시 확인토록하여 잘못 입력하는 실수를 미연에 방지한다.

다음 명령으로 파일을 확인해보면, 이제 이 파일(*)은 LUKS encrypted file 임을 확인할 수 있다.

# file /root/test1
test1: LUKS encrypted file, ver 1 [aes, cbc-essiv:sha256, sha1] UUID : 1851db36-3223-4ee1-8e3e-cc65c49e05f3

이제 파일(*) 안에 컨테이너를 생성하였으니, 다음과 같은 명령어로 컨테이너를 열 수 있다.

# cryptsetup luksOpen /path/to/LUKS/file mapping_name

이 가이드의 경우에는 /root/test1 파일을 volume1이라는 이름으로 사용한다.

# cryptsetup luksOpen /root/test1 volume1
복호화를 위해 이전에 설정한 비밀번호를 입력해야 할 것이다.

위 명령은 LUKS 장치를 열고 우리가 입력한 이름으로 매핑을 하는데, 이 경우에는 /dev/mapper/volume1 이 된다. 위 명령이 기본적으로 파일(*)을 local loopback 장치로 열어서, 시스템의 다른 부분이 파일(*)을 마치 실제 장비처럼 다룰수 있도록 해준다.

파일 시스템 생성하고 마운트하기

LUKS 컨테이너를 생성하였고 시스템에서 일반 장치처럼 사용될수 있도록 컨테이너를 열었으니, 이제 보통 장치들에서와 같은 작업을 수행할 수 있다.

우선, 장치(*)를 포맷하고 새로운 파일 시스템을 구축해야 한다. 파일 시스템은 당신이 원하는 무엇이든지 가능하다. 이 가이드에서는 standard Ext4 파일 시스템을 사용할 것이지만 당신은 당신의 서버에서 작업하기 편한 파일 시스템을 사용하면 된다.

이를 위한 명령은 다음과 같다.

# mkfs.ext4 -j /dev/mapper/volume1
이제 파일 시스템에 관한 정보가 LUKS 컨테이너의 머릿 부분에 기록되었다. 이제 파일을 마치 (일반적인) 장치처럼 다룰수 있으므로 다음 작업으로 장치(*)를 마운트하는 것이 자연스럽다.

장치(*)가 마운트될 마운트 지점을 생성하자.

# mkdir /mnt/files

이제, 파일시스템을 마운트만 하면 된다.

# mount /dev/mapper/volume1 /mnt/files

이제 파일(*)이 사용가능한 파일 시스템이 된 것을 확인할 수 있다.

#df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda 59G 2.7G 54G 5% /
udev 2.0G 12K 2.0G 1% /dev
tmpfs 791M 216K 791M 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 2.0G 0 2.0G 0% /run/shm
/dev/mapper/volume1 486M 2.3M 459M 1% /mnt/files
파일(*)의 사용가능한 공간이 암호화 overhead와 파일시스템 overhead로 인해 줄어든 것을 확인할 수 있다. 하지만 아직 많은 부분이 사용가능하다.

우리가 파일(*)을 마운트한 곳에서 확인을 하면 다른 장치에서의 Ext4 파일 시스템과 정확히 일치하는 모습을 볼 수 있다.

# cd /mnt/files
# ls
lost+found

lost+found 복구 디렉토리가 생성되어 있다. 이제부터 데이터를 쓸 수 있고, 데이터들은 암호화되어 파일(*) 안에 저장될 것이다. 예를 들어, /etc 디렉토리를 마운트된 지점으로 복사를 해보자.

# cp -r /etc/* /mnt/files
파일 시스템 마운트 해제하고 LUKS 컨테이너 닫기

데이터 읽기, 쓰기를 마쳤다면, 다음 명령으로 파일시스템 마운트를 해제해 보자.

# cd
# umount /mnt/files

위 명령은 /dev/mapper/volume1 장치(*)를 마운트 지점인 /mnt/files 로부터 분리한다.

# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/vda 59G 2.7G 54G 5% /
udev 2.0G 12K 2.0G 1% /dev
tmpfs 791M 216K 791M 1% /run
none 5.0M 0 5.0M 0% /run/lock
none 2.0G 0 2.0G 0% /run/shm

그런데, 파일(*)은 아직 열려있고 시스템에서 /dev/mapper/volume1 사용가능하다.

#ls /dev/mapper/
control volume1
control 장치는 다른 매핑 장치를 생성하는데 사용되는 장치이다. 이를 무시하고 그것이 여기 있다고 가정하자.

volume1을 닫아 내용을 보호하기 위해, 파일(*)을 닫아야 하며, 원론적으로 장치 매핑을 파일(*)로부터 제거해야 한다. 이 것은 비밀번호를 다시 입력하기 전에는 파일(*)의 내용에 접근할 수 없음을 의미한다.

# cryptsetup luksClose volume1

장치 매핑 디렉토리를 확인해보면 volume1 장치가 사라진 것을 확인할 수 있다.

# ls /dev/mapper control
암호화 볼륨(*)은 이제 마운트 해제되었으며 LUKS 컨테이너도 닫혔으므로 우리의 데이터는 완벽하게 암호화되어 안전히 보관된다.
간단히 사용하기

처음부터 파일 시스템까지의 생성 과정을 마쳤다면, 암호화 볼륨(*)을 사용하고 싶을 때 다음과 같이 빠르게 작업할 수 있다.

이제 우리에겐 LUKS 파일이 있고, 원할 때면, 다음의 간단한 명령으로 LUKS 파일을 열수 있다.

# cryptsetup luksOpen /root/test1 volume1
여기서 처음에 사용했던 것과 다른 이름을 사용할 수 있으며, 이는 파일(*)이 열려 있는 경우에만 문제가 될 것이다. 비밀번호를 입력하자.

그 다음엔, 매핑된 장치를 마운트하자.

# mount /dev/mapper/volume1 /mnt/files
이제 파일(*) 안의 내용에 접근하여 읽고 쓸 수 있다.

작업이 끝났다면, 마운트 해제를 해야 할 것이다.

# umount /mnt/files

장치 마운트가 해제되었다면, LUKS 파일(*) 닫음으로서 데이터를 암호화 할 수 있다.

# cryptsetup luksClose volume1
결론

이로써 우리는 중요한 자료를 보관할 수 있는 암호화된 파일(*)을 생성할 수 있다. 성능과 사용의 편이성과 보안성 사이의 균형을 고려할 필요가 있음을 기억하길 바란다. 또한, 설정한 비밀번호는 절대 잃어버리지 않도록 다시 한번 강조한다. 왜냐하면 비밀번호 없이 데이터를 복호할 수 있는 방법은 절대로 없기 때문이다.

이 가이드가 데이터 보호에 필수적인 고려사항이 될 뿐만 아니라, 당신이 이것을 활용하여 리눅스 서버의 보안을 강화하는데 도움이 되기를 희망한다.