저자: 제프 다이크(Jeff Dike)
유저-모드 리눅스(UML)는 "소프트웨어" 머신의 일종으로 리눅스를 부팅하는 리눅스에서 돌아가는 리눅스 가상 머신이다. 이것은 가상 머신이기 때문에 프로그램의 생성 및 파괴가 용이하며 사실상 물리적인 시스템과 거의 똑 같은 수준으로 프로그램을 수행할 수 있다. 이와 같은 UML의 능력으로 인해 UML의 용도는 과거에 비해 훨씬 다양해졌다. 나는 이 기사에서 당연히 주목 받아야 하지만 주목 대상의 근처에도 가보지 못한 애플리케이션에 대해 이야기 하려고 한다.
UML 가상 머신은 설정 및 부팅이 아주 쉽다는 점을 제외하고는 실제 물리적 머신과 아주 흡사하다. 따라서 시스템 관리자들을 훈련하고 연습시키는 데에는 아주 이상적인 도구라고 할 수 있다. 특히 관리자들이 최악의 상태를 생성해내고 그 재해 복구 연습을 해보는 데 아주 적합하도록 만들어졌다. 나는 세 가지 재해 상황을 만들어내고 그것을 복구하는 방법에 대해 기술할 것이다. 보너스로 재해만 만들고 복구는 하지 않은 네 번째 상황도 연출해 낼 것이다.
우선 여러분이 가장 먼저 해야 할 일은 UML을 다운받아서 설치하는 것이다.
http://user-mode-linux.sourceforge.net/dl-sf.html에 가면 UML RPM과 deb을 다운받을 수 있다. 이것들 중 여러분의 시스템에 적합한 것을 골라서 설치하면 된다. 다운로드 받은 프로그램에는 UML뿐만 아니라 추가로 여러 가지 다른 유틸리티도 있을 것이다. UML을 부팅시키려면 파일시스템 이미지도 필요한데 이것도 역시 같은 페이지에서 다운 받을 수 있다. 참고로 이 기사의 예제는 데비안 루트 파일시스템을 사용하여 만든 것이다. 만약 시스템이 데비안 루트 파일시스템을 다운 받기에 대역폭이 너무 짧으면 대신에 tomsrtbt 파일시스템을 다운받아도 된다.
그 모든 파일들이 어디로 갔지?
여러분이 UML을 사용하는 것에 익숙해지도록 특별하게 재해부터 설명하는 것으로 이 기사를 시작할 것이다. 그리고 그 재해를 복구해보지는 않을 생각이다. 여러분이 숙련된 UML 유저라 할지라도 어떻게 해서든지 평소에는 정말 해보고 싶었던 것이기 때문에 아마 이와 같은 재해 상황을 모두 따라 해볼 것이라 생각된다.
그냥 무슨 일이 일어날지 알아보기 위해 rm -rf /를 실행해 보자.
그러면 UML은 다음과 같이 시작된다.
이것은 UML이 root_fs 파일에서 cow 파일과 함께 부팅되었다는 것을 말하는 것으로 cow 파일은 root_fs 파일 상위의 copy-on-write (COW) 층을 뜻한다. 파일명 cow는 임의적인 것이며 자동적으로 생성된 것이므로 일관성을 유지하는 한 다른 파일명을 사용할 수도 있다. 우리는 이것과 관련된 유틸리티를 나중에 살펴볼 것이다. 압축을 풀면 root_fs_debian2.2_small 또는 root_fs_tomrtbt_1.7.205 중에서 하나로 루트 파일시스템의 이름이 붙여질 것이다. 이 이름 역시 축약형인 root_fs로 이름을 바꾸어 실제 이름처럼 사용할 수 있다.
부팅이 되면 콘솔 출력으로 아래와 같이 보이는 라인을 적어넣어 보자.
mconsole initialized on /tmp/uml/d4oIw6/mconsole
|
로그인 프롬프트에 루트(패스워드 "root")로 로그인 하여 아래와 같이 실행해 보자.
usermode:~# cd /
usermode:/# rm -rf /
|
모든 것들이 심각하게 망가질 때까지 단계를 높여서 계속해 보자. UML 사이트로부터 데비안 파일시스템과 함께 결국은 아래와 같은 메시지를 받을 것이다.
rm: cannot remove directory "//dev/pty": Directory not empty
rm: WARNING: Circular directory structure.
This almost certainly means that you have a corrupted file system.
NOTIFY YOUR SYSTEM MANAGER.
The following two directories have the same inode number:
//dev
//dev/pts
|
여러분이 병적인 타입이라면 포기하지 않고 여전히 취할 수 있는 조치가 있는지 살펴볼 것이다. 여러분이 자주 사용하는 유틸리티들이 없어졌을지도 모르기 때문에 아마도 내장 bash가 필요할 것이다.
시스템을 휴지통처럼 완전히 망쳐놓았다면 확실하게 시스템을 닫아야 한다. halt가 작동하지 않기 때문에 최선의 방법은 시스템을 중지시키는 uml_mconsole 유틸리티를 사용하는 것이다. 호스트에서 uml_mconsole를 실행시키고 부팅될 때 주의 깊은 메모를 남길 수 있는 디렉토리 이름을 부여한다. 그러면 그것은 UML을 중지시킬 것을 명령할 것이다.
% uml_mconsole d4oIw6
(d4oIw6) halt
OK
|
이제 여러분은 우리가 왜 COW 파일을 사용했는지 눈치챘을 것이다. 파일시스템에 입힌 피해는 모두 COW 파일 내에 있는 것들과 연관되어 있다. COW 파일 하부에 있는 root_fs 파일에는 어떠한 피해도 가지 않은 상태이다. 이것을 보기위해 COW 파일을 끄집어낼 수 있다.
그리고 방금 여러분이 했던 대로 UML을 부팅시켜보자.
여러분은 부팅이 성공적으로 실행되고 파일시스템이 전혀 손상되지 않은 것을 발견할 것이다. 우리는 실제 파일시스템에는 돌이킬 수 없는 손상을 입히지 않고 재해를 생성해 낼 경우 이와 같은 기술을 사용할 수 있다.
패스워드 파일을 잃어버린 경우
이제부터는 상대적으로 간단한 재해상황을 연출하여 그것을 복구해보도록 할 것이다.
% rm cow
% linux ubd0=cow,root_fs
|
패스워드 파일을 없앤 후에 머신을 중지시켜보자.
usermode:~# rm /etc/passwd
usermode:~# halt
You don"t exist. Go away.
|
halt는 이제 더 이상 작동하지 않는다. 따라서 우리는 mconsole에서 닫아야 한다.
uml_mconsole zJwanV
(zJwanV) sysrq u
OK
(zJwanV) halt
OK
|
sysrq u는 파일시스템을 디스크로 비우고 그것들을 읽기 전용으로 재탑재할 것이다. 이것은 다음 부팅에 대비하여 우리가 fsck를 저장하도록 해줄 것이다. 다시 부팅해보자. 이번에는 명령 라인에 cow 파일만을 기입할 것이다.
이제 우리는 패스워드 파일 없이도 리눅스가 얼마나 잘 작동하는지를 볼 것이다.
Debian GNU/Linux 2.2 usermode ttys/0
usermode login: root
Password:
Login incorrect
|
부팅은 성공적으로 실행되었지만 놀랍게도 로그인은 할 수 없다. 따라서 이것을 mconsole에서 다시 한 번 닫은 후 고쳐보도록 하자.
uml_mconsole b9cpus
(b9cpus) sysrq u
OK
(b9cpus) halt
OK
|
우리는 단일 유저로만 부팅하여 루트가 로그인 할 수 있게 패스워드 파일을 잠시 쉬게 할 것이다.
분포는 single의 해석에 따라 달라진다. single로 셸을 얻을 수 없다면 대신에 emergency를 시도해 보자. 데비안 파일시스템은 두 가지 모두 셸을 제공한다.
/etc/passwd: No such file or directory
Give root password for maintenance
(or type Control-D for normal startup):
|
리턴을 치는 것을 포함하여 여기 있는 모든 것들이 실행되는 것처럼 보인다.
sh-2.03# cat > /etc/passwd
sh: /etc/passwd: Read-only file system
|
하지만 여기에도 문제는 있으며 그 첫번째는 다음과 같다. 우리는 이외에 어떤 것을 실행하기 전에 루트 파일시스템 읽기/쓰기를 리마운트 할 필요가 있다.
sh-2.03# mount / -o remount
|
이제 예정된 재해로 돌아가보자. 우리는 여기서 cat을 사용할 수 있다. 하지만 vi를 더 선호한다면 vi를 사용해도 된다.
sh-2.03# cat > /etc/passwd
root::0:0:root:/root:/bin/bash
^D
|
지금까지 잘 해왔다. 유틸리티가 패스워드 파일을 좋게 생각하는지 확실히 해두기 위해 점검을 해보자.
점검 결과도 좋으니 이제 기존의 단일 유저 셸로 부팅을 해보자.
그리고 루트로 로그인 할 수 있는지 알아보자.
Debian GNU/Linux 2.2 usermode ttys/0
usermode login: root
Last login: Tue Nov 13 18:28:32 2001 on ttys/0
Linux usermode 2.4.13-1um #2 Fri Oct 26 15:42:47 EDT 2001 i686 unknown
usermode:~#
|
성공이다. 루트로 다시 로그인 할 수 있게 되었다. 만약 이것이 가상 머신이 아닌 실제 머신에서 발생한 일이라면 여러분이 다음에 할 일은 가장 최근의 백업 테잎을 추적하여 /etc/passwd에 다시 복원하는 것이다.
셸이 없는 경우
이번에는 단일 사용자 모드로 부팅한다 해도 수정될 수 없는 bash를 제거해 보자.
이 기사를 작성중일 때 나는 UML 블록 드라이버에 버그가 있다는 사실을 발견했다. 이것은 COW 파일이 루트 파일시스템으로 마운트되지 않았을 경우 COW 파일의 실행을 부적절하게 만들어 준다. 따라서 우리는 잠시동안 이것을 사용하지 않을 것이다.
root_fs을 no_bash으로 복사하여 부팅하고 로그인 한 후 bash를 삭제하자.
% cp root_fs no_bash
% linux ubd0=no_bash
usermode:~# rm /bin/bash
usermode:~# halt
|
만일 정지되는 것이 지연되면 mconsole로 UML을 중단시키자. 다시 부팅시키고 셸 없이 어떻게 실행하는지 살펴보자.
부팅은 아주 빨리 되었으며 로그인도 불가능하게 되었다.
INIT: cannot execute "/etc/init.d/rcS"
INIT: Entering runlevel: 2
INIT: cannot execute "/etc/init.d/rc"
Debian GNU/Linux 2.2 (none) ttys/0
(none) login: root
Unable to determine your tty name.
|
따라서 우리는 이제 mconsole로 닫아야만 하고 어떻게 고칠 지에 대해 생각해보아야 한다.
우리는 구조 디스크에서 부팅을 시뮬레이션 할 것이다. 우리는 구조 디스크로서 root_fs을 사용할 것이며 디스크 0으로 할당할 것이다. 그리고 손상된 파일시스템은 디스크 1로 옮길 것이다.
% linux ubd0=root_fs ubd1=no_bash
|
그러면 이제 로그인하여 /mnt에 손상된 파일시스템을 마운트하고 bash를 없애도록 하자.
usermode:~# mount /dev/ubd/1 /mnt
usermode:~# ls /mnt/bin/bash
ls: /mnt/bin/bash: No such file or directory
|
이제 훨씬 고치기 쉬워진 것을 발견할 수 있을 것이다. 그리고 여러분은 다음과 같이 구조 디스크에서 셸을 복사할 수 있다.
usermode:~# cp -p /bin/bash /mnt/bin/bash
usermode:~# ls -l /bin/bash /mnt/bin/bash
-rwxr-xr-x 1 root root 461400 Feb 20 2000 /bin/bash
-rwxr-xr-x 1 root root 461400 Feb 20 2000 /mnt/bin/bash
|
이제 여러분은 UML을 중지할 수 있으며 no_bash에서 다시 OK를 부팅한다는 것을 확인하기 위해 부팅할 수 있다.
백업! 백업! 백업!
이제 마지막으로 파일시스템을 백업하고 백업한 것의 대부분을 파괴하여 백업한 것을 복원함으로써 수정하는 작업을 실시해 볼 것이다. 백업 장치는 파일시스템을 가지기에 충분할 정도로 거대한 빈 파일이 될 것이다.
% dd if=/dev/zero of=backup seek=600 bs=$((1024*1024)) count=1
|
내 파일시스템은 이제 막 500 메가바이트를 넘어섰기 때문에 나는 백업 포맷의 오버헤드를 수용할 수 있는 600 메가바이트짜리 백업 파일을 만들었다. 따라서 위 라인에서 보이는 seek=600은 여러분에게 적합하게끔 그 사이즈를 여러분이 조정할 수 있다. 이제 root_fs를 trashed에 복사하고 디스크1의 backup으로 복사하여라.
% cp root_fs trashed
% linux ubd0=trashed ubd1=backup
|
로그인 하여 /dev/ubd/1에서 백업하여라. 여기서 나는 tar를 사용할 것이다. 만약 여러분이 자주 사용하는 다른 백업 도구가 있다면 그것을 사용해도 상관없다. 우리가 이 디바이스에 파일시스템을 만드는 것이 아니라는 점만 명심하기 바란다. 그것은 테잎이 사용된 것과 아주 똑같은 방법으로 처리하지 않은 데이터 디바이스로 사용되었다.
만약 I/O 에러로 인해 실패했다면 여러분이 만든 백업 파일이 너무 작다는 뜻이다. 이때는 단순히 더 큰 seek 인자와 함께 파일에 dd를 실행시키고 백업을 재시도함으로써 확장할 수 있다.
usermode:~# tar clf /dev/ubd/1 /
tar: Removing leading "/" from member names
tar: Removing leading "/" from link names
|
이 작업이 다 끝나면 우리는 그 이름에 딱 맞는 "trashed(휴지들)"를 만들게 될 것이다.
usermode:~# rm -rf /bin /lib /usr/lib
|
여러분이 없애고 싶은 것을 삭제해라. 여기서도 마찬가지로 여러분이 내키는 대로 파일을 망가뜨려 놓을 수 있다. 신나게 망치는 작업을 하고 난 후 필요하다면 mconsole을 사용하여 시스템을 닫아보자.
백업을 사용해 재해를 복구할 시간이다. 구조 디스크의 root_fs, 또다시 디스크 1의 backup, 디스크 2의 trashed로 UML을 부팅시키자.
% linux ubd0=root_fs ubd1=backup ubd2=trashed
|
로그인하여 /mnt, cd에 손상된 파일시스템을 마운트하고 백업한 것을 복원하자.
usermode:~# mount /dev/ubd/2 /mnt
usermode:~# cd /mnt
usermode:/mnt# tar xpf /dev/ubd/1
tar: : Cannot mkdir: No such file or directory
tar: Error exit delayed from previous errors
|
에러가 발생했음에도 불구하고 성공했다.
usermode:/mnt# ls bin
arch dd fgrep ls pidof run-parts touch
...
|
이제 우리는 UML을 중단하고 "trashed"에서 다시 부팅함으로써 재해를 복구할 수 있다는 것을 점검할 수 있다.
결론
다행스럽게도 이 기사는 UML이 귀중한 시스템 관리 도구가 될 수 있음을 알려주고 있다. 이 기사에서 나는 다양한 종류의 시스템 관리 재해 상황을 연출해내고 또 복구하는 과정을 설명했다.
명백하게도 여기에서 제시된 예들은 실재 상황에서 발생할 수 있는 여러 가지 재해 중 아주 작은 부분만을 보여준 것에 불과하다. 하지만 여기에서처럼 재해를 만들어 그것을 고쳐보려고 노력하는 과정이야말로 실재 재해에 미리 대비하는 가장 좋은 방법이라고 확신한다. 이러한 재해 상황 연출과 재해 복구를 실제 머신에서 일어나게 하는 것은 불가능하지만 UML로 시뮬레이션 시켜볼 수 있기 때문에 이 방법이야 말로 아주 편리하고 실제 머신에서와 거의 똑같이 실습해볼 수 있는 기회라는 것은 확실하다. 이 디바이스는 이름은 다를지 몰라도 그 실행절차는 실제 머신과 아주 똑같기 때문이다.
이 기사를 발표함과 동시에 나는
http://user-mode-linux.sourceforge.net/sdotm.html라는 UML 웹사이트에 이 달의 시스템 관리 재해를 개시하고 있다. 나는 그곳에서 각종 재해상황을 발표하고 해결방법을 모을 것이다. 그리고 독창성, 정교함, 간결성, 절제성과 같은 내가 선정한 기준에 근거하여 매달 수상자를 발표할 것이다. 물론 제시된 재해에 대한 감수도 받을 것이다. 만약 여러분이 꾸며보고 싶은 재해가 있다면 제시된 해결책을 따라 그것을 감수해 보도록 하여라.