15.2.보안 원격 접근을 위한 도커 엔진 설정

보안 채널을 통해 API 요청 * 전송 계층 보안(Transport Layer Securty. TLS) * HTTPS 프로토콜의 디지털 인증서와 같은 방식의 암호화를 사용한다. * 도커 API는 상호 TLS를 사용하므로 서버와 클라이언트가 각각 인증서를 갖는다. * 서버의 인증서는 자신을 증명하고 전송되는 내용을 암호화하는 데 사용되며, 클라이언트의 인증서는 자신을 증명하는 데 사용된다. * 보안 셸(Secure Shell, SSH) * 이 프로토콜은 리눅스 서버에 원격 접속하는 표준 프로토콜이지만, 윈도에서도 사용 가능하다. * SSH로 원격 서버에 접근하려면 사용자명과 패스워드 혹은 비밀키가 필요하다.

TLS vs. SSH * 어떤 보안 채널을 사용하느냐에 따라 클러스터에 접근할 권한을 부여하는 방법이 달라진다. * 상호 TLS는 더 널리 사용되는 방법이지만 인증서를 생성하고 교체하는 관리 업무에서 오버헤드가 발생한다. * 이에 비해 SSH는 사용하는 컴퓨터에 대부분 설치돼 있는 SSH 클라이언트만 있으면 되며 접근 권한 관리가 상대적으로 쉽다.

상호 TLS를 이용한 보안 원격 접근 * 우선 상호 TLS를 이용해 도커 엔진의 보안 원격 접근을 설정해 보자. * 상호 TLS를 사용하려면 먼저 인증서와 키 파일(인증서의 패스워드 역할) 쌍을 두 개 만들어야 한다. * 하나는 도커 API가 사용하고, 다른 하나는 클라리언트에서 사용한다. * Play with Docker 웹 사이트에서 사용할 수 있는 인증서를 미리 준비해 두었으니 실습에서는 이 인증서를 사용하면 된다.

실습 Play with Docker 웹 사이트에 로그인한 후 노드 하나를 생성하라. 그리고 같은 세션에서 인증서를 배포할 컨테이너를 실행한다. 그다음에는 도커 엔진이 이 인증서를 사용하도록 설정한 후 도커를 재시작하라.

001) # 인증서를 둘 디렉터리를 생성한다.
002) $ mkdir -p /diamol-certs
003) 
004) # 인증서 및 설정값을 적용할 컨테이너를 실행한다.
005) $ docker container run -v /diamol-certs:/certs -v /etc/docker:/docker diamol/pwd-tls:server
006) 
007) # 새로운 설정을 적용해 도커를 재시작한다.
008) $ pkill dockerd
009) $ dockerd &>/docker.log &
010) [1] 340
  1. 005: 이 컨테이너는 호스트에서 생성한 볼륨 마운트를 사용해 Play with Docker에서 사용 가능한 TLS 인증서를 노드로 복사하고 도커 설정 파일을 수정한다.
  2. 008~010: 도커 엔진을 재시작해 수정된 설정을 반영한다. 이런 식으로 도커를 재시작하는 것은 주로 Play with Docker에서 쓰인다. 보통은 도커 서비스를 재시작하는 형태다.

  3. 조금 전 실행한 컨테이너에는 Play with Docker 노드에서 만든 두 개의 볼륨이 마운트된다.

  4. 그리고 이 컨테이너가 갖고 있던 인증서와 daemon.json 파일을 노드로 복사한다.
  5. 도커 엔진 설정을 반영하려면 dockerd 명령으로 도커 엔진을 재시작해야 한다.
  6. 지금부터 도커 엔진은 TLS를 사용해 2376번 포트를 주시한다(보안 TCP 접근을 위해 관습적으로 사용되는 포트다)

포트 오픈 * 한 단계만 더 거치면 로컬 컴퓨터에서 Play with Docker 노드의 도커 엔진을 원격에서 사용할 수 있다. * Open Port 버튼을 클릭해 2376번 포트를 지정한다 * 그러면 오류 메시지가 찍힌 탭이 열리면 오류 메시지는 무시하고 URL을 클립보드로 복사한다. * 이 URL이 현재 Play with Docker 세션의 유일한 도메인이다. * 이 도메인을 사용해 로컬 컴퓨터에서 Play with Docker 웹 사이트에서 실행 중인 도커 엔진에 접속할 수 있다. * 이제 현재 사용 중인 Play with Docker 세션에 원격으로 접속할 준비가 끝났다.

인증 기관, 서버 인증서와 클라이언트 인증서 * TLS 인증서와 OpenSSH에 대한 더 자세한 설명은 생략하자먼 인증 기관, 서버 인증서와 클라이언트 인증서의 관계에 대해서는 잘 알아 두어야 한다. * TLS를 통해 도커 엔진에 접근하려면 인증 기관과 한 쌍의 인증서(클라이언트 인증서, 서버 인증서)가 필요하다. * 인증서에는 수명이 있어서 원격 도커 엔진에 대한 접근 권한을 임시로 부여하고 싶다면 단기 클라이언트 인증서를 사용하면 된다. * 이와 관련된 모든 절차를 자동화할 수는 있지만 인증서 관리에 대한 오버헤드가 여전히 존재한다. * TLS를 사용해 원격 접근이 가능하게끔 도커 엔진을 설정하려면 먼저 인증 기관 인증서, 서버 인증서 및 키의 쌍이 위치한 경로를 지정해야 한다. * 예제 15-2는 Play with Docker 세션의 도커 엔진에 적용된 TLS 원격 접근 허용 설정이다.

예제 15-2 TLS를 이용한 원격 접근 설정

{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2376"],
  "tls": true,
  "tlscacert": "/diamol-certs/ca.pem",
  "tlskey": "diamol-certs/server-key.pem",
  "tlscert": "diamol-certs/server-cert.pem"
}
  • 이제 도커 엔진 원격 접근에 보안이 적용됐다.
  • 지금부터는 인증 기관 인증서, 클라이언트 인증서및 키 없이는 Cur로 REST API를 호출하거나 도커 명령행 도구로 이 원격 도 커 엔진에 명령을 내릴 수 없다.
  • 이전에 만들어진 클라이언트 인증서도 마찬가지로 접근을 허용하지 않는다.
  • 도커 엔진에 접근하려면 서버 인증서와 같은 인증 기관에서 발급 된 클라이언트 인증서가 필요하다.
  • 클라이언트 TLS 없이 API 사용을 시도하면 도커 엔진이 접근을 차단한다.
  • Play with Docker에서 실행한 이미지의 다른 버전을 사용하면 로컬 컴퓨터로 클라이언트 인증서를 내려받을 수 있다.
  • 그다음에는 이 인증서를 사용해 원격 도커 엔진에 접근하면 된다.

실습 Play with Docker에서 실행 중인 도커 엔진에 접근할 때는 항상 2376번 포트를 사용해야 한다. 앞서 2376번 포트를 개방할 때 복사한 현재 세션의 도메인을 사용 한다. 이제 원격 도커 엔진에 접근해 보자.

001) # address 항목에서 현재 세션의 도메인을 복사한다
002) # 대략 ip172-18-0-11-cj2vgeggftqg00c9qjo0-2376.direct.labs.play-with-docker.com 과 비슷한 값이다.
003) # 도메인을 환경 변수로 설정한다(윈도)
004)  $pwdDomain="<나의_현재세션_pwd_도메인>"
005) 
006) # 도메인을 환경 변수로 설정한다(리눅스)
007)  pwdDomain="<나의_현재세션 pwd 도메인>"
008) 
009) # 도커 API에 직접 접근을 시도한다
010)  curl "http://$pwdDomain/containers/ison"
011) Client sent an HTTP request to an HTTPS server.
012) 
013) # 명령행 도구로도 직접 접근을 시도한다
014)  docker --host "tcp://$pwdDomain" container ls
015) Error response from daemon: Client sent an HTTP request to an HTTPS server.
016) 
017) # 클라이언트 인증서를 로컬 컴퓨터로 추출한다
018)  mkdir -p /tmp/pwd-certs
019)  cd ./ch15/exercises
020)  tar -xvf pwd-client-certs -C /tmp/pwd-certs
021) x ca.pem
022) x client-cert.pem
023) x client-key.pem
024) 
025) # 클라이언트를 사용해 도커 엔진에 접근을 시도한다
026)  docker --host "tcp://$pwdDomain" --tlsverify --tlscacert /tmp/pwd-certs/ca.pem --tlscert /tmp/pwd-certs/client-cert.pem --tlskey /tmp/pwd-certs/client-key.pem container ls
027) CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
028) 
029) # 도커 명령행 도구로 명령을 내릴 수 있다.
030)  docker --host "tcp://$pwdDomain" --tlsverify --tlscacert /tmp/pwd-certs/ca.pem --tlscert /tmp/pwd-certs/client-cert.pem --tlskey /tmp/pwd-certs/client-key.pem container run -d -P diamol/apache
031) Unable to find image 'diamol/apache:latest' locally
032) latest: Pulling from diamol/apache
033) f84cab65f19f: Pull complete
034) 87259b7246e5: Pull complete
035) 3e84dc11ea39: Pull complete
036) d632c8441234: Pull complete
037) 0fcb24848396: Pull complete
038) Digest: sha256:f3fafa07dd17a03d5e5c7ad959419faf459b087fbd25a53c7db08b87d586520b
039) Status: Downloaded newer image for diamol/apache:latest
040) b62004889054867156ead579335e9eabca63f3bf3afbc3055e2f2160b06a4020
  1. 004: 2376번포트의 정보가 포함된 도메인을 환경 변수로 저장한다. Play with Docker에서는 포트마다 도메인이 다르게 부여된다.
  2. 010: 도커 엔진에 TLS 보안이 적용됐다 적합한 클라이언트 인증서를 제시하지 않으면 접근이 거절된다.
  3. 026: 일치하는 클라이언트 인증서를 갖고 있다면 Play with Docker 속 노드에서 동작하는 도커 엔진에 로컬 컴퓨터에서 마음대로 명령을 내릴 수 있다.

  4. 매번 TLS 관련 인자를 입력해야 하는 것이 조금 번거롭지만, 인잣값을 환경 변수로 정의해 두면 불편함이 조금 줄어든다.

  5. 클라이언트 인증서를 제대로 지정하지 않으면 오류를 일으키지만, 인증서를 정확히 지정하면 Play with Docker 웹 사이트에서 동작 중인 도커 엔진을 로컬 컴퓨터에서 마음대로 조작할 수 있다.

SSH를 이용한 보안 원격 접근 * 도커 엔진에 원격 접근할 수 있는 다른 보안 채널로 SSH가 있다. * SSH의 장점은 도커 명령행 도구가 표준 SSH 클라이언트를 사용하기 때문에 도커 엔진 쪽에서 설정을 변경할 필요가 없다는 점이다. * 사용자 인증은 서버가 대신 처리해 주기 때문에 따로 인증서를 생성할 필요도 없다. * 도커 엔진을 실행 중인 컴퓨터에서 원격 접속에 사용할 계정을 추가 하기만 하면 된다. * 이 계정을 사용해 도커 엔진에 원격으로 명령을 내릴 수 있다.

실습 Play with Docker 웹 사이트의 현재 세션으로 돌아가자. node1의 IP 주소를 옮겨 적은 뒤, 다른 노드를 하나 더 생성한다. 다음 명령을 입력해 node2에서 SSH를 통해 node1에서 실행 중인 도커 엔진에 명령을 내려 보자.

001) # node1의 IP 주소를 환경 변수로 정의한다
002) node1ip="<node1-ip-address-goes-here>"
003) 
004) # 접속 테스트를 위해 SSH로 접속을 시도한다
005) ssh root@$node1ip
006) exit
007) 
008) # node2에서 해당 노드에서 실행 중인 컨테이너의 목록을 확인한다
009) docker container ls
010) 
011) # node1에서 원격으로 접근한 도커 엔진에서 실행 중인 컨테이너의 목록을 확인한다
012) docker -H ssh://root@$node1ip container ls
013) CONTAINER ID   IMAGE           COMMAND              CREATED          STATUS          PORTS                   NAMES
014) b62004889054   diamol/apache   "httpd-foreground"   18 minutes ago   Up 18 minutes   0.0.0.0:32768->80/tcp   romantic_wright
  1. 005: Play with Docker에서 생성한 노드는 서로의 SSH 공개 키를 자동으로 주고받으므로 패스워드 입력 없이 SSH 접속이 가능하다.

  2. Play with Docker를 사용하면 이 과정이 매우 간단해진다.

  3. 왜냐하면 Play with Docker 웹 사이트가 도커 엔진 원격 접근에 필요한 모든 사항을 직접 관리하기 때문이다.
  4. 운영 환경이었다면 사용자 계정을 만들고, 게다가 패스워드 입력을 건너뛸 필요가 있는 경우에는 SSH 키를 생성해 공개 키는 서버에, 비밀키는 사용자에게 전달해야 한다.

links

social