Skip to content

Nền Tảng Firewall Rules — Stateful Inspection, Priority và Connection Tracking

Firewall GCP Không Phải Là Thiết Bị Vật Lý

Điều đầu tiên cần hiểu về GCP firewall: không có firewall appliance. Firewall rules được enforce tại Andromeda agent chạy trên mỗi hypervisor — distributed, per-VM, không có central enforcement point.

Điều này có ý nghĩa quan trọng:

  • Traffic giữa 2 VMs trong cùng subnet vẫn phải qua firewall (không bypass)
  • Không có "firewall bypass" bằng cách đặt VMs trong cùng network segment
  • Performance của firewall không bị limited bởi một thiết bị trung tâm
  • Mỗi VM có firewall state riêng (connection tracking table per VM)

Tài liệu GCP xác nhận: "Connections are allowed or denied on a per-instance basis" và "traffic can only be controlled and logged as it leaves or arrives at a VM."

Internal Model: Stateful Connection Tracking

GCP firewall là stateful — điều này không chỉ là một tính năng, nó thay đổi cách bạn phải nghĩ về rules.

Cơ Chế 5-Tuple Tracking

Mỗi connection được track bằng 5-tuple:

  1. Source IP
  2. Destination IP
  3. Source Port
  4. Destination Port
  5. Protocol (TCP, UDP, ICMP...)

Khi một connection được cho phép bởi firewall rule, GCP lưu 5-tuple này vào connection tracking table. Return traffic matching connection này được tự động cho phép mà không cần rule riêng.

Flow 1: Client (203.0.113.5:54321) → Web Server (10.0.0.5:443)
  Firewall check: Có ingress rule allow tcp:443 từ 0.0.0.0/0? → YES
  Action: ALLOW
  Connection tracking entry: (203.0.113.5:54321 ↔ 10.0.0.5:443, TCP, ESTABLISHED)

Flow 2 (return): Web Server (10.0.0.5:443) → Client (203.0.113.5:54321)
  Firewall check: Connection trong tracking table? → YES
  Action: ALLOW (không cần egress rule cho return traffic)

Hệ quả thiết kế: Với ingress-focused rules (allow traffic vào), không cần egress rules cho return traffic. Ngược lại, với egress-focused rules (allow traffic ra), không cần ingress rules cho return traffic.

Connection Tracking Timeout

Connection tracking entry không tồn tại mãi mãi. Nếu "at least one packet is sent every 10 minutes," connection được coi là active. Sau 10 phút không có packet, connection bị expire và entry bị xóa.

Điều này có hệ quả cho long-lived, low-traffic connections (ví dụ: database connections với long idle periods):

Kịch bản: Application giữ database connection idle trong 15 phút
  → Connection tracking entry expire sau 10 phút idle
  → Application gửi query lần tiếp theo
  → Server nhận packet với existing connection state
  → Firewall không có tracking entry → packet bị drop (hoặc RST)
  → Application thấy "Connection reset" hoặc timeout

Giải pháp: TCP keepalive trong ứng dụng hoặc database driver, hoặc application-level heartbeats. Không phải lỗi của firewall — đây là expected behavior của stateful tracking với timeout.

Connection Tracking Table: Giới Hạn Tuyệt Đối

Đây là một trong những giới hạn kỹ thuật quan trọng nhất:

Machine typeMax tracked connections
Shared-core (f1-micro, g1-small, e2-micro, ...)130,000 total
1-8 vCPU130,000 per vCPU
8+ vCPU1,040,000 total

Ví dụ: VM với 4 vCPUs có thể track tối đa 520,000 connections đồng thời.

Khi limit bị vượt qua:

"When limits are exceeded, tracking is stopped for the connections that have the longest idle interval."

Những connections idle nhất bị evict khỏi tracking table. Packet tiếp theo của connection đó sẽ bị firewall treat như new connection — nếu không có rule allow cho new connections, nó bị drop.

Server với 4 vCPUs, max 520K connections:
  Connections hiện tại: 519,000 (98% capacity)
  
Tình huống 1: 1,000 connections mới đến
  → 520,000 limit hit
  → Oldest idle connections bị evict
  → Nếu evicted connection gửi packet: drop hoặc RST
  
Tình huống 2: Connection storm (DDoS, botnet)
  → Tracking table overflow
  → Legitimate connections bị evict
  → Service disruption

Production implication: Workloads với connection-intensive patterns (gaming servers, real-time messaging, websockets với hàng nghìn clients) cần:

  • Scale horizontally (nhiều VMs thay vì một VM lớn) để distribute connection tracking
  • Monitor connections metric
  • Xem xét connection pooling để giảm tổng số connections

Implied Rules: Luôn Tồn Tại, Không Thể Xóa

Hai implied rules luôn tồn tại ở cuối mọi VPC firewall:

Implied Rule 1 (INGRESS DENY):
  Direction: INGRESS
  Priority: 65534 (evaluated cuối cùng, trước priority 65535)
  Action: DENY ALL
  
Implied Rule 2 (EGRESS ALLOW):
  Direction: EGRESS
  Priority: 65534
  Action: ALLOW ALL

Bạn không thể xóa chúng, nhưng có thể override bằng rules có priority thấp hơn:

bash
# Override implied ingress deny với custom deny ở priority cao hơn
gcloud compute firewall-rules create explicit-deny-ingress \
  --direction=INGRESS \
  --priority=65000 \
  --action=DENY \
  --rules=all

# Override implied egress allow với explicit block
gcloud compute firewall-rules create block-all-egress \
  --direction=EGRESS \
  --priority=65000 \
  --action=DENY \
  --destination-ranges=0.0.0.0/0 \
  --rules=all

Bất Đối Xứng Quan Trọng

Ingress: mặc định DENY (bạn phải explicitly ALLOW những gì muốn vào)
Egress:  mặc định ALLOW (bạn phải explicitly DENY những gì muốn block ra)

Đây là nguồn gốc của nhiều security misconfigurations:

  • Nhiều team chỉ configure ingress rules, quên egress → VM bị compromise có thể exfiltrate data ra ngoài thoải mái
  • Khi implement "zero-trust", phải explicitly deny egress với rules có priority cao, rồi allow specific destinations

Hệ Thống Priority 0-65535

Quy tắc cốt lõi: Số nhỏ hơn = ưu tiên cao hơn. Rule với số nhỏ nhất matching traffic sẽ được apply, tất cả rules khác bị bỏ qua.

Rules trong VPC:

Priority  Direction  Sources       Targets         Protocol  Action
100       INGRESS    10.0.0.0/8    tag:internal    TCP:ALL   ALLOW
500       INGRESS    0.0.0.0/0     tag:web         TCP:443   ALLOW
1000      INGRESS    0.0.0.0/0     tag:web         TCP:80    ALLOW
65000     INGRESS    0.0.0.0/0     ALL             ALL       DENY
65534     INGRESS    [implied]     [implied]       ALL       DENY

Packet: TCP:443 từ 203.0.113.5 → VM với tag:web
  Check priority 100: Sources match 203.0.113.5? 10.0.0.0/8 → NO
  Check priority 500: Sources match? 0.0.0.0/0 → YES. Target match? tag:web → YES
  → ALLOW (stop evaluating)
  Rule priority 1000, 65000, 65534 không được check

Khi Cùng Priority: Behavior Không Xác Định

Rule A: Priority 1000, ALLOW tcp:80 từ 10.0.0.0/8
Rule B: Priority 1000, DENY tcp:80 từ 10.0.0.5/32

Packet: TCP:80 từ 10.0.0.5 (match cả 2 rules)

GCP documentation không guarantee behavior khi nhiều rules cùng priority match cùng traffic. Trong thực tế, Google sử dụng internal algorithm — nhưng outcome là non-deterministic từ góc nhìn người dùng.

Thực hành bắt buộc: Đừng bao giờ để hai rules cùng priority có thể match cùng traffic với actions khác nhau. Sử dụng unique priorities hoặc design rules để chúng không bao giờ conflict.

Targeting: Network Tags vs Service Accounts

Firewall rules cần biết rules này áp dụng cho VMs nào. GCP cung cấp hai cơ chế:

Network Tags

Network tags là string labels gắn vào VM. Bất kỳ ai có quyền edit VM đều có thể thêm/xóa tags.

bash
# Thêm tag vào VM
gcloud compute instances add-tags my-vm \
  --tags=web-server,public-facing

# Firewall rule target theo tag
gcloud compute firewall-rules create allow-https \
  --direction=INGRESS \
  --action=ALLOW \
  --source-ranges=0.0.0.0/0 \
  --target-tags=web-server \
  --rules=tcp:443

Đặc điểm:

  • Tags là arbitrary strings, không có validation
  • Nhiều tags per VM (không giới hạn)
  • Có thể thêm/xóa tags mà không cần restart VM
  • Tags có thể tùy chỉnh tên theo convention của team

Security weakness của tags: Ai có compute.instances.setTags permission có thể thêm bất kỳ tag nào vào VM. Nếu user thêm tag web-server vào một VM không phải web server, VM đó nhận được tất cả firewall rules cho web servers — có thể tạo unintended access.

Service Accounts

Service accounts là identities của VM — được gắn khi create hoặc khi update (cần restart).

bash
# Firewall rule target theo service account
gcloud compute firewall-rules create allow-backend-to-db \
  --direction=INGRESS \
  --action=ALLOW \
  --source-service-accounts=backend-sa@project.iam.gserviceaccount.com \
  --target-service-accounts=database-sa@project.iam.gserviceaccount.com \
  --rules=tcp:5432

Đặc điểm:

  • Tối đa 1 service account per VM
  • Thay đổi SA cần restart VM (strong guarantee)
  • Quản lý bởi IAM — ai có iam.serviceAccounts.actAs mới gán được
  • SA không thể bị thêm tùy tiện như tags

Security của service accounts: IAM bảo vệ việc gán SA, khó bị misuse hơn tags. Tuy nhiên, sử dụng SA làm firewall target có trade-off: khó debug hơn (phải trace từ VM → SA → firewall rules), và restart requirement khi thay đổi.

Không Thể Kết Hợp Tags và Service Accounts Trong Cùng Rule

bash
# LỖI: không thể dùng cả hai trong cùng rule
gcloud compute firewall-rules create bad-rule \
  --target-tags=web-server \
  --source-service-accounts=backend-sa@project.iam.gserviceaccount.com
# Error: Cannot specify both targetTags and sourceServiceAccounts

Đây là hard constraint của GCP firewall engine — phải chọn một cơ chế targeting per rule.

Ma Trận Quyết Định

Tiêu chíNetwork TagsService Accounts
FlexibilityCao (thêm/xóa runtime)Thấp (cần restart)
SecurityThấp (dễ misuse)Cao (IAM-protected)
Debug dễDễ (visible trong VM properties)Khó hơn
ScaleTốt (nhiều tags per VM)Khó scale (1 SA per VM)
AuditKhó (tags changes ít audit trail)Tốt (IAM logs)

Recommendation: Dùng service accounts cho critical security boundaries (prod → prod-db access). Dùng network tags cho less-sensitive grouping (load-balancer-frontend, monitoring-agent).

Source và Destination: Các Tùy Chọn Matching

Cho Ingress Rules

Source criteria (ai được phép vào):

  • sourceRanges: IP CIDRs (0.0.0.0/0, 10.0.0.0/8, ...)
  • sourceTags: VMs với tag này làm source
  • sourceServiceAccounts: VMs với SA này làm source

Target criteria (rules áp dụng cho VMs nào):

  • Không specify → áp dụng cho tất cả VMs trong VPC
  • targetTags: VMs có tags này
  • targetServiceAccounts: VMs có SA này

Cho Egress Rules

Destination criteria:

  • destinationRanges: IP CIDRs

Target criteria (VMs nào bị rule này govern):

  • Không specify → tất cả VMs
  • targetTags
  • targetServiceAccounts

Combining Sources Trong Một Rule

yaml
# Rule với multiple sources (OR logic)
sourceRanges:
  - 10.0.0.0/8      # OR
  - 192.168.0.0/16

# Rule với sourceTags (OR logic)
sourceTags:
  - frontend-app    # OR
  - api-gateway

# Nhưng không thể kết hợp sourceRanges VÀ sourceTags:
# sourceRanges và sourceTags trong cùng rule là NOT ALLOWED
# (phải chọn một loại source)

Firewall Logging: Visibility Và Cost

Firewall logging cho phép log mỗi connection được allow hoặc deny:

bash
gcloud compute firewall-rules update allow-https \
  --enable-logging \
  --logging-metadata=INCLUDE_ALL_METADATA

Log entries trong Cloud Logging:

json
{
  "jsonPayload": {
    "connection": {
      "src_ip": "203.0.113.5",
      "dest_ip": "10.0.0.5",
      "src_port": 54321,
      "dest_port": 443,
      "protocol": 6
    },
    "disposition": "ALLOWED",
    "rule_details": {
      "reference": "allow-https",
      "priority": 500
    }
  }
}

Cost consideration: Firewall log entries được tính phí như Cloud Logging ingestion. Với VMs có traffic cao (web servers, proxies), logging ALL connections có thể generate GBs của logs per day → significant cost.

Selective logging: Chỉ enable logging cho security-sensitive rules (access đến databases, admin ports), không phải tất cả rules.

Failure Modes Quan Trọng Ở Scale

Failure 1: Firewall Rule Drift

Trong môi trường large-scale, rule drift xảy ra khi các rules được thêm ad-hoc theo thời gian mà không có cleanup:

Sau 2 năm:
  - 500+ firewall rules trong một VPC
  - Nhiều rules có priority 1000 (tất cả mọi người dùng default priority)
  - Rules conflict với nhau một cách không rõ ràng
  - Không ai biết rule nào đang thực sự apply hay không apply
  - "Delete một rule?" → Không ai dám vì sợ break production

Giải pháp: Hierarchical firewall policies với lifecycle management, regular audit bằng Firewall Insights (trong Network Intelligence Center).

Failure 2: Tag-based Security Bypass

Bạn có rule: allow tcp:5432 từ tag:backend đến tag:database

Sự cố: Developer tạo test VM và thêm tag "backend" để test query
→ Test VM không phải là legitimate backend
→ Nhưng nó có access vào database server
→ Nếu test VM bị compromise: attacker có access vào database

Đây là fundamental weakness của tag-based firewall trong môi trường có nhiều người dùng. Giải pháp: dùng service accounts cho high-security boundaries, IAM control ai có thể gán tag.

Failure 3: Connection Tracking Table Exhaustion Under Load

Đã đề cập ở trên nhưng cần nhấn mạnh: connection tracking exhaustion không có warning — suddenly connections start failing và không có error message rõ ràng.

Monitor metric compute.googleapis.com/firewall/dropped_packets_countcompute.googleapis.com/instance/connections để detect sớm.

References