Skip to content

https 개요부터 배포까지 🧾

joh16 edited this page Dec 7, 2020 · 2 revisions

https 개요

배경

HTTP(HyperText Tranfer Protocol)

HTTP는 웹브라우저(Client)와 서버(Server)간의 웹페이지같은 자원을 주고 받을 때 쓰는 통신 규약 HTTP는 브라우저와 서버 사이에서 정보를 평문으로 전송하므로 정보가 전달되는 네트워크에서 전송되는 정보를 엿볼 수 있다. 이런 보안 문제로 인해 클라이언트와 서버가 먼저 암호화 통신 채널을 설정한 다음 평문 HTTP 메시지를 전송함으로써 정보 유출을 막는 HTTPS (HTTP Secure)가 소개되었다.

HTTPS

HTTPS는 인터넷 상에서 정보를 암호화하는 SSL(Secure Socket Layer)프로토콜을 이용하여 웹브라우저(클라이언트)와 서버가 데이터를 주고 받는 통신 규약

  • HTTPS는 http 메세지(text)를 암호화하는 것
  • HTTPS의 S가 Secure Socket, 보안 통신망을 말함
  • HTTPS의 암호화 원리의 핵심은 공개키 암호화 방식

HTTPS에서 제공하는 것

HTTPS로 전환을 고민하는 이유부터 살펴보자. HTTPS는 다음 세 가지 주요 이유 때문에 사용한다.

  • 기밀성 : HTTPS는 인터넷과 같은 공공 매체에서 두 참여자 간의 통신을 보호한다. 예를 들어, HTTPS가 없다면 와이파이(Wi-Fi) 액세스 포인트(Access Point)를 운영하는 사람은 액세스 포인트를 사용하는 사람이 온라인에서 무언가를 구입할 때 신용카드와 같은 개인정보를 볼 수도 있다.
  • 무결성 : HTTPS는 변조되지 않은 정보로 목적지에 도달하게 한다. 예를 들어, 와이파이가 웹사이트에 광고를 추가하거나, 대역폭을 절약하고자 이미지 품질을 저하시키거나, 읽는 기사의 내용을 변조할 수 있지만 HTTPS는 웹사이트를 변조할 수 없도록 한다.
  • 인증 : HTTPS를 통해 웹사이트의 진위 여부를 확인할 수 있다. 예를 들어, 와이파이 액세스 포인트을 운영하는 사람이 가짜 웹사이트를 브라우저에 보낼 수도 있다. HTTPS는 example.com이라는 웹사이트가 실제로 example.com인지 확인한다. 일부 인증서는 yourbank.com이 YourBank.Inc라는 걸 알리기 위해 해당 웹사이트의 법적 신원을 검사하기도 한다.

암호화 방식

  • 암호화, 복호화시킬 수 있는 서로 다른 키 2개가 존재하는데 이 두 개의 키는 서로 1번 키로 암호화하면 반드시 2번키로만 복호화할 수 있고 2번 키로 암호화하면 반드시 1번키로만 복호화할 수 있는 룰이 있는 것이다.
  • 그 중에서 하나 키는 모두에게 공개하는 공개키(1번 키)로 만들어서 공개키 저장소(CA: Certificate Authority)에 등록해 놓는다.
  • 서버는 서버만 알 수 있는 개인키(2번 키)를 소유하고 있으면 된다.
  • 그러면 1번키로 암호화된 http 요청, 즉 HTTPS 프로토콜을 사용한 요청이 온다면 서버는 개인키(2번 키)를 이용하여 1번키로 암호화된 문장을 해독하게 된다.
  • 서버는 요청이 무엇인지 알게되고 요청에 맞는 응답을 다시 개인키(2번 키)로 암호화해서 요청한 클라이언트에게 보내주게 된다.
  • 응답을 받은 클라이언트는 공개키(1번 키)를 이용해서 개인키(2번 키) 암호화된 HTTPS 응답을 해독하고 사용한다.

HTTPS를 지원하는 서버에 요청(Request)을 하려면 공개키가 필요하다는 것을 알 수 있다.

그러면 그 공개키는 공개키 저장소에 있다는 것은 알겠는데 어떻게 공개키 저장소에서 가져올까? 추가적으로 공개키는 누구나 얻을 수 있고 공개키를 알면 서버가 주는 데이터(Response)는 알 수 있는데 보안상에 의미가 있을까? 보안상의 의미는 없다. 대신 얻을 수 있는 이점은 해당 서버로부터 온 응답임을 확신할 수 있다. 왜? 공개키로 해독이 가능했으니까 반드시 해당 서버의 개인키로 암호화했다는 것을 보장하기 때문이다.

HTTPS 통신 흐름

공개키가 공개키 저장소에 있는데 어떻게 가져올 수 있을까? HTTPS 통신 흐름에 대해서 자세히 들여다보면 알 수 있다. 일단 공개키 저장소라고 부르던 곳이 원래 명칭은 CA(Certificate Authority)다. CA는 민간기업이지만 아무나 운영할 수 없고 신뢰성이 검증된 기업만 CA를 운영할 수 있다.

  1. 먼저 애플리케이션 서버(A)를 만드는 기업은 HTTPS를 적용하기 위해서 공개키와 개인키를 만든다.

  2. 그 다음에 신뢰할 수 있는 CA 기업을 선택하고 그 기업에 내 공개키를 관리해달라고 계약하고 돈을 지불한다.

  3. 계약을 완료한 CA 기업은 또 CA 기업만의 공개키와 개인키가 있다. CA 기업은 CA기업의 이름과 A서버의 공개키, 공개키의 암호화 방법 등의 정보를 담은 인증서를 만들고, 해당 인증서를 CA 기업의 개인키로 암호화해서 A서버에게 제공한다.

  4. A서버는 암호화된 인증서를 갖게 되었다. 이제 A서버는 A서버의 공개키로 암호화된 HTTPS 요청이 아닌 요청(Request)이 오면 이 암호화된 인증서를 클라이언트에게 준다.

  5. 이제 클라이언트 입장에서, 예를 들어 A서버로 index.html 파일을 달라고 요청했다. 그러면 HTTPS 요청이 아니기 때문에 CA기업이 A서버의 정보를 CA 기업의 개인키로 암호화한 인증서를 받게 될 것이다.

  6. 여기서 중요하다. 세계적으로 신뢰할 수 있는 CA 기업의 공개키는 브라우저가 이미 알고 있다.

  7. 브라우저가 CA 기업 리스트를 쭉 탐색하면서 인증서에 적혀있는 CA기업 이름이 같으면 해당 CA기업의 공개키를 이미 알고 있는 브라우저는 해독할 수 있을 것이다. 그러면 해독해서 A서버의 공개키를 얻었다.

  8. 그러면 A서버와 통신할 때는 A서버의 공개키로 암호화해서 Request를 날리게 될 것이다.

HTTPS를 지원한다고 해서 무조건 안전한 것은 아니다. 왜냐하면 신뢰할 수 있는 CA 기업이 아니라 자체적으로 인증서를 발급할 수도 있고, 신뢰할 수 없는 CA 기업을 통해서 인증서를 발급받을 수도 있기 때문이다. 그렇게 되면 브라우저에서는 https지만 "주의 요함", "안전하지 않은 사이트"등의 알림을 주게된다.

참조 https://webactually.com/2018/11/16/http에서-https로-전환하기-위한-완벽-가이드/ https://jeong-pro.tistory.com/89

https 배포

계기

WebCodecs을 사용하기 위해서는 secure domain(localhost 또는 https)을 포함하여 사용 신청을 해야 하기 때문에 HTTPS 배포를 시도하게 되었다.

흐름

도메인 생성 -> DNS 설정 -> SSL 도메인 소유권 인증 -> 서버 SSL 설정

도메인 생성

www.freenom.com 에서 도메인의 루트 경로로 희망하는 문자열로 검색하면 이를 포함하는 사용 가능한 도메인 목록을 보여준다.

프로젝트 이름인 wave는 단독으로 식별하기에는 너무 흔한 단어여서 유료 도메인조차 구하기 쉽지 않았기에, 부스트캠프의 boost를 따서 boostwave로 검색을 시도하니 boostwave.ga 등은 무료로 사용이 가능했다.

해당 도메인을 사용 신청한 결과는 아래와 같다. freenom my domains

DNS 설정

Custom DNS 네임서버를 쓸 수도 있지만, freenom에서 기본으로 제공하는 네임서버를 사용하기로 하였다. 아래와 같이 DNS 레코드의 값을 서버 공인 IP로 설정하였다. freenom DNS management

SSL 도메인 소유권 인증

www.sslforfree.com 에서 SSL 발급을 진행하였다. 여기에 설명된 것처럼 email, DNS CNAME, file upload 중 하나의 방식을 통하여 도메인이 자신의 소유임을 인증하면 3개월간 유효한 인증서가 발급된다. sslforfree validation

DNS CNAME 방식을 시도하려 했으나, freenom DNS 설정에서 문제가 발생하여 file upload 방식으로 진행하였다. 브라우저에서 txt 파일을 다운로드받고 요구하는 경로에서 vi로 내용물을 붙여넣기 하였다. file upload setup

서버 SSL 설정

sslforfree 측에서 해당 경로에 있는 txt 파일의 내용을 확인하면 아래와 같이 certificate이 발급된다. sslforfree certification

압축 파일의 내용물은 아래와 같다. 이는 scp로 서버(/etc/ssl)에 업로드하였다. SSL zip file

Frontend는 nginx로 구동하고 있으므로 installing SSL certificate on NGINX에 나온 설명에 따라 nginx에서 SSL 설정을 하였다.

server {
  listen 443;

  ssl    on;
  ssl_certificate    /etc/ssl/certificate.crt;
  ssl_certificate_key    /etc/ssl/private.key;

  server_name boostwave.ga;

  location / {
    root /var/lib/jenkins/workspace/wave/client/dist;
    index index.html
    try_files $uri $uri/ /index.html;
  }
}

그런데 짜잔, 문제가 생겼다. nginx가 죽었는데, certificate.crt 파일에 문제가 있다고 한다. 위에서 하라는 대로 cat 명령어로 bundle을 합쳤는데, 이 때 합치는 과정에서 newline을 주지 않아 두 인증서가 줄바꿈 없이 붙어버리는 바람에 오류가 생긴 듯 하다. vi로 해당 파일을 열어 수동으로 줄바꿈을 주고 나니 https 접속이 잘 되었다. https 배포 성공

그런데, 브라우저에서 https를 따로 입력해주지 않으면 기본적으로 http로 시도하기 때문에 거슬렸다. 따라서, http로 접속을 시도 시 https로 리다이렉트해주는 로직을 추가하였다.

또한, HTTPS 사이트에서 HTTP로 API 요청을 보내면 Chrome에서 경고를 띄우며 중단시키기 때문에 API 요청도 HTTPS 도메인으로 보내도록 하였고, 같은 도메인을 사용하기 위해 /api 경로로 오는 요청을 express 서버(https://boostwave.ga:3000/) 쪽으로 보내주도록 프록시 설정을 했다. 동영상 파일을 업로드하는 경우 request의 크기가 굉장히 큰데, nginx 기본값이 작아서 413 Payload too large가 뜨는 문제도 설정을 통해 해결하였다.

server {
  listen 443;

  ssl    on;
  ssl_certificate    /etc/ssl/certificate.crt;
  ssl_certificate_key    /etc/ssl/private.key;

  server_name boostwave.ga;

  location / {
    root /var/lib/jenkins/workspace/wave/client/dist;
    index index.html
    try_files $uri $uri/ /index.html;
  }

  location /api/ {
    client_max_body_size 2G;
    proxy_pass https://boostwave.ga:3000/;
    proxy_set_header Host $host;
  }
}

server {
  listen 80 default_server;

  server_name _;

  return 301 https://$host$request_uri;
}

이제 정말 우리의 서비스를 https로 즐길 준비가 되었다! Secure origin을 확보했으니 이제 본래 취지였던 Web Codecs 사용 등록을 해 보자. Web Codecs registration

등록을 완료하면 이렇게 token이 부여된다. Web Codecs token

index.html 파일에 <meta http-equiv="origin-trial" content="[token here]"> 를 포함하면 이제 Web Codecs를 쓸 수 있게 되는 것 같다.

Clone this wiki locally