View Categories

Docker Socket Proxy: 도커 해킹을 원천 차단하는 3단계 보안 방화벽 구축 가이드

1 min read

🚨 왜 /var/run/docker.sock 마운트는 ‘자살 행위’인가? #

도커 환경을 운영하다 보면 Docker Socket Proxy의 필요성을 절실히 느끼는 순간이 옵니다. 보통 Traefik이나 Portainer, Watchtower 같은 도구들은 실시간으로 컨테이너 상태를 감시하거나 제어하기 위해 /var/run/docker.sock 파일에 접근해야 합니다. 하지만 아무런 보호 장치 없이 이 소켓 파일을 컨테이너 내부에 직접 볼륨 마운트하는 것은, 해당 컨테이너를 장악한 해커에게 호스트 서버의 Root 권한을 통째로 바치는 것과 다름없습니다.

실제로 컨테이너 내부에서 도커 소켓에 접근할 수 있다면, 해커는 호스트의 파일 시스템을 마운트한 새로운 컨테이너를 띄워 중요 데이터를 탈취하거나 시스템 전체를 마비시킬 수 있습니다. 이러한 Privilege Escalation 공격을 막기 위한 최선의 대안이 바로 API 방화벽 역할을 수행하는 Docker Socket Proxy입니다.

docker socket security architecture

🛠️ Docker Socket Proxy 구축을 위한 Compose 설정 #

단순히 프록시를 띄우는 것보다 중요한 것은 네트워크 격리입니다. 호스트 포트(2375)를 외부로 노출하지 않고, 오직 내부 네트워크(socket_proxy)를 통해서만 통신하도록 설정해야 합니다. 아래는 실무에서 바로 적용 가능한 최적화된 docker-compose.yml 예시입니다.

services:
  socket-proxy:
    container_name: socket-proxy
    image: tecnativa/docker-socket-proxy
    networks:
      socket_proxy:
        ipv4_address: 192.168.91.254
    security_opt:
      - no-new-privileges:true
    restart: always
    # 포트포워딩 주석 처리: 외부 노출 철저 차단
    # ports:
    #   - "2375:2375"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock"
    environment:
      - LOG_LEVEL=info
      ## API 접근 권한 설정 (1=허용, 0=차단)
      - EVENTS=1
      - PING=1
      - VERSION=1
      - AUTH=0
      - SECRETS=0
      - CONTAINERS=1
      - IMAGES=1
      - INFO=1
      - NETWORKS=1
      - SERVICES=1
      - TASKS=1
      - VOLUMES=1
      - POST=1 # Watchtower 등 업데이트 도구 사용 시 필요
      - BUILD=0
      - COMMIT=0
      - CONFIGS=0
      - NODES=0
      - SWARM=0

💡 DevOps 실무 팁: ipv4_address를 고정하는 이유는 Traefik이나 Portainer 설정에서 엔드포인트를 지정할 때 컨테이너 재시작 후에도 IP가 바뀌지 않도록 보장하기 위함입니다.

docker api access control

🔐 ACL 튜닝: 최소 권한 원칙의 적용 #

Docker Socket Proxy의 핵심은 환경 변수를 통한 세밀한 ACL(Access Control List) 관리입니다. 무조건 모든 권한을 1로 설정하면 프록시를 쓰는 의미가 퇴색됩니다. 사용하는 서비스별로 필요한 최소 권한을 아래 표를 참고하여 설정하십시오.

서비스명필요 권한 (최소)설명
TraefikCONTAINERS, NETWORKS레이블 기반 라우팅 정보 수집
PortainerINFO, VOLUMES, IMAGES…전반적인 대시보드 모니터링
WatchtowerIMAGES, POST, CONTAINERS_DELETE이미지 비교 및 컨테이너 재실행

특히 POST=1 설정은 주의가 필요합니다. Watchtower처럼 컨테이너를 중지시키고 다시 실행해야 하는 도구를 사용할 때만 허용하고, 읽기 전용 모니터링 툴만 사용한다면 반드시 0으로 유지하는 것이 보안상 유리합니다.

🚀 실무 적용: Traefik 연동 예시 #

이제 기존에 /var/run/docker.sock을 직접 마운트하던 설정들을 모두 제거할 차례입니다. Traefik 설정 파일에서 endpoint를 프록시 서버의 내부 IP로 변경합니다.

# Traefik 컨테이너 설정 예시
command:
  - "--providers.docker=true"
  - "--providers.docker.endpoint=tcp://192.168.91.254:2375"
  - "--providers.docker.exposedByDefault=false"
# volumes:
#   - /var/run/docker.sock:/var/run/docker.sock # 과감히 삭제하세요!

이렇게 설정하면 Traefik은 더 이상 호스트의 소켓 파일에 직접 접근하지 않습니다. 대신 socket-proxy를 거치게 되며, 허용되지 않은 API 호출(예: 도커 설정 변경 등)은 프록시 단에서 차단됩니다. 이는 공격자가 Traefik의 취약점을 이용해 컨테이너 내부로 침투하더라도, 호스트 서버로 권한을 확장하는 것을 물리적으로 막아주는 최후의 방어선이 됩니다.

💡 트러블슈팅 경험: 간혹 특정 앱에서 ‘Permission Denied’ 로그가 발생한다면, 프록시 컨테이너의 LOG_LEVEL=debug로 올려보세요. 어떤 API 경로(Endpoint)가 차단되었는지 정확히 파악할 수 있어 ACL 수정이 훨씬 수월해집니다.

보안은 언제나 ‘불편함’과 ‘안전함’ 사이의 저울질입니다. 하지만 도커 소켓 노출만큼은 타협의 대상이 되어서는 안 됩니다. Docker 공식 보안 가이드에서도 강조하듯, 권한 분리는 컨테이너 아키텍처의 핵심입니다.

더 많은 가이드 보기를 통해 인프라 보안을 한 단계 더 업그레이드해 보세요.

Powered by BetterDocs

답글 남기기