티스토리 뷰
AWS 프리티어
AWS 프리티어란 AWS에서 계정 생성일로부터 12개월 동안 여러 서비스를 무료로 사용할 수 있도록 제공해주는 일종의 맛보기 서비스라고 할 수 있습니다. 주요 서비스는 AWS EC2, AWS S3, AWS RDS 가 있습니다.
자세한 내용은 우측 링크를 통해 확인하실 수 있습니다. AWS 프리티어
무료라고 했잖아요..
프로젝트를 위해 AWS 프리티어를 사용하던 중 비용 발생 이메일이 와서 청구서를 확인해보니 실제로 과금이 되었습니다.
프리티어 범위 내에서 사용하면 비용이 발생하지 않을 것이라 생각했기에 이 부분에서 당황했는데, 비용이 발생한 부분은 아래와 같습니다.
청구서를 확인해보면 EC2에 public ipv4가 연결되어 있고, 이는 프리티어로 비용이 발생하지 않은 케이스입니다.
아래에 public ipv4가 2개가 생성된 것이고, 이 때문에 비용이 발생하는 것 이었습니다.
생성된 2개의 public ip를 확인해보고자 AWS IPAM을 활용했고, 이는 로드밸런서에서 생성된 ip인 것을 확인하였습니다.
왜 로드밸런서에서 public ip를?
로드밸런서는 ip 주소 설정에 따라 선택한 서브넷의 대상으로 트래픽을 라우팅하게 됩니다.
즉, 서브넷을 할당하기 위해 각 서브넷에 public ip를 구성하게 되는 것이고
aws 로드밸런서에서는 가용 영역 생성을 2개 이상 강제하기 때문에 위와 같이 2개의 public ip가 생성된 것 입니다.
로드밸런서를 사용했던 이유는
프로젝트 aws 구성 시 로드밸런서를 사용했던 이유는 단순히 https 프로토콜을 사용하기 위해서였습니다.
ACM을 통해 SSL 인증서를 발급하고, 이를 로드밸런서에 설정해 https 리스너 규칙을 추가해 간편하게 https 프로토콜 사용이 가능했기 때문입니다.
하지만, 프리티어임에도 비용이 부과되는 점과 단순히 https 프로토콜 사용만을 위해 로드밸런서를 사용하는 것이 비합리적이라고 생각했고 다른 방식으로
https 프로토콜을 적용할 수 있게 변경하는 과정이 필요했습니다.
기존에 사용하던 로드밸런서를 삭제하면 연결된 public ip 또한 삭제됩니다. 우선 로드밸런서를 삭제해야 합니다.
로드밸런서를 삭제하면 하루 뒤 IPAM을 통해 로드밸런서에 연결된 public ip가 삭제된 것을 확인하실 수 있을 것 입니다.
NGINX를 통해 SSL 적용하기
위에서 언급했던 것 처럼, 단순히 SSL 적용을 위해 로드밸런서를 사용했었는데 이를 NGINX를 통해 기능을 위임할 수 있습니다.
NGINX란 웹 서비스, 리버스 프록시, 캐싱, 로드 밸런싱, 미디어 스트리밍 등을 위한 오픈 소스 소프트웨어입니다.
우선 NGINX를 설정하기 전 Let's Encrypt를 사용하여 SSL 인증서를 발급해야 합니다.
sudo snap install certbot --classic
certbot certonly --manual --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory -d 도메인 -d *.도메인
위와 같이 설치하고 진행하면 Route53에 DNS TXT 레코드를 생성해야 합니다.
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Enter email address (used for urgent renewal and security notices)
(Enter 'c' to cancel): 이메일 입력
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please read the Terms of Service at
https://letsencrypt.org/documents/LE-SA-v1.3-September-21-2022.pdf. You must
agree in order to register with the ACME server. Do you agree?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing, once your first certificate is successfully issued, to
share your email address with the Electronic Frontier Foundation, a founding
partner of the Let's Encrypt project and the non-profit organization that
develops Certbot? We'd like to send you email about our work encrypting the web,
EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: Y
Account registered.
Requesting a certificate for 도메인 and *.도메인
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:
_acme-challenge.도메인.
with the following value:
~~~ 입력해야 하는 TXT ~~~
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Press Enter to Continue
해당 문구가 나온다면 Enter를 누르지 말고 AWS Route53 레코드를 _acme-challenge.도메인 으로 이름 짓고, 값에는 with the following value 값을 작성하여 레코드를 생성합니다.
레코드 적용이 완료되면 Enter를 누르고, 기존 생성한 레코드에 값을 추가해야 하는 부분이 나옵니다.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please deploy a DNS TXT record under the name:
_acme-challenge.도메인
with the following value:
~~~ 추가해야 하는 값 ~~~
(This must be set up in addition to the previous challenges; do not remove,
replace, or undo the previous challenge tasks yet. Note that you might be
asked to create multiple distinct TXT records with the same name. This is
permitted by DNS standards.)
Before continuing, verify the TXT record has been deployed. Depending on the DNS
provider, this may take some time, from a few seconds to multiple minutes. You can
check if it has finished deploying with aid of online tools, such as the Google
Admin Toolbox: https://toolbox.googleapps.com/apps/dig/#TXT/_acme-challenge.도메인.
Look for one or more bolded line(s) below the line ';ANSWER'. It should show the
value(s) you've just added.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
기존 레코드 값에 추가해야 하는 값을 이어서 작성하고 편집하면 인증서 발급이 완료됩니다.
이제 NGINX를 컨테이너에 올리고 reverse proxy 적용을 하면 완료됩니다! (필자의 서버는 EC2 내부 docker 안에서 구성됩니다.)
인스턴스 홈 디렉토리에서 data/nginx/app.conf 파일을 생성하여 아래와 같이 구성합니다.
server {
listen 80;
server_name 도메인;
server_tokens off;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
server_name 도메인;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/도메인/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/도메인/privkey.pem;
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://도메인:8080/;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
해당 스크립트의 내용은 다음과 같습니다.
1. EC2 내에서 도메인으로 들어오는 80 포트 요청을 읽어낸다.
2. SSL 적용을 위하여 443(https)로 리다이렉트 한다.
3. 8080(스프링)으로 reverse proxy 역할을 한다.
reverse proxy 역할을 하는 NGINX 스크립트를 작성 완료하면, SSL 관련 설정을 하기 위해 certbot에서 제공하는 스크립트를 적용해야 합니다.
/etc/letsencrypt 디렉토리에 options-ssl-nginx.conf 파일에 다음과 같은 스크립트를 적용합니다.
# This file contains important security parameters. If you modify this file
# manually, Certbot will be unable to automatically provide future security
# updates. Instead, Certbot will print and log an error message with a path to
# the up-to-date file that you will need to refer to when manually updating
# this file. Contents are based on https://ssl-config.mozilla.org
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
그리고 해당 디렉토리에서 OpenSSL로 디피-헬만 파라미터 키를 생성합니다. (보안을 강화하기 위한 목적, 필수는 아닐 것 같습니다 ㅎㅎ)
디피-헬만 파라미터는 SSL 통신시 암호화를 도와주는 방식 중 하나로 dhparam 키를 이용해 암호화 복잡도를 높여 보안을 강화하는것이 목적으로 각종 WAS의 SSL 통신에서 dhparam을 지원합니다. SSL 등급을 매기는 테스트 사이트에서 A등급을 받기 위해서는 필수로 적용해야 하는 사항입니다.
sudo openssl dhparam -out ssl-dhparams.pem 4096
해당 명령어를 작성하면 별 모양의 텍스트가 펼쳐지는 것을 확인하실 수 있습니다. 키를 생성하는데 대략 10 ~ 15 분 정도 소요되는 것 같습니다.
이로써 Let's Encrypt를 통해 SSL 인증서를 발급받고, NGINX를 통해 reverse proxy를 적용하였습니다.
구성된 환경에 따라 다르겠지만, 필자의 인스턴스는 docker를 통해 서버 구성을 했기 때문에 docker-compose를 통해 NGINX 컨테이너를 올리는 작업까지 진행하도록 하겠습니다.
EC2 인스턴스 루트 위치에 docker-compose.yml을 작성하여 컨테이너를 올리겠습니다.
작성해야 하는 스크립트는 다음과 같습니다.
version: '3'
services:
nginx:
image: nginx:1.15-alpine
restart: unless-stopped
volumes:
- ./data/nginx:/etc/nginx/conf.d
- /etc/letsencrypt:/etc/letsencrypt
- /var/log/nginx/도메인:/var/log/nginx/도메인
ports:
- "80:80"
- "443:443"
command:
"/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"
이후 다음 명령어로 docker-compose를 구동해야 합니다.
docker-compose up -d
모든 작업을 완료하면 다음과 같이 NGINX 컨테이너가 잘 올라간 것을 확인하실 수 있습니다.
완.
이렇게 AWS 로드밸런서를 사용하던 서버 구성에서 NGINX를 활용한 reverse proxy 구성 및 SSL 적용을 해보았습니다.
단순히 로드밸런서를 사용하여 SSL 적용할 수 있다는 편리함에 로드밸런서를 선택했지만, 비용이 발생하고 로드밸런서 적용만이 최선일까 라는 궁금증에 이렇게 포스팅까지 이어져 온 것 같습니다.
아마 로드밸런서를 사용하여 단순히 SSL을 적용하시는 분들이 있으실 것이라 생각하는데, 다른 방안을 찾으신다면 해당 포스팅이 도움이 되었으면 좋겠습니다!
여담이지만 AWS Route53을 사용하게 되면 0.5달러가 부과됩니다.
도메인을 등록하면 도메인과 동일한 이름의 호스팅 영역이 자동으로 생성됩니다.
호스팅 영역을 사용해 Amazon Route 53이 도메인의 트래픽을 라우팅할 곳을 지정할 수 있습니다. 호스팅 영역 요금은 월 0.50 달러입니다.
https://aws.amazon.com/ko/getting-started/hands-on/get-a-domain/