도커는 Linux 기반 기술을 사용하여, 어플리케이션에 대해 격리된 공간을 만들어주는 가상화 서비스다. 여기에는 cgroup, chroot 등의 기반 기술들이 포함되는데, 추가로 보안을 위하여 커널에서 제공하는 보안 컴퓨팅 모드(seccomp) 또한 사용할 될 수 있다.
seccomp filter
Docker 에는 호스트 커널에 SECCOMP가 활성화되어 있는 경우 컨테이너를 생성할 때마다 기본적으로 사용하는 내장 SECCOMP 필터가 있다.
이를 확인하기 위해 간단한 도커 컨테이너를 구동해본다.
root@localhost~$ docker run -it --rm ubuntu /bin/sh
#
# date -s '23 OCT 2022 13:46:00'
date: cannot set date: Operation not permitted
컨테이너 안에 접속하여 date 명령으로 os 의 시간을 변경하려고 하면 변경할 수 없다고 나온다. (컨테이너 바깥에서 실행할 경우 정상적으로 시간이 변경되는 것도 확인할 수 있다.)
더 자세히 확인하기 위해 현재 접속해 있는 /bin/sh (PID 1)의 상태를 확인해본다.
# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 13:47 pts/0 00:00:00 /bin/sh
root 8 1 0 13:47 pts/0 00:00:00 ps -ef
#
# pidof sh
1
#
# cat /proc/1/status | grep Seccomp
Seccomp: 2
Seccomp_filters: 1
1번 프로세스의 Seccomp 값이 2로 설정되어 있다. Seccomp 의 모드는 다음과 같다.
타입 | 의미 | 설명 |
mode0 | <DISABLED> | 비활성화 |
mode1 | <STRICT> | read(), write(), exit(), sigreturn() 을 제외한 모든 syscall 거부 |
mode2 | <FILTERED> | 선택적 필터링. 지정한 정책에 따라 syscall 마다 승인/거부 |
seccomp 의 값이 2로 설정되어 있으므로, 시스템콜이 제한적으로 필터링되어 거부될 수 있다. 도커는 seccomp 에 대한 profile 을 이용하여 mode2에 대한 선별적 시스템콜 허용/거부를 수행한다.
whitelist profile 과 blacklist profile
잠시 간단한 seccomp profile 을 보면 다음과 같다.
{
"defaultAction": "SCMP_ACT_ERRNO",
"architectures" : [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
],
"syscalls": [
{
"names": [
"mount",
"chmod",
"chown"
],
"action": "SCMP_ACT_ALLOW"
}
]
}
seccomp profile 은 위와 같은 yaml 파일의 형식을 갖는다.
최상위 기준으로 3개의 필드가 존재하는데, "architectures" 필드의 경우 이 profile 이 사용될 수 있는 아키텍처를 표시한다.
그리고 "syscalls" 필드의 경우 배열로 이루어져 있으며, 각 배열에는 특정 시스템콜이 허용/거부 정책을 표시한다. 위 예에서는 mount, chmod, chown 시스템 콜에 대하여 "SCMP_ACT_ALLOW" 와 같이 허용하고 있다.
마지막으로 "defaultAction" 의 경우, 하단 syscall 에서 지정되지 않은 모든 시스템콜에 대한 허용/거부 정책을 정하는데 여기서는 모두 거부(SCMP_ACT_ERRNO) 하는 것을 볼 수 있다.
즉, 위 profile 은 mount, chmod, chown 을 허용하고 그 외에 모든 시스템 콜을 거부하는 프로파일이다. "defaultAction" 에 따라 프로파일의 성격이 정해지며, 이 파일의 경우 기본적으로 모두 거부하고 있기에 <whitelist type profile> 이라고 불린다.
반대로 <blacklist type profile> 도 생각해볼 수 있다. 예시는 아래와 같다.
{
"defaultAction": "SCMP_ACT_ALLOW",
"architectures" : [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
],
"syscalls": [
{
"names": [
"fchdir",
"flock",
"getuid"
],
"action": "SCMP_ACT_ERRNO"
}
]
}
위 profile 은 fchdir, flock, getuid 시스템 콜을 제외한 모든 시스템 콜을 허용하는 profile 이다.
추가로, docker 의 기본 seccomp profile 은 [여기에서] 확인 가능하다.
상단에 컨테이너 안에서 date 명령이 허용되지 않았던 건 docker 의 default seccomp profile 이 whitelist 방식이며, clock_settime 시스템콜이 조건적으로만 허용되고, 기본적으로는 거부되어 있기 때문이다.
docker default seccomp profile
...
{
"names": [
"settimeofday",
"stime",
"clock_settime",
"clock_settime64"
],
"action": "SCMP_ACT_ALLOW",
"includes": {
"caps": [
"CAP_SYS_TIME"
]
}
},
...
위와 같이 CAP_SYS_TIME 플래그가 있을 경우에만 허용되는 것을 볼 수 있다.
# docker run -it --rm --cap-add CAP_SYS_TIME ubuntu /bin/sh
#
# date -s '23 OCT 2022 13:46:00'
Sun Oct 23 13:46:00 UTC 2022
# date
Sun Oct 23 13:46:04 UTC 2022
#
위와 같이 플래그를 추가하여 새로 만든 컨테이너에서는 clock_settime() 시스템콜의 권한을 획득하여 date 명령을 정상적으로 사용할 수 있다. 위 docker default seccomp 페이지에서 특정 시스템콜 함수를 사용하기위한 플래그들을 확인할 수 있다.
사용자 정의 seccomp profile
docker run -it --rm --security-opt seccomp=/root/custom.json \
ubuntu /bin/sh
위와 같이, 직접 custom profile 을 생성한 후 이를 이용하여 컨테이너를 구동할 수도 있다.
docker run -it --rm --security-opt seccomp=unconfined \
ubuntu /bin/sh
위와 같이 '--security-opt' 의 옵션으로 'seccomp=unconfined' 를 줄 경우, 모든 시스템콜 함수를 허용하게 된다.
보안성을 높이기 위하여 seccomp 기능과 profile 에 대하여 이해하고, 어플리케이션에 필요한 최소한의 권한만을 주도록 하자.
'소프트웨어 아키텍처 > Docker' 카테고리의 다른 글
Docker registry API - push (1) | 2021.10.14 |
---|---|
리눅스 환경(온라인)에 도커 설치하기 (0) | 2021.09.24 |
Docker - data directory 변경하기 (0) | 2021.09.23 |
Docker registry API - pull (0) | 2021.09.22 |
Docker compose 의 사용 (0) | 2021.09.07 |
댓글