CertNote/ 출퇴근 학습 노트
로드맵
KOEN
CLF-C02 · FoundationalCloud Practitioner - Foundational
DVA-C02 · AssociateDeveloper - Associate
SAA-C03 · AssociateSolutions Architect - Associate
SOA-C02 · AssociateCloudOps Engineer - Associate
SAP-C02 · ProfessionalSolutions Architect - Professional
DOP-C02 · ProfessionalDevOps Engineer - Professional
SCS-C03 · SpecialtySecurity - Specialty
  • Week 1
    • 1.공동 책임 모델과 SCS-C03 6개 도메인: 보안 엔지니어의 큰 그림
    • 2.IAM 핵심: 사용자·그룹·역할·정책과 정책 평가의 기본 흐름
    • 3.IAM 정책 심화: Identity vs Resource 정책, 조건 키, 최소 권한 설계
    • 4.STS와 임시 자격 증명: AssumeRole, 페더레이션, 역할 체이닝, Confused Deputy 방지
    • 5.Week 1 종합: IAM과 자격 증명을 시나리오로 통합 복습
  • Week 2
  • Week 3
    • 1.VPC 보안 설계: 네트워크가 첫 번째 방어선이다
    • 2.보안 그룹 vs 네트워크 ACL: 상태 저장과 비저장의 본질
    • 3.VPC Flow Logs와 트래픽 가시성: 로그로 침해를 읽는다
    • 4.프라이빗 연결: VPC 엔드포인트와 데이터 유출 봉쇄
    • 5.Week 3 종합: 네트워크 격리와 트래픽 통제를 하나로
  • Week 4
  • Week 5
  • Week 6
  • Week 7
  • Week 8
  • Week 9
  • Week 10
  • Week 11
  • Week 12
MLA-C01 · AssociateMachine Learning Engineer - Associate
AIF-C01 · FoundationalAI Practitioner - Foundational
DEA-C01 · AssociateData Engineer - Associate
MLS-C01 · SpecialtyMachine Learning - Specialty
합격 후기

© CertNote · 주간랩스

  • 소개
  • 수정 기록
  • 문의
  • 이용약관
  • 개인정보처리방침
← SCS-C03/Week 3/Day 1

기준: SCS-C03 시험 가이드·오류 제보

SCS-C03· AssociateWeek 3 · Day 1읽기 약 24분

Day 1 - VPC 보안 설계: 네트워크가 첫 번째 방어선이다

클라우드 보안을 처음 배우는 사람은 흔히 IAM이 전부라고 생각한다. 권한만 잘 묶으면 안전하다는 믿음이다. 하지만 실제 침해 사고 보고서를 읽어보면 패턴이 다르다. 공격자는 거의 항상 "네트워크 도달 가능성(reachability)"을 먼저 확보한다. 노출된 RDP 포트, 인터넷에 열린 데이터베이스, 잘못 라우팅된 서브넷. IAM이 아무리 견고해도 공격 가능한 표면(attack surface)이 인터넷에 닿아 있으면 자격증명 탈취·취약점 익스플로잇의 첫 발판이 된다.

그래서 SCS-C03 시험은 도메인 3(Infrastructure Security, 18%)에서 네트워크를 "정책의 끝단"이 아니라 가장 바깥의 방어선으로 다룬다. 오늘은 VPC의 보안 설계를 본다. 서브넷을 어떻게 격리하는지, 라우팅 테이블이 왜 보이지 않는 보안 통제인지, 그리고 "이 리소스에 인터넷이 닿는가"라는 질문에 정확히 답하는 사고법을 정리한다.

도달 가능성: 보안 엔지니어가 던지는 단 하나의 질문

네트워크 보안에서 가장 먼저 몸에 붙여야 하는 사고 습관은 "이 리소스에 인터넷이 닿는가"를 하나의 조건이 아니라 조건들의 곱(AND)으로 보는 것이다. 초심자는 보안 그룹 하나만 보고 노출 여부를 판단한다. 실제로 인터넷에서 패킷이 도달하려면 다음이 모두 참이어야 한다.

[ 인터넷 → 내 리소스, 도달 성립 조건은 AND ]

  ① 리소스에 퍼블릭 주소가 있다          (Public IPv4 / EIP / 라우팅 가능한 IPv6)
        AND
  ② 서브넷 라우팅에 0.0.0.0/0 → IGW      (경로가 없으면 여기서 끝)
        AND
  ③ NACL 인바운드가 허용                  (서브넷 경계, stateless)
        AND
  ④ 보안 그룹 인바운드가 허용             (ENI, stateful)
        AND
  ⑤ NACL 아웃바운드가 응답(임시 포트)을 허용
        AND
  ⑥ OS 방화벽이 열려 있고 애플리케이션이 listen 중

  ── 하나라도 거짓이면 도달 불가.
     "SG에 0.0.0.0/0이 있다"는 사실만으로는 노출이 성립하지 않는다.

거꾸로 말하면 차단은 OR다. 여섯 중 하나만 끊어도 막힌다. 그래서 보안 조치의 우선순위는 "가장 근본적인 것부터 끊는다"가 되고, 그 가장 근본적인 것이 ②의 라우팅이다. 라우팅에 경로가 없으면 나머지 다섯이 전부 활짝 열려 있어도 패킷은 오지 않는다. 시험이 "가장 근본적인(most fundamental) 조치"를 물을 때 보안 그룹 축소가 아니라 서브넷 재배치나 PubliclyAccessible 해제가 답이 되는 이유가 여기에 있다.

반대 방향, 즉 내 리소스가 밖으로 나갈 수 있는가도 같은 방식으로 분해된다. 아웃바운드에서는 ①이 필요 없고(NAT를 쓰면 퍼블릭 주소는 NAT가 갖는다) ②가 0.0.0.0/0 → IGW가 아니라 0.0.0.0/0 → NAT로 바뀐다. 데이터 유출을 걱정한다면 봐야 할 것은 인바운드 조건표가 아니라 이 아웃바운드 조건표다. 4일차에서 다룰 VPC 엔드포인트 설계는 결국 이 아웃바운드 조건표에서 ②를 지워 버리는 작업이다.

이 AND/OR 구조는 보안공학에서 말하는 공격 트리(attack tree) 의 축약형이다. 공격이 성립하려면 여러 전제가 동시에 만족되어야 하고(AND 게이트), 방어자는 그중 하나만 부수면 된다. 방어 비용과 공격 비용의 비대칭이 여기서 나온다 — 공격자는 여섯 개를 다 통과해야 하지만 방어자는 하나만 지키면 되고, 그래서 "가장 값싸게 확실히 끊을 수 있는 노드"를 고르는 것이 설계의 본질이다. 클라우드에서 그 노드는 거의 항상 라우팅이다. 라우팅 변경은 무료이고, 실수로 되돌리기 어렵고, 로그와 Config 규칙으로 감시하기도 쉽다.

VPC라는 격리 경계: CIDR과 테넌시

VPC(Virtual Private Cloud)는 AWS 계정 안에서 논리적으로 격리된 가상 네트워크다. 핵심은 격리다. 다른 고객의 VPC와도, 같은 계정의 다른 VPC와도 기본적으로 트래픽이 흐르지 않는다. 명시적으로 Peering, Transit Gateway, VPC Endpoint를 연결하기 전까지는 완전한 사일로다.

구성 요소보안 관점에서의 의미
CIDR 블록VPC가 차지하는 사설 IP 주소 범위. 겹치면 Peering 불가 — 설계 시 비중첩 IPAM 필수
서브넷AZ에 묶인 IP 구획. Public/Private 구분은 라우팅으로 결정됨(서브넷 속성 아님)
라우팅 테이블어디로 트래픽을 보낼지 결정. 보이지 않는 보안 통제
테넌시(Tenancy)default / dedicated. 규제 요건상 물리 격리가 필요하면 dedicated

VPC는 네트워크 가상화의 한 형태다. 물리적으로는 다른 고객과 같은 하이퍼바이저·스위치를 공유하지만, AWS의 Mapping Service와 Hyperplane이 패킷 단위로 소유권을 검증한다. 한 인스턴스가 위조한 출발지 IP로 다른 VPC에 패킷을 보내려 해도 호스트 레벨에서 차단된다. 즉 "사설 IP가 겹쳐도 격리된다"는 보장이 소프트웨어 레이어에서 강제된다. 이 때문에 같은 10.0.0.0/16을 쓰는 두 VPC가 안전하게 공존할 수 있다(단 Peering은 못 함).

보안 시험에서 "퍼블릭 서브넷"이라는 용어는 함정이 될 수 있다. 서브넷 자체에 public/private 속성 플래그는 없다. 서브넷이 연결된 라우팅 테이블에 Internet Gateway(IGW)로 향하는 0.0.0.0/0 경로가 있으면 Public, 없으면 Private이다. 따라서 "이 서브넷이 인터넷에 노출됐는가"를 판단하려면 (1) 라우팅 테이블의 IGW 경로, (2) 인스턴스의 Public IP 할당 여부, (3) 보안 그룹/NACL을 모두 봐야 한다. 셋 중 하나라도 끊겨 있으면 인터넷 도달 불가.

CIDR 계획이 곧 보안 설계다

주소 계획을 "IP를 몇 개 쓸까"의 문제로만 보면 나중에 보안 통제를 걸 자리가 없어진다. 계층별로 주소 블록을 연속되게 잡아 두면, 나중에 NACL 규칙이나 SG 소스 CIDR을 한 줄로 표현할 수 있다. 반대로 계층이 주소 공간에 뒤섞여 있으면 "App 계층 전체"를 가리키는 규칙 하나를 쓸 수 없고, 서브넷이 늘어날 때마다 규칙이 늘어난다.

계획 요소보안적 함의
VPC CIDR 비중첩겹치면 Peering·TGW 연결 자체가 불가 — 조직 차원 IPAM으로 미리 할당
계층별 연속 블록10.0.0.0/20=Public, 10.0.16.0/20=App 식으로 잡으면 규칙 1줄로 계층 전체 표현
서브넷당 예약 IP 5개AWS가 각 서브넷의 처음 4개와 마지막 1개를 예약 — /28은 실사용 11개뿐
보조 CIDR 추가나중에 붙일 수 있으나, 이미 만든 NACL·SG 규칙과 라우팅을 다시 검토해야 함
IPv6 활성화IPv6 주소는 기본적으로 공인 라우팅 가능 — NAT 개념이 다르다(아래)

⚠️ 함정: IPv6는 사설/공인 구분이 IPv4와 다르다. VPC에 IPv6 CIDR을 붙이고 서브넷에 IPv6를 할당하면 그 주소는 본질적으로 인터넷에서 라우팅 가능한 주소다. IPv4 기준으로 "사설 대역이니 안전하다"고 생각하고 IPv6를 켜 두면, 라우팅 테이블에 ::/0 → IGW가 있는 순간 의도치 않은 양방향 노출이 생긴다. 아웃바운드만 원한다면 반드시 Egress-only Internet Gateway를 쓴다. 보안 그룹·NACL 규칙도 IPv4와 IPv6가 별개 규칙이라, IPv4만 좁혀 놓고 IPv6는 열어 둔 상태가 흔한 감사 지적 사항이다.

3-Tier 서브넷 격리: 표준 패턴

가장 널리 쓰이는 격리 패턴은 계층(tier)별 서브넷 분리다.

VPC (10.0.0.0/16)
 ├── Public Subnet (10.0.0.0/24)   ← ALB, NAT Gateway, Bastion
 │     라우팅: 0.0.0.0/0 → IGW
 ├── App Subnet (10.0.10.0/24)     ← EC2, ECS, Lambda(VPC 연결)
 │     라우팅: 0.0.0.0/0 → NAT Gateway
 └── Data Subnet (10.0.20.0/24)    ← RDS, ElastiCache, Aurora
       라우팅: 로컬만 (인터넷 경로 없음)

계층을 나눈 것만으로는 절반이다. 나머지 절반은 계층 사이를 어떻게 통과시키는가이고, 그것이 보안 그룹의 참조 관계로 표현된다. 아래 그림이 실제 배치와 통제를 한 장에 겹쳐 놓은 것이다.

[ 3-Tier의 트래픽 방향과 통제가 걸리는 지점 ]

           인터넷
             │
        ┌────▼────┐
        │   IGW   │
        └────┬────┘
             │  (0.0.0.0/0 → igw)
  ┌──────────▼──────────────────────────────┐
  │ Public Subnet   10.0.0.0/24  (AZ-a/b)   │
  │   ALB(sg-alb)      NAT GW      Bastion  │
  └────┬───────────────────┬────────────────┘
       │ 443               │ (0.0.0.0/0 → nat)
       │ sg-app 인바운드는  │  아웃바운드 전용
       │ "source = sg-alb" │
  ┌────▼───────────────────▼────────────────┐
  │ App Subnet      10.0.10.0/24 (AZ-a/b)   │
  │   EC2 / ECS (sg-app)                    │
  └────┬───────────────────┬────────────────┘
       │ 5432              │ vpce (S3/KMS/SSM)
       │ sg-data 인바운드는 │  ← 4일차 주제
       │ "source = sg-app" │
  ┌────▼───────────────────┴────────────────┐
  │ Data Subnet     10.0.20.0/24 (AZ-a/b)   │
  │   RDS (sg-data)      인터넷 경로 없음     │
  └─────────────────────────────────────────┘

  핵심: 계층 간 허용은 CIDR이 아니라 **SG 참조**로 쓴다.
        인스턴스가 늘고 IP가 바뀌어도 규칙은 그대로다.
  • Public Tier: 인터넷에서 직접 받아야 하는 것만(로드밸런서, NAT, Bastion). 워크로드 자체는 두지 않는다.
  • App Tier: 아웃바운드는 NAT를 통해 가능(패치 다운로드 등), 인바운드는 ALB에서만.
  • Data Tier: 인터넷 경로 자체가 없음. App Tier에서만 접근. 가장 강한 격리.

이 계층 분리는 Defense in Depth(심층 방어, NSA가 정착시킨 군사 개념)의 네트워크 구현이다. 한 겹이 뚫려도 다음 겹이 막는다. 공격자가 ALB의 취약점으로 App Tier에 들어와도, Data Tier는 라우팅 자체가 없으므로 외부로 데이터를 직접 빼낼 수 없다. NIST SP 800-41(방화벽 가이드)은 이를 "tiered/segmented architecture"로 권고한다.

⚠️ 함정: "Data Subnet에 인터넷 경로가 없으면 OS 패치를 어떻게 받나?"라는 질문이 시험에 나온다. 답은 RDS 같은 관리형 서비스는 AWS가 패치하므로 인터넷 경로가 필요 없다는 것. 만약 데이터 계층에 직접 운영하는 EC2 DB가 있다면 패치는 Systems Manager(SSM) + VPC Endpoint로 받는다. NAT를 열어 데이터 계층을 인터넷에 연결하는 보기는 대개 오답.

라우팅 테이블: 보이지 않는 보안 통제

보안 엔지니어가 자주 놓치는 것이 라우팅 테이블이다. 보안 그룹·NACL은 "차단"을 명시하지만, 라우팅 테이블은 "경로가 없으면 갈 수 없다"는 암묵적 차단을 만든다.

대상(Destination)타깃(Target)의미
10.0.0.0/16localVPC 내부 통신(삭제 불가, 항상 존재)
0.0.0.0/0igw-xxxx인터넷 양방향
0.0.0.0/0nat-xxxx아웃바운드만(인바운드 차단)
pl-xxxx (S3)vpce-xxxxGateway Endpoint로 S3 사설 접근

라우팅 테이블은 서브넷 단위(혹은 게이트웨이 단위)로 연결된다. 한 서브넷에 두 개의 라우팅 테이블을 동시에 연결할 수는 없다. 명시적으로 연결하지 않은 서브넷은 VPC의 Main Route Table을 사용한다. 보안 사고가 자주 나는 지점이 여기다 — 새 서브넷을 만들고 라우팅을 명시 연결하지 않았는데, Main Route Table에 IGW 경로가 있으면 의도치 않게 Public이 된다. 따라서 Main Route Table에는 절대 0.0.0.0/0 → IGW를 두지 않는 게 표준이다.

🎯 시나리오: "보안 감사 결과, Data Tier의 RDS가 인터넷에서 접근 가능한 것으로 의심된다. 무엇을 확인하나?" — 순서대로: (1) RDS의 PubliclyAccessible 플래그, (2) 서브넷 라우팅 테이블에 IGW 경로 존재 여부, (3) 보안 그룹 인바운드에 0.0.0.0/0, (4) NACL. 이 중 RDS가 진짜 인터넷에 닿으려면 라우팅(IGW)과 Public IP가 모두 있어야 한다. 라우팅이 없으면 SG가 열려 있어도 도달 불가. 이 "도달 가능성 분석"이 보안 엔지니어의 핵심 역량이다.

라우팅 테이블의 종류와 잘 안 보이는 두 가지

라우팅 테이블이라고 하면 보통 서브넷에 붙는 것만 떠올리지만, 실제로는 붙는 위치가 몇 가지 더 있고 그중 둘은 감사에서 자주 누락된다.

종류붙는 대상보안 관점
Main Route Table명시 연결이 없는 모든 서브넷여기에 IGW 경로가 있으면 새 서브넷이 자동으로 Public이 된다
커스텀 라우팅 테이블명시 연결한 서브넷계층별로 하나씩 두는 것이 표준
Gateway Route TableIGW 또는 VGW 자체들어오는 트래픽을 검사 어플라이언스로 우회시킬 때(Week 4의 인그레스 라우팅)
Local Gateway / Outpost온프레미스 확장하이브리드 경로가 우회 통로가 되지 않는지 확인

여기서 두 가지를 기억한다. 첫째, 10.0.0.0/16 → local 경로는 삭제할 수 없다. "VPC 내부 통신을 라우팅으로 끊자"는 보기는 오답이다. 같은 VPC 안의 격리는 라우팅이 아니라 보안 그룹으로 만든다. 둘째, 라우트의 대상이 사라지면 그 경로는 blackhole 상태가 된다 — 예를 들어 NAT 게이트웨이를 지웠는데 0.0.0.0/0 → nat-xxxx 경로가 남아 있으면, 트래픽은 인터넷으로 새는 것이 아니라 그냥 버려진다. "NAT를 지웠는데 인스턴스가 여전히 인터넷에 나간다"면 blackhole이 아니라 다른 경로(IGW 직결, 피어링, TGW)가 있다는 뜻이므로 라우팅 테이블 전체를 다시 봐야 한다.

# 이 VPC의 모든 라우팅 테이블에서 인터넷으로 나가는 경로만 뽑아 본다
aws ec2 describe-route-tables \
  --filters "Name=vpc-id,Values=vpc-0abc1234" \
  --query 'RouteTables[].{RT:RouteTableId,
             Assoc:Associations[].SubnetId,
             Internet:Routes[?DestinationCidrBlock==`0.0.0.0/0`].[GatewayId,NatGatewayId,TransitGatewayId,State]}' \
  --output json
 
# Main Route Table이 무엇인지, 거기에 IGW 경로가 있는지 확인
aws ec2 describe-route-tables \
  --filters "Name=vpc-id,Values=vpc-0abc1234" \
            "Name=association.main,Values=true" \
  --query 'RouteTables[].Routes'

서브넷이 어느 라우팅 테이블에 연결됐는지를 콘솔의 서브넷 화면에서만 보고 판단하면 놓치는 경우가 있다. 명시 연결이 없는 서브넷은 화면에 "Main"이라고 표시되는데, 이때 실제 경로는 Main Route Table을 따라간다. 감사 스크립트를 짤 때 Associations가 비어 있는 서브넷을 "라우팅 없음"으로 처리하면 가장 위험한 케이스를 정상으로 분류하게 된다. 반드시 Main Route Table의 내용까지 합쳐서 판정해야 한다.

NAT Gateway vs Internet Gateway: 방향성의 차이

항목Internet Gateway (IGW)NAT Gateway
트래픽 방향양방향(인/아웃)아웃바운드만
사용 위치퍼블릭 서브넷퍼블릭 서브넷에 두고 Private이 사용
보안 의미외부에서 시작 가능외부에서 먼저 연결 불가
비용무료시간당 + 데이터 처리 요금

NAT의 보안적 가치는 비대칭성에 있다. 내부에서 시작한 연결의 응답만 돌아올 수 있고, 외부가 먼저 연결을 시도할 수 없다. 이는 상태 추적(stateful translation) 덕분이다. 가정용 공유기의 NAT와 같은 원리다. 따라서 App Tier가 인터넷에서 패치를 받되 인터넷이 App Tier에 먼저 접근하지 못하게 하는 표준 수단이다. IPv6에서는 NAT 대신 Egress-only Internet Gateway가 같은 역할을 한다.

NAT Gateway는 반드시 퍼블릭 서브넷에 있어야 한다(자신이 IGW로 나가야 하므로). NAT를 프라이빗 서브넷에 두면 동작하지 않는다. 또 NAT는 단방향이라 인바운드 차단을 보장하지만, 아웃바운드는 모두 허용하므로 데이터 유출(exfiltration) 경로가 될 수 있다. 민감 워크로드에서는 NAT 대신 VPC Endpoint로 필요한 서비스만 사설 연결하는 게 더 안전하다(Day 4 주제).

인터넷으로 나가는 네 가지 문, 그리고 각각의 차단 수단

"밖으로 나가는 길"은 하나가 아니다. 유출을 막겠다면서 NAT만 지우면 나머지 문이 열려 있는 채로 남는다. 아래 표가 감사에서 실제로 훑어야 하는 목록이다.

유출 경로성립 조건차단·축소 수단
IGW 직결퍼블릭 IP + 0.0.0.0/0 → igw워크로드를 프라이빗 서브넷으로, IGW 경로 제거
NAT Gateway0.0.0.0/0 → natNAT 제거 후 VPC 엔드포인트로 대체(4일차)
Egress-only IGW (IPv6)::/0 → eigwIPv6를 쓰지 않으면 서브넷에 IPv6를 할당하지 않는다
Peering / TGW / VPN / DX상대 VPC나 온프레미스에 인터넷 경로 존재상대편의 egress 정책까지 포함해 감사, TGW 라우팅 도메인 분리
VPC 엔드포인트엔드포인트 경유 AWS API엔드포인트 정책으로 대상 리소스·조직 제한(4일차)
DNS 터널링53/UDP가 열려 있음Resolver DNS Firewall(7주차)

마지막 두 줄이 중요한 이유는, 인터넷 경로를 전부 지운 "zero-internet VPC"에서도 유출이 원리적으로 가능하다는 점 때문이다. AWS 서비스로 나가는 통로(엔드포인트)와 이름 해석 통로(DNS)는 남아 있고, 공격자는 남아 있는 통로를 쓴다. 그래서 4일차의 엔드포인트 정책과 7주차의 DNS 통제가 이 표의 마지막 두 줄을 메우는 작업이 된다.

NAT Instance와 NAT Gateway의 차이는 시험에서 가끔 등장한다. NAT Instance는 우리가 관리하는 EC2이므로 소스/대상 확인(source/destination check)을 꺼야 동작하고, 보안 그룹을 붙일 수 있으며, 스스로 패치·이중화를 해야 한다. NAT Gateway는 관리형이라 SG를 붙일 수 없고(트래픽 통제는 서브넷 NACL과 라우팅으로 한다), AZ 단위로 이중화한다. 보안 관점에서 흥미로운 차이는 "SG를 붙일 수 있느냐"인데, NAT Instance에 SG를 걸어 목적지를 제한하는 방식은 실무에서 권장되지 않는다 — 관리 부담과 단일 장애점이 늘어나는 데 비해, AWS 서비스 IP 대역은 자주 바뀌어 실효성이 낮기 때문이다. 목적지 제한이 목적이라면 NAT를 정교하게 만드는 대신 엔드포인트로 갈아타거나 Network Firewall을 세우는 편이 정석이다.

보안 관점의 VPC 추가 통제

# VPC Flow Logs 활성화 (Day 3에서 심화)
aws ec2 create-flow-logs \
  --resource-type VPC --resource-ids vpc-xxxx \
  --traffic-type ALL \
  --log-destination-type cloud-watch-logs \
  --log-group-name /vpc/flowlogs
 
# 기본 SG의 모든 규칙 제거 (최소 권한 시작점)
aws ec2 revoke-security-group-ingress \
  --group-id sg-default --protocol -1 --source-group sg-default
 
# DNS 쿼리 로깅 (Route 53 Resolver) — DNS 기반 exfil 탐지
aws route53resolver create-resolver-query-log-config \
  --name vpc-dns-log --destination-arn arn:aws:logs:...:log-group:/vpc/dns

VPC의 기본 보안 그룹과 기본 NACL은 동작이 다르다. 기본 SG는 같은 SG에 속한 리소스끼리는 모두 허용, 그 외 인바운드는 차단(아웃바운드 전체 허용). 기본 NACL은 모든 인바운드·아웃바운드를 허용한다. 그래서 "새 서브넷이 기본 NACL을 쓰면 NACL 레벨에서는 무방비"라는 점을 기억해야 한다. 격리는 라우팅과 SG로 만든다.

2019년 Capital One 사고의 네트워크 측면을 보면, SSRF 취약점으로 EC2 메타데이터에 접근한 뒤 그 자격증명으로 S3 데이터를 빼냈다. 만약 S3 접근이 VPC Endpoint + Endpoint Policy로만 허용되고 인터넷 경로가 막혀 있었다면, 탈취한 자격증명으로도 외부에서 데이터를 가져가기 훨씬 어려웠을 것이다. 네트워크 격리는 IAM 침해 이후의 "두 번째 방어선"으로 작동한다.

노출 자가진단: 손으로 확인하는 순서

"우리 VPC에 인터넷에 노출된 것이 있는가"를 답할 때, 콘솔을 헤매는 대신 앞의 AND 조건표를 그대로 명령어로 옮기면 된다. 순서는 넓은 것에서 좁은 것으로 — 라우팅부터 본다. 라우팅에 인터넷 경로가 없는 서브넷은 그 아래를 볼 필요가 없기 때문이다.

# ① 인터넷 경로를 가진 서브넷 목록을 먼저 확정한다
aws ec2 describe-route-tables --filters "Name=vpc-id,Values=vpc-0abc1234" \
  --query 'RouteTables[?Routes[?GatewayId!=null && starts_with(GatewayId, `igw-`)]].Associations[].SubnetId'
 
# ② 그 서브넷 안에서 퍼블릭 주소를 가진 ENI만 추린다
aws ec2 describe-network-interfaces \
  --filters "Name=subnet-id,Values=subnet-public-a" \
  --query 'NetworkInterfaces[?Association.PublicIp!=null].[NetworkInterfaceId,PrivateIpAddress,Association.PublicIp,Description]' \
  --output table
 
# ③ 남은 대상의 보안 그룹에서 0.0.0.0/0 인바운드만 뽑는다
aws ec2 describe-security-groups \
  --filters "Name=vpc-id,Values=vpc-0abc1234" \
  --query 'SecurityGroups[?IpPermissions[?IpRanges[?CidrIp==`0.0.0.0/0`]]].{Id:GroupId,Name:GroupName,
             Open:IpPermissions[?IpRanges[?CidrIp==`0.0.0.0/0`]].[IpProtocol,FromPort,ToPort]}'
 
# ④ 서브넷 경계의 NACL도 함께 본다 (기본 NACL이면 사실상 무통제)
aws ec2 describe-network-acls \
  --filters "Name=vpc-id,Values=vpc-0abc1234" \
  --query 'NetworkAcls[].{Id:NetworkAclId,Default:IsDefault,
             Assoc:Associations[].SubnetId,
             Entries:Entries[?RuleAction==`allow`].[RuleNumber,Egress,Protocol,CidrBlock,PortRange]}'

손으로 훑는 것과 별개로, AWS가 이 판정을 대신 해 주는 도구가 둘 있다. 시험에서 이름으로 갈리므로 역할을 구분해 둔다.

도구답하는 질문언제 쓰나
Reachability Analyzer"A에서 B로 갈 수 있는가, 못 간다면 어느 컴포넌트가 막았는가"연결 실패 트러블슈팅(구체적 출발지·목적지가 있을 때)
Network Access Analyzer"인터넷에서 우리 DB 서브넷에 닿는 경로가 존재하는가"의도치 않은 경로 상시 감사(출발지·목적지를 범위로 기술)
VPC Flow Logs"실제로 어떤 트래픽이 흘렀는가"사후 조사·이상 탐지(3일차)

앞의 둘은 패킷을 흘리지 않고 구성만 보고 정적으로 판정한다는 점이 중요하다. 즉 트래픽이 아직 발생하지 않은 새 환경에서도 노출을 찾아낼 수 있고, 반대로 "지금 조용하니 안전하다"는 착각을 깨 준다. Flow Logs는 이미 일어난 일만 보여 준다.

Reachability Analyzer가 실무에서 특히 강한 지점은 여러 계층이 동시에 얽혔을 때다. 사람이 손으로 볼 때는 SG를 고치고 나서 NACL을 보고, NACL을 고치고 나서 라우팅을 보는 식으로 한 번에 하나씩 확인하게 되어 왕복이 길어진다. Reachability Analyzer는 경로 전체를 한 번에 계산해 "차단 컴포넌트"를 지목하므로, 고치고 다시 돌리는 사이클이 짧다. 다만 이것은 구성 기반 판정이라 OS 방화벽(iptables, Windows Defender Firewall)이나 애플리케이션이 listen하지 않는 문제는 잡아내지 못한다. 앞의 AND 조건표에서 ⑥번은 AWS가 볼 수 없는 영역이라는 점을 기억해 두면, "모든 AWS 통제가 초록불인데 여전히 연결이 안 된다"는 상황에서 헤매지 않는다.

경계를 넓힐 때: Peering, Transit Gateway, VPC 공유

VPC가 하나일 때의 격리는 쉽다. 문제는 연결을 시작하는 순간이다. 연결 수단마다 노출되는 표면이 다르고, 시험은 이 차이를 묻는다.

연결 수단노출 표면주의점
VPC Peering두 VPC의 CIDR이 서로 보임전이(transitive) 라우팅 불가 — A-B, B-C가 있어도 A-C는 통신 못 함. CIDR 중첩 시 불가
Transit Gateway연결된 모든 VPC가 잠재적으로 서로 보임라우팅 테이블 분리로 도메인을 나누지 않으면 전 계정 평면 네트워크가 된다
PrivateLink제공자가 노출한 서비스 하나만 보임노출 표면이 가장 작다(4일차)
VPC 공유(RAM)참여 계정이 같은 서브넷에 리소스를 만듦소유 계정이 라우팅·NACL을 쥐고, 참여 계정은 자기 리소스만 관리

Transit Gateway를 "연결만 하면 되는 라우터"로 취급하는 것이 가장 흔한 설계 실수다. TGW의 기본 동작은 모든 연결(attachment)을 하나의 라우팅 테이블에 넣어 서로 통신하게 하는 것이고, 이는 계정 수십 개를 하나의 평면 네트워크로 만든다. 격리가 필요하면 TGW 라우팅 테이블을 용도별로 나누고(예: prod / nonprod / shared-services) 연결마다 어느 테이블과 연관될지, 어느 테이블로 전파(propagate)될지를 명시해야 한다. "개발 계정이 침해되면 프로덕션 DB에 네트워크로 닿는가"라는 질문의 답이 여기서 갈린다.

보안 그룹 참조(source에 다른 SG 지정)는 같은 VPC 안에서는 언제나 되지만, VPC 경계를 넘을 때는 조건이 붙는다. 같은 리전 내 VPC Peering으로 연결된 두 VPC 사이에서는 SG 참조가 가능하다. 반면 Transit Gateway를 경유하는 트래픽에는 SG 참조가 적용되지 않으므로 CIDR로 써야 한다. 설계 단계에서 이 제약을 모르면, "SG 참조로 깔끔하게 쓰겠다"고 계획한 규칙이 TGW 도입 시점에 전부 CIDR로 풀어헤쳐지는 일이 생긴다. 그리고 CIDR로 풀리는 순간 계층별 연속 주소 계획을 해 두었는지가 규칙 개수를 좌우한다 — 앞의 CIDR 계획 절이 여기서 되돌아온다.

정리

오늘 잡아야 할 그림은 네 가지다. 첫째, 인터넷 도달은 조건들의 AND로 성립하고 차단은 OR다 — 퍼블릭 주소, IGW 라우팅, NACL, SG, 응답 경로, 리스닝 프로세스 중 하나만 끊어도 막히며, 그중 가장 값싸고 확실한 노드가 라우팅이다. 둘째, VPC는 강한 격리 경계이고 같은 IP가 겹쳐도 소프트웨어 레이어가 소유권을 강제한다. 셋째, 서브넷의 Public/Private은 속성이 아니라 라우팅이 결정하며, 명시 연결이 없는 서브넷은 Main Route Table을 따라가므로 Main에는 절대 IGW 경로를 두지 않는다. 넷째, 3-Tier(Public/App/Data) 격리는 심층 방어의 네트워크 구현이고, 계층 간 허용은 CIDR이 아니라 SG 참조로 표현하는 것이 표준이다.

여기에 오늘 새로 얹은 관점이 하나 더 있다. 밖으로 나가는 문은 하나가 아니다. IGW 직결, NAT, Egress-only IGW, 피어링·TGW·VPN을 통한 우회, 엔드포인트, 그리고 DNS까지 — 유출을 막겠다고 NAT만 지우면 나머지가 그대로 남는다. 이 문 목록을 손에 쥐고 감사하는 습관이 "인터넷 0(zero-internet) VPC"라는 목표를 실제로 달성하게 해 준다.

노출 판정은 손으로도, 도구로도 할 수 있다. describe-route-tables로 인터넷 경로를 가진 서브넷을 먼저 확정하고 그 안에서만 좁혀 들어가는 순서를 기억하고, 구체적 출발지·목적지가 있으면 Reachability Analyzer, 의도치 않은 경로를 상시 감시하려면 Network Access Analyzer를 쓴다. 두 도구 모두 구성만 보고 정적으로 판정하므로 트래픽이 없어도 노출을 찾아내지만, OS 방화벽과 애플리케이션 리스닝 여부는 보지 못한다는 한계도 함께 기억해 둔다.

"이 리소스에 인터넷이 닿는가"라는 질문에 라우팅·Public IP·SG·NACL을 모두 따져 답하는 능력이 보안 엔지니어의 출발점이다. 다음 글에서는 그중 헷갈리기 쉬운 보안 그룹과 NACL의 차이를 상태 저장/비저장 관점에서 정밀하게 본다.

📝 연습 문제

선택지를 클릭하면 정답·해설이 펼쳐집니다.

문제 1

한 보안 감사에서 RDS 인스턴스가 인터넷에서 접근 가능한지 의심된다. RDS가 실제로 인터넷에서 도달 가능하려면 반드시 충족돼야 하는 조건의 조합은?

문제 2

새로 만든 서브넷을 라우팅 테이블에 명시적으로 연결하지 않았다. 이 서브넷의 라우팅 동작은?

문제 3

Data Tier 서브넷(RDS 전용)의 라우팅 설계로 가장 적절한 것은?

문제 4

민감 데이터를 다루는 App Tier에서 인터넷으로 데이터가 유출되는 것을 막으면서도 AWS 서비스(S3, DynamoDB) 접근은 허용하고 싶다. NAT Gateway 대비 더 안전한 접근은?

문제 5

기본(default) NACL과 기본 보안 그룹의 동작 차이로 옳은 것은?

이전Week 2 종합: 멀티계정 IAM 거버넌스 시나리오 통합Week 2 · Day 5다음 보안 그룹 vs 네트워크 ACL: 상태 저장과 비저장의 본질Week 3 · Day 2

참고 공식 자료

  • SCS-C03 공식 시험 안내(새 탭에서 열림)
  • Amazon VPC 공식 문서(새 탭에서 열림)
  • Amazon RDS · Aurora 공식 문서(새 탭에서 열림)
  • Amazon S3 공식 문서(새 탭에서 열림)
  • Amazon EC2 공식 문서(새 탭에서 열림)
  • AWS IAM 공식 문서(새 탭에서 열림)

이 페이지

  • 도달 가능성: 보안 엔지니어가 던지는 단 하나의 질문
  • VPC라는 격리 경계: CIDR과 테넌시
  • CIDR 계획이 곧 보안 설계다
  • 3-Tier 서브넷 격리: 표준 패턴
  • 라우팅 테이블: 보이지 않는 보안 통제
  • 라우팅 테이블의 종류와 잘 안 보이는 두 가지
  • NAT Gateway vs Internet Gateway: 방향성의 차이
  • 인터넷으로 나가는 네 가지 문, 그리고 각각의 차단 수단
  • 보안 관점의 VPC 추가 통제
  • 노출 자가진단: 손으로 확인하는 순서
  • 경계를 넓힐 때: Peering, Transit Gateway, VPC 공유
  • 정리
  • 연습 문제