メインコンテンツまでスキップ

NAT & Security trong AWS VPC

Tài liệu này dành cho backend/DevOps engineers đã nắm VPC cơ bản. Mục tiêu: hiểu đúng bản chất NAT, Security Group, NACL và áp dụng được vào thiết kế production.


1. Tổng quan

NAT trong VPC là gì?

NAT (Network Address Translation) cho phép resource trong private subnet kết nối ra Internet (outbound) mà không cần public IP. Chiều ngược lại — Internet không thể tự khởi tạo kết nối vào private subnet.

Đây là nền tảng của mô hình bảo mật phổ biến nhất trên AWS: EC2 production nằm hoàn toàn trong private subnet, chỉ ra Internet khi cần thiết (cập nhật OS, gọi API bên ngoài).

Security layer trong VPC

AWS cung cấp hai lớp kiểm soát traffic ở network level:

LớpTênÁp dụng tạiMặc định
Lớp 1Security Group (SG)Instance (ENI)Cho phép outbound, chặn inbound
Lớp 2Network ACL (NACL)SubnetCho phép tất cả

Hai lớp này hoạt động độc lập và bổ sung cho nhau — không thay thế nhau.


2. NAT Gateway vs NAT Instance

NAT Gateway

NAT Gateway là managed service do AWS vận hành. Bạn không quản lý server, chỉ cần tạo trong public subnet và cấu hình route table.

  • Managed hoàn toàn: AWS xử lý patching, failover, scaling
  • Throughput: Tự động scale lên đến 100 Gbps
  • High availability: Redundant trong một AZ. Để multi-AZ, cần tạo một NAT Gateway mỗi AZ
  • Chi phí: ~$0.045/giờ + $0.045/GB data xử lý (us-east-1)

NAT Instance

NAT Instance là EC2 instance thông thường được cấu hình để làm NAT. Bạn tự quản lý toàn bộ.

  • Self-managed: Tự patch OS, tự xử lý failover
  • Throughput: Bị giới hạn bởi instance type (ví dụ: t3.medium ~5 Gbps)
  • High availability: Không tự động — phải tự dựng script failover
  • Chi phí: Chi phí EC2 instance (có thể dùng Spot)

So sánh chi tiết

Tiêu chíNAT GatewayNAT Instance
Quản lýManaged (AWS)Self-managed
HATự động trong AZPhải tự dựng
ThroughputTự động scale, tối đa 100 GbpsGiới hạn theo instance type
PerformanceCao, ổn địnhPhụ thuộc instance
Chi phí cố định~$32/tháng/AZTheo instance (có thể dùng Spot)
Chi phí dataTính phíTính phí (như EC2 transfer)
Security groupKhông áp dụngCó thể gắn SG
Port forwardingKhông hỗ trợHỗ trợ
Bastion hostKhông thểCó thể kết hợp

Khi nào dùng NAT Gateway

  • Mọi môi trường production
  • Không muốn quản lý thêm infrastructure
  • Cần throughput cao hoặc traffic không dự đoán được
  • Đội nhỏ, ưu tiên operational simplicity

Khi nào dùng NAT Instance

  • Môi trường dev/staging cần tiết kiệm chi phí tối đa
  • Cần port forwarding (ví dụ: bastion kiêm NAT)
  • Traffic rất thấp và dự đoán được
  • Đội có khả năng tự vận hành
Đừng dùng NAT Instance cho production

NAT Instance không tự failover. Nếu instance gặp sự cố, toàn bộ private subnet mất kết nối Internet. Incident này khó debug vì resource vẫn "chạy" nhưng không gọi được API ngoài.

Best practices cho NAT

  • Tạo một NAT Gateway mỗi AZ — đừng share NAT Gateway giữa các AZ (cross-AZ data transfer có phí và tăng latency)
  • Dùng VPC Endpoint (Gateway type) cho S3 và DynamoDB để bypass NAT — miễn phí và nhanh hơn
  • Gắn Elastic IP vào NAT Gateway để whitelist IP cố định ở các service bên ngoài
  • Bật VPC Flow Logs để monitor traffic qua NAT

Mỗi AZ có NAT Gateway riêng — traffic không cần cross-AZ, giảm chi phí và tăng resilience.


3. Security Group vs Network ACL (NACL)

Security Group (SG)

Security Group là firewall ở cấp instance (gắn vào ENI). Nó kiểm soát traffic vào/ra từng EC2, RDS, Lambda...

Đặc điểm quan trọng:

  • Stateful: Nếu inbound được phép, response outbound tự động được phép (không cần rule ngược lại)
  • Chỉ có rule Allow: Không có rule Deny — những gì không được phép mặc nhiên bị chặn
  • Có thể tham chiếu SG khác: Thay vì ghi IP, viết "cho phép từ SG-web-tier" — linh hoạt và maintainable hơn
  • Áp dụng tại ENI: Một instance có thể gắn nhiều SG

Network ACL (NACL)

NACL là firewall ở cấp subnet. Mọi traffic vào/ra subnet đều đi qua NACL.

Đặc điểm quan trọng:

  • Stateless: Response traffic phải có rule riêng (inbound và outbound tách biệt)
  • Có cả Allow và Deny: Có thể chặn một IP cụ thể ở cấp subnet
  • Rule có số thứ tự: AWS đánh giá từ số nhỏ đến lớn, dừng lại khi match
  • Áp dụng cho toàn subnet: Ảnh hưởng đến mọi resource trong subnet

So sánh chi tiết

Tiêu chíSecurity GroupNetwork ACL
Cấp độInstance (ENI)Subnet
Trạng tháiStatefulStateless
Rule DenyKhông
Thứ tự ruleKhông (tất cả được đánh giá)Có (đánh số, dừng khi match)
Phạm vi áp dụngChỉ instance được gắnToàn bộ subnet
Mặc địnhChặn inbound, cho outboundCho tất cả (allow all)
Tham chiếu SG khácKhông
Stateless NACL — hay bị quên

Với NACL stateless, nếu bạn cho phép inbound TCP port 443, bạn cũng phải tạo outbound rule cho ephemeral ports (1024–65535) để response traffic đi được. Đây là lỗi phổ biến khi mới làm việc với NACL.

Ví dụ minh họa thực tế

Tình huống: Web server (public subnet) → App server (private subnet) → RDS (private subnet)

Security Group cho ALB (lớp ngoài cùng):

Inbound:
- Port 443 từ 0.0.0.0/0 (HTTPS từ Internet)
- Port 80 từ 0.0.0.0/0 (HTTP, redirect sang HTTPS)
Outbound:
- Port 8080 đến SG-app-tier (gọi vào app server)

Security Group cho EC2 App (private subnet):

Inbound:
- Port 8080 từ SG-alb (chỉ nhận từ ALB)
Outbound:
- Port 5432 đến SG-rds (kết nối PostgreSQL)
- Port 443 đến 0.0.0.0/0 (gọi API bên ngoài qua NAT)

Security Group cho RDS (private subnet):

Inbound:
- Port 5432 từ SG-app-tier (chỉ nhận từ app)
Outbound:
- (thường không cần)

Lưu ý: SG tham chiếu lẫn nhau (SG-alb, SG-app-tier, SG-rds) thay vì dùng IP range — khi scale hoặc thay đổi IP, không cần cập nhật rule.


4. Kiến trúc mẫu

Mô hình 3-tier production

Internet


┌─────────────────────────────────────────────────┐
│ Internet Gateway │
└─────────────────────────────────────────────────┘


┌─────────────────────────────────────────────────┐
│ PUBLIC SUBNET (us-east-1a / us-east-1b) │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ ALB │ │ NAT Gateway │ │
│ │ (HTTPS 443) │ │ (Elastic IP) │ │
│ └──────┬───────┘ └──────────────┘ │
│ │ ▲ │
└─────────│──────────────────│─────────────────────┘
│ inbound │ outbound
▼ │
┌─────────────────────────────────────────────────┐
│ PRIVATE SUBNET - App Tier │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ EC2 (AZ-a) │ │ EC2 (AZ-b) │ │
│ │ [SG-app] │ │ [SG-app] │ │
│ └──────┬───────┘ └──────┬───────┘ │
│ │ │ │
└─────────│──────────────────│─────────────────────┘
│ DB query │
▼ ▼
┌─────────────────────────────────────────────────┐
│ PRIVATE SUBNET - Data Tier │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ RDS Multi-AZ (Primary + Standby) │ │
│ │ [SG-rds, chỉ nhận từ SG-app] │ │
│ └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘

Sơ đồ Mermaid

Giải thích traffic flow

Inbound (user → app):

  1. User gửi HTTPS request → Internet Gateway
  2. ALB nhận request, terminate TLS, forward đến EC2 (port 8080)
  3. SG-alb cho phép inbound 443. SG-app cho phép inbound 8080 từ SG-alb
  4. EC2 xử lý → query RDS. SG-rds chỉ nhận từ SG-app

Outbound (app → Internet):

  1. EC2 cần gọi API ngoài (ví dụ: Stripe, SendGrid)
  2. Traffic đi qua route table → NAT Gateway (public subnet)
  3. NAT Gateway dịch source IP sang Elastic IP → ra IGW → Internet
  4. Response về theo đúng connection — EC2 không cần public IP

5. Best practices

Defense in depth (bảo mật nhiều lớp)

Không phụ thuộc vào một lớp duy nhất. Kết hợp:

  • NACL: Chặn IP xấu đã biết ở cấp subnet
  • Security Group: Kiểm soát chặt port và source ở cấp instance
  • WAF: Lọc HTTP request độc hại tại ALB/CloudFront
  • AWS Shield: Bảo vệ DDoS ở edge

Không expose resource private ra Internet

  • EC2 production không có Public IP — chỉ qua ALB
  • RDS không có public access — chỉ nhận từ app tier SG
  • Truy cập admin (SSH): dùng AWS Systems Manager Session Manager thay vì Bastion host (không cần mở port 22)
Thay Bastion bằng SSM Session Manager

SSM Session Manager cho phép SSH/shell vào EC2 private qua AWS console hoặc CLI, không cần public IP, không cần mở port 22. Log đầy đủ trong CloudTrail và SSM Session History.

Giảm chi phí NAT

  • Dùng VPC Endpoint Gateway cho S3 và DynamoDB — miễn phí, traffic không qua NAT
  • Dùng VPC Endpoint Interface cho ECR, Secrets Manager, SSM — giảm data transfer qua NAT
  • Đặt NAT Gateway cùng AZ với resource sử dụng — tránh cross-AZ data transfer fee
  • Monitor BytesOutToDestination metric của NAT Gateway để phát hiện traffic bất thường

Logging & monitoring

Bật VPC Flow Logs — đây là công cụ debug network số một trong VPC:

# Terraform — bật Flow Logs ghi vào CloudWatch
resource "aws_flow_log" "vpc_flow_log" {
iam_role_arn = aws_iam_role.flow_log.arn
log_destination = aws_cloudwatch_log_group.flow_log.arn
traffic_type = "ALL"
vpc_id = aws_vpc.main.id
}

Flow Logs ghi lại: source IP, dest IP, port, protocol, bytes, action (ACCEPT/REJECT). Dùng để:

  • Debug tại sao connection bị reject
  • Phát hiện port scan hoặc traffic bất thường
  • Audit trail khi có incident

Tài liệu liên quan