당신의 서비스에서 모두의 프라이버시 지키기

에드워드 스노든이 2013년에 내부 고발한 NSA의 광범위한 사찰까지 얘기 하지 않아도 ISP, 통신사나 여러분의 고용주가 컴퓨터 네트워크 위의 통신을 들여다보는 일은 비일비재하다. 하지만 조금만 더 노력을 기울이면 이런 프라이버시를 침해하는 일을 막거나 훨씬 어렵게 만들 수 있다. 이 글에서는 표준 프로토콜인 SSL/TLS를 어떻게 일반적인 웹 서버 프로세스나 응용 프로그램 프로세스에 적용할지 설명한다.

SSL/TLS

요즘의 웹 / 네트워크 환경에서는 인터넷 위로 통신하는 부분의 안전성을 위해서 TLS (transport layer security) 를 사용한다. 많은 곳에서 SSL (secure socket layer)이라고 부른다. 하지만 가장 나중 버전인 SSL v3 도 IETF에서 2016에 나온 RFC 7568에서 사용을 피하고 TLS v1.2 를 쓰라고 한다. 그래서 이 글에서는 TLS 라는 용어로 지칭하겠다.

TLS 가 제공하는 것

크게 다음 세 가지 기능을 제공한다.
• 인증 (authentication): 지금 통신 중인 서버가 연결하려고 한 서버가 맞는지 확인
• 보안 (confidentiality): 주고 받는 메시지를 남이 해독할 수 없게 변환
• 무결성 (integrity): 주고 받는 메시지를 남이 조작했는지 확인

TLS 표현 방식

wikipedia-tls.png

파이어폭스에서 확인한 위키 TLS 설정
구글 크롬이나 파이어폭스의 보안 탭을 열어보면 — 혹은 다른 OpenSSL 기반의 설정을 해봤다면 — 아래와 같은 문자열을 볼 수 있다. (아래 예는 위키백과 접속했을 때 사용한 알고리즘이다)
ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
대략 아래와 같은 의미이다.

• ECDHE 키교환: 타원곡선 디피-헬만 알고리즘 (ephemeral 키 방식)
• ECDSA 인증서 알고리즘: 타원곡선을 이용한 디지털 서명 알고리즘
• CHACHA20 스트림 암호화: 메시지를 암호화할 때 CHACHA20 스트림 암호화 알고리즘
Poly1305 MAC, SHA-256 HMAC: 메시지 무결성 검증 알고리즘 두 가지

TLS 표기 방식의 의미

인증을 담당하는 부분은 여기서 ECDSA 하나에 해당한다. 이 부분은 해당 웹 사이트에서 제공하는 인증서 서명 알고리즘에 해당한다.
보안에 해당하는 부분은 키 교환메시지 암호화 (블럭 혹은 스트림 암호화) 에 해당하는 ECDHE 와 Chacha20이다.
무결성 검증을 위해서 사용한 부분이 MAC에 해당하는 Poly1305 와 SHA-256 알고리즘이다.
이 중에서 보안무결성 보장을 위해서 사용한 부분은 웹 서버나 응용 프로그램에서 설정하는 부분이다. 즉, 아파치 웹 서버나 nginx 설정을 하다보면 설정해야하는 부분이다. 모질라 재단에서 제공하는 웹 서버용 권장 설정이나 권장 암호화 알고리즘 목록 의 모범 설정 예시를 참고하면 좋다. 이에 대해서는 이전 블로그 글에서 설명했다.

TLS 인증 기능?

TLS 의 (서버 쪽) 인증 기능은 서버 설정만으로 동작하지 않는다. TLS의 인증 기능이 어떻게 동작하는지 아래에서 살펴보겠다.

TLS 인증서

TLS 인증서는 아주 간단히 말하면 “믿을 수 있는 누군가가 특정 형식으로 전자 서명한 공개키” 다. 여기서 “믿을 수 있는 누군가” 에 해당하는 역할을 담당하는게 “인증 기관” 이다. 그리고 특정 형식에 해당하는게 X.509 형식이다.
주의할 점은 믿을 수 있는 누군가 에 대해서는 강제적인 합의가 있는 것이 아니라서, 웹 브라우저 / OS에 따라서 특정 인증 기관을 신뢰할 수도 있고, 신뢰하지 않을 수도 있다. 예를 들어 올해 초에 한국 전자 인증 (crosscert) 에서 권한없이 인증서를 발급해서 모질라 재단 쪽에서 문제를 재기했고, 이에 대해 관리/모니터링할 책임이 있는 시만텍 인증서 사업 부문에 대한 조사가 이뤄졌다. 그 결과 구글 크롬과 모질라 파이어폭스에선 조만간 시만텍에서 발급한 서버 인증서를 모두 신뢰하지 않게 된다.

전자 서명 구조

전자 서명은 단순히 특정 키 + 서명 형식이 아니고, 공개키 인프라 (PKI) 를 이용해서 키를 단계적으로 서명한다. 우선 인증 기관들의 공개키를 루트 인증서 (root certificate) 이라고 한다. 이 루트 인증서는 웹 브라우저나 운영 체제 수준에서 포함하고 있다. 그리고 이 루트 인증서로 서명한 중간 단계 인증서 (intermediate certificate) 혹은 이걸로 다시 서명한 인증서를 생성한다. 이렇게 몇 단계를 거쳐서 생성한 서명키(=공개키)로 실제 웹 서버의 인증서(=공개키)를 전자 서명 알고리즘으로 서명하면 TLS 인증서가 완성된다. 즉, 서버의 TLS 인증서에는 루트 인증서 바로 아래에 있는 서명키부터, 서버의 공개키까지를 포함한다.
그리고 이런 루트 인증 기관, 혹은 이를 대행하는 인증 기관들은 이런 공개키 서명할 때 비용을 청구한다. 흔히 “인증서 발급 비용” 이라고 말하는게 이런 부분이다.

자가 서명 인증서

인증 기관을 통하지 않고 스스로 서명한 인증서 (self-signed certificate) 를 만들 수도 있다. 하지만, 해당 인증서는 클라이언트 프로그램 (웹 브라우저 혹은 게임 클라이언트 등등) 에서 확인할 방법이 없어서 절대로 피해야 한다. 대안은 무엇일까? 공짜로 인증서를 만들 순 없을까?

공짜로 인증서를 만들 방법은 없을까?

서두에서 언급한것처럼 스노든의 내부 고발 이후로 프라이버시에 대한 관심/걱정은 대폭 증가했고, 2014년에 전자 프런티어 재단 (EFF), 모질라 재단, 미시건 주립대 등이 참여해서 Let’s Encrypt 라는 새로운 CA 를 만들었다. Let’s Encrypt 의 설립 목적이 “자동화된 방법”으로, “비용없이” 원하는 모두에게 TLS 인증서를 발급하는 것이라, 대부분의 경우에서 사용할 수 있는 인증서쉽게(?) 발급할 수 있다.

Let’s Encrypt 에서 TLS 인증서 발급해서 적용하기

foo.example.com처럼 도메인 주소를 가지고 있는 서버라면 아래 과정으로 TLS 인증서를 발급할 수 있다. 이를 DV; domain validated인증서라고 한다. 이외에 OV 나 EV 처럼 웹 브라우저에 기관 이름 혹은 사업자 이름이 뜨는 인증서도 있지만 Let’s Encrypt 에선 발급할 수 없다. 이런 인증서는 발급할 때 추가 확인절차가 있어서 “자동화” 발급만 지원하는 Let’s Encrypt 등에선 지원할 수 없다.

리눅스 서버에 적용하기

리눅스에서 인증서를 발급받는다면 다음과 같은 과정으로 TLS 인증서를 발급할 수 있다.
1. 웹 서버를 설치한다. (nginx, apache2, …; 여기서는 nginx 를 예제로 사용) bash $ sudo yum install -y nginx # centos; nginx $ sudo apt-get install -y nginx # ubuntu; nginx

2. 웹 서버에서 80번 포트로 접근할 때의 루트 디렉터리를 지정한다. 예를 들어 nginx 라면 아래와 같은 설정이 필요하다.
>server {
# 80
번 포트에 대한 설정
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    #
이 경로를 기억해두자.
    root /usr/share/nginx/html;

    location / {}

    # Let’s Encrypt 용 추가 설정
    location ~ /.well-known { allow all; }
   }

3. certbot 프로그램을 설치한다. 아래 명령 중에 사용 중인 서버 OS에 맞는 명령을 고르자.
   $ sudo yum install -y certbot # centos
   $ sudo apt-get install -y letsencrypt # ubuntu
   $ pip install certbot # python 사용 가능한 임의의 운영체제 (virtualenv 여도 무방)

4. 인증서 발급. 발급하려는 모든 도메인을 -d some.domain.com 하는 형식으로 여러번 지정할 수 있다. 2에서 설정한 웹 서버 루트 경로 (위에선 root 설정으로 지정) 를 webroot -w 의 인자로 전달해야 한다.
   $ sudo letsencrypt certonly –webroot -w /usr/share/nginx/html -d foo.example.com -d http://www.foo.example.com
해당 명령 실행 후에 /etc/letsencrypt/live 밑에 도메인 이름으로 심볼릭 링크가 걸린 디렉터리가 생긴다.

5. 서버 설정에 반영
   server {
    listen 443 default_server;
    listen [::]:443 default_server;
    server_name foo.example.com;
# 서버 도메인 지정
    root /usr/share/nginx/html;

# TLS 패러미터들 (인증을 제외한 나머지)
    ssl on;
    ssl_certificate /etc/letsencrypt/live/foo.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/foo.example.com/privkey.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:!MD5;
    ssl_prefer_server_ciphers on;
 }

윈도우즈 지원

공식은 아니지만 Microsoft Windows 용 클라이언트 가 있으며, 위 웹 사이트의 Release 페이지에서 다운로드할수 있다. 이 커맨드라인 프로그램으로 유사한 작업을 해서 인증서를 발급받을 수 있다.

요약

• 현대적인 방법으로 프라이버시를 보호하는데 사용할 수 있는 TLS 레이어가 있다.
• TLS는 인증, 기밀 유지, 무결성 검증 기능을 제공한다. 이중 뒷쪽 두 가지는 서버 설정에 따라 동작한다.
• 인증을 위해서 인증 기관들이 존재하며, 여기서 발급받은 인증서가 필요하다.
• 인증서 발급을 자동화 + 무료로 처리하는 Let’s Encrypt 가 있으며, 서버에서 자동으로 처리할 수 있다.

아이펀팩토리 김진욱 CTO

답글 남기기

댓글을 게시하려면 다음의 방법 중 하나를 사용하여 로그인 하세요:

WordPress.com 로고

WordPress.com의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Twitter 사진

Twitter의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Facebook 사진

Facebook의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

Google+ photo

Google+의 계정을 사용하여 댓글을 남깁니다. 로그아웃 / 변경 )

%s에 연결하는 중