Cloud Network Exposure Runbook: Kiểm Soát Public IP Và Firewall Rule Trên Production

Trong môi trường cloud, câu hỏi không phải là “có ai đó vô tình mở public không?”, mà là “mất bao lâu để phát hiện và đóng lại?”. Một security group mở SSH/RDP ra Internet, bucket cho phép đọc công khai, database nhận kết nối từ mọi IP hoặc load balancer trỏ nhầm service nội bộ đều có thể biến thành sự cố bảo mật thật sự.

Bài viết này là một runbook thực chiến cho Cloud Engineer, SysAdmin và DevOps muốn kiểm soát cloud network exposure trên AWS, Azure hoặc GCP. Mục tiêu là xây dựng quy trình kiểm tra bề mặt tấn công, phân loại rủi ro, khóa truy cập đúng cách, kiểm thử không làm gãy dịch vụ và đưa việc rà soát exposure thành thói quen vận hành.

Cloud network exposure là gì?

Cloud network exposure là mức độ tài nguyên cloud có thể bị truy cập từ bên ngoài hoặc từ vùng mạng không mong muốn. Exposure không đồng nghĩa luôn luôn là lỗi. Website public cần mở HTTP/HTTPS. VPN gateway cần mở cổng VPN. Nhưng SSH tới toàn Internet, admin panel nằm sau load balancer public, database lộ port 5432/3306 hoặc storage endpoint public thường là dấu hiệu cần xử lý ngay.

Các dạng exposure thường gặp

  • Public IP gắn trực tiếp vào VM: instance có địa chỉ public và security rule cho phép inbound.
  • Security group/NSG/firewall rule quá rộng: ví dụ 0.0.0.0/0 hoặc ::/0 cho SSH, RDP, database.
  • Load balancer public trỏ nhầm service nội bộ: dashboard, admin API, staging app.
  • Object storage public: bucket/container cho phép anonymous read hoặc list.
  • Managed database public: PostgreSQL/MySQL/Redis/Elasticsearch có endpoint public và allowlist rộng.
  • Kubernetes ingress public không kiểm soát: ingress class public cho service nội bộ.

Bối cảnh production/lab

Giả sử bạn quản lý một hệ thống thương mại điện tử nhỏ gồm:

  • VPC/VNet có subnet public cho load balancer.
  • Subnet private cho application VM hoặc Kubernetes worker.
  • Managed PostgreSQL dùng cho database chính.
  • Object storage chứa ảnh sản phẩm và file backup.
  • Một bastion hoặc VPN dùng cho truy cập quản trị.

Yêu cầu vận hành là: khách hàng chỉ được truy cập HTTPS qua load balancer; kỹ sư chỉ truy cập SSH qua VPN/bastion; database không public; bucket backup không public; mọi thay đổi rule phải có lý do và có thể audit.

Nguyên tắc thiết kế: public ít nhất có thể

Trước khi chạy lệnh, hãy thống nhất nguyên tắc:

  • Default deny: không mở inbound nếu không có nhu cầu rõ ràng.
  • Public endpoint phải có chủ sở hữu: biết service nào, ai chịu trách nhiệm, SLA ra sao.
  • Không quản trị trực tiếp từ Internet: SSH/RDP/admin panel nên đi qua VPN, bastion, Zero Trust hoặc SSM/IAP.
  • Allowlist có thời hạn: nếu cần mở tạm IP vendor, đặt ticket và ngày hết hạn.
  • Log trước, chặn sau có kiểm thử: tránh khóa nhầm traffic production.

Bước 1: Lập danh sách tài nguyên có public endpoint

AWS: liệt kê EC2 có Public IP

aws ec2 describe-instances \
  --query 'Reservations[].Instances[?PublicIpAddress!=`null`].[InstanceId,PublicIpAddress,State.Name,Tags[?Key==`Name`].Value|[0]]' \
  --output table

Lệnh này trả về danh sách instance đang có public IP. Output mẫu:

-------------------------------------------------------
|                  DescribeInstances                  |
+----------------------+---------------+---------+----+
|  i-0123456789abcdef0 |  18.140.10.20 | running | web-01 |
|  i-0abcdef1234567890 |  54.251.8.11  | running | bastion |
+----------------------+---------------+---------+----+

Nếu thấy VM ứng dụng hoặc database self-hosted có public IP, đó là mục cần kiểm tra kỹ. Không phải public IP nào cũng sai, nhưng phải có lý do.

Azure: liệt kê Public IP Address

az network public-ip list \
  --query '[].{name:name, resourceGroup:resourceGroup, ip:ipAddress, allocation:publicIPAllocationMethod}' \
  -o table

Tiếp theo, kiểm tra public IP đang gắn vào NIC, load balancer hay application gateway nào:

az network public-ip show \
  -g rg-prod \
  -n pip-web-prod \
  --query '{ip:ipAddress, attachedTo:ipConfiguration.id}'

GCP: liệt kê external IP

gcloud compute instances list \
  --format='table(name,zone,status,networkInterfaces[0].accessConfigs[0].natIP)'

Nếu cột NAT IP có giá trị, instance đang có external IP. Với production chuẩn, thường chỉ bastion, NAT gateway hoặc load balancer được public.

Bước 2: Tìm rule mở rộng ra Internet

AWS Security Group mở 0.0.0.0/0

aws ec2 describe-security-groups \
  --query 'SecurityGroups[?IpPermissions[?IpRanges[?CidrIp==`0.0.0.0/0`]]].[GroupId,GroupName,IpPermissions]' \
  --output json

Hãy tập trung vào các port rủi ro cao:

  • 22: SSH
  • 3389: RDP
  • 3306: MySQL/MariaDB
  • 5432: PostgreSQL
  • 6379: Redis
  • 9200: Elasticsearch/OpenSearch
  • 8080/8081/9000: admin/debug dashboard

Azure NSG rule có Source Any

az network nsg rule list \
  --resource-group rg-prod \
  --nsg-name nsg-app-prod \
  --query '[?access==`Allow` && direction==`Inbound`].{name:name,priority:priority,source:sourceAddressPrefix,port:destinationPortRange,protocol:protocol}' \
  -o table

Nếu source*, Internet hoặc 0.0.0.0/0, rule đó cần được giải thích. Rule HTTPS public có thể hợp lệ; rule SSH/RDP/database thì thường không.

GCP firewall rule cho 0.0.0.0/0

gcloud compute firewall-rules list \
  --filter='direction=INGRESS AND sourceRanges:0.0.0.0/0' \
  --format='table(name,network,allowed[].map().firewall_rule().list(),targetTags,disabled)'

GCP thường dùng network tag hoặc service account làm target. Nếu rule public áp vào tag quá rộng như web hoặc áp toàn mạng, hãy xem lại phạm vi ảnh hưởng.

Bước 3: Phân loại rủi ro trước khi đóng

Không nên đóng rule theo cảm tính. Hãy phân loại:

Mức Critical

  • Database public với source 0.0.0.0/0.
  • Redis/Elasticsearch public không có auth mạnh.
  • SSH/RDP public trên nhiều VM production.
  • Bucket backup public.

Hành động: cô lập ngay nếu có thể, snapshot/log lại bằng chứng, thông báo owner, kiểm tra dấu hiệu truy cập bất thường.

Mức High

  • Admin dashboard public nhưng có login.
  • Staging app public chứa dữ liệu gần production.
  • Security group cho phép dải IP quá rộng từ vendor.

Hành động: đưa sau VPN/SSO/WAF, giới hạn IP, thêm MFA, đặt deadline remediation.

Mức Medium/Low

  • HTTP public redirect sang HTTPS.
  • Port health check public nhưng không lộ dữ liệu.
  • Endpoint demo không chứa thông tin nhạy cảm.

Hành động: chuẩn hóa rule, document owner, kiểm tra định kỳ.

Bước 4: Đóng SSH/RDP public bằng mô hình quản trị an toàn

Phương án 1: VPN hoặc Zero Trust

Chỉ cho phép SSH/RDP từ subnet VPN hoặc connector Zero Trust. Ví dụ AWS security group:

aws ec2 revoke-security-group-ingress \
  --group-id sg-0123456789abcdef0 \
  --protocol tcp \
  --port 22 \
  --cidr 0.0.0.0/0

aws ec2 authorize-security-group-ingress \
  --group-id sg-0123456789abcdef0 \
  --protocol tcp \
  --port 22 \
  --cidr 10.20.0.0/16

Dòng đầu xóa rule SSH public. Dòng thứ hai chỉ cho phép SSH từ mạng VPN nội bộ 10.20.0.0/16. Trước khi chạy trên production, hãy chắc chắn VPN hoạt động và có session dự phòng.

Phương án 2: AWS Systems Manager Session Manager

Nếu dùng AWS, Session Manager giúp truy cập shell mà không cần mở port 22:

aws ssm start-session --target i-0123456789abcdef0

Điều kiện: instance có SSM Agent, IAM role phù hợp và route ra SSM endpoint. Đây là cách tốt để giảm bề mặt tấn công vì không cần public IP cho quản trị.

Phương án 3: GCP IAP TCP forwarding

gcloud compute ssh app-01 \
  --zone asia-southeast1-b \
  --tunnel-through-iap

IAP cho phép kiểm soát truy cập qua IAM và audit log, thay vì mở SSH ra Internet.

Bước 5: Khóa database public

Managed database nên nằm private hoặc chỉ nhận kết nối từ application subnet/security group. Với AWS RDS, kiểm tra thuộc tính public:

aws rds describe-db-instances \
  --query 'DBInstances[].{id:DBInstanceIdentifier,public:PubliclyAccessible,endpoint:Endpoint.Address,vpc:DBSubnetGroup.VpcId}' \
  --output table

Nếu PubliclyAccessibleTrue, hãy đánh giá lại. Để tắt public access:

aws rds modify-db-instance \
  --db-instance-identifier prod-postgres \
  --no-publicly-accessible \
  --apply-immediately

Lưu ý: thay đổi network có thể gây gián đoạn kết nối nếu application đang đi qua public endpoint. Trước khi áp dụng, kiểm tra route, DNS, security group và thử kết nối từ private subnet.

Bước 6: Kiểm tra object storage public

AWS S3 public access

aws s3api get-public-access-block --bucket my-prod-backup-bucket

Output an toàn thường giống:

{
  "PublicAccessBlockConfiguration": {
    "BlockPublicAcls": true,
    "IgnorePublicAcls": true,
    "BlockPublicPolicy": true,
    "RestrictPublicBuckets": true
  }
}

Để bật chặn public access:

aws s3api put-public-access-block \
  --bucket my-prod-backup-bucket \
  --public-access-block-configuration \
  BlockPublicAcls=true,IgnorePublicAcls=true,BlockPublicPolicy=true,RestrictPublicBuckets=true

Với bucket chứa asset public như ảnh website, có thể cần public read hoặc CDN origin policy. Nhưng bucket backup, log, export database tuyệt đối không nên public.

Bước 7: Xác minh từ bên ngoài

Sau khi chỉnh rule, đừng chỉ tin console. Hãy kiểm tra từ một máy ngoài cloud hoặc dùng scanner có kiểm soát.

nmap -Pn -p 22,80,443,3306,5432 203.0.113.10

Output mong muốn cho application public:

PORT     STATE    SERVICE
22/tcp   filtered ssh
80/tcp   open     http
443/tcp  open     https
3306/tcp filtered mysql
5432/tcp filtered postgresql

filtered nghĩa là firewall đang chặn hoặc không phản hồi. Với web server public, 80/443 mở là bình thường; các cổng quản trị/database nên đóng.

Bước 8: Bật giám sát và cảnh báo exposure

Kiểm tra thủ công chỉ giải quyết một thời điểm. Production cần cảnh báo tự động.

AWS

  • AWS Config managed rule: INCOMING_SSH_DISABLED, RDS_INSTANCE_PUBLIC_ACCESS_CHECK, S3_BUCKET_PUBLIC_READ_PROHIBITED.
  • Security Hub để gom findings theo chuẩn CIS/AWS Foundational Security Best Practices.
  • VPC Flow Logs để xem traffic thực tế.
  • CloudTrail để biết ai tạo hoặc sửa rule.

Azure

  • Microsoft Defender for Cloud recommendations.
  • Azure Policy chặn NSG inbound từ Internet tới SSH/RDP.
  • Activity Log alert khi có thay đổi NSG/public IP.

GCP

  • Security Command Center findings.
  • Organization Policy để hạn chế external IP.
  • Firewall Rules Logging và Cloud Audit Logs.

Policy-as-code: chặn lỗi từ lúc review

Nếu dùng Terraform, hãy kiểm tra rule trước khi merge. Ví dụ rule nguy hiểm:

resource "aws_security_group_rule" "bad_ssh" {
  type              = "ingress"
  from_port         = 22
  to_port           = 22
  protocol          = "tcp"
  cidr_blocks       = ["0.0.0.0/0"]
  security_group_id = aws_security_group.app.id
}

Có thể dùng Checkov:

checkov -d infrastructure/terraform

Output mẫu:

FAILED CKV_AWS_24: Ensure no security groups allow ingress from 0.0.0.0:0 to port 22
File: /security-group.tf:12-20

Điểm quan trọng là biến kiểm tra exposure thành bước bắt buộc trong CI/CD, không chờ đến lúc audit mới phát hiện.

Lỗi thường gặp khi xử lý exposure

Đóng rule nhưng quên health check

Load balancer có thể dùng health check từ dải IP riêng của cloud provider. Nếu khóa quá chặt, target bị đánh dấu unhealthy. Hãy đọc tài liệu dải IP health check và test trước khi áp dụng.

Chặn SSH trước khi có đường quản trị thay thế

Đây là lỗi kinh điển. Trước khi xóa SSH public, hãy xác minh VPN/SSM/IAP/bastion hoạt động, có ít nhất hai admin truy cập được và có break-glass process.

Nhầm giữa public IP và public access

Một VM có public IP nhưng firewall đóng vẫn có bề mặt thấp hơn VM mở port. Ngược lại, một database private nhưng security group cho phép từ subnet quá rộng vẫn có rủi ro nội bộ. Hãy đánh giá cả endpoint, route và rule.

Không kiểm tra IPv6

Nhiều hệ thống khóa 0.0.0.0/0 nhưng quên ::/0. Nếu cloud đã bật IPv6, hãy rà soát cả rule IPv6.

Troubleshooting khi dịch vụ bị ảnh hưởng

  • Ứng dụng mất kết nối database: kiểm tra security group/NSG của database có cho phép source là app subnet hoặc app security group không.
  • Load balancer báo unhealthy: kiểm tra health check path, port, source range và target firewall.
  • Admin không SSH được: thử qua VPN/bastion/SSM/IAP; kiểm tra route table và DNS nội bộ.
  • CDN không lấy được origin: nếu origin đã khóa IP, cần allowlist dải IP CDN hoặc dùng origin access identity/control.
  • Scanner vẫn thấy port open: xác nhận đang scan đúng IP, rule đã apply vào đúng security group/NIC/subnet, và không có firewall rule khác priority cao hơn.

Checklist nghiệm thu

  • Đã có danh sách public IP, load balancer, public database endpoint và bucket public.
  • Không còn SSH/RDP public rộng 0.0.0.0/0 hoặc ::/0 trên production.
  • Database production không public hoặc chỉ allowlist nguồn bắt buộc.
  • Bucket backup/log/export đã bật block public access.
  • Public endpoint hợp lệ có owner, purpose và ticket/documentation.
  • Đã kiểm tra ngoài mạng bằng nmap hoặc công cụ tương đương.
  • Đã bật audit log/cảnh báo khi security rule/public access thay đổi.
  • Đã thêm policy-as-code vào pipeline IaC.
  • Đã có break-glass process cho tình huống cần truy cập khẩn cấp.

Lab thực hành 45 phút

  1. Tạo một VM lab trong cloud provider bạn đang dùng.
  2. Mở tạm port 22 từ IP cá nhân, không mở 0.0.0.0/0.
  3. Chạy lệnh liệt kê public IP và firewall/security group.
  4. Dùng nmap từ máy cá nhân để xác minh chỉ port mong muốn mở.
  5. Chuyển truy cập quản trị sang VPN/SSM/IAP nếu có.
  6. Xóa rule SSH public và kiểm tra vẫn quản trị được qua kênh thay thế.
  7. Viết lại kết quả thành một runbook ngắn cho team.

Kết luận

Cloud giúp mở rộng hạ tầng rất nhanh, nhưng cũng khiến việc mở nhầm tài nguyên ra Internet xảy ra nhanh không kém. Một runbook cloud network exposure tốt cần kết hợp kiểm kê public endpoint, rà soát firewall rule, phân loại rủi ro, đóng quyền theo nguyên tắc least privilege, xác minh từ bên ngoài và cảnh báo tự động.

Nếu bạn chỉ làm một việc sau bài này, hãy tìm toàn bộ rule inbound từ 0.0.0.0/0::/0 trong tài khoản cloud production. Danh sách đó thường cho bạn biết rất nhiều về mức độ trưởng thành bảo mật hạ tầng hiện tại.

Tác giả: Mạnh Hoàng

Tôi là Hoàng Mạnh, người sáng lập blog SysadminSkills.com. Tôi viết về quản trị hệ thống, bảo mật máy chủ, DevOps và cách ứng dụng AI để tự động hóa công việc IT. Blog này là nơi tôi chia sẻ những gì đã học được từ thực tế – đơn giản, ngắn gọn và áp dụng được ngay.