1-2. 컨테이너 격리(pivot_root)

Gyullbb·2022년 3월 18일
2

K8S

목록 보기
5/5

🌈페이스북 Kubernetes Korea Group에서 진행한 '쿠버네티스 네트워크' 스터디에서 진행한 1주차 스터디 내용입니다.

1) 개요

앞서 chroot로 생성한 격리공간에는 다음과 같은 단점이 있었다.

  1. 탈옥이 가능하다.
  2. 완전한 격리가 불가능하다. (Host의 filesystems, network 등에 접근 가능)
  3. root 권한 사용 가능하다.
  4. host의 자원을 무제한으로 사용할 수 있다.

이러한 단점의 일부를 극복할 수 있는 pivot_root를 통한 격리에 대해 알아보겠다.


2) pivot_root를 이용한 프로세스 격리

pivrot_root란 root 파일시스템의 마운트 포인트를 변경함으로써 특정 디렉토리를 새로운 루트 디렉토리로 만드는 명령어이다.

앞서 chroot로 만든 격리공간은 root 파일시스템이 동일하였기 때문에 탈옥이 가능했던 한편, pivrot_root를 이용하면 root 파일시스템의 마운트 포인트 자체가 변경되기 때문에 탈옥 자체가 불가능하다.

위 그림과 같이 새로운 root 파일 시스템을 지정하고, 기존 root 파일시스템 마운트 포인트를 새로운 root 파일시스템 하위 폴더로 옮겨주는 작업을 진행해보자.


2-1) 격리 공간 생성

man pivot-root로 매뉴얼을 보면 다음과 같이 새로운 root 경로와 기존 root 경로를 제공함으로써 격리공간을 생성하게 된다.

PIVOT_ROOT(8)                           System Administration                          PIVOT_ROOT(8)

NAME
       pivot_root - change the root filesystem

SYNOPSIS
       pivot_root new_root put_old

앞 실습과 마찬가지로 격리 시킬 새로운 경로를 만든 후 nginx 이미지로 환경을 구성해주자.

# mkdir jail
# docker export $(docker create nginx:latest) | tar -C jail -xvf -

2-2) 탈옥 코드 작성 및 탈옥 확인

chroot 테스트 때 작성한 탈옥 코드를 똑같이 복사하여 실행시켜보자.

# vi escape_chroot.c
#include <sys/stat.h>
#include <unistd.h>

int main(void)
{
  mkdir(".out",0755); 
  chroot(".out");
  chdir("../../../../../");
  chroot(".");

  return execl("/bin/sh","-i",NULL);
}

[격리 공간 하위로 탈옥 코드 복사]

# apt install gcc
# gcc -o jail/escape_chroot escape_chroot.c
# ls ./jail
bin   dev   docker-entrypoint.sh  etc   lib    media  opt   root  sbin  sys  usr
boot  docker-entrypoint.d  escape_chroot  home  lib64  mnt    proc  run   srv   tmp  var

[탈옥 실행]

# chroot jail /bin/sh
# ./escape_chroot

앞 실습에서 실행했던 것과 마찬가지로 탈옥코드를 통해 격리공간을 빠져나올 수 있다.

2-3) pivot_root를 활용한 탈옥 방지

이제 pivot_root 를 활용하여 root 파일시스템 위치를 아예 바꿈으로써 탈옥이 불가능하도록 한다.

우선 새로운 root 파일시스템이 될 새로운 폴더를 생성해준 후 tmpfs 파일시스템을 새로운 폴더에 마운트시켜준다.

# mkdir new_jail
# mount -n -t tmpfs -o size=800M none ./new_jail/
# df -h /new_jail
Filesystem      Size  Used Avail Use% Mounted on
none            800M     0  800M   0% /new_jail
# mount | grep new_jail
none on /new_jail type tmpfs (rw,relatime,size=819200k)

새로운 폴더(new_jail)에 기존 jail 내부 파일들을 복사한다. 그 후 pivot_root 시 기존의 root filesystem을 mount 할 mount point로 /new_jail 하위에 old_jail/ 폴더를 생성한다.

# cp -r jail/* ./new_jail/
# mkdir ./new_jail/old_jail
# tree -L 1 ./new_jail/
./new_jail/
├── bin
...
├── escape_chroot
...
├── old_jail
...
└── var

pivot_root로 root 파일시스템의 마운트 포인트를 기존 root에서 /new_jail/old_jail로 변경할 때 호스트에 영향을 주지 않기 위해서 호스트와 newjail의 마운트 네임스페이스를 분리해야 한다.

linux의 명령어 중 네임스페이스(격리공간)을 생성하는 명령어는 unshare이다. 이 명령어를 사용하여 호스트에서부터 마운트 네임스페이스를 격리해주자.

root@ubuntu-focal:/# cd ./new_jail/
root@ubuntu-focal:/new_jail# unshare -m

마운트 네임스페이스 격리란?

프로세스와 그 자식 프로세스가 서로 다른 파일시스템 마운트 지점을 제공함으로써 자식 프로세스에서 파일 시스템을 마운트/언마운트 해도 부모 프로세스에 영향을 미치지 않는 상태를 의미한다.

마운트 네임스페이스 격리를 했으면 pivot_root명령어로 root 파일시스템의 마운트 포인트를 old_jail로 변경한다.

root@ubuntu-focal:/new_jail# pivot_root . old_jail
root@ubuntu-focal:/new_jail# cd /
root@ubuntu-focal:/# ls
bin   docker-entrypoint.d   etc   lib64  old_jail  root  srv  usr
boot  docker-entrypoint.sh  home  media  opt       run   sys  var
dev   escape_chroot         lib   mnt    proc      sbin  tmp

탈옥 코드 명령어를 실행해도 빠져나갈 수 없는 것을 확인할 수 있다.

# ./escape_chroot
# ls
bin   docker-entrypoint.d   etc   lib64  old_jail  root  srv  usr
boot  docker-entrypoint.sh  home  media  opt       run   sys  var
dev   escape_chroot         lib   mnt    proc      sbin  tmp

3) 네임스페이를 통한 격리

pivot_root 는 chroot로 만든 격리공간의 단점인 탈옥을 해결하였다. 그러나 나머지 단점들은 아직 해결이 안되었는데, 이는 네임스페이스라는 개념으로 해결할 수 있다.

  1. 탈옥이 가능하다. -> pivot_root로 해결!
  2. 완전한 격리가 불가능하다. (Host의 filesystems, network 등에 접근 가능)
  3. root 권한 사용 가능하다.
  4. host의 자원을 무제한으로 사용할 수 있다.

다음 글에서는 네임스페이스 개념과 그 종류에 대해 알아보겠다.

reference

profile
🎈도전 속의 여유를 즐기자🎈

0개의 댓글