이번 포스트에서는 AWS ELB application load balancer를 이용해 SSL을 적용 하는 방법을 정리한다. 

즉 이 포스트의 목적은 아래 Fig 1과 같은 architecture 로 서버 운영 구조를 완성하는 것이다. 

 

이 구조를 간단히 설명 하면 서버로 request 가 들어오면 load balancer는 요청이 https(port 443) 요청인지 확인한다. 만약 http(port 80) 요청이면 load balancer 가 이 요청을 https 로 redirection 한다. https 요청이면 load balancer 가 SSL session 의 종단점 역할을 대신해 요청을 decryption 해 target group 의 80 번 포트로 요청을 forwarding 한다. 이렇게 구성 하면 ec2 인스턴스에서 실행 중인 server가 ssl decryption 을 수행 하지 않아도 되니 조금더 가벼워 질수 있다. 

t2.micro 인스턴스인 내 서버의 짐을 줄여 주기 위한 시도이다. 

 

Fig 1. application load balancer를 이용한 SSL 적용 구조

aws ELB application load balancer 를 이용해 SSL을 적용하기 위한 순서는 아래와 같다. 

내 경우 django app 에 SSL 을 적용하기 위한 것으로 ec2 인스턴스는 이미 생성한 것을 이용한다. 


순서

1. ACM(amazon certificate manager) 에서 SSL 인증서 발급 및 호스팅 영역에 레코드 등록 

2. Target group 생성 

3. application load balancer 생성 및 security 정책 설정(

4. route53의 domain A 레코드 변경

 

ACM(amazon certificate manager) 에서 SSL 인증서 발급 및 호스팅 영역에 레코드 등록

aws에는 amazon certificate manager 줄여서 ACM이 라는 서비스가 존재 한다. 

acm 콘솔로 이동하기 위해서는 'aws console -> 검색 창에서 certificate manager' 검색 -> cerificate manager 클릭 하면 된다. 

acm 은 ssl/tsl 인증서 발급이 가능 한데 나는 이중 ssl 인증서 발급을 요청했다. 

참고로 ssl 인증서를 발급받기 위해서는 DNS 검증이나 이메일 검증이 필요한데 여기서는 DNS 검증 방식을 사용 한다. 즉, 등록된 domain 이 있어야 한다는 의미이다. 

생성한 SSL 인증서는 ELB 인스턴스에 등록해 사용할 수 있다.

 

  1. SSL 인증서 생성을 위해 acm 콘솔에서 "인증서 요청"을 클릭하고 "퍼블릭 인증서"를 선택한다. 
  2. 다음과 같은 화면 이 나오는데 도메인 이름에는 ssl을 이용해 통신을 암호화 하고자 하는 domain 을 입력한다. 
    예를 들어 내 웹페이지의 주소가 askmeanything.com 이라 하면 이 주소를 입력하면 된다. 검증 방법은 DNS 와 이메일 검증이 있는데 DNS 검증을 추천한다. 다만 DNS 인증을 이용하기 위해서는 askmeanything.com 이 DNS 서버에 등록이 되어있어야 한다. DNS 서버에 domain 을 등록 하는 방법은 [aws]ec2 인스턴스 도메인 연결을 참조하자.
  3.  키 알고리즘은 원하는 걸 선택하면 된다.

Fig 2. 퍼블릭 인증서 요청

 

옵션을 다 선택하고 "요청"을 누르면 인증서가 생성된다. acm 콘솔에서 "인증서 나열" 에 들어가 방금 생성한 인증서를 클릭하면 다음과 같은 화면을 볼 수 있다. 

Fig 3. 인증서 상태

 

우측 위에 "상태"를 보면 "검증 대기 중" 이라고 나오는데 인증서 생성시 등록한 domain 에 대한 소유권 검증이 끝나지 않았기 때문에 다. 검증을 마치기 위해서는 Fig 3. 인증서 상태 페이지에서 아래 순서를 따라하자. 

 

4. "도메인 -> Route53에서 레코드 생성" 클릭

5. "Amazon Route 53에서 DNS 레코드 생성" 페이지 에서 SSL 인증서를 등록하고자 하는 domain 선택 및 레코드 생성 클릭.

이 과정에서 askmeanythin.com 호스팅 영역에는 CNAME 레코드가 추가 된다. CNAME 사용자가 도메인을 통제함을 증명하는 키-값 페어가 포함되어 있다. CNAME 레코드에 대한 자세한 설명은 이 페이지를 참조하자.

 

6. route53 에 5번에서 생선한 cname 레코드가 생성되고 시간이 좀 지나면 Fig2. 인증서 상태가 active 로 바뀐다. (얼마의 시간이 걸리는지는 정확하지 않은것 같다. 나의 경우 23:00 에 등록을 했고 20분이 지나도 상태가 바뀌지 않아 자고 일어났더니 바뀌어있었다.)

 

Target group 생성 

Fig 4. Load balancer 동작

Target group은 AWS ELB 로드벨런서가 요청을  route 하는 대상의 집합이다. 요청을 처리 할수 있는 lambda 나 ec2 instance등이  target group 에 속할 수 있다.  Fig 4. 을 보면 load balancer는 외부로 부터 들어 오는 요청을 target group 에 속한 ec2-2 로 route 한다. 

 

대상 그룹 생성을 위해서는 "ec2 콘솔 -> 로드벨런싱-> 대상 그룹" 페이지에서 우측 위에 있는 "create target group" 버튼을 누르면 된다. 버튼 클릭하면 Fig 5와 같은 페이지를 볼 수 있다. 나의 경우 ec2 인스턴스에 요청을 route 하는게 목적이므로 target type"instances" 로 선택했다.

Target group name에는 식별하기 쉬운 이름을 입력하자. 이 이름으로 load balancer 를 만들때 target group을 선택할 것이다. VPC 는 이 target group에 포함 시킬 ec2 인스턴스들이 할당된 VPC와 같은 것으로 선택한다. 이게 다르면 통신이 되지 않는다. 

 

Fig 5. target group 생성 페이지

생성을 클릭하고 나면 다음과 같은 페이지가 보인다. 이 과정이 실질적으로 방금 만든 target group에 요청을 처리할ec2 인스턴스를 추가하는 과정이다. 추가하고자 하는 ec2 인스턴스를 선택하고 해당 인스턴스의 어떤 port로 요청을 routing 할지 정하고 "Include as pending"을 클릭하면 된다.

아래 그림에서는 선택한 인스턴스의 80번 포트로 요청을 routing  하도록 설정했다.   

 

 

application load balancer 및 security 정책 설정

AWS ELB application load balancer 는 클라이언트에 단일 접속점을 제공하고 로드밸런싱을 수행한다. 무슨 말이냐면 같은 서비스를 제공하는 물리적인 서버가 여러개 있을때 이 서버들은 서로 다른 IP를 가지고 있을 수 있다. 클라이언트가 이 서버들 중 하나에 의해 서비스를 받기 위해서는 해당 IP에 접근을 해야 한다. 접근한 서버가 매우 바쁜고 다른 서버는 놀고 있다면 서비스의 가용성은 떨어지게 된다. 그렇다고 사용자가 어떤 서버가 놀고 있는지 일일이 모니터링 해서 덜 바쁜 서버에 접근 할 수도 없고 그렇게 한다고 해도 동일 한 서비스를 받기 위해 서로 다른 서버의 IP를 이용해 접근하는 것도 매우 불편하다. (극단적인 예로 설명 하다 보니 서버의 IP 로 접근한다고 표현했는데 domain을 사용하기 때문에 이렇게 되진 않는다)

 

application load balancer는 이런 상황에서 해법을 제공한다. 동일한 서비스를 제공하는 여러 물리 서버를 target group으로 묶고 이 target group으로 가는 모든 요청을 application load balancer가 받아서 target group 에 정해진 정책에 따라 업무를 배분한다. 사용자 입장에서는 서비스를 제공하는 각 서버의 IP 를 몰라도 되고 application load balancer의 IP 나 domain만 알면된다. 또한 load balancer 가 서버에 업무를 분배하므로 어떤 서버가 덜 바쁜지 모니텅링 할필요도 없다. 

 

또한 application load balancer를 이용 하면 이 포스트의 목적이었던 암호화된 통신 SSL 을 적용 할 수 있다. Fig 1 에서 처럼 암호화 되지 않은 요청이 application load balancer 로 도착하면 암호화 된 통신을 위해 이 요청을 https(port 443)으로 redirection 한다. 요청이 암호화된 요청이면 application load balancer 가 SSL 연결의 종단점 역할을 수행해 암호화된 요청을 해독하고 해도된 요청(request)를 target group의 80번 포트로 포워딩한다. 이렇게 되면 서비스를 제공하는 서버들은 요청을 해독하는데 자원을 할당하지 않아도 되는 장점(?)이 있다. 

 

이제 application load balancer 를 생서하는 방법을 알아 보자. "ec2 콘솔 -> 로드 밸런서" 페이지에 들어가 우측 상단의 "create load balancer"를 클릭한다. "Select load balancer type" 페이지에서 application load balancer 를 선택한다. 그럼 아래 Fig 7 과 같은 페이지를 볼 수 있다. 

Fig 7. Load balancer 설정 페이지

외부에서 들어오는 요청을 받아서 처리하는게 목적이므로 Basic configuration 의 scheme 에서 "internet-facing"을 선택한다. IP address type은 IP4 를 선택했다. 요즘은 IPv6가 많으니 실제 서비스를 위해서는 Dualtask 를 선택하는게 적절할거 같다. (나는 처음엔 IPv4 를 선택했다 나중에 dualstask으로 변경했다.)

 

Network mapping 에서는 target group 에 속한 ec2 인스턴스들이 속해 있는 VPC 와 같은 것을 선택하면 된다. Mappings 는 target group 에 속한 ec2 인스턴스의 가용영역(ec2 인스턴스 네트워크 페이지에서 확인가능)을 확인해 동일 한 것을 선택하면 된다. 최소 두개 선택하게 되어있는데 나의 경우 ec2 인스턴스의 가용영역인 ap-northeast-2a와 ap-northeast-2b (apne2-az2) 를 선택했다. 

 

 다음으로 Fig 8 처럼 security groups과 listener 정책을 설정한다. Security group(보안그룹)은 임의의 protocol과 port로의 요청을 어떻게 처리 할것인지 에 대한 규정을 담고 있다. ec2 인스턴스와 동일한 정책을 사용하기 위해서는 ec2 인스턴스에 할당한 보안그룹을 선택해도 된다. 나는 target group에 속한 ec2 인스턴스와는 다른 보안정책을 설정 하기 위해 default로 두었다. 

 

 listeners and routing은 생성중인 application load balancer 가 몇번 port로 들어오는 어떤 protocol의 요청을 어떻게 처리 할지 설정하는 것이다. Fig 8에서는 80번 포트로 들어오는 http 요청과 443 번 포트로 들어오는 https 요청에 대해 default action 으로 이전 섹션인 "Target group 생성"  단계에서 생성한 target group 으로 요청을 forwaring 하도록 설정 했다. 하지만 이렇게 설정해 놓으면 Fig 1에서 80번 포트로 들어오는 비암호화된 요청을 암호화된 요청으로 redirection 하고자 하는 계획과 다르므로 잠시 후 80번 포트로 들어오는 http 요청에 대한 routing 정책을 을 변경 할 것이다. 

Fig 8. 보안 그룹 및 리스너 세팅

 

application load balancer 의 생성단계는 거의 다 되었다. 443 번 포트로 들어오는 https 요청에 대한 listener를 등록 하면 아래와 같이 "Secure listener settings" 이라는 추가 설정 섹션이 생긴다. SSL 통신을 위한 certification 을 선택하라는 것인데 "ACM(amazon certificate manager) 에서 SSL 인증서 발급 및 호스팅 영역에 레코드 등록" 에서 생성한 인증서를 선택하면 된다. 이렇게 설정 하면 application load balancer 가 SSL 통신의 종단점 역할을 수행 할 수 있다. 인증서 선택 말고도 왼쪽에 "SEcurity policy"를 선택하는 란이 있는데 나는 이에 대한 지식이 부족해 일단 default 로 두었다. 

FIg 9. SSL 인증서 선택

 

 여기 까지 설정 하고 생성을 누르면 application load balancer 가 생성된다. "ec2 콘솔 -> 로드 밸런서" 페이지에 들어가면 생성한 application load balancer 를 볼 수 있다. 생성한 로드 밸런서의 "state" 가 Active라면 잘 생성되어 실행 중인 것이다. 하지만 몇번 만들어 본 결과 만들고 바로 확인 하면 "state" 가 "provisioning" 으로 나온 일종의 준비중 이라는 상태로 10분 정도 기다리면 Active 상태로 바뀐다. 

 

다음으로 80번 포트로 들어오는 http 요청을 어떻게 처리 할지에 대한 정책을 바꿔야 한다. 80번 포트는 http 요청으로 비보안이므로 이 요청을 https 요청으로 redirect 하도록 할 것이다. 위에서 application load balancer의 Listener 를 설정 할때 80 번 포트로 들어오는 요청에 대해 target group 으로 포워딩 하게 했기 때문에 이를 바꿔 주어야 한다. "ec2 콘솔 -> 로드 밸런서" 에서 생성한 로드 밸런서를 선택하고 아래 Fig 10처럼 Listener 상세 페이지에서 80번 포트 리스너의 Rules 값을 클릭한다.

Fig 10 로드 밸런서 상세

리스너 상세 페이지에서 우상단에 있는 manage ruls를 클릭한다. 아래 Fig 11 처럼 80번 포트에 대한 규칙을 리디렉션으로 바꾸고 대상을 HTTPS 로 하고 저장한다. 이렇게 설정 하면 80번 포트로 오는 요청을 443 번의 HTTPS 로 리디렉션 하게 된다. 

Fig 11. 리스너 규칙 변경 페이지

 

다음으로 할일은 load balancer에 할당된 보안 그룹에서 로드 밸런서의 리스너 포트를 오픈하는 것이다. 로드 밸런서 생성시 리스너를 등록 했다고 보안 그룹에서 해당 포트가 자동으로 오픈되지 않는다. 나는 이걸 몰라서 약 3시간을 디깅했다. 로드 밸런서에 할당된 보안 그룹 페이지로 들어가 아래 Fig 12 같이 인바운드 규칙을 바꾼다. 80, 443 번 이외의 포트를 허용 하고자 한다면 해당 포트도 추가 한다. 

Fig 12 로드 밸런서 보안 규칙

 

이제 target group에 속한 ec2 인스턴스는 로드 밸런서에서 오는 요청 만 받으면 되니 ec2 인스턴스의 보안 그룹 규칙도 변경해야 한다. application load balancer 가 SSL 종단점 역할을 해서 요청을 해독하고 ec2 인스턴스의 80 번 포트로 forwarding 해주므로 ec2 인스턴스의 보안그룹은 load balancer 의 보안 그룹에서 80 번 포트로 들어오는 요청만 받게 하면 된다. 아래 Fig 13 은 내 ec2 인스턴스 보안 그룹의 인바운드 규칙이다.

80번 포트의 소스가 위 Fig 12 에 나온 로드 밸런서 보안 규칙의 식별자임에 주의를 기울이자. 이렇게 설정하면 이 ec2 인스턴스는 로드밸런서를 통해서 80번 포트로 들어오는 요청만 받아서 처리하게된다. 아래 Fig 13에는 80 번 포트 외에 SSH접속을 위해 22 번 포트를 열어 놨는데 이건 어디서든 접근 할 수 있게 0.0.0.0/0 으로 소스를 설정했다.

Fig 13. target group 에 속한 ec2 인스턴스의 보안 규칙

 

이 단계 까지 끝났으면 application load balancer 가 정상 동작하는지 확인을 해보는게 좋다.

생성한 로드 밸런서의 상세 정보를 보면 ("ec2 콘솔 -> 로드 밸런서") DNS name 이라는 정보가있다. 이걸 카피 해서 웹 브라우저에 복사하자. Fig 13의 붉은 박스 부분이다. 

Fig 14. 로드 밸런서 상세 정보

target group에 속한 ec2 인스턴스에서 nginx 가 80번 포트로 요청을 리슨 하도록 설정되어있다면 로드 밸런서 주소로 접근 하면 nginx 의 "Welcome to nginx!" 페이지를 볼 수 있다. DNS name 통해 접속했는데 이 페이지를 볼수 없다면 무언가 잘못 설정했을 확률이 높으니 확인해 보자. 

 

 route53의 domain A 레코드 변경

이제 마지막 스탭이나 이 부분은 아주 쉽다. route53 서비스에서 호스팅 영역에 레코드 A의 값을 바꿔 주기만 하면된다. 

기존 레코드 A는 도메인 이름에 해당하는 ec2 인스턴스, 즉 서버의 IP를 가지고 있다. 서버가 실행 중인 ec2 앞에 로드 밸런서가 있고 모든 요청은 이 로드 밸런서를 통해서 서버로 포워딩 되도록 할것 이므로 도메인 이름 으로 접속을 하면 ec2 인스턴스가 아닌 로드 밸런서로 요청이 가도록 레코드 A를 변경하는 것이다. 

"route53 콘솔 -> 호스팅 영역 선택 -> 유형이 A인 레코드 선택 -> 레코드 편집 클릭" 

아래 Fig 15 처럼 "별칭"을 enable 하면 기존 값을 입력 하던 입력 폼이 "트래픽 라우팅 대상"을 선택하는 폼으로 바뀐다. 

이 라우팅 대상으로 이전 섹션에서 만들었던 application load balancer를 지정하면 된다. 

첫번 째 라우팅 대산의 type을 선택 옵션에서 "application/classic load balancer"를 선택한다. 다음으로 가용역영을 선택하는데 application load balancer를 생성할 때 Fig 7의 mapping 에서 지정한 지역 정보를 선택하면 된다. ec2 인스턴스의 가용영역과 같은 값이기도 하다.  마지막으로 라우팅 대상 application load balancer의 DNS를 선택하면 되는데 여기서 한가지 주의 할 점이 있다. 생성한 로드 밸런서를 선택 하려고 하는데 로드밸런서의 DNS name 앞에 "dualstack" 이라는 첨자가 붙는 경우가 있다. 내 경우가 이랬는데 로드 밸런서의 DNS name 이 "alb-app-lb-1790508963.ap-northeast-2.elb.amazonaws.com." 이라면 

"dualstack.alb-app-lb-1790508963.ap-northeast-2.elb.amazonaws.com." 와 같은 이름이 추천으로 뜨는 경우다. 

이런 경우 "dualstack" 이라는 첨자를 지우고 반드시 생성한 로드 밸런서의 DNS name 과 같은 값으로 입력해야 한다. 

나는 이 'dualstack' 이라는 첨자를 무시 했다가 또 2시간을 디버깅에 허비했다. 

Fig 15 레코드 편집 화면

 

 

 

- 끝 -

 

참조: 

아래 링크는 실제 서버 작업을 하면서 참고 했던 사이트 들입니다. 

1. https://docs.aws.amazon.com/ko_kr/elasticloadbalancing/latest/application/introduction.html

2. chatgpt(https://openai.com/blog/chatgpt/)

3. https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-ELB-Elastic-Load-Balancer-%EA%B0%9C%EB%85%90-%EC%9B%90%EB%A6%AC-%EA%B5%AC%EC%B6%95-%EC%84%B8%ED%8C%85-CLB-ALB-NLB-GLB

 

'AWS' 카테고리의 다른 글

[aws]ec2 인스턴스 도메인 연결  (0) 2023.01.26
[aws] ec2와 rds 연동  (0) 2023.01.22
[aws] ec2 상태검사 1/2개 통과  (2) 2023.01.21
[aws] 인바운드 규칙 변경  (2) 2023.01.18
[AWS] ec2 인스턴스 볼륨 추가 및 마운트  (0) 2023.01.15

+ Recent posts