안녕하세요 !
클라우드 기반 취약점 진단 및 대응 실무 첫 번째 정리에 대해서 써보려고 합니다 !
바로 시작하겠습니다 !
1. 도커와 마이크로서비스 이해
* 모놀리식 아키텍처
- 전통적인 아키텍처, 기존에 사용하던 서비스 방법
- 서비스가 하나의 애플리케이션으로 돌아가는 구조이다.
- 기존의 개발 방식을 사용해 개발하여서 간단하게 배포한다.
- 하나의 서비스 또는 애플리케이션이 하나의 거대한 아키텍처
- 다양한 기능을 동작하는 서비스를 서버에서 실행하여 서비스 합니다.
단점 1. 모놀리식 서비스 아키텍처를 스케일링 하면 ?!
- 기존의 애플리케이션을 그대로 복제하여 로드밸런싱을 합니다.
- 필요한 서비스까지 모두 복제해야 합니다.
단점 2. 종속적인 라이브러리의 충돌
- 각각의 기능들은 서로 다른 기능을 제공하여 버전의 종속성을 필요한 경우가 존재한다.
- 각 기능의 따른 라이브러리를 매업데이트마다 관리하기 매우 어렵다.
단점 3. 조금만 수정해도 전체 빌드 및 배포 필요
- 소스 코드 전체가 하나로써 동작하기 작은 수정만 있더라도 전체를 빌드하여서 다시 배포해야 한다.
- 프로그램의 크기가 어느정도 커지면 한 번만 컴파일 해서 전체 테스트를 돌려도 30분 내지 수 시간 소모해야 한다.
- 하루에 버그가 여러 개 순차적으로 발견되면 ? 그야말로 지옥이다.
* 마이크로서비스 아키텍처
- 모놀리식 아키텍처의 대안으로 반대되는 개념이다.
- 애플리케이션의 각각의 기능을 분리하여 개발 및 관리한다.
- 마이크로서비스 장점
서비스 단위 빠른 개발 : 개발자가 특정 비즈니스 로직에 대해서만 집중해서 개발이 가능하다.
배포가 용이하다. 개별 서비스 단위로 개발, 패키징, 빌드, 테스트, 배포로 각 서비스마다 유연한 스케줄이 가능하다.
서비스 단위 고효율 저비용 스케일 아웃 구조 : 서비스 단위로 스케일링이 가능하여 불필요한 서비스는 줄이고 많은 자원이 필요한 서비스는 확장이 가능하다.
- 분산 시스템 환경에서 트랜잭션 보장, 테스트, 배포, 관리가 복잡하다.
* 마이크로서비스 장점
- 서비스 단위 고효율 저비용 스케일 아웃 구조
-> 서비스 단위로 스케일링이 가능하여 불필요한 서비스는 줄이고 더 많은 자원이 필요한 서비스는 확장이 가능하다.
- 라이브러리 종속성 고민이 없다.
* 컨테이너로 해결할 수 있다.
- 컨테이너는 가상머신을 사용해서 각 마이크로 서비스를 격리하는 기술이다.
- 컨테이너는 가상머신처럼 하드웨어를 전부 구현하지 않기 때문에 매우 빠르게 실행이 가능합니다.
- 프로세스의 문제가 발생할 경우 컨테이너 전체를 조정해야 하기 때문에 컨테이너에 하나의 프로세스를 실행하도록 하는 것이 좋다.
* 도커
도커는 컨테이너 기반 가상화 플랫폼으로 애플리케이션을 소프트웨어 컨테이너 안에 패키징하고 실행하는 데 사용이 된다. 이것을 통해서 애플리케이션을 환경에서 독립적으로 실행할 수 있고 이식성과 확장성을 향상시킬 수 있습니다.
1. 도커 엔진 : 도커 컨테이너를 생성하고 관리하는 핵심 엔진이다. 이 엔진은 호스트 시스템에서 동작하며, 컨테이너의 빌드, 실행, 관리 등을 담당한다.
2. 도커 이미지 : 애플리케이션을 실행하기 위한 파일과 설정 등을 포함하는 템플릿이야. 이 이미지는 읽기 전용입니다. 여러 개의 컨테이너를 생성할 때 사용됩니다.
3. 도커 컨테이너 : 도커 이미지의 인스턴스로 격리된 환경에서 애플리케이션을 실행하는 실행 가능한 단위이다. 각 컨테이너는 독립된 파일 시스템, 네트워크 및 프로세스를 갖춰 서로 영향을 주지 않고 실행될 수 있습니다.
4. 도커 레지스트리 : 도커 이미지를 저장하고 공유하는데 사용되는 저장소이다. 가장 유명한 도커 레지스트리 서비스 중 하나는 도커 허브이다.
- 컨테이너 기술을 지원하는 다양한 프로젝트 중에 하나이다.
- 컨테이너 기술을 이전에도 있었으나 도커로 인해 알려졌습니다.
- 컨테이너 기술의 사실상 표준입니다.
- 2014년 가장 인기 있는 클라우드 오픈 소스 2위이다.
- 다양한 운영체제에서 사용이 가능합니다.
- 애플리케이션에 국한 되지 않고 의존성 및 파일 시스템까지 패키징하여서 빌드, 배포, 실행을 단순화 시킵니다.
- 리눅스의 네임 스페이스와 cgroups 와 같은 커널 기능을 사용해서 가상화 합니다.
* 도커는 다양한 클라우드 서비스 모델과 같이 사용 가능합니다.
- 컨테이너 : 이미지를 격리하여 독립된 공간에서 실행한 가상 환경이다.
- 이미지 : 필요한 프로그램과 라이브러리, 소스를 설치한 뒤 만든 하나의 파일이다.
* 도커 아키텍처
- 도커 엔지니어 : 이미지, 네트워크, 디스크 등의 관리 역할이다.
- 컨테이너드 : OCI 구현체를 이용해서 컨테이너를 관리해주는 데몬
- 두 프로그램이 각각 돌아가기 때문에 도커 엔지니어를 재시작해도 각 이미지에 영향이 없습니다.
* 도커 레지스토리
- 도커 레지스트리에는 사용자가 사용할 수 있도록 데이터베이스를 통해 이미지를 제공해주고 있습니다.
- 누구나 이미지를 만들어 푸시할 수 있으며 푸시된 이미지는 다른 사람들에게 공유가 가능합니다.
* 이미지 추가와 삭제에 따른 스톨리지 용량을 확보합니다.
- 도커의 이미지를 생성할 때는 만드는 매니페스트 파일의 명시된 내용을 사용하여서 어떤 이미지를 쓰는지 알립니다.
- 도커 이미지는 다양한 도커를 사용할 때 중복된 이미지를 생성하거나 삭제할 때 중복된 이미지에 대해서는 삭제하거나 생성되지 않는다.
이제부터 도커에 대해서 실습을 해보도록 하겠습니다.
1. 도커 컨테이너 기본, 웹 페이지 변경 등
현재 사진에서 보시다시피 도커와 이더넷은 서로 통신할 수 있습니다.
pull nginx 명령어로 이미지를 다운받아 옵니다.
이미지 명령어를 입력해서 nginx 에 대한 정보를 볼 수 있습니다.
$ sudo docker run --name wrb01 -d -p 8001:80 nginx 를 입력하여서 web01 파일을 생성합니다.
localhost : 8001 을 입력하면 페이지가 뜨는 것을 확인할 수 있습니다.
실제 홈페이지에서도 호스트 주소와 8001 을 입력하면 nginx 페이지가 뜨는 것을 확인할 수 있습니다.
그리고 칼리 stop , start 명령어를 입력해서 페이지를 중단하고 시작하고 할 수 있습니다.
$ sudo docker ps -a 이 명령어를 입력하면 페이지가 중단된 것까지 볼 수 있습니다.
삭제를 하기 전에 인스턴스를 중지시키고 해야 삭제가 됩니다.
이미지스를 입력하면 삭제가 되진 않았지만 컨테이너에는 삭제가 된 것을 알 수 있습니다.
컨테이너에서 이미지를 하나라도 사용하고 있다면 삭제할 수 없습니다.
이미지를 미리 다운로드 태그가 된 상태가 아니면 런이라고 입력을 해도 상관없이 실행이 됩니다.
docker images 를 입력하면 열개의 이미지 ID가 뜰 것 입니다.
거기서 더 자세하게 정보를 알고 싶다면 inspect 명령어를 입력하면 됩니다.
lowerdir 에서 있는 경로를 통해서 레이어들의 각각의 내용들을 확인할 수 있습니다.
참고로 아직 컨테이너로 동작하고 있지 않은 내용입니다.
그렇다면 다시 $ sudo docker ps 를 들어가서 하나의 ID 를 선택한 뒤에 inspect 명령어를 입력해주면
/var/lib/docker/containers/aae22c482b24896f82e05a4a74feefd57d7a9e8a3453db1aa4e761a71d42ff4f/resolv.conf
실제로 컨테이너로 동작하고 있는 운영 체제의 경로라는 것을 알 수 있습니다.
aae22c482b24896f82e05a4a74feefd57d7a9e8a3453db1aa4e761a71d42ff4f-json.log 에 실시간이 저장이 되고 로그 파일도 확인할 수 있습니다.
logs -f 명령어를 사용해서 로그 파일의 기록들을 볼 수 있습니다.
리눅스 컨테이너 파일 안으로 접속을 합니다.
도커 컨테이너 보안을 설정하지 않으면 왠만해서 root 권한으로 되어 있습니다.
/usr/share/nginx/html 으로 이동을 하고 echo 명령어로 인덱스 페이지를 만들어주면 페이지를 만들 수 있습니다.
도커 컨테이너 안에서 실행해서 페이지를 출력했습니다.
search bwapp 명령어를 입력해서 bwapp16.04 를 다운 받습니다.
명령어는 $ sudo docker run --name bwapp -d -p 8003:80 j912944946/bwapp16.04 으로 입력합니다.
$ sudo docker login 명령어를 입력해서 도커 허브에서 만들었던 아이디와 비밀번호를 입려해서 성공이 뜨게 합니다.
이번에는 커밋 명령어를 사용해서 새로운 이미지를 만들겠습니다.
commit -a 명령어를 사용하면 이미지를 하나 더 만들 수 있는데 이것이 최종 버전입니다.
태그 명령어를 입력해서 원본의 이미지에서 태그를 입력해서 새로운 이미지를 생성합니다.
$ sudo docker push rlaqjarl97/webfront:1.0 태그를 입력했던 명령어를 push 로 업로드 합니다.
그러면 이렇게 배포를 했던 결과물을 볼 수 있습니다.
그러면 이번에는 우분투 리눅스 이미지를 다운로드 받아서 컨테이너에 실행을 하고 아파치 2 서버를 설치한 뒤에 인덱스 홈페이지를 수성을 합니다. 그리고 웹 서비스가 동작하는지 확인하고 만들어진 이미지를 도커 허브에 배포한 뒤에 최종 다운로드 다른 포드로 연결해서 확인하도록 하겠습니다.
exec 로 사용해도 상관없습니다. attach 로 사용해도 상관이 없습니다. 베쉬로 들어가서 apt 로 업데이트를 해줍니다.
그런 다음에 apt install apache2 를 다운 받고 아파치를 스타트 합니다.
그리고 서비스 아파치 시작을 합니다. cd /var/www/html 으로 이동해서 기존의 인덱스 파일을 삭제하고 다시 CAT 명령어를 입력해서 index.hml 을 입력합니다. 그리고 종료 exit 를 입력해줍니다.
그리고 cp 명령어를 이용해서 밖에서도 원하는 내용을 복사해서 직접적으로 들어가지 않고 칼리 밖에서 복사한 뒤에 실행할 수 있습니다. 즉, 칼리에서 인덱스 페이지를 덮어버리겠다는 것 입니다.
그러면 기존에 인덱스 페이지에서 새롭게 다시 수정된 것을 볼 수 있습니다.
2. 도커 볼륨 및 네트워크
이번에는 볼륨을 사용해서 컨테이너가 없어지면 컨테이너 안에 있는 데이터들이 사라져버리는데 그럴 경우를 대비해서 새로운 컨테이너를 생성했을 때 데이터베이스에 연동을 바로 할 수 있도록 외부에서 연결하는 것을 볼륨. 즉, 저장소 입니다.
volume create 명령어를 입력해서 볼륨을 하나 생성합니다.
그리고 인스펙트 명령어를 이용해서 세부 정보를 확인할 수 있습니다.
마운드 포인트를 보면 경로가 나와있는데 앞으로 저 경로에 저장을 하는 것 입니다.
sudo docker run -it --name=mysql_test -e MYSQL_ROOT_PASSWORD=admin -e MYSQL_DATABASE=test -v my-data-1:/var/lib/mysql -d mysql:5.7
- e 는 환경 변수 입니다. 즉, MYSQL_ROOT_PASSWORD=admin, MYSQL_DATABASE=test MYSQL 루드 사용자 비밀번호 설정과 MYSQL 데이터베이스 테스트라는 이름의 데이터베이스를 생성한다는 뜻 입니다.
-v 볼륨이라는 뜻 입니다. my-data-1:/var/lib/mysql 호스트 시스템의 디렉토리를 컨테이너 내부의 /var/lib/mysql 디렉토리에 마운트 합니다. 이것을 통해 MySQL 데이터베이스 파일이 호스트 시스템에 저장됩니다.
-d 컨테이너를 백그라운드에서 실행한다는 뜻 입니다.
mysql:5.7 은 사용할 도커 이미지를 지정합니다. 여기서는 공식 MySQL 도커 이미지의 버전 5.7 을 사용합니다.
그리고 $ sudo docker exec -it mysql_test bash 을 입력해서 리눅스 환경으로 접속합니다. 참고로 리눅스 환경에 MYSQL 이 설치가 되어 있는 것 입니다.
show databases; 명령어를 통해서 데이터베이스에 뭐가 있는지 확인할 수 있고 create 명령어를 입력해서 test2 를 생성할 수 있습니다. 그렇다면 여기서 대체 생성한 데이터가 어디 경로에 저장이 되는지 확인하고 싶다면 아까 인스펙트 명령어를 사용해서 정보를 확인한 마운트포인트 경로에 있다는 것을 알 수 있습니다.
sudo su - 명령어를 입력해서 root 권한으로 접속해서 확인해야 합니다.
cd /var/lib/docker/volumes/my-data-1/_data 명령어를 입력해서 그 디렉토리로 이동한 뒤에 ls 명령어를 입력하면 저장했던 데이터베이스의 정보들을 확인할 수 있습니다.
여기서 컨테이너를 삭제했을 때 컨테이너 안에 있는 데이터들이 날아갈 것인데 볼륨에 저장이 되어 있기에 새로운 컨테이너하고 버전이 같기 때문에 실제로도 호환이 되어서 불러올 수 있는지 확인하도록 하겠습니다.
$ sudo docker network create webapp-net1 명령어를 입력해서 하나 더 생성합니다.
$ sudo docker stop $(sudo docker ps -q -f status=running)
$ sudo docker ps -q -f status=exited
$ sudo docker rm $(sudo docker ps -q -f status=exited)
$ sudo docker system prune -a
이 명령어들을 사용하고 다시 네트워크를 생성합니다.
$ sudo docker network create --driver=bridge --subnet 172.100.1.0/24 --gateway 172.100.1.1 vm-net
$ sudo docker run -itd -p 8002:80 --name=web02 --net=vm-net nginx
네트워크를 새로 만들고 생성될 컨테이너의 이름을 web02 로 지정한 뒤에 vm-net 이라는 도커 네트워크에 연결합니다.
그 다음은 nginx 의 이미지를 사용하게 명령어를 입력합니다.
끝
'클라우드 취약점 진단 및 대응 실무' 카테고리의 다른 글
클라우드 기반 취약점 진단 및 대응 실무 [ 네 번째 정리 ] (0) | 2024.05.30 |
---|---|
클라우드 기반 취약점 분석 및 대응 실무 [ 세 번째 정리 ] (0) | 2024.05.07 |
클라우드 기반 취약점 대응 및 실무 [두 번째 정리] (1) | 2024.05.05 |