AWS(Nginx server)를 http에서 https로 변경하기

SongWoo Yu·2025년 7월 3일
post-thumbnail

개요

기존 HTTP 프로토콜로 운영되던 Quasar 기반의 AWS 웹애플리케이션서버를 보안이 강화된 HTTPS 프로토콜로 전환하려고 한다. 이를 위해 Nginx proxy manager을 도입하여 리버스 프록시 아키텍처를 구축하고, Let's Encypt를 통해 SSL 인증서를 자동으로 발급 및 관리하는 방식으로 진행했다.

해당 작업이 목표는 보안을 강화하여 민감한 정보(API key, 개인정보)를 전송 구간 암호화를 통해 탈취 위험으로부터 원천 차단하기 위함이다. 그리고 브라우저의 안전하지 않음 경고를 제고하여 사용자 및 관리자에게 신뢰도 높은 서비스를 제공하기 위해서도 필요하다.

이를 위해 핵심 아키텍처를 변경했다. 기존의 단순한 웹 서버 구조에서 리버스 프록시 구조로 변경한 것이다. 기존에는 Nginx가 직접 80번 포트에서 요청을 받아 웹페이지를 보여주는 구조였다. 인터넷 트래픽이 생기면 80번 포트를 통해 서버의 Nginx 컨테이너(웹서버)가 퀘이사 웹을 띄어준 것이었다.

이제는 Nginx Proxy Manager가 모든 외부 요청을 받는 관문 역할을 한다. 따라서 80번, 443번 포트를 통해 인터넷 트래픽이 생기면 NPM이 서버의 Nginx 컨테이너 8080포트를 통해 퀘이사 앱을 보여준다.

1. 도메인 구매하기

GoDaddy에 가입하고 도메인 검색, pqm.kr로 도메인을 구매했다.

2. Cloudflare

cloudflare에 가입하고 계정 홈에서 도메인을 추가한다. 구매한 도메인을 입력하고 DNS 레코드를 빠른 스캔하고 계속한다. 그대로 진행하다보면 네임서버 주소가 두 개 나온다. 이를 복사해서 GoDaddy의 도메인 소유권을 cloudflare로 양도해야 한다. GoDaddy에서 도메인 - DNS - 네임서버로 들어가 아까 복사한 네임서버 주소를 붙여넣고, 네임서버를 변경한다. 그리고 free 요금제에 가입한다.

3. DNS 레코드 설정

거래하는 업체나, 프로젝트 네임을 붙여 서브 도메인을 만들어 AWS Lightsail 서버의 공인 IP 주소로 연결하는 A 레코드를 생성한다. 이때 유형 A를 선택하고 서브 도메인의 앞에 들어갈 이름을 만들고, IPv4에 라이트세일의 공인 ip를 넣는다. 프록싱하지 말고 DNS 전용으로 TTL을 2분 정도로 설정해주고 만들면 된다.
이때 프록싱하지 않는 이유는 서브 도메인이 서버의 ip를 직접 가르키게 하여 let;s encrypt가 서버를 정확히 찾아 인증서를 발급하도록 하기 위함이다.

4. 서버 구성 변경

기존의 웹서버 설정을 변경한다. 기존 앱에서 이용하던 /opt/nginx/docker-compose.yml 파일의 ports 설정을 "80:80" 에서 "8080:80" 으로 변경한다. 이는 외부 요청을 받은 80번 포트를 NPM(Nginx Proxy Manager)가 사용해야 하기에 내부에서만 사용할 8080포트로 자리를 비켜주어 포트 충돌을 막기 위함이다.

그리고 기존의 컨테이너를 중지한다. docker compose down명령으로 포트 변경 전의 Nginx 컨테이너를 완전히 중지한다. 이제 변경된 컨테이너를 실행한다. docker compose up -d로 포트가 8080으로 변경된 Nginx 컨테이너를 다시 실행한다.

그리고 새로운 NPM을 생성한다. NPM용 디렉토리 및 설정 파일 생성: /opt/npm 디렉토리를 만들고, 공식 문서에 따라 docker-compose.yml 파일을 작성한다. https://nginxproxymanager.com/setup/ 이 사이트에서 Running the App을 복사해서 파일을 만들면, docker compose up -d을 통해 80, 443, 81포트를 사용할 수 있다.

이후 AWS Lightsail에 접속하여 NPM이 사용하는 81번 포트와 443번 포트를 추가로 열어주는 방화벽 설정을 해줘야 한다.

5. 리버스 프록시 및 SSL 인증서 설정

NPM 관리자 페이지에 접속한다. http://(공인ip):81로 접속하여, 아까 레코드에 만든 서브 도메인 네임을 입력하고 스키마에 http, Forward Hostname ip에 사설 ip를 입력한다. forward 포트에는 8080을 입력한다. 캐쉬 어시스트 등을 켜주고 프록시 호스트를 추가고 ssl certificate 탭으로 넘어와서 agree 항목을 체크한 다음에 저장한다.

6. AWS Lightsail의 8080포트 닫기

AWS에서 8080포트를 닫지 않으면 기존의 공인 ip를 통한 http 접속이 가능하다. 물론 http://공인 ip:8080으로 접속해야 하지만 가능하다. 그러나 이게 열려있다는 것은 지금까지 https를 통해 접속하도록한 노력이 무산되는 것과 같다. 모든 접속은 NPM을 통해서만 이루어져야 보안을 강화할 수 있다. 앞서 8080포트를 통해 컨테이너에 접속하도록 Nginx에 설정해놨기에 이 부분을 바꾸면 NPM을 통한 접속에서도 내부망에서 사설망 접속도 막히기 때문에 이걸 건들면 안 되고, AWS만 변경해주면 된다.

7. NPM도 같은 방법으로 HTTPS 접속으로 변경하기

NPM을 http://(공인ip):81로 접속하고 있었는데, 이것도 npm.~.kr로 변경하려고 한다. 마찬가지로 cloudflare에서 DNS 레코드를 추가하고, Nginx proxy manager에서 사설 ip의 81번 포트로 등록해주면 된다.

Q&A

Q1. 왜 Forward IP로 공인(Public) IP가 아닌 사설(Private) IP를 사용했나요?
A. 매우 중요한 포인트입니다. Nginx Proxy Manager 컨테이너와 Quasar 웹서버 컨테이너는 같은 서버(AWS Lightsail 인스턴스) 안에서 실행되고 있습니다. 이들은 서버 내부의 가상 네트워크를 통해 서로 통신할 수 있습니다.

사설 IP 통신: 서버 내부에서의 통신입니다. 훨씬 빠르고 안전하며 불필요한 외부 네트워크 트래픽을 유발하지 않습니다.

공인 IP 통신: 인터넷을 통해 자기 자신에게 다시 돌아오는 비효율적인 경로입니다. 보안상으로도 내부 서비스는 외부에 노출하지 않는 것이 원칙입니다.

따라서 서버 내부의 서비스끼리 통신할 때는 사설 IP를 사용하는 것이 정석입니다.

Q2. SSL 인증서가 10월 1일에 만료된다고 나오는데, 괜찮은가요?
A. 네, 괜찮습니다. Let's Encrypt 인증서는 정책상 유효기간이 90일로 짧습니다. 하지만 Nginx Proxy Manager의 핵심 기능 중 하나가 바로 이 인증서를 만료되기 전에 자동으로 갱신해주는 것입니다. 따라서 별도로 신경 쓰지 않아도 NPM이 알아서 인증서를 최신 상태로 유지해 줍니다.

Q3. 서브 도메인의 호스트명을 변경하고 싶습니다.
A. 이때는 CloudFlare에서 DNS의 레코드에서 기존의 레코들ㄹ 삭제해야 합니다. 그리고 새로운 유형을 A로 설정하고, 이름을 바꾸려고 하는 호스트명으로, IPv4주소는 이전에 등록했던 AWS lightsail의 공인 ip로 등록고 프록시 상태도 꺼주면 됩니다. 그런 다음에 Nginx Proxy Manager에서 인증서를 삭제한 다음 새롭게 만들어주시면 됩니다.

Q4. 추가적으로 유지보수해야 할 사항이 있나요?
A. 주기적인 시스템 및 이미지 업데이트가 필요합니다. 📈
서버의 운영체제(sudo apt update && sudo apt upgrade)와 Docker, 그리고 NPM 이미지(docker compose pull 명령어로 최신 버전 받기)를 주기적으로 업데이트하여 최신 보안 패치를 적용하는 것이 중요합니다.

먼저 서버의 운영체제를 업데이트하는 것이다.
1.sudo apt update
2. sudo apt upgrade -y 도중에 package configuration이 뜨면서 ssh 설정을 덮어쓸것인지 물어본다면, 내가 설정한 것을 초기화하면 안 될 수도 있다.이때는 keep the local version currently installed를 선택하면 된다.

다음은 도커와 Enginx 이미지를 업데이트하는 과정이다.
1. yml 파일이 있는 곳으로 이동한다.
cd opt/npm 이랑 cd opt/nginx
2. sudo docker compose pull
3. sudo docker compose up -d

Q5. 서버에 있는 포트 구성이 어려워요. 8080 80?
ifconfig를 통해서 네트워크 구성 분석을 해보세요. 이를 바탕으로 분석하면 됩니다.
http://<공인IP>:8080 요청이 Quasar 앱까지 도달하는 여정을 따라가 보겠습니다.
사용자의 요청은 인터넷을 통해 서버의 공인 IP로 오고, 최종적으로 서버의 ens5 (사설 IP 172.26.4.213)에 8080 포트로 도착합니다.
/opt/nginx/docker-compose.yml에 설정된 ports: - "8080:80" 규칙이 이 요청을 가로챕니다.
Docker는 이 규칙에 따라 ens5로 들어온 8080 포트 트래픽을 Quasar Nginx 컨테이너가 속한 전용 네트워크 허브(br-4f430c1a9c69 같은)로 보냅니다.
이 트래픽은 가상의 랜선(veth...)을 타고 Quasar Nginx 컨테이너 내부에 도착합니다.
이때 ports 규칙의 :80 부분에 따라, 컨테이너 내부의 80번 포트로 최종 전달됩니다.
컨테이너 안의 Nginx는 80번 포트로 요청을 받고 Quasar 앱 화면을 사용자에게 보여줍니다.
이렇게 ifconfig의 각 요소들은 외부 요청이 서버 내부의 특정 컨테이너까지 전달되는 과정을 단계별로 처리하는 역할을 하고 있습니다.

0개의 댓글