VPC 다시 배우기 : 서브넷과 Dual-Stack

서브넷은 격리 경계가 아니다, 그리고 Dual-Stack VPC와 E-IGW

written by tiaz0128

2019년 AWS Architecture Blog에 올라온 One to Many: Evolving VPC Design을 다시 읽으면서 VPC를 처음부터 정리하고 있습니다. 꽤 오래된 글이지만 기본 개념은 지금도 그대로 유효합니다.

오히려 요즘 기능인 Dual-Stack VPC, IPv6-only 서브넷과 이어서 보니 ‘왜 이렇게 설계했는가’가 더 선명해졌습니다. 이번 글에서는 서브넷의 정체부터 Dual-Stack, 그리고 E-IGW까지 다뤄보겠습니다.

'VPC, 서브넷, CIDR, 라우트 테이블의 기본 개념'에 대해 더 자세히 알고 싶으시다면, "AWS 네트워크 기본" 글을 확인 해주세요!

서브넷은 격리 경계가 아닙니다

VPC를 처음 배울 때 흔히 하는 오해가 ‘서브넷을 나누면 네트워크가 격리된다’는 생각입니다. 저도 한동안 그렇게 이해하고 있었습니다. 정확히는 이렇습니다.

즉 서브넷 자체에는 격리 기능이 내장되어 있지 않습니다. 이전 글에서도 같은 이야기를 했었습니다.

사실 서브넷은 기본적으로 격리되어있지만, ‘인터넷 게이트웨이로 라우팅이 가능한가’에 따라 Public / Private 서브넷으로 나눠질 뿐입니다.

Public 서브넷 / Private 서브넷이라는 구분도 결국 그 서브넷의 라우트 테이블이 어디를 가리키는가의 문제입니다. AWS 콘솔 어디에도 ‘이 서브넷을 Private으로 만들기’ 같은 체크박스는 없습니다. 우리가 라우트 테이블을 그렇게 구성했기 때문에 그렇게 부르는 것뿐입니다.

그럼 격리는 누가 하나요

  Security Group Network ACL
적용 단위 인스턴스(ENI) 서브넷
상태 상태 저장(Stateful) 상태 비저장(Stateless)
규칙 허용(Allow)만 가능 허용 + 거부(Deny)
평가 모든 규칙을 종합 번호 순서대로

정리하면 서브넷은 ‘어디로 보낼지’를 정하고, SG와 NACL은 ‘무엇을 통과시킬지’를 정합니다. 서로 하는 일이 다릅니다.

예약 주소도 서브넷 단위입니다

서브넷 CIDR 안에서 앞의 4개와 마지막 1개, 총 5개의 IPv4 주소는 AWS가 예약해 사용할 수 없습니다. /28 서브넷을 만들면 16개 중 11개만 쓸 수 있다는 뜻입니다.

\[2^{32-28} - 5 = 16 - 5 = 11\]

IPv6 서브넷도 예약 주소가 있습니다. 다만 브로드캐스트 주소가 없기 때문에 앞의 4개만 예약됩니다.

Dual-Stack VPC : IPv4는 필수, IPv6는 선택

VPC를 만들면 IPv4 CIDR은 무조건 따라붙습니다. 그리고 이 기본 IPv4 CIDR은 제거할 수 없습니다. VPC를 삭제하는 방법밖에 없습니다.

IPv6는 원하면 추가로 붙이는 방식입니다. Amazon이 제공하는 /56 대역을 받거나, 보유한 대역을 BYOIP로 가져올 수 있습니다. 이렇게 IPv6를 추가한 VPC를 Dual-Stack VPC라고 부릅니다.

'IPv6-only VPC'는 존재하지 않습니다. VPC 레벨에서는 IPv4가 항상 필수입니다.

서브넷은 세 가지로 섞을 수 있습니다

흥미로운 건 서브넷 레벨입니다. Dual-Stack VPC 안에서는 서브넷을 세 가지로 자유롭게 조합할 수 있습니다.

서브넷 타입 IPv4 IPv6 설명
IPv4-only O X 기존 방식
Dual-Stack O O 둘 다 할당
IPv6-only X O IPv4 주소를 아예 할당받지 않음

IPv6-only 서브넷의 인스턴스는 ENI에 IPv4 주소가 전혀 없습니다. VPC는 IPv4를 갖고 있어도, 그 안의 특정 서브넷은 IPv4를 완전히 배제할 수 있다는 뜻입니다.

IPv6 서브넷의 제약

IPv4 서브넷과 달리 IPv6 서브넷 CIDR은 /64로 고정입니다. Prefix 길이를 마음대로 정할 수 없습니다. VPC가 받은 /56 대역을 /64 단위로 쪼개면 256개의 서브넷을 만들 수 있는 셈입니다.

\[2^{64-56} = 2^{8} = 256\]

그 외에 IPv6-only 서브넷을 쓸 때 미리 알아두면 좋은 것들입니다.

왜 지금 IPv6를 보는가

2024년 2월 1일부터 모든 퍼블릭 IPv4 주소에 시간당 요금이 부과되기 시작했습니다. 사용 중인 주소든 미사용 EIP든 예외가 없습니다. 인스턴스가 수백 대 규모가 되면 무시할 수 없는 금액이 됩니다.

그래서 IPv6-only 서브넷을 실무에서 검토하는 사례가 늘고 있습니다. 예전에는 ‘언젠가 해야 할 일’이었다면, 지금은 청구서에 바로 찍히는 문제가 되었습니다.

E-IGW : IPv6에 NAT가 필요 없는 이유

IPv6는 주소 공간이 방대해서 IPv4처럼 ‘부족한 공인 IP를 나눠 쓰기 위한 NAT’가 필요 없습니다. 인스턴스에 할당되는 IPv6 주소 자체가 이미 Global Unicast, 즉 공인 주소입니다.

그런데 여기서 문제가 하나 생깁니다.

그럼 Private 서브넷처럼 인바운드는 막고 아웃바운드만 허용하고 싶을 때는 뭘 쓰나요?

여기서 등장하는 것이 Egress-Only Internet Gateway(E-IGW) 입니다.

주소를 숨기는 게 아니라 방향을 통제합니다

핵심은 E-IGW가 NAT처럼 주소를 바꾸거나 숨기지 않는다는 점입니다. 인스턴스의 IPv6 주소는 그대로 노출된 채 나갑니다. E-IGW가 하는 일은 연결의 방향을 통제하는 것뿐입니다.

%%{
  init: {
    'theme': 'base',
    'themeVariables': {
      'primaryColor': '#2a3844',
      'lineColor': '#fff',
      'primaryTextColor': '#fff',
      'primaryBorderColor': '#fff',
      'tertiaryColor': '#fff'
    }
  }
}%%

flowchart LR
    EC2A["EC2
Public Subnet"] EC2B["EC2
Private Subnet"] IGW["Internet
Gateway"] EIGW["Egress-Only
Internet Gateway"] NET(["Internet"]) EC2A <--> IGW IGW <--> NET EC2B -- "아웃바운드 개시" --> EIGW EIGW -- "리턴 트래픽만" --> EC2B EIGW <--> NET

> 그림 1. IGW는 양방향, E-IGW는 아웃바운드 개시만 허용

그리고 하나의 서브넷에 연결된 라우트 테이블에서 ::/0 경로는 IGW든 E-IGW든 하나만 가리킬 수 있습니다. 어느 쪽을 쓸지는 그 서브넷을 Public으로 설계할지 Private으로 설계할지에 달려 있습니다.

E-IGW는 IPv6 전용입니다. IPv4 트래픽에는 사용할 수 없고, 그쪽은 여전히 NAT 게이트웨이의 역할입니다.

그냥 IGW 쓰고 SG로 막으면 안 되나요?

기술적으로는 가능합니다. IGW를 연결한 뒤 SG에서 인바운드 규칙을 하나도 열지 않으면 결과적으로는 비슷해 보입니다. 하지만 이건 방어가 걸리는 계층이 다릅니다.

  IGW + SG/NACL E-IGW
인바운드 연결 시도 인스턴스까지 도달 → SG/NACL이 평가 후 drop 게이트웨이에서 차단, 애초에 들어올 경로가 없음
실패 시나리오 SG 규칙 하나 잘못 열면 즉시 인바운드 노출 SG를 열어도 경로가 없어 여전히 차단
방어 계층 인스턴스 레벨 라우팅 레벨

‘IGW + SG’는 인바운드 차단을 인스턴스 레벨 설정에 전적으로 의존하는 구조입니다. 누군가 실수로 SG에 ::/0 인바운드 규칙을 추가하는 순간 인터넷에 그대로 노출됩니다.

반면 E-IGW는 라우팅 레벨에서 원천적으로 경로를 없애는 구조입니다. IPv4의 Private 서브넷도 원래 ‘NAT 게이트웨이가 라우팅 레벨에서 인바운드를 막아주는’ 설계였다는 걸 생각하면, E-IGW는 그 설계 철학을 IPv6로 그대로 옮긴 것에 가깝습니다.

SG는 인스턴스 레벨, E-IGW는 라우팅 레벨. 서로 다른 계층에서 같은 목적(인바운드 차단)을 이중으로 보장하는 Defense in Depth 구조입니다.

라우트 테이블로 정리하기

지금까지의 이야기를 결국 라우트 테이블 한 장으로 정리하면 이렇게 됩니다. VPC CIDR이 10.0.0.0/16, IPv6 CIDR이 2001:db8:1a00::/56인 경우입니다.

Public 서브넷의 라우트 테이블

Destination Target
10.0.0.0/16 local
2001:db8:1a00::/56 local
0.0.0.0/0 igw-id
::/0 igw-id

Private 서브넷의 라우트 테이블

Destination Target
10.0.0.0/16 local
2001:db8:1a00::/56 local
0.0.0.0/0 nat-gateway-id
::/0 eigw-id

IPv4는 NAT 게이트웨이, IPv6는 E-IGW. 역할은 같지만 담당하는 프로토콜이 다릅니다. 이 표만 이해하면 Public / Private 서브넷의 정체는 사실상 끝입니다.

마무리

VPC를 다시 보면서 정리한 핵심은 다음과 같습니다.

다음글에서 계속 됩니다.

다음 편에서는 Public 서브넷과 IGW를 조금 더 깊게 보고, Private 서브넷의 NAT 게이트웨이 HA 구성을 다뤄보겠습니다.

감사합니다! 😊

참고 문헌

AWS VPC IPv6 Subnet

tiaz0128

Eat Sleep Coding.

Never Never GiveUp.

Security  |  BackEnd  |  Multi Cloud