EC2 인스턴스에 SSL/TLS를 구성해 HTTPS로 접속해 보기

EC2 인스턴스에 SSL/TLS를 구성해 보는 과정을 정리해 봤습니다.
2022.02.23

안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번에는 EC2 인스턴스에 SSL/TLS를 구성해 보는 과정을 정리해 봤습니다.

EC2 기본 설정

yum update -y
yum install httpd-2.4.51 -y
systemctl start httpd
systemctl enable httpd
httpd -v

cp /usr/share/httpd/noindex/index.html /var/www/html/index.html

다음 명령어를 통해 아파치 웹 서버를 설치합니다.

보안그룹에서는 HTTP와 HTTPS를 열어줍니다.

EC2 주소로 접속해서 아파치 테스트 페이지가 나오는지 확인합니다.

웹 사이트를 식별하고 인증하려면 TLS 퍼블릭 키 인프라(PKI)는 도메인 이름 시스템(DNS)을 사용합니다. EC2 인스턴스를 사용하여 퍼블릭 웹 사이트를 호스팅하려는 경우, 웹 서버의 도메인 이름을 등록하거나 Amazon EC2 호스트로 기존 도메인 이름을 전송해야 합니다. 수많은 타사 도메인 등록 및 DNS 호스팅 서비스를 이에 사용할 수 있습니다. 또는 Amazon Route 53을 사용할 수도 있습니다.

그리고 도메인을 등록할 필요가 있기 때문에, Route53와 ACM을 이용해서 도메인을 등록하고 해당 도메인으로 EC2에 접속합니다. 도메인 등록에 관해서는 아래 블로그를 참고해 주세요.

서버에서 TLS 활성화

yum install -y mod_ssl

아파치에서 ssl을 구성하기 위해서는 mod_ssl 모듈이 설치되어 있어야 합니다.

mod_ssl 모듈을 설치하면 다음 파일이 설치됩니다.

  •  /etc/httpd/conf.d/ssl.conf mod_ssl의 구성 파일입니다. 여기에는 Apache에 암호화 키 및 인증서의 위치, 허용하는 TLS 프로토콜 버전, 허용하는 암호화 암호를 알려주는 명령이 포함되어 있습니다.
  • /etc/pki/tls/certs/make-dummy-cert 서버 호스트에 대한 프라이빗 키와 자체 서명된 X.509 인증서 생성용 스크립트입니다. 이 인증서는 Apache가 TLS를 사용하도록 올바르게 설치되었는지 테스트하는 데 유용합니다. 제공하는 자격 증명이 없기 때문에 프로덕션에서 사용되어서는 안됩니다. 프로덕션 환경에서 사용되는 경우 웹 브라우저에서 경고를 트리거합니다.

자체 서명된 테스트용 더미 인증서와 키를 이용하는 방법도 있지만 곧바로 CA가 서명한 인증서를 가져와서 SSL/TLS를 구성해 보도록 하겠습니다.

CA가 서명한 인증서 가져오기

cd /etc/pki/tls/private/
openssl genrsa -out custom.key

TLS에 대한 서버의 프라이빗 키를 저장하는 디렉터리로 이동해서 기본 RSA 호스트 키를 만듭니다. 이외에도 공식문서에 의하면 다음과 같은 호스트 키들을 만들 수 있습니다.

  • openssl genrsa -out custom.key 4096 더 큰 모듈러스로 더 강력한 RSA 키를 만듭니다. 결과 파일인 custom.key는 4096비트 RSA 프라이빗 키입니다.
  • openssl genrsa -out custom.key 4096 암호로 보호되는 4096비트 암호화 RSA 키를 생성합니다. 그러면 AES-128 암호화로 암호화된 4096비트 RSA 프라이빗 키인 custom.key 파일이 생성됩니다.
  • sudo openssl ecparam -name prime256v1 -out custom.key -genkey 비 RSA 암호를 사용하여 키를 생성합니다. RSA 암호화는 두 개의 라지 소수의 결과를 기반으로 하는 공개 키의 크기 때문에 상대적으로 느릴 수 있습니다. 그러나 RSA 암호화 이외의 암호화를 사용하는 TLS의 키를 생성할 수 있습니다.
chown root:root custom.key
chmod 600 custom.key
ls -al custom.key

프라이빗 키에 권한을 부여합니다.

openssl req -new -key custom.key -out csr.pem
ls -al /etc/pki/tls/private/csr.pem

이제 CSR을 생성하고 CSR이 생성 되었는지 체크합니다.

이름 설명
Country Name 해당 국가의 두 자리 ISO 약자. US(=미국)
State or Province Name 해당 조직이 위치한 주 또는 지방의 이름. 이 이름은 약어로 사용할 수 없음. 워싱턴
Locality Name 조직의 위치(예: 도시). 시애틀
Organization Name 해당 조직의 정식 이름. 조직 이름의 약칭을 사용하지 마세요. Example Corporation
Organizational Unit Name 조직에 대한 추가 정보(있는 경우). 부서 예
Common Name 이 값은 사용자가 브라우저에 입력해야 하는 웹 주소와 정확히 일치해야 합니다. www.example.com의 형식으로, 호스트 이름 또는 별칭이 앞에 붙는 도메인 이름을 뜻합니다. CA는 *.example.com과 같이 와일드 카드 이름을 허용하는 비싼 인증서도 제공합니다. www.example.com
Email Address 서버 관리자의 이메일 주소. someone@example.com
  • openssl req -new -key custom.key -out csr.pem

명령어를 입력하면 국가코드 부터 시작해서 도메인 등등을 입력해야합니다.

Common Name에는 도메인 명을 적어주면 됩니다. Common Name은 필수 입력이지만 다른 부분들은 생략해도 되기 때문에 생략하고 진행 했습니다.

openssl x509 -req -days 365 -in csr.pem -signkey custom.key -out custom.crt
Signature ok
subject=/C=KR/L=Default City/O=Default Company Ltd/CN=www.입력한도메인
Getting Private key

서명을 위해 서명 요청을 제3자에게 제출하거나, 개발 및 테스트를 위해 자체 서명할 수 있습니다. 자체 서명된 인증서는 로드 밸런서와 EC2 인스턴스 간의 백엔드 HTTPS에도 사용할 수 있습니다.

cp /etc/pki/tls/private/custom.crt /etc/pki/tls/certs/custom.crt
chown root:root /etc/pki/tls/certs/custom.crt
chmod 600 /etc/pki/tls/certs/custom.crt
ls -al /etc/pki/tls/certs/custom.crt

이어서 /etc/pki/tls/certs 디렉터리에 CA가 서명한 새 인증서와 모든 중간 인증서를 배치합니다.

chown root:root /etc/pki/tls/private/custom.key
chmod 600 /etc/pki/tls/private/custom.key
ls -al /etc/pki/tls/private/custom.key

private 경로에 있는 custom.key 또 한 권한을 부여합니다.

vi /etc/httpd/conf.d/ssl.conf

#Server Certificate:
# Point SSLCertificateFile at a PEM encoded certificate. If
# the certificate is encrypted, then you will be prompted for a
# pass phrase. Note that a kill -HUP will prompt again. A new
# certificate can be generated using the genkey(1) command.
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt 주석처리
SSLCertificateFile /etc/pki/tls/certs/custom.crt 추가

#  Server Private Key:
#  If the key is not combined with the certificate, use this
#  directive to point at the key file. Keep in mind that if
#  you’ve both a RSA and a DSA private key you can configure
#  both in parallel (to also allow the use of DSA ciphers, etc.)
#SSLCertificateKeyFile /etc/pki/tls/private/localhost.key 주석처리
SSLCertificateKeyFile /etc/pki/tls/private/custom.key 추가

systemctl restart httpd

이제 새 인증서와 새 키 파일을 반영하기 위해서 아파치를 수정하고 재시작합니다.

보안 구성 테스트 및 강화

vi /etc/httpd/conf.d/ssl.conf

#  SSL Protocol support:
# List the enable protocol levels with which clients will be able to
# connect. Disable SSLv2 access by default:
#SSLProtocol all -SSLv3 주석처리
SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2 추가

#  SSL Cipher Suite:
#  List the ciphers that the client is permitted to negotiate.
#  See the mod_ssl documentation for a complete list.
#SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA 주석처리

SSLProtocol all -SSLv3를 주석처리하고, SSLProtocol -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 +TLSv1.2를 추가합니다. 이러한 명령은 SSL 버전 2 및 3과 TLS 버전 1.0 및 1.1을 명시적으로 비활성화합니다. 이제 이 서버는 TLS 1.2 이외의 프로토콜을 사용하는 클라이언트와의 암호화된 연결을 허용하지 않습니다.

그리고 SSL Cipher Suite:에서 SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA 또 한 주석처리합니다. 명시적 암호 그룹과 전방향 보안을 우선순위에 두고 부정확한 암호를 방지하는 암호 오더를 지정합니다. 여기에 사용된 SSLCipherSuite 명령은 서버에서 실행되는 특정 소프트웨어에 맞게 TLS 구성을 조정하는 Mozilla SSL Configuration Generator의 출력에 기반합니다.

웹사이트에 접속후, 다음과 같이 선택합니다.

환경 버전의 경우 EC2에서 다음 명령어를 통해 확인합니다.

  • yum list installed | grep httpd
  • yum list installed | grep openssl

입력을 끝마치고 아래로 내려와서 SSLCipherSuite를 복사합니다.

vi /etc/httpd/conf.d/ssl.conf

#  SSL Cipher Suite:
#  List the ciphers that the client is permitted to negotiate.
#  See the mod_ssl documentation for a complete list.
#SSLCipherSuite HIGH:MEDIUM:!aNULL:!MD5:!SEED:!IDEA 주석처리
SSLCipherSuite 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

#  Speed-optimized SSL Cipher configuration:
#  If speed is your main concern (on busy HTTPS servers e.g.),
#  you might want to force clients to specific, performance
#  optimized ciphers. In this case, prepend those ciphers
#  to the SSLCipherSuite list, and enable SSLHonorCipherOrder.
#  Caveat: by giving precedence to RC4-SHA and AES128-SHA
#  (as in the example below), most connections will no longer
#  have perfect forward secrecy - if the server’s key is
#  compromised, captures of past or future traffic must be
#  considered compromised, too.
#SSLCipherSuite RC4-SHA:AES128-SHA:HIGH:MEDIUM:!aNULL:!MD5
SSLHonorCipherOrder on 주석 해제

systemctl restart httpd

그리고 복사한 SSLCipherSuite를 붙여놓고, SSLHonorCipherOrder on 부분의 주석을 제거하고 아파치를 재시작합니다.

Amazon Linux 2에서 Certbot의 Let’s Encrypt

cd /home/ec2-user
wget -r --no-parent -A 'epel-release-*.rpm' https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/
rpm -Uvh dl.fedoraproject.org/pub/epel/7/x86_64/Packages/e/epel-release-*.rpm
yum-config-manager --enable epel*

EPEL(Extra Packages for Enterprise Linux) 7 리포지토리 패키지를 다운로드합니다. Certbot에 필요한 종속성을 공급하는 데 필요합니다.

vi /etc/httpd/conf/httpd.conf

Listen 80

ServerName 도메인 주소
ServerAlias www.도메인.ga, *.도메인.ga
ServerAdmin 이메일
DocumentRoot /var/www/html

Options Indexes FollowSymlinks
AllowOverride all
Require all granted

systemctl restart httpd

/etc/httpd/conf/httpd.conf에서 VirtualHost 설정을 합니다. Listen 80을 찾아서 그 아래에 VirtualHost를 추가하면 됩니다. 그리고 아파치를 재시작합니다.

yum install -y certbot python2-certbot-apache
certbot

Certbot 패키지 및 종속성을 설치하고,  Certbot을 실행합니다.

If you really want to skip this, you can run the client with
--register-unsafely-without-email but you will then be unable to receive notice
about impending expiration or revocation of your certificates or problems with
your Certbot installation that will lead to failure to renew.

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.2-November-15-2017.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: n

EFF의 소식을 이메일로 받을지에 대해서 선택합니다.

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: www.입력한 도메인.ga
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel):

이어서 웹서버 도메인이 나오고, 엔터를 누릅니다.

vi /etc/crontab
39 1,13 * * * root certbot renew --no-self-upgrade
systemctl restart crond

모든 인증서를 점검하고 만료 날짜가 다가오고 있는 인증서를 갱신하기 위해 crontab을 수정합니다.

  • 39 1,13 * * * 명령이 매일 01:39와 13:39에 실행되도록 예약합니다. 선택한 값은 임의이지만 Certbot 개발자는 최소한 매일 두 번 명령을 실행하는 것을 제안합니다. 이를 통해 손상된 것으로 발견된 모든 인증서가 즉시 취소 및 교체됩니다.
  • root 명령은 루트 권한으로 실행됩니다.
  • certbot renew --no-self-upgrade 실행할 명령입니다. renew 하위 명령을 사용하면 Certbot이 이전에 얻은 모든 인증서가 점검하고 만료 날짜가 다가오고 있는 인증서를 갱신합니다. --no-self-upgrade 플래그를 사용하면 Certbot이 사용자의 개입 없이 자체 업그레이드하지 않습니다.

다시 도메인으로 접속해 보면 HTTPS로 접속되는 것을 확인할 수 있습니다.

이제 다음 사이트에서 보안 설정에 관해서 체크를 받습니다.

문제없이 A등급이 나오는 것을 확인할 수 있습니다.

본 블로그 게시글을 보시고 문의 사항이 있으신 분들은 클래스메소드코리아 (info@classmethod.kr)로 연락 주시면 빠른 시일 내 담당자가 회신 드릴 수 있도록 하겠습니다 !

참고