본문으로 건너뛰기
김신건의 로그

[AWS] Security Group vs NACL: stateful vs stateless 방화벽

· 수정 · 📖 약 2분 · 908자/단어 #aws #security #network #vpc #cloud #firewall
Security Group, SG, NACL, Network ACL, stateful firewall, subnet ACL, aws-sg, ephemeral port

정의

AWS VPC 에는 두 계층의 네트워크 방화벽이 존재.

항목SG (Security Group)NACL (Network ACL)
상태StatefulStateless
적용 레벨ENI / 인스턴스Subnet
규칙 종류Allow 만Allow + Deny
규칙 평가모든 규칙 종합번호 순 (첫 매칭)
기본 Inbounddeny allallow all
기본 Outboundallow allallow all
반환 트래픽자동 허용명시적 설정 필요

Stateful vs Stateless 심화

Stateful: Security Group

sequenceDiagram
    Client->>SG: "TCP SYN (port 80, inbound)"
    SG->>Server: forward (inbound rule 일치)
    Note over SG: "connection 상태 추적"
    Server->>SG: "TCP SYN-ACK (ephemeral port, outbound)"
    SG-->>Client: "forward (상태 추적, outbound 규칙 검사 안 함)"

SG 는 연결 상태를 추적. Inbound 를 허용하면 그 연결의 응답은 자동으로 허용. Outbound 규칙을 닫아도 기존 연결 응답은 통과.

Stateless: NACL

sequenceDiagram
    Client->>NACL: "TCP SYN (port 443, inbound)"
    NACL->>Server: "inbound rule 100: allow 443 -> 통과"
    Server->>NACL: "TCP SYN-ACK (ephemeral port 32768, outbound)"
    NACL->>NACL: "outbound rule 검사: 1024-65535 허용? -> 확인"
    NACL-->>Client: "outbound rule 있어야 통과"

NACL 은 각 패킷을 독립적으로 검사. 응답 트래픽도 별도 outbound rule 필요. 특히 ephemeral port 처리가 핵심.

Ephemeral Port 이해

클라이언트가 서버에 요청할 때 임시 포트를 사용:

  • Linux: 32768-60999
  • Windows: 49152-65535
  • AWS 권장: 1024-65535
# NACL Outbound rule (올바른 설정)
Rules:
  - RuleNumber: 100
    Direction: outbound
    Action: allow
    Protocol: tcp
    PortRange: { From: 1024, To: 65535 }   # ephemeral ports
    CidrBlock: 0.0.0.0/0

# 이것만 있으면 Inbound 요청의 응답도 통과

WARNING

NACL 에서 ephemeral port 누락 = 응답이 차단. NACL outbound 에 반드시 1024-65535 포트 범위 허용 규칙 추가.

Security Group 규칙

기본 설정 패턴

# 웹 서버 Security Group
WebServerSG:
  Inbound:
    - Protocol: tcp
      Port: 443
      CidrIp: 0.0.0.0/0         # 인터넷에서 HTTPS
    - Protocol: tcp
      Port: 80
      CidrIp: 0.0.0.0/0         # 인터넷에서 HTTP (리다이렉트용)
  Outbound:
    - Protocol: -1               # 모든 아웃바운드 (기본)
      CidrIp: 0.0.0.0/0
# DB 서버 Security Group
DatabaseSG:
  Inbound:
    - Protocol: tcp
      Port: 5432
      SourceSecurityGroupId: sg-webserver   # 웹 SG 에서만 PostgreSQL
  Outbound:
    - Protocol: -1
      CidrIp: 0.0.0.0/0

SG Referencing SG (핵심 기능)

IP 대신 다른 SG 를 source/destination 으로 지정. Dynamic IP 환경에서 강력.

DatabaseSG:
  Inbound:
    - Protocol: tcp
      Port: 5432
      SourceSecurityGroupId: sg-app         # app SG 가진 ENI 만 허용
flowchart LR
    AppInstance["앱 EC2<br/>sg-app"] -->|"port 5432"| DB["RDS<br/>sg-db"]
    DB -.->|"sg-app 만 허용"| DB
    Internet["인터넷"] -.-x|"차단"| DB

Auto Scaling 으로 앱 인스턴스 IP 가 변해도 sg-app 이 붙어있으면 자동 허용. IP 추적 불필요.

NACL 규칙 작성

번호 순 평가

NACL Inbound Rules:
  RuleNumber: 100
    Action: ALLOW
    Protocol: tcp
    PortRange: 443
    CidrBlock: 0.0.0.0/0

  RuleNumber: 200
    Action: ALLOW
    Protocol: tcp
    PortRange: 1024-65535    # ephemeral ports (응답)
    CidrBlock: 0.0.0.0/0

  RuleNumber: 300
    Action: DENY
    CidrBlock: 1.2.3.4/32   # 악의적 IP 차단

  RuleNumber: 32767
    Action: DENY
    Protocol: -1             # 기본 모두 차단
    CidrBlock: 0.0.0.0/0

IMPORTANT

번호가 낮을수록 먼저 평가. 첫 번째 일치 규칙으로 결정. 100번에 ALLOW, 200번에 같은 IP 의 DENY 가 있으면 100번 ALLOW 가 우선.

특정 IP 차단 (NACL 만 가능)

NACL Rules:
  RuleNumber: 50
    Action: DENY
    CidrBlock: 1.2.3.0/24   # 악성 IP 범위 차단
  RuleNumber: 100
    Action: ALLOW
    CidrBlock: 0.0.0.0/0    # 나머지 허용

SG 는 Allow 만 지원하므로 특정 IP 차단에는 NACL 사용.

패킷 흐름: 전체 평가 순서

flowchart TD
    Internet["인터넷"] -->|"요청"| NACL_In["NACL Inbound<br/>(번호 순 평가)"]
    NACL_In -->|"ALLOW"| SG_In["SG Inbound<br/>(모든 규칙 종합)"]
    SG_In -->|"ALLOW"| Instance["EC2 / RDS"]
    Instance -->|"응답"| SG_Out["SG Outbound<br/>(stateful - 자동)"]
    SG_Out -->|"ALLOW"| NACL_Out["NACL Outbound<br/>(번호 순, ephemeral)"]
    NACL_Out -->|"ALLOW"| Internet

패킷이 통과하려면 NACL + SG 모두 통과해야 함.

레이어드 보안 설계

[인터넷]
    |
[NACL - subnet 경계]
 - 악성 IP 차단 (Deny)
 - 허용 포트 제한
    |
[Security Group - 인스턴스 경계]
 - 세밀한 포트 제어
 - SG-to-SG 참조
    |
[EC2/RDS/Lambda]

실전 사용 패턴:

  • NACL: subnet 레벨 coarse-grained 제어, 악성 IP 차단, 간단한 화이트리스트
  • SG: 인스턴스 레벨 fine-grained 제어, SG 참조, 대부분의 방화벽 규칙

변경 즉시 반영

SG 변경: 즉시 반영. 새로운 연결에 바로 적용. 기존 연결은 stateful 로 유지.

NACL 변경: 즉시 반영. 단, 기존 연결의 다음 패킷부터.

# SG 인바운드 규칙 추가
aws ec2 authorize-security-group-ingress \
  --group-id sg-12345 \
  --protocol tcp \
  --port 443 \
  --cidr 0.0.0.0/0

# NACL 규칙 추가
aws ec2 create-network-acl-entry \
  --network-acl-id acl-12345 \
  --rule-number 100 \
  --protocol 6 \
  --rule-action allow \
  --ingress \
  --port-range From=443,To=443 \
  --cidr-block 0.0.0.0/0

Session Manager vs SSH: SG 설계

IMPORTANT

SSH 포트 22 를 인터넷에 오픈하지 말 것. AWS Systems Manager Session Manager 사용 시 SSH 포트 전혀 불필요.

# 잘못된 설계 (SSH 공개)
IngressRules:
  - Port: 22, CidrIp: 0.0.0.0/0   # 즉시 공격 대상

# 올바른 설계 (Session Manager)
IngressRules: []                    # 인바운드 없음
EgressRules:
  - Port: 443, CidrIp: 0.0.0.0/0  # SSM endpoint 접근용

비용

SG 와 NACL 모두 추가 비용 없음. VPC 의 기본 포함 기능.

함정

WARNING

NACL ephemeral port 누락: Stateless NACL 에서 응답 포트 (1024-65535) outbound 허용 없으면 응답 차단. SG 는 자동이지만 NACL 은 수동.

WARNING

SG outbound 모두 닫기: 일반적으로 outbound 는 모두 허용. 닫으면 외부 API 호출, DNS 조회 모두 차단. stateful 이므로 inbound 응답은 별개.

CAUTION

너무 넓은 0.0.0.0/0 inbound: SSH/RDP 를 인터넷에 열면 즉시 brute force 공격 대상. Session Manager, Bastion Host, IP 제한 중 선택.

WARNING

SG 변경 후 기존 연결: SG 는 stateful 이므로 규칙 변경 후에도 기존 연결은 유지. 즉시 차단이 필요하면 인스턴스 재시작 또는 연결 강제 종료.

CAUTION

NACL 규칙 번호 간격: 10, 20, 30 처럼 촘촘하게 쓰면 중간 삽입 불가. 100, 200, 300 처럼 여유있게 번호 부여.

WARNING

SG 규칙 상한: 기본 60개 inbound + 60개 outbound. 너무 세분화된 규칙은 SG 여러 개로 분리하거나 NACL 사용.

관련 위키

이 글의 용어 (6개)
[AWS] ALB vs NLB: L7 vs L4 로드 밸런서cloud
정의 | | ALB | NLB | (Classic ELB) | |---|---|---|---| | Layer | L7 (HTTP) | L4 (TCP/UDP) | L4 + L7 (…
[AWS] Amazon RDS (Relational Database Service)cloud
정의 Amazon RDS (Relational Database Service) 는 AWS 가 관리하는 관계형 데이터베이스 서비스 입니다. 6개 엔진 (MySQL, PostgreS…
[AWS] EC2: 인스턴스 타입, AMI, EBScloud
정의 EC2 (Elastic Compute Cloud) = AWS 의 VM 서비스. instance type (CPU / RAM / NW) 결정 + AMI (OS 이미지) + E…
[AWS] IAM: User, Role, Policy, STScloud
정의 IAM (Identity and Access Management) = AWS 의 권한 관리 전부. User, Group, Role, Policy 로 구성. "누가 어떤 리소…
[AWS] VPC: subnet, route, NAT, peeringcloud
정의 VPC (Virtual Private Cloud) = AWS 안의 논리적 격리 네트워크. CIDR 정의 + subnet 분할 + 라우팅. AWS 리소스를 격리된 네트워크에 …
[K8s] NetworkPolicy: pod 간 네트워크 차단kubernetes
정의 NetworkPolicy = pod 간 허용된 트래픽만 통과. 없으면 모든 pod ↔ pod 가 허용 (기본 open). [!IMPORTANT] NetworkPolicy 는…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기