
nginx를 활용해 http://mydomain.com 사이트를 올리는데 성공했다.
이번엔 Certbot을 활용해 인증서를 발급받고, https프로토콜을 적용함으로 보안적인 요소를 확보해보겠다.
먼저 HTTP에 대해서 알아보자
HTTP는 클라이언트와 서버가 서로 통신하는 방법을 표준화하는 TCP/IP 기반 애플리케이션 계층 통신 프로토콜이다.
HTTP는 인터넷에서 데이터를 주고받기 위해 사용되는 프로토콜이다. 클라이언트와 서버 간의 통신을 담당하며, 웹 브라우저와 웹 서버 간의 데이터 전송을 위해 주로 사용된다.
HTTP는 요청(Request)과 응답(Response)의 형태로 이루어져 있다. 클라이언트는 HTTP 요청 메시지를 서버에 전송하고, 서버는 이 요청에 대한 응답 메시지를 클라이언트에게 전송한다. 요청과 응답은 각각 헤더와 바디로 구성된다. 헤더는 요청이나 응답에 대한 메타데이터를 포함하고, 바디는 요청이나 응답에 대한 실제 데이터를 포함한다.
HTTPS(Hypertext Transfer Protocol Secure)는 HTTP의 확장 버전 또는 더 안전한 버전입니다. HTTPS에서는 브라우저와 서버가 데이터를 전송하기 전에 안전하고 암호화된 연결을 설정합니다.

HTTP로 웹사이트를 만들면 귀찮게 SSL인증서를 발급받고 적용할 필요가 없을텐데, 왜 굳이 사람들은 HTTPS를 사용할까?
HTTP 메시지는 일반 텍스트로, 권한이 없는 당사자가 인터넷을 통해 쉽게 엑세스하고 읽을 수 있다. 반면 HTTPS는 모든 데이터를 암호화된 형태로 전송한다.
검색 엔진은 HTTP의 신뢰성이 더 낮기 때문에 보통 HTTP 웹 사이트 콘텐츠의 순위를 HTTPS 웹 페이지보다 낮게 지정합니다. 고객도 HTTP보다 HTTPS 웹 사이트를 더 선호합니다. 브라우저는 브라우저 주소 표시줄에서 웹 사이트 URL 옆에 있는 자물쇠 아이콘을 배치하여 사용자에게 HTTPS 연결을 표시합니다. 사용자는 이러한 추가 보안 및 신뢰 요소 때문에 HTTPS 웹 사이트 및 애플리케이션을 선호합니다.
HTTPS 웹 애플리케이션은 HTTP 애플리케이션보다 로드 속도가 더 빠릅니다. 마찬가지로, HTTPS는 참조 링크도 더 잘 추적합니다. 추천 트래픽은 광고 또는 소셜 미디어 백링크와 같은 서드 파티 소스에서 생성되는 웹 사이트 트래픽입니다. 분석 소프트웨어가 신뢰할 수 있는 트래픽 소스를 정확하게 식별하도록 하려면 HTTPS를 활성화해야 합니다.
아래의 그림에서 처럼 HTTP 방식은 어플리케이션 계층에서 직접 TCP 레이어와 통신하지만, SSL을 사용하면 HTTP와 SSL이 통신하고, SSL과 TCP 가 통신하게 됩니다. 이렇게 통신하는 방식을 HTTPS 라고 부르는 것 입니다.


대칭키 암호화 방식이란, 하나의 암호화키(key)를 평문으로 암호화하고, 다시 암호문을 원해의 평문으로 복호화할 때 사용하는 방식
공개키 암호화 방식은 공개키, 개인키 이렇게 두 개의 키를 한 쌍(키페어: key pair)로 각각 암호화/복호화에 사용
공개키 방식은 대칭키 방식에 비해 안전하지만, 계산 과정이 복잡하고 연산 도중 컴퓨터 자원을 많이 사용, 실제 IT에서는 공개키, 대칭키 방식을 혼합하여 사용함

다음 정보를 Client Hello 단계에서 보냄
대부분 브라우저에서는 공신력 있는 CA들의 정보와 CA가 만든 공개키가 이미 설치되어 있음. 서버가 보낸 SSL 인증서가 정말 CA가 만든것인지를 확인하기 위해, 내장된 CA공개키로 암호화된 인증서를 복호화
정상적으로 복호화 되었다면 CA가 발급한 것이 증명이 되고, 등록된 CA가 만든 인증서처럼 꾸몄다면 브라우저에 경고를 보냄
웹 서버 인증서에 딸려 온 웹사이트의 공개키로 이것을 암호화 하여 서버로 전송
복호화 한 값을 master secret 값으로 저장, 이것을 사용하여 방금 브라우저와 만들어진 연결에 고유한 값을 부여하기 위한 세션 키 생성. 세션키는 대칭키 암호화에 사용할 키로 브라우저와 서버 사이에 주고받는 데이터를 암호화하고 복호화함
브라우저와 서버는 SSL 핸드셰이크를 종료하고 웹상에서 데이터를 세션키를 사용해 암호화/복호화하며, HTTPS 프로토콜을 통해 주고받을 수 있다.
| 단계 | 암호화 방식 | 목적 |
|---|---|---|
| 인증서 검증 | 비대칭키 | 서버 신뢰 검증 |
| 세션키 전달 | 비대칭키 | 안전한 세션키 교환 |
| 데이터 전송 | 대칭키 | 빠르고 효율적인 암호화 |
HTTP를 적용하기 위해서 인증 기관으로부터 인증을 받아야한다.
나는 Webroot 방식을 활용했다.
실제 돌아가고 있는 웹 서버에 특정 파일 쓰기 작업을 통해 인증하는 방식으로, 접근할 수 있는 특정 디렉터리를 제공해서 접근이 가능한지 확인하는 방식이다.
server {
listen 80;
server_name mywebdomain;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
일단 인증을 받고, 아래 코드를 통해 서버가 시작될 때 인증서 유효기간 확인 및 갱신을 하고, 추후 프로젝트가 완성되면 유효기간(90일)에 맞춰 자동 갱신을 적용할 예정이다.
sh "ssh -o StrictHostKeyChecking=no ubuntu@$AWS_IP 'cd ~/Myprojectname/cert/certbot && sudo docker-compose -f cert-compose.yml up -d'"
sh "ssh -o StrictHostKeyChecking=no ubuntu@$AWS_IP 'cd ~/Myprojectname/cert/certbot && sudo docker-compose -f cert-compose.yml down'"
nginx/default.conf 파일에 새로운 내용을 추가하여 https를 받을 수 있도록 했다.
주석을 남겨두었으니, 참고바람
# HTTP 요청 처리 (80포트)
server {
listen 80;
listen [::]:80;
# 이 서버 블록이 처리할 도메인
server_name mydomain;
# 모든 HTTP 요청을 HTTPS로 리다이렉트
return 301 https://mydomain$request_uri;
}
# HTTP 요청 처리 (443포트)
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name www.mydomain;
# 인증서 경로 (Let's Encrypt로 발급받은 것)
ssl_certificate /etc/letsencrypt/live/mydomain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain/privkey.pem;
# www 붙은 도메인 요청도 non-www 도메인으로 리다이렉트
return 301 https://mydomain$request_uri;
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
server_name mnmwa.kr;
ssl_certificate /etc/letsencrypt/live/mydomain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mydomain/privkey.pem;
# include /etc/letsencrypt/option-ssl-nginx.conf;
# ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
# React 정적 파일 서빙
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri /index.html;
}
# API 프록시 설정
location /api/v1/ {
# docker network 내부에서 통신
proxy_pass http://mybackend:8080;
# proxy 요청에 원래 호스트 헤더를 설정
proxy_set_header Host $host;
# 클라이언트의 실제 IP를 X-Real-IP 헤더에 설정. 백엔드 서버가 실제 클라이언트의 IP를 알기 위함. -> 로깅, IP 제한, 지리적 위치 서비스 등에 사용.
proxy_set_header X-Real-IP $remote_addr;
# X-Forwarded-For 클라이언트의 IP와 경유한 프록시 서버의 IP 목록을 전달. 백엔드 서버가 전체 경로를 추적할 수 있게 함.
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 프로토콜을 X-Forwarded-Proto 헤더에 설정. 이유는 프로토콜이 http인지 https인지 알기 위함 -> 보안 분석, 트래픽 분석 등에 사용.
proxy_set_header X-Forwarded-Proto $scheme;
}
}
위 같은 설정으로
http://www.mydomain -> https://mydomain
http://mydomain -> https://mydomain
https://www.mydomain -> https://mydomain
으로 리다이렉트 되어서 https 설정을 마칠 수 있었다.