2019년 4월 11일 목요일

회사 프록시 서버 뒤에서 docker pull을 실행하지 못하는 문제에 도전해 보자

프록시(proxy) 서버란 네트워크 서비스의 중계 역할을 하는 장비를 일컫는다. 과거에는 IP 주소를 세탁하고 접속이 차단된 곳을 둘러서 연결하게 만드는 뭔가 음험한 물건으로만 생각했었다. 원래 이 장비는 네트워크 트래픽을 줄이기 위한 목적으로 쓰는 것이라 하였다. 즉, 한번 접속해서 가져왔던 정보를 프록시 서버의 캐시에 저장해 둔 뒤, 같은 내용을 클라이언트에서 요청하는 경우 캐시의 것을 재전송함으로써 다시 원격 서버에 연결을 할 필요가 없게 만드는 것이다.

도대체 프록시 서버가 나와 무슨 관계가 있을까? 집에서 편히 앉아서 고속 인터넷망으로 접속을 하는 경우라면 프록시 서버의 존재에 신경을 쓸 필요가 없다. 그러나 회사 내 전산망이라면 사정은 다르다. 업무와 무관한 웹사이트의 접속을 차단하고, 중요 내부 정보의 유출을 막기 위한 보안 차원에서 프록시 서버를 사용하는 경우가 많다고 한다.

과연 나는 프록시 서버를 통해서 외부에 접속하는 것일까? Am I behind a proxy? 사이트에 접속을 하면 프록시 서버가 있는지를 알 수 있다고는 하지만, 이러한 서비스가 항상 프록시 서버의 존재 여부를 정확하게 검출하는 것은 아니다. 

기업의 입장에서 프록시 서버를 도입하여 운용하는 것을 뭐라고 할 수는 없다. 다만 HTTPS 트래픽을 복호화하여 필요한 '차단' 혹은 '기록(이것을 실제로 하는지는 잘 모른다)' 조치를 취한 다음 다시 암호화하여 내부로 돌려보내는 암호화 트래픽 복호화·가시성 장비(예: 소만사 HTTPS프록시)가 그렇게 만족스럽게 작동하지는 않는다는 것이다. SSL 가시성이라고 좋게 표현하지만, TLS(Transport Layer Security, SSL과 거의 같은 의미) interception이라고 써 놓으면 왠지 마뜩찮아 보인다.
보이지 않는 것은 보호할 수 없다.
멋진 말이기는 한데, 한편으로는 찝찝하다. 예를 들어 내가 소유한 은밀한 사진들을 비밀스런 사설 금고에 보관하고 싶은데, 이를 맡아주는 사람은 그 사진을 투명한 비닐백에 넣어 오지 않으면 안된다고 하는 것과 무엇이 다른가. '공공의 이익에 부합되지 않은 것을 보관해 줄 수는 없으니 금고지기는 내용물을 꼭 보아야 되겠다'라는 논리와 비슷하다. 물론 이 짧은 글을 통해서 이에 대한 논쟁을 확대하고 싶지는 않다.

어찌되었든 내가 앉아있는 책상 위의 컴퓨터에서 외부 세계로 HTTPS 접속을 한 뒤 인증서 정보를 열어보면 Somansa가 Root CA인 것으로 바뀌어서 나온다. 물론 소만사는 최상위 인증기관이 아니다. 소만사의 '공인되지 아니한' 루트 인증서는 업무용 컴퓨터(윈도우)를 세팅하는 과정에서 웹 브라우저에 설치가 되었다. 전산 담당자가 해 준 것인가, 저절로 한 것인가? 그건 잘 모르겠다. 변경(변조?)된 루트 인증서 정보에 보이는 Somansa라는 회사명으로 짐작하건대 아마도 이 회사의 프록시 서버가 변경을 했을 것이다. 이러한 루트 인증서 변경이 일어진다는 것을 안 것은 며칠 되지 않았다. 구글을 검색해 보면 이는 이미 잘 알려진 일이다.

[StackOverflow] Can proxy change SSL certificate? - 네, 그렇습니다!

문제는 리눅스 서버를 사용할 때이다. conda, curl, docker 등 https://(433번 포트)를 사용하는 서비스마다 연결이 제대로 되지 않아서 무척 애를 먹었다. 앞의 두 개는 각 프로그램의 고유한 설정 파일에 Somansa 루트 인증서를 넣어서 해결을 하였으나 docker는 도무지 해결이 되지 않았다.

$ docker pull ubuntu:16.04
Pulling repository ubuntu
Get https://index.docker.io/v1/repositories/library/ubuntu/images: x509: certificate signed by unknown authority

[StackOverflow] Docker : Get https://registry-1.docker.io/v2/: x509: certificate signed by unknown authority를 비롯한 많은 글에서 이에 대한 질문과 답변을 볼 수 있었다.
We have also a proxy. For monitoring our https connection to avoid malwares, our proxy creates a certificate on the fly for the secured connection between a station and the proxy. Then another secured connection is done between the proxy and the website. The message indicates that the certificate produced by the proxy was signed by an unknown authority: the "fake authority" which generates the certificates.
CentOS 6의 경우 소만사의 루트 인증서 파일을 받아다가 /etc/pki/ca-trust/source/anchors/ 아래에 복사한 다음 update-ca-trust force-enable와 update-ca-trust extract 명령을 차례로 실행한 뒤 docker 서비스를 재시동하면 된다는데 도무지 성공의 기미가 없다.
(인증서 파일을 받으려면 웹브라우저에서 내보내기를 하거나 openssl 프로그램을 쓰는 방법이 있다.)
남은 방법은 어떻게 해서든 docker image를 받아서(프록시 서버 영향을 받지 않는 다른 장비에서 docker pull 사용) 파일로 만든 뒤 이를 작업하고자 하는 리눅스 서버로 전송하여 docker load -f tar_file을 하는 것뿐이다. 네트워크를 거치는 docker pull만 아니라면, 일단 받은 이미지 파일을 docker run으로 올리는 데에는 문제가 없다. 혹은 docker pull 명령어를 쓰지 않고 이미지를 다운로드하는 유틸리티인 docker-drag(python 2.7 필요)을 쓰는 방법도 가능하다고 한다. 이는 검색에 검색을 거듭하여 겨우 알아낸 것인데([StackOverflow] How do I download docker images without using the pull command?), 아직 절반의 성공일 뿐이다. 왜냐하면 ubuntu:14.04 및 ubuntu:16.04를 다운로드하여 docker run을 하는 것은 성공하였지만...

$ python docker_pull.py ubuntu:14.04
Creating image structure in: tmp_ubuntu_14.04
e082d4499130: Pull complete [67148830]
371450624c9e: Pull complete [72650]
c8a555b3a57c: Pull complete [363]
1456d810d42e: Pull complete [162]
Docker image pulled: library_ubuntu.tar
$ docker load -i library_ubuntu.tar 
$ docker images
REPOSITORY                      TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                          14.04               7dc2e660bb0c        4 weeks ago         188.1 MB
hello-world                     latest              c72cc8666399        3 months ago        1.84 kB
anvio_jeong180710_cog           latest              bf09cd455d01        9 months ago        3.936 GB
... 중간 생략...
phacnml/plasmidprofiler_0_1_6   latest              ae30d10d24fc        2 years ago         6.564 GB
$ docker run --rm -it ubuntu:14.04 /bin/bash
root@d604c684d26c:/# df -h
Filesystem                                                                                         Size  Used Avail Use% Mounted on
/dev/mapper/docker-8:19-12583470-d604c684d26c2cfaf0f3e234dd867535d306734b37c4c35884bfa7673fe489ea  9.8G  219M  9.1G   3% /
tmpfs                                                                                              127G     0  127G   0% /dev
shm                                                                                                 64M     0   64M   0% /dev/shm
/dev/sdb3                                                                                          5.3T  1.9T  3.2T  37% /etc/hosts

qiime2/core:2018.11을 다운로드할 때에는 'IOError: Not a gzipped file'이라는 에러 메시지가 나면서 실패를 했기 때문이다.

같은 링크에서 소개한 download-frozen-image-v2.sh는 golang, jq 등 생소한 것들을 같이 설치해야 하는 문제로 테스트에 시간이 걸리고 있다. 이에 대해서는 나중에 기록할 예정이다. 이 두 가지 유틸리티 외에도 Downloading Docker Images from Docker Hub without using Docker를 살펴보면 좋은 아이디어가 많으니 참고해 보도록 한다.

download-frozen-image-v2.sh의 활용법(아직은 실패)

위에서 소개한 URL에서 스크립트를 다운로드한다. 추가적으로 jqgo가 필요하다. 두 프로그램 전부 리눅스용 바이너리로 배포되는 것을 받아서 사용하였다. 

curl은 anaconda2 base environment에서 재설치하였고, 문제의 Somansa 루트 인증서는 /opt/anaconda3/ssl/에 설치하였다. 인증서 재설치에 관해서는 curl에 신뢰하는 인증서 추가하기를 참조하였다. 그러나 qiime2은커녕 docker-drag로 받아서 잘 돌아가던 ubuntu 이미지조차 잘 실행되지 않는다.


$ ./download-frozen-image-v2.sh temp_download ubuntu:16.04
Downloading 'library/ubuntu:16.04@16.04' (4 layers)...
#######################################################

Download of images into 'temp_download' complete.
Use something like the following to load the result into a Docker daemon:
  tar -cC 'temp_download' . | docker load
$ tar -cC 'temp_download' . | docker load
Error response from daemon: could not find image: Prefix can't be empty

에혀~ 나도 모르겠다. 동료가 윈도우 Hiper-V 환경에서 받은 도커 이미지를 제공해 주어서 이것을 리눅스 서버로 갖고 들어와서 사용해 보았다. qiime2만 생각한다면 bioconda로 설치를 해 두었으니 실행을 하는 데에는 무리가 없다. 그러나 앞으로의 확장 가능성을 생각한다면 docker를 피해나갈 수는 없을 것이다.

2019년 4월 16일 업데이트

CentOS의 버전이 너무 오래된 것이 문제라는 생각이 든다. 현재의 docker 설치 안내문서(Get Docker CE for CentOS)를 읽어보면 다음과 같이 기재되어 있다.

OS requirements
To install Docker CE, you need a maintained version of CentOS 7. Archived versions aren’t supported or tested.

이제 진지하게 CentOS 6을 버리고 7로 업그레이드하는 것을 생각해 보도록 하자.

댓글 없음: