On-premise 환경에서 현재 회사의 성장세를 따라가기 어렵다고 판단하고, 1년 전부터 Cloud 환경으로 마이그레이션을 진행하고 있습니다. 현재는 중요 서비스의 90%
이상이 Cloud 환경으로 마이그레이션 되었으며, 그 과정에서 인프라를 구성하는 많은 구성 요소가 변경, 대체 되었습니다. 또한, 여러 보안 요구사항
을 만족시키기 위해서 추가적인 시스템 도입에 대해서 고민하였고, 그 과정을 공유하고자 합니다.
멀웨어 2차 확산 방지
* Outbound - FQDN filtering +@(TCP/IP)
* HTTP/HTTPS +@((Wildcard)*.domain.com)
* Multiple Accounts and Cloud Platform Support
* 확장성, 관리 편의성 (Infrastructure as code, Update)
* 안정성 (다양한 레퍼런스, Monitoring, HA)
* 비용 (저렴한 구축/라이센스 비용)
그 이후에는 오픈소스(Squid), 유료 솔루션(paloalto, Cisco vMX 등)을 검토 하였고, 그 중 국내에서는 레퍼런스를 찾아보기 쉽지 않지만 Aviatrix
유료 솔루션을 선정하였습니다. 선정 과정에서 확인해본 결과 해외 레퍼런스의 경우에는 NASA, Netflix, Hyatt 등이 있었으며, 요구 사항에서 필요로 하는 Service(FQDN, TransitGW, VPN)에 대한 비용 및 IaC 배포, 구성이 타 유료 솔루션보다 이점이 있다는 것을 감안하여 Aviatrix을 선정하게 되었습니다. 선정 과정에서 참고로 한 자료는 다음과 같습니다.
Aviatrix 솔루션 테스트를 위해, AWS Marketplace에서 Aviatrix을 선택 후 Free Trial 이용이 가능한 Custom 유형을 선택하여 테스트 초기 환경을 구성합니다. AWS 인프라(EC2 등) 사용 금액이 발생하기 때문에 EC2 Instanc Type은 최소 스펙을 선택하여 테스트를 진행합니다.
설치 방법은 두가지를 제공합니다.
원활한 테스트를 위해 CloudFormation Template을 선택하여 진행합니다. Amazon Machine Image를 통한 구성 시에는 Role, Network 구성 등의 추가 설정이 필요합니다. 상세 설치 과정은 Aviatrix에서 Guide를 제공하고 있습니다. (CloudFormation Template 의 IAM Role, Policy 등은 아래에 별도 분석하겠습니다.)
CloudFormation 배포가 완료된 상태에서 Output 카테고리에서 AviatrixControllerEIP 정보를 확인합니다. EIP에 대한 구성을 하지 않을 경우에는 AviatrixControllerPrivateIP 정보를 확인하여 웹 페이지 주소로 사용됩니다. PrivateIP는 초기 임시 패스워드로도 구성됩니다.
AviatrixControllerEIP 접속 이후 관리자 아이디 및 버전을 설정합니다.
설정을 완료할 경우에는 초기 로그인화면에서 Onboarding 화면이 노출됩니다.
화면에서 이용하고 있는 Cloud Platform을 지정하고 추가적인 설정을 진행합니다.
모든 설정을 완료한 이후에 제공되는 Aviatrix의 사용자 페이지 입니다.
EC2 의 Outbound 트래픽을 로깅 및 관리하기 위해서 우선적으로 Gateway의 설정이 필요해서, Aviatrix 사용자 카테고리에서 Gateway 설정으로 이동합니다.
New Gateway 설정을 진행합니다.
“OK”를 클릭할 경우 퍼센트에 대한 상태 이미지가 노출됩니다. 이후 작업은 직접 설치를 진행하지 않아도 자동 설치 및 Gateway 서버에 대한 환경이 구성됩니다.
(HA 구성의 경우에는 다양한 방법을 제공하고 있어 아래 링크를 추가해 드립니다, Aviatrix 깊게 들여다보기(HA, Egress FQDN Discovery) 내용은 블로그 하단에 분류하였습니다.)
Private Subnet의 Route Table을 생성해, 외부로 나가는 모든 트래픽이 Aviatrix-GW를 통해서 나가도록 설정을 진행합니다. "0.0.0.0/0"
에 대한 Target을 Aviatrix-GW ENI로 지정합니다. 자동 등록을 원할 경우 Aviatrix Controller 사용자 웹 페이지에서 Gateway > Aviatrix-GW: Edit > Source NAT
를 통한 설정이 가능합니다.
FQDN 로깅 및 관리를 위해, Aviatrix Controller 사용자 웹 페이지에서 security > Egress Control > Egress FQDN Filter를 설정합니다.
테스트를 위해서 FQDN Filter를 아래의 이미지와 같이 White 설정한 이후에, Aviatrix-GW를 바라 보고 있는 Private-route-table
의 Private-Subnet
에서 운영되는 인스턴스에서 다음 명령어를 실행하였습니다.
curl -L -k -s -o /dev/null -w "%{http_code}\n" https://www.naver.com
curl -L -k -s -o /dev/null -w "%{http_code}\n" https://google.com
curl -L -k -s -o /dev/null -w "%{http_code}\n" https://www.google.com
curl -L -k -s -o /dev/null -w "%{http_code}\n" https://docs.google.com
테스트에 대한 Egress FQDN View Log
2019-09-01T16:40:35.886612+00:00 ip-172-31-14-85 avx-nfq: AviatrixFQDNRule[CRIT]nfq_ssl_handle_client_hello() L#274 Gateway=Aviatrix-GW S_IP=172.31.24.52 D_IP=210.89.164.90 hostname=www.naver.com state=NO_MATCH drop_reason=NOT_WHITELISTED
2019-09-01T16:40:53.442375+00:00 ip-172-31-14-85 avx-nfq: AviatrixFQDNRule[CRIT]nfq_ssl_handle_client_hello() L#274 Gateway=Aviatrix-GW S_IP=172.31.24.52 D_IP=172.217.27.78 hostname=google.com state=MATCHED
2019-09-01T16:40:53.654101+00:00 ip-172-31-14-85 avx-nfq: AviatrixFQDNRule[CRIT]nfq_ssl_handle_client_hello() L#274 Gateway=Aviatrix-GW S_IP=172.31.24.52 D_IP=216.58.197.164 hostname=www.google.com state=MATCHED
2019-09-01T16:40:58.707731+00:00 ip-172-31-14-85 avx-nfq: AviatrixFQDNRule[CRIT]check_ip() L#65 Gateway=Aviatrix-GW S_IP=172.31.24.52 D_IP=216.58.197.164 hostname=www.google.com state=MATCHED
2019-09-01T16:41:21.940692+00:00 ip-172-31-14-85 avx-nfq: AviatrixFQDNRule[CRIT]nfq_ssl_handle_client_hello() L#274 Gateway=Aviatrix-GW S_IP=172.31.24.52 D_IP=172.217.26.14 hostname=docs.google.com state=MATCHED
2019-09-01T16:41:22.323298+00:00 ip-172-31-14-85 avx-nfq: AviatrixFQDNRule[CRIT]nfq_ssl_handle_client_hello() L#274 Gateway=Aviatrix-GW S_IP=172.31.24.52 D_IP=172.217.25.77 hostname=accounts.google.com state=MATCHED
로그를 통해 state를 확인하고 후속 조치가 가능합니다. Aviatrix 서비스에 대한 다양한 로그 관리 및 시각화 등이 가능하기 때문에, 별도 추가로 확인하고 싶으신 내용은 아래의 링크에서 확인해 주시기 바랍니다.
위 내용에서 google.com FQDN에 대해서 호스트 명을 지정하지 않을 때에는 "*"
로 적용됩니다. (*.google.com = google.com)
AWS Account with Aviatrix Gateway Architecture
Instance Outbound Flow & Aviatrix Controller Gateway HA Flow
Route table
을 참조"0.0.0.0/0"
통신을 Aviatrix Gateway의 ENI
로 전달Aviatrix Controller
정책에 따라 Outbound 트래픽 체크 이후에, Aviatrix Gateway에 Internet gateway로 전달Route table
"0.0.0.0/0"
업데이트Aviatrix 자세히 들여다보기
HA 구성은 모든 인프라의 기본으로 Aviatrix을 사용할 경우 아래와 같은 간단한 작업으로 적용이 가능합니다.
Gateway > Edit > Gateway Single AZ HA “Enable”
Gateway > Edit > Gateway for High Availability Peering
(HA 구성을 위해 운영 중인 Gateway Subnet과 다른 AZ의 Public-Subnet을 선택합니다.)
HA 구성을 위한 설정은 마무리하였으며, 정상적으로 Failover가 되는지 확인을 위해 아래 구성을 진행하였습니다.
* Private-Subnet에서 운영되는 인스턴스에 대한 실시간 모니터링 설정
* Failover 기능 테스트를 위해 Aviatrix-GW 인스턴스를 AWS Console에서 강제 종료(STOP)
* Private-Subnet에서 운영되는 인스턴스에 대한 실시간 모니터링 지표 확인
Failover를 테스트하기 전의 Aviatrix Gateway 상태 이미지입니다.
Failover를 테스트하기 위해 Gateway를 강제 종료한 Aviatrix Gateway 상태 이미지입니다.
테스트 결과: Private-Subnet에서 운영되고 있는 인스턴스에 모니터링 에이전트(Telegraf)를 설정하여, ICMP 프로토콜을 이용한 1s 기준으로 Packet Loss 현상이 발생 되지 않았습니다. 웹사이트 기준에서는 Gateway가 Failover 되는 시점을 인지할 수 없는 정도입니다.
Aviatrix-Gateway HA Flow (Failover)
Fail
"0.0.0.0/0"
Target Gateway_HA
ENI로 업데이트해당 기능은 실 서버에 적용하기에 앞서 실 서버에서 FQDN outbound의 사용 리스트를 정리하는데 유용한 기능입니다.
Security > Egress Control > (Optional) Egress FQDN Discovery > Gateway “Start” (선택된 Gateway는 FQDN Filter에 연결이 안 되어 있어야 합니다.)
테스트를 위해 Private-Subnet에서 운영되고 있는 인스턴스에서 아래 명령어를 실행합니다.
curl -L -k -s -o /dev/null -w "%{http_code}\n" https://tech.socarcorp.kr
1번 HA 테스트로 인해 변경된 Aviatrix-GW-hagw에서 발생한 FQDN 내용을 확인할 수 있습니다.
테스트 결과: FQDN Discovery 기능을 통해 실 서버 FQDN Outbound를 모두 사전에 확인하고, 필요 유무에 따라서 FQDN Filter 정책을 정의하는 데 유용합니다.
2번 내용을 보면 HTTPS/TLS 통신을 Gateway가 어떻게? 가로 채지 라는 의문점이 있습니다, 해당 내용은 SNI에 대한 이해가 필요해서 SNI 내용을 정리해 드립니다.
SNI(Server Name Indication)
여러 개
의 독립 사이트 중에 하나의 사이트
를 지정 하기 위해 필요한 필드입니다.하기 전인
ClientHello 과정에 적용됩니다.TLS Handshake
TLS_1.3 Handshake > ClientHello
암호화가 되지 않은 평문
으로 전송하기 때문입니다.타인
이 중간에 트래픽을 가로채서 사용자가 조회하는 사이트를 확인 할 수 있습니다.Encrypted SNI
로 인해서 Gateway가 SNI 필드를 확인하는 방법이 불가능 할 수도 있었지만, TLS 1.3 최종안
에서는 필수
가 아닌, 확장
기능으로써 추가되었습니다.
위에 내용은 CloudFormation Template의 Role, Policy 관계를 보면 알 수 있습니다. 아래의 소스는 CloudFormation Template의 일부 내용입니다.
EC2 생성 과정에서 aviatrix-role-ec2를 등록하는 내용입니다.
"IAMRoleParam": {
"Description": "Determine if IAM roles aviatrix-role-ec2 and aviatrix-role-app should be created.",
"Default": "New",
"Type": "String",
"AllowedValues": [
"aviatrix-role-ec2",
"New"
]
},
EC2에 등록하기 위한 role-ec2를 생성하는 내용입니다.
"AviatrixRoleEC2": {
"Type": "AWS::IAM::Role",
"Condition": "AviatrixIAMRoleNotExist",
"Properties": {
"RoleName": "aviatrix-role-ec2",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"Service": [
"ec2.amazonaws.com"
]
},
"Action": [
"sts:AssumeRole"
]
}]
},
"Path": "/"
}
},
여기서 주목할 점
이 있습니다, role-app을 사용할 수 있는 Principal에 “Ref”: “AWS::AccountId” 등록을 통해서 가능하도록 설정되는 것을 알 수 있습니다.
"AviatrixRoleApp": {
"Type": "AWS::IAM::Role",
"Condition": "AviatrixIAMRoleNotExist",
"Properties": {
"RoleName": "aviatrix-role-app",
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {
"AWS": [{
"Fn::Join": [
"", [
"arn:aws:iam::",
{
"Ref": "AWS::AccountId"
},
":root"
]
]
}]
},
"Action": [
"sts:AssumeRole"
]
}]
},
"Path": "/"
}
},
여기서 주목할 점
은 arn:aws:iam::*:role/aviatrix-* 설정에 있습니다. 해당 "*"
설정으로 role-ec2의 Policy는 arn:aws:iam::AccountId
:role/aviatrix-role-app의 Policy를 할당 받아서 사용할 수 있게됩니다.
"CreateAviatrixAssumeRolePolicy": {
"Type": "AWS::IAM::ManagedPolicy",
"Condition": "AviatrixIAMRoleNotExist",
"Properties": {
"ManagedPolicyName": "aviatrix-assume-role-policy",
"Description": "Policy for creating aviatrix-assume-role-policy",
"Path": "/",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": "arn:aws:iam::*:role/aviatrix-*"
},
{
"Effect": "Allow",
"Action": [
"aws-marketplace:MeterUsage"
],
"Resource": "*"
}
]
},
"Roles": [{
"Ref": "AviatrixRoleEC2"
}]
}
},
role-app Policy의 경우에는 아래 추가된 이미지처럼 많은 Action이 정의되어있습니다.
"CreateAviatrixAppPolicy": {
"Type": "AWS::IAM::ManagedPolicy",
"Condition": "AviatrixIAMRoleNotExist",
"Properties": {
"ManagedPolicyName": "aviatrix-app-policy",
"Description": "Policy for creating aviatrix-app-policy",
"Path": "/",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": [..........................
CloudFormation Template 으로 구성된 AWS 인프라의 이미지
를 통해 정리할 경우, 아래와 같은 구성이 설정됩니다.
{
"Action": [
"sts:AssumeRole"
],
"Resource": "arn:aws:iam::*:role/aviatrix-*",
"Effect": "Allow"
},
위임
받아서 사용할 수 있는 상태가 됩니다. role-ec2는 Aviatrix Controller Instance에 등록 되어있는 role 이기 때문에, Aviatrix Controller 웹 페이지에서 role-app에 적용 되어있는 Policy 에 대한 이용이 가능합니다. (멀티 Account의 경우에는 멀티 Account에 설정 되어 있는 role-app에 대한 AccountId Trust 등록을 진행하여, 멀티 Account의 role-app을 Controller Account의 role-app이 공유 받아 사용하는 방법으로 동일합니다.)
Multiple AWS Accounts with Role Switchin Aviatrix Architecture
거의없습니다.
Role의 활용
및 위에서는 자세하게 다루지 않았지만, "EXPORT TO TERRAFORM" 카테고리 부분에서 리소스 형식에 맞는 *.tf 파일들을 다운로드 받아서 IaC 환경에 활용이 가능합니다.Transit GW를 이용한 트래픽 중앙 관리
를 통해서 운영하고 있기 때문에 On-premise 적용 등 다양한 아키텍처 구성이 가능합니다.많은 장점
가운데 지속가능성에 대한 문제는 있습니다, TLS 1.3 최종안이 적용된 지 얼마 되지 않은 상황이지만, Gateway가 SNI 필드를 통해 FQDN Filter 과정이 이후 SNI 암호화 이후 FQDN Filter를 어떻게 진행할 것인가에 대한 문제점이 있습니다.쏘카는 언제나 쏘카 서비스를 함께 만들며 기술적인 문제를 함께 풀어나갈 능력있는 개발자/디자이너/기획자/데이터 사이언티스트 등을 모시고 있습니다. 자세한 내용은 쏘카 채용공고 페이지를 확인 부탁드립니다 :)