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ớp | Tên | Áp dụng tại | Mặc định |
|---|---|---|---|
| Lớp 1 | Security Group (SG) | Instance (ENI) | Cho phép outbound, chặn inbound |
| Lớp 2 | Network ACL (NACL) | Subnet | Cho 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 Gateway | NAT Instance |
|---|---|---|
| Quản lý | Managed (AWS) | Self-managed |
| HA | Tự động trong AZ | Phải tự dựng |
| Throughput | Tự động scale, tối đa 100 Gbps | Giới hạn theo instance type |
| Performance | Cao, ổn định | Phụ thuộc instance |
| Chi phí cố định | ~$32/tháng/AZ | Theo instance (có thể dùng Spot) |
| Chi phí data | Tính phí | Tính phí (như EC2 transfer) |
| Security group | Không áp dụng | Có thể gắn SG |
| Port forwarding | Không hỗ trợ | Hỗ trợ |
| Bastion host | Khô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
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 Group | Network ACL |
|---|---|---|
| Cấp độ | Instance (ENI) | Subnet |
| Trạng thái | Stateful | Stateless |
| Rule Deny | Không | Có |
| Thứ tự rule | Không (tất cả được đánh giá) | Có (đánh số, dừng khi match) |
| Phạm vi áp dụng | Chỉ instance được gắn | Toàn bộ subnet |
| Mặc định | Chặn inbound, cho outbound | Cho tất cả (allow all) |
| Tham chiếu SG khác | Có | Không |
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):
- User gửi HTTPS request → Internet Gateway
- ALB nhận request, terminate TLS, forward đến EC2 (port 8080)
- SG-alb cho phép inbound 443. SG-app cho phép inbound 8080 từ SG-alb
- EC2 xử lý → query RDS. SG-rds chỉ nhận từ SG-app
Outbound (app → Internet):
- EC2 cần gọi API ngoài (ví dụ: Stripe, SendGrid)
- Traffic đi qua route table → NAT Gateway (public subnet)
- NAT Gateway dịch source IP sang Elastic IP → ra IGW → Internet
- 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)
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
BytesOutToDestinationmetric 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