Let’s Encrypt로 nginx 서버의 SSL 통신 구현하기

1. 공개키 암호화 방식

출처: https://commons.wikimedia.org/wiki/File:Public_key_encryption.svg 

공개키 방식은 암호화와 복호화에 같은 키를 사용하는 대칭키 방식과 다르게 누구나 알수 있는 공개키와 소유자만이 알고 있는 비밀키 두개를 사용하는 암호화기법입니다. 만약 엘리스가 밥에게 기밀을 전달한다고 가정하면 먼저 밥이 공개키를 공개하면 엘리스는 공개키를 가지고 문서를 암호화 합니다. 엘리스가 암호화된 문서를 밥에게 전달하면 밥은 비밀키를 활용하여 해독합니다.

출처: https://en.wikipedia.org/wiki/File:Public_key_signing.svg 

암호화이외에 공인인증서등의 신원증명, 변조 방지에도 활용할수 있습니다. 엘리스가 공개키를 공개한후 어떤 문서를 자신의 개인키로 암호화 합니다. 암호화된 문서를 공개하여, 자신이 만들었음을 증명하고 다른사람들은 공개키로 해당문서를 해독할수 있습니다. 타인이 A의 공개키를 사용하여 해독할수 있는 문서를 생성하는것은 불가능에 가깝기 때문에 신원증명, 변조방지를 할수 있는것입니다.

2. RSA 기법을 활용한 대략적인 SSL 통신 과정

출처: https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/

SSL은 NETSCAPE사에서 만들었던 서버와 클라이언트 사이의 암호화 통신 기법입니다. 향후 더발전된 버전인 TLS가 출시되었지만 사람들은 SSL이라는 용어에 더 익숙한 경향이 있습니다. Well known 포트인 443번을 주로 사용하여 암호화 통신을 합니다.

RSA기반의 SSL 통신은 먼저 클라이언트와 서버가 3-way handshake를 통해 연결을 확인한후 서로 Hello 메시지를 보내어 TLS 버전을 확인하는것으로 시작합니다. 서버에서 hello 메시지를 보낼때 공개키와 서비스의 정보가 담긴 인증서를 같이 보냅니다. 인증서는 신뢰할수 있는 CA기관에서 발급되었고 이름, 발급기관, 서버의 공개키등의 정보와 함께 CA기관의 비밀키로 인정서의 내용을 종합해 hash한 결과를 암호화한 값이 들어있습니다.

인증서를 받은 클라이언트는 어떤 CA에 의해 발급되었는지 확인합니다. 이때 공인된 CA가 아닌경우 경고메시지를 표시할 가능성이 높습니다. 해당하는 CA의 공개키로 hash값을 복호화하여 진위여부가 확인되면 본격적인 암호화통신을 위한 준비가 시작됩니다.

클라이언트는 서버가 보낸 hello 메시지에 있는 랜덤 데이터와 클라이언트가 생성한 랜덤데이터를 조합해 premaster secret값을 하나 생성한후 인증서에 포함된 서버의 공개키로 암호화하여 서버로 전송합니다. 서버는 자신의 개인키를 사용해 premaster secret키를 알아냅니다. 이때 서버, 클라이언트는 동일한 premaster secret키를 가지고 동일한 세션키를 만든후 대칭키 방식으로 암호화 통신을 진행하게 됩니다.

3. Let’s Encrypt를 통해 공인된 인증서 발급하기

Let’s Encrypt를 통해서 웹서버의 암호화통신을 위한 3달 기한의 무료 인증서를 발급할수 있습니다. (물론 갱신도 가능합니다!) Let’s Encrypt에서 인증서를 받을때는 Certbot이라는 프로그램을 자주 사용합니다. 패키지 매니저를 통해 설치할수도 있고 직접 바이너리를 받아오는 방법이 있는데 이번에는 바이너리를 직접 받아 설치해보았습니다.

바이너리를 받은 후 nginx 웹서버를 위한 인증서를 발급해보았습니다. 인증서를 발급받을때 해당 도메인의 소유 유무를 증명해야 하는데 저는 –preferred-challenges dns 를 argument로 넘겨주어서 제가 소유하고 관리하는 route 53의 호스팅영역에 TXT 타입의 값을 추가하는 방식을 사용했습니다.

# certbot 설치
wget https://dl.eff.org/certbot-auto
chmod a+x ./certbot-auto

# 인증서 발급
sudo ./certbot-auto --manual --preferred-challenges dns certonly

4. nginx.conf에 반영후 reload 하기

인증서가 성공적으로 발급되면 /etc/letsencrypt/live/your_domain/ 폴더에 공개키인 fullchain.pem과 개인키인 privkey.pem 이 생성됩니다.

발급된 keyset들을 nginx.conf에 반영하고 reload하면 SSL 통신을 위한 구축과정은 끝나게 됩니다. 일반적으로 443번 포트로 암호화통신을 하지만 저처럼 다른 포트를 사용하는것도 가능합니다.

# nginx.conf
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;

    server {
        listen 80 ssl;
        server_name your_domain;

        ssl_certificate     /etc/letsencrypt/live/your_domain/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;

        charset     utf-8;
        client_max_body_size 20M;

        access_log /app/access.log;
        error_log /app/error.log;


        location / {
            proxy_set_header Host $host;
            proxy_pass http://was:80;
            proxy_read_timeout 60s;
            proxy_send_timeout 60s;
            proxy_connect_timeout 60s;
        }

        location /static/ {
            alias /app/static/;
        }

        location /media/ {
            alias /app/media/;
        }
    }
}

5. 참고자료

  1. https://www.cloudflare.com/learning/ssl/what-happens-in-a-tls-handshake/
  2. https://aileen93.tistory.com/119

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다

이 사이트는 스팸을 줄이는 아키스밋을 사용합니다. 댓글이 어떻게 처리되는지 알아보십시오.

Scroll to top