이번 장바구니 협업 미션을 진행하면서 배포를 해보게 되었고 https라는 개념도 처음 다루게 되었습니다. 이번 아티클을 통해 https의 개념은 대략적으로 무엇인지, 어떻게 ec2 기반 서버에 적용할 수 있는지 알아보고자 합니다.
HTTP, HTTPS?
HTTPS(Hyper Text Transfer Protocol Secure)이란, HTTP에서 SSL 혹은 TLS라고 불리는 암호화 방식이 추가된 것입니다. HTTP는 바디, 헤더등을 암호화할 수 없어서 민감한 정보까지도 순전히 드러나게 된다는 문제가 있었는데, HTTPS가 이를 해결한 것으로 보입니다. 즉, HTTPS는 HTTP + TLS, SSL이고 HTTP의 확장된 버전으로 생각할 수 있습니다. 그리고 HTTP와 다르게 HTTP는 443번 포트를 사용합니다.
암호화 방식
HTTPS가 이런 암호화 방식을 지원할 수 있는 이유는 독립된 인증 기관(CA, Certificate Authority)에서 인증서를 획득했기 때문입니다. 브라우저와의 상호작용은 다음과 같은 순서로 구성됩니다.
- 사용자는 웹사이트로 방문합니다.
- 브라우저는 서버의 SSL 인증서를 요청해서 사이트의 신뢰성을 검증하려고 시도합니다.
- 서버는 퍼블릭 키가 포함된 SSL 인증서를 회신으로 전송합니다.
- 웹 사이트의 SSL 인증서는 서버 아이덴티티를 증명합니다. 브라우저에서 인증이 완료되면 브라우저가 퍼블릭 키를 사용해서 비밀 세션 키가 포함된 메세지를 암호화하고 전송합니다.
- 웹 서버는 프라이빗 키를 사용하여 메세지를 해독하고 세션 키를 검색합니다. 그리고 세션 키를 암호화해서 브라우저에게 승인 메세지를 보냅니다.
- 이제 브라우저와 웹 서버 모두 동일한 세션 키를 사용해서 메세지를 안전하게 교환합니다.
즉, 요약하자면 HTTPS 방식에서는 브라우저와 서버가 통신할 때 세션 키를 통해 암호화/복호화가 이루어지는데, 이러한 암호화/복호화를 위한 세션 키를 공유하기 위해 비대칭 키를 사용합니다. 즉, 대칭 키를 이용한 암호화 방식, 비대칭 키를 이용한 암호화 방식을 모두 사용하는 구조라고 말할 수 있습니다.
문제 상황
이번 미션에서는 Github Pages를 사용하는 프론트엔드 https 서버와 통신해야 했습니다.
백엔드 서버는 EC2를 사용했는데, 정말 기본적인 세팅만 하고 JAR 파일을 실행시키면 HTTP 프로토콜을 사용합니다. 즉 프론트 서버는 HTTPS 프로토콜을 사용하는데 백엔드 서버는 HTTP 프로토콜을 사용하는 상황이 발생합니다. 이렇게 혼합해서 프로토콜을 사용하면 다음과 같은 문제들이 발생할 수 있습니다.
- 보안 약화: HTTPS를 사용하는 이유는 보안을 강화하기 위함인데, 실질적인 데이터를 주고받는 백엔드 서버가 HTTP로 통신한다면 HTTPS를 사용하는 이유가 없어집니다.
- 혼합 콘텐츠 문제: HTTPS로 페이지에 접근했으나(프론트엔드 페이지), 서버 자원에는 HTTP로 접근하므로 혼합 콘텐츠 문제가 발생합니다. 이러한 혼합 콘텐츠 문제는 심각한 보안 허점으로 이어지기도 한다고 합니다. 혼합 콘텐츠 문제와 관련된 내용은 다음의 페이지에서 잘 설명이 되어 있습니다. (https://web.dev/i18n/ko/what-is-mixed-content/)
EC2에서 Nginx + certbot 사용하기
HTTPS 통신을 허용하는 쉬운 방법 중 하나로는 certbot 사용이 있습니다. certbot은 LetsEncrypt 인증서를 자동으로 사용하여 HTTPS를 활성화시켜주는 무료 오픈소스입니다.
그럼 이제 본격적으로 EC2에서 Nginx와 certbot을 사용해 https 프로토콜을 사용하도록 서버를 개선해보겠습니다. 명령어만 주루룩 치면 끝나기는 하지만, 하나하나 곱씹으면서 이해해보고자 합니다.
1. nginx 설치
우선 Nginx를 설치해야 합니다.
sudo apt-get update
sudo apt-get install nginx
sudo, 즉 root 권한으로 apt-get update를 수행합니다. apt는 참고로 (advanced packaging tool)로, 데비안 GNU/리눅스 배포판 계열에서 사용할 수 있는 패키지 관리 도구입니다. 즉, 우선 이런 패키지 관리 도구를 업데이트해주고 이를 통해 nginx를 설치합니다.
2. certbot 설치
sudo apt-get install certbot python3-certbot-nginx
마찬가지의 방법으로 certbot과 python3-certbot-nginx를 설치해줍니다. install 명령어 뒤에 공백으로 구분하면 여러 패키지를 설치한다는 의미입니다.
3. 인증서 만들기
이제 https 통신을 위한 SSL 인증서를 만들 수 있습니다(모든 설치 준비가 끝났으므로).
sudo certbot --nginx -d [domain] -d www.[domain]
위와 같이 명령어를 작성합니다. --는 서브 커맨드를 지정하는 것으로 nginx라는 서브 커맨드를 사용한다는 것을 의미합니다. 그리고 -d 옵션을 통해 여러 도메인을 지정해줄 수 있습니다. www이 붙은 버전과 붙지 않은 버전을 모두 입력해줬는데요. 저는 가비아에서 구매한 도메인에 www를 붙인 버전과 붙이지 않은 버전(naked domain)을 모두 DNS 설정해줬기 때문입니다.
4. nginx 설정 변경
sudo vim /etc/nginx/sites-available/default
이제 인증서를 만들어줬으니 nginx 설정을 변경해 HTTPS 통신을 수행하도록 해야 합니다. vim 에디터로 해당 경로의 파일에 접근합니다. 해당 경로는 nginx의 기본 설정 파일이 존재하는 위치입니다.
그리고 다음과 같은 내용을 추가합니다.
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/[domain]/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/[domain]/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
server_name [domain] www.[domain];
location / {
proxy_pass http://localhost:8080;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Port $server_port;
}
}
해당 코드블록 삽입하는 것은 nginx의 가상 호스팅 정보를 수정하는 것입니다. 가상 호스팅은 하나의 웹 서버에서 여러 개의 도메인 또는 서브도메인을 호스팅하는 기술인데, 이를 통해 단일 서버에서 다수의 웹사이트를 운영할 수 있다고 합니다.
443번 포트를 ssl 방식으로 listening 하면서, 여러 ssl 인증서 정보의 위치를 명시해줍니다. 그리고 server_name을 명시해주는데 저는 앞서 도메인을 두 개 등록했으므로 두개 다 명시해줬습니다.
그리고 location 블록을 사용하는데, 'location /' 는 / 하위의 위치에 전부 적용한다는 뜻입니다. 그럼 무엇을 적용하는지도 살펴봐야겠죠. 여기서 proxy_pass 라는 개념이 등장하는데요, 이는 리버스 프록시를 위한 문장입니다. 즉 Nginx가 리버스 프록시의 역할을 하여 https로 요청이 들어오면 localhost:8080으로 다시 요청을 전달해주는 것을 의미합니다. 스프링의 서버는 8080번 포트를 사용하니까요. 이외에도 proxy_set_header를 통해 헤더를 지정해주고 있습니다.
5. Nginx 정상 작동 여부 체킹 및 리로딩
sudo nginx -t
sudo systemctl reload nginx
여기까지 왔으면 설정은 모두 끝났고, -t 옵션을 통해 nginx의 설정 파일이 잘 적용되어 있는지 테스트합니다. 이 과정에서 설정 파일 문법 이 체크됩니다.
그리고 systemctl reload 명령어를 통해 nginx 서비스를 갱신합니다.
마무리
위에서 제시한 과정들을 통해 HTTPS 프로토콜을 지원하는 서버를 구성해보았습니다.
아직 웹 개념도 낯설고 HTTPS 적용의 모든 메커니즘을 이해한 것은 아니지만, 이번 아티클을 통해 전체적인 틀이라도 잡힌 것 같다고 생각합니다.
참고자료
https://aws.amazon.com/ko/compare/the-difference-between-https-and-http/
https://mangkyu.tistory.com/98
https://opentutorials.org/module/384/4529
'우테코 5기' 카테고리의 다른 글
Web Server vs. WAS(Web Application Server) (0) | 2023.05.28 |
---|---|
도메인 엔티티 ID 부여에 대한 주관적인 생각 (0) | 2023.05.27 |
[레벨 2 미션] 웹 장바구니 미션 학습 기록 (2) (0) | 2023.05.20 |
[레벨 2 미션] 웹 장바구니 미션 학습 기록 (1) (1) | 2023.05.14 |
[레벨 2 미션] 웹 자동차 경주 미션 학습 기록 (0) | 2023.05.07 |