도커는 컨테이너화된 애플리케이션을 실행할 때 매우 유용한 도구이지만, 보안 측면에서도 주의가 필요합니다. 이번 포스팅에서는 도커의 보안 개념들과 이를 실제로 적용하는 방법에 대해 살펴보겠습니다.
Rootless Mode는 도커를 루트 권한 없이 실행할 수 있게 해주는 기능입니다. 보안을 강화하기 위해 도커 데몬과 컨테이너가 비루트(non-root) 사용자로 실행되며, 호스트 시스템에 대한 접근 권한이 최소화됩니다.
루트 권한 없이 도커 실행: 루트 권한이 없기 때문에 컨테이너가 호스트 시스템에 미치는 영향을 줄입니다.
네임스페이스 활용: 사용자 네임스페이스(User Namespaces)를 활용하여 루트 권한을 격리합니다.
설치 및 설정: dockerd-rootless-setuptool.sh 스크립트를 사용하여 간단하게 설정할 수 있습니다.
보안 강화: 루트 권한 탈취 등의 보안 취약점을 줄입니다.
제한 사항: 일부 네트워크 기능이나 파일 시스템 기능이 제한될 수 있습니다.
sudo apt-get update
sudo apt-get install -y docker-ce-rootless-extras
dockerd-rootless-setuptool.sh install
export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock
docker run hello-world
Rootless 모드에서 도커가 정상적으로 실행되는지 확인합니다.
Linux Capabilities는 리눅스 커널에서 프로세스에 부여할 수 있는 특정 권한의 세트입니다. 이는 전통적인 루트 권한을 세분화하여 필요한 최소한의 권한만 부여할 수 있게 해줍니다.
CAP_CHOWN: 파일의 소유권을 변경할 수 있는 권한.
CAP_NET_ADMIN: 네트워크 인터페이스를 설정하고 관리할 수 있는 권한.
CAP_SYS_TIME: 시스템 시간을 변경할 수 있는 권한.
docker run --rm -it --cap-add=NET_ADMIN ubuntu
위 명령은 NET_ADMIN 권한을 추가하여 네트워크 인터페이스를 설정할 수 있게 합니다.
docker run --rm -it --cap-drop=ALL --cap-add=NET_ADMIN ubuntu
모든 Capabilities를 제거한 후, NET_ADMIN 권한만 추가한 컨테이너를 실행합니다.
Privileged Container는 도커 컨테이너가 호스트 시스템에 대해 거의 모든 권한을 가지도록 설정된 컨테이너입니다. 이 모드는 컨테이너가 호스트의 모든 디바이스와 네트워크 설정에 접근할 수 있게 하여 유연성을 제공하지만, 보안 위험이 매우 큽니다.
docker run --rm -it --privileged ubuntu
위 명령으로 Ubuntu 컨테이너를 Privileged 모드에서 실행합니다. 이 컨테이너는 호스트 시스템의 모든 자원에 접근할 수 있습니다.
ls /dev
컨테이너 내부에서 /dev 디렉토리를 확인하여 모든 호스트 디바이스에 접근할 수 있는지 확인합니다.
Unprivileged Container는 제한된 권한으로 실행되는 도커 컨테이너로, 보안이 강화된 상태에서 실행됩니다. 기본적으로 도커는 컨테이너를 Unprivileged 모드로 실행하여, 호스트 시스템의 자원에 대한 접근을 제한합니다.
docker run --rm -it ubuntu
이 명령은 기본적으로 Unprivileged 모드에서 컨테이너를 실행합니다.
ls /dev
Unprivileged 컨테이너에서는 /dev 디렉토리에 대한 접근이 제한됩니다.
docker run --rm -it --cap-drop=ALL --cap-add=NET_ADMIN ubuntu
제한된 권한으로 컨테이너를 실행하면서 특정 Capabilities(NET_ADMIN)만 부여하여 보안과 기능성을 모두 확보합니다.
Share Namespace는 리눅스 커널에서 제공하는 네임스페이스를 여러 컨테이너나 프로세스가 공유하도록 설정하는 기능입니다. 네임스페이스는 시스템 리소스의 특정 부분을 격리하는 메커니즘으로, 다양한 자원을 독립적으로 관리할 수 있게 합니다.
--pid: 프로세스 ID (PID) 네임스페이스를 공유하여, 여러 컨테이너가 동일한 PID 네임스페이스를 사용할 수 있습니다.
--ipc: Inter-Process Communication (IPC) 네임스페이스를 공유하여, 컨테이너 간에 메시지 큐나 공유 메모리 등을 공유할 수 있습니다.
--network: 네트워크 네임스페이스를 공유하여, 컨테이너 간에 동일한 네트워크 설정을 사용할 수 있습니다.
docker run --rm -it --pid=host ubuntu
이 명령은 컨테이너가 호스트의 PID 네임스페이스를 공유하도록 합니다. 컨테이너 내에서 ps aux를 실행하면 호스트의 모든 프로세스를 볼 수 있습니다.
docker run --rm -it --ipc=container:<container_id> ubuntu
특정 컨테이너(container_id)와 IPC 네임스페이스를 공유하여, 메시지 큐나 공유 메모리를 사용할 수 있습니다.
###네트워크 네임스페이스 공유
docker run --rm -it --network=container:<container_id> ubuntu
특정 컨테이너와 네트워크 네임스페이스를 공유하여 동일한 네트워크 설정을 사용할 수 있습니다.
Security Layer는 시스템 보안을 강화하기 위해 여러 겹의 보안 메커니즘을 적용하는 방법론입니다. 도커 컨테이너 환경에서는 다양한 보안 기술과 도구를 조합하여 시스템을 보호할 수 있습니다.
AppArmor: 프로세스가 수행할 수 있는 작업을 프로파일로 정의하여, 해당 프로세스의 시스템 접근 권한을 제한합니다.
Seccomp: 컨테이너가 호출할 수 있는 시스템 콜을 제한하여 보안 공격 표면을 줄입니다.
Linux Capabilities: 특정 Capabilities만 부여하여 컨테이너가 필요한 권한만 가지도록 설정합니다.
docker run --rm -it --security-opt apparmor=profile_name ubuntu
AppArmor 프로파일(profile_name)을 적용하여 컨테이너의 시스템 접근을 제한합니다.
docker run --rm -it --security-opt seccomp=/path/to/seccomp-profile.json ubuntu
Seccomp 필터를 적용하여 시스템 콜을 제한합니다.
docker run --rm -it --cap-drop=ALL --cap-add=NET_ADMIN ubuntu
특정 Capabilities만 부여하여 보안을 강화합니다.