container VS vm
기존에 있던 VirtureMachine 은 하드웨어를 가상화 해서, 한 머신에서 여러 서버를 구동시킬 수 있다.
hypervisor 에서 여러 머신을 구동할 수 있게 해주기 때문에다.
근데 머신에 사용되는 각각의 os image 를 올리기 때문에, 메모리, 저장장치에서 overhead 를 추가시킨다.
이런 VM 과는 달리, container 는 호스트 os, 커널 , 바이너리, 라이브러리를 공유해서
vm 과는 다르게, 가볍고 빠르다. 프로세스의 실행환경을 격리하기 때문이다
host 커널과 container 의 커널이 달라도, 다른 부분만 패키징 해서 커널이 다른 container 도 쓸 수 있다.
하지만, 가볍다고 장점만 있는 것은 아니다. container 은, host os 를 가상화해서 올리고, 커널을 공유하게 되는데,
이 때, 완전히 격리된 상태가 아니기 때문에, host 커널이 보안에 취약해질 수 있다.
docker
docker 는 , 컨테이너형 가상화를 지원하는 플랫폼이다.
docker 설치
curl -s https://get.docker.com | sudo sh
https://get.docker.com 에는 알아서 도커를 설치해주는 쉘 스크립트가 있다.
이 스크립트를 파이프를 통해 sh 로 넘겨주면, 도커가 설치가 된다.
근데 이런 형태의 명령은, 사이트에 있는 쉘 스크립트를 그대로 실행시켜주기 때문에,
안전한 사이트가 아니면 저런 형태의 명령어를 사용하는 것은 비추한다.
docker 는 앞에 sudo 를 붙여 관리자 권한으로 실행해야 하는데,
sudo usermod -aG docker $USER
sudo su - $USER
docker 그룹에 지금 사용자를 추가하면, sudo 없이도 사용할 수 있다고 한다.
docker 실행과정
docker image 준비
docker 은 vm 과 마찬가지로 image 를 이용해 컨테이너를 생성한다.
docker image 는 docker 에서 공식적으로 제공되는 UBUNTU, DEBIAN, MYSQL 등의 이미지가 있고,
사람들이 이런 base image 를 이용해 만든 다른 이미지파일을 docker hub 에 올리기도 한다.
하지만 이런 생 이미지를 다운받아 컨테이너로 사용한다면, 사용해야할 각종 툴들도 설치해야 하는데,
컨테이너는 휘발성이다. 그래서 사람들은 Dockerfile 을 이용해 base image 에 세팅을 한 뒤,
이미지로 빌드해 사용하곤 한다.
FROM MAINTAINERRUN CMD LABEL EXPOSEENV ADDCOPY ENTRYPOINT VOLUME USER WORKDIR ARG ONBUILD SHELL ... 등의 명령어로 이루어져 있다.
docker 컨테이너 실행
docker run <이미지> 를 이용해 컨테이너를 생성할 수 있다.
-it 옵션은 터미널과 상호작용하기 위한 옵션,
-v 현재경로:컨테이너경로, 디렉터리를 마운트해서 호스트와 컨테이너가 폴더를 공유할 수 있다.
-d 백그라운드 모드
--name 컨테이너 이름 설정
docker-compose
ctf 에 문제를 낼 때는, 보통 한 개가 아니라 여러개를 내게 된다.
이 때, 도커를 하나하나 설정하는 것이 아니라, docker-compose 를 이용해 한꺼번에 키고 끌 수 있다.
service 명, build 경로, ports 를 지정해주는 docker-compose.yml 파일을 작성하고,
(Dockerfile 에서 ARG 를 사용한다면, docker-compose.yml 에서 넘겨줄 수 있다)
docker-compose up ( -d 백그라운드 ) ( --build 바뀐점 빌드 )
docker-compose down
이렇게 닫고 열 수 있다.
pwnable 문제 deploy
간단하게 race condition 기초 pwnable 문제를 deploy 해보장.
폴더구조는 다음과 같다. 소스파일과 익스파일은 현재 경로에 놔두고,
문제서버에 필요한 바이너리파일, flag 는 share 폴더에 놔둔다.
settings/race.xinetd
기본적인 구조를 가지고 있다. 유저는 waylab 이고, 서버는 run.sh 인데, docker 파일에서 만드는 파일이다.
Dockerfile
급하게 짜느라 조잡하게 했다.
xinetd 를 설치하고, TERM 환경변수를 xterm 으로 설정해준다. (안쓰면 에러남)
user waylab 과 홈디렉터리를 만들고, share 에 있는 바이너리와 플레그를 옮긴 뒤
바이너리 timeout 을 설정해주는 run.sh 를 만든다.
권한도 설정해주고, 아까 settings/race.xinetd 을 /etc/xinetd.d/race 로 옮겨준다.
현재 폴더의 이름은 race 이다.
상위 폴더에 docker-compose.yml 파일을 다음과 같이 작성해주고,
docker-compose up -d --build 명령어로 도커들을 실행시켜주면
잘 실행된다. 외부접속도 잘 된다.
https://www.n1net4il.kr/posts/how-to-run-docker-for-ctf
n1net4il 님의 도커파일을 보면, 미러서버도 설정해주고 하는 것을 볼 수 있다.
ARG 를 통해 인자를 이용하므로 docker-compose.yml 파일을 통해 dockerfile 을 편하게 수정할 수 있다.
!!주의사항
포너블 문제를 낼 때, 드림핵과 같이 setvbuf 함수로 버퍼를 설정해줘야 메시지가 바로 출력된다.
(리눅스 기본 버퍼링설정때문)
설정하지 않으면 메시지가 안 뜨고 입력만 받게된다. (setvbuf(stdin/stdout,0,2,0)
python 으로 문제파일을 낼 때도, 버퍼링 설정을 해줘야한다.
또한, 아까 말했다싶이 Dockerfile 에 ENV TERM xterm 을 명시해줘야한다.
참고
docker
https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html
https://medium.com/@darkrasid/docker%EC%99%80-vm-d95d60e56fdd
https://www.44bits.io/ko/post/easy-deploy-with-docker
https://subicura.com/2017/01/19/docker-guide-for-beginners-1.html