Firewall Debugging: Rule Priority and Evaluation
Tại sao Firewall Debugging Quan Trọng
Firewall rules là rào cản đầu tiên (first barrier) mà các packet gặp phải ngay sau interface nguồn (chiều egress) hoặc trước interface đích (chiều ingress). Cấu hình sai ở đây sẽ chặn traffic hợp lệ hoặc cho phép traffic không mong muốn đi qua.
VPC firewall rules sử dụng đánh giá dựa trên độ ưu tiên (priority-based evaluation) từ 0-65535 (số nhỏ hơn = độ ưu tiên cao hơn), không phải theo thứ tự tuần tự (sequence-based) như các firewall truyền thống. Nếu không hiểu rõ mô hình này, việc debug firewall rules sẽ rất phức tạp và dễ gây nhầm lẫn.
Cơ chế bên trong: Priority-Based Evaluation
Cấu trúc Rule
Mỗi VPC firewall rule gồm các thành phần:
Rule {
name: "allow-http"
direction: INGRESS // hoặc EGRESS
priority: 1000 // 0-65535, số nhỏ hơn = độ ưu tiên cao hơn
action: ALLOW // hoặc DENY
match {
sourceRanges: ["10.0.0.0/8"] // nếu là INGRESS
destinationRanges: ["10.0.0.0/8"] // nếu là EGRESS
sourceTags: ["web-client"] // tag của source instance
targetTags: ["web-server"] // tag của destination instance
protocol: "tcp"
ports: [80, 443]
}
}Thuật toán Đánh giá (Evaluation Algorithm)
Khi packet truyền đến (ingress) hoặc gửi đi (egress), firewall sẽ áp dụng:
Bước 1: Tìm tất cả các rules khớp (match) về direction, protocol, ports, ranges, và tags.
Bước 2: Sắp xếp các rules khớp theo thứ tự ưu tiên (priority tăng dần, từ 0 trở lên).
Bước 3: Áp dụng rule khớp đầu tiên tìm được (chỉ áp dụng duy nhất rule đó, bỏ qua các rule còn lại).
Bước 4: Nếu không có rule nào khớp, áp dụng hành động default deny mặc định.
Ví dụ:
Packet: Ingress TCP tới port 443 từ 10.0.1.2 đến 10.1.1.2 (target tag: "web-server")
Rules hiện có:
Rule A: priority=100, action=DENY, sourceRanges=[10.0.0.0/8]
Rule B: priority=500, action=ALLOW, sourceRanges=[10.0.1.0/24]
Rule C: priority=1000, action=ALLOW, sourceRanges=[0.0.0.0/0]
Rule D: priority=2000, action=DENY, ports=[443]
Bước 1: Tìm các rule khớp
- Rule A: Khớp (sourceRange khớp, target tag khớp)
- Rule B: Khớp (sourceRange khớp, target tag khớp)
- Rule C: Khớp (sourceRange khớp, target tag khớp)
- Rule D: Không khớp (độ ưu tiên thấp hơn, khớp port nhưng không khớp các điều kiện khác)
Bước 2: Sắp xếp theo priority (ưu tiên từ cao xuống thấp)
1. Rule A (priority 100) ← ĐỘ ƯU TIÊN CAO NHẤT (SỐ NHỎ NHẤT)
2. Rule B (priority 500)
3. Rule C (priority 1000)
4. Rule D (priority 2000)
Bước 3: Áp dụng rule khớp đầu tiên
→ Rule A khai báo DENY
→ Traffic bị chặn
Kết quả: DENIED (bởi Rule A)Key insight: Không quan trọng việc Rule B chi tiết hơn (exact source range là 10.0.1.0/24) so với Rule A (10.0.0.0/8). Vì Rule A có priority cao hơn (số 100 nhỏ hơn 500), nên Rule A sẽ chiến thắng.
Quy tắc Tiebreaker: Deny Wins
Nếu hai rules có cùng priority (trong trường hợp hiếm hoi), hành động DENY sẽ chiến thắng:
Rule X: priority=1000, action=ALLOW
Rule Y: priority=1000, action=DENY
→ DENY được áp dụng (để đảm bảo an toàn)Trên thực tế, GCP không cho phép tạo các rule trùng priority trong cùng một VPC network, do đó trường hợp này hiếm khi xảy ra.
Các lỗi Firewall thường gặp khi Debug
Trường hợp 1: Luật Deny quá rộng (Overly Broad Deny Rule)
Kịch bản:
Rule 1: priority=100, action=DENY, sourceRanges=[0.0.0.0/0]
Rule 2: priority=500, action=ALLOW, sourceRanges=[10.0.0.0/8]Vấn đề: Rule 2 không bao giờ được kích hoạt, vì Rule 1 (deny all) có priority cao hơn (100 < 500).
Triệu chứng: Mọi traffic đều bị chặn, kể cả traffic từ các dải IP nội bộ.
Debug:
gcloud compute firewall-rules list --filter="priority<1000" --format=table
# Kiểm tra xem có rule DENY rộng nào có priority cao hay khôngCách sửa: Xóa Rule 1 (dựa vào cơ chế default deny mặc định), hoặc giảm độ ưu tiên của nó (tăng số priority):
gcloud compute firewall-rules update rule-1 --priority=9999Trường hợp 2: Thiếu luật Allow (Missing Allow Rule)
Kịch bản:
Không có rule allow rõ ràng cho kiểu traffic X
Mặc định: Deny allVấn đề: Traffic X bị chặn.
Triệu chứng: Connectivity Tests báo cấu hình OK, nhưng flow logs hiển thị action=DENY với rule_name="default-deny" (hoặc không tìm thấy rule khớp).
Debug:
# Kiểm tra các rule tồn tại cho kiểu traffic này
gcloud compute firewall-rules list \
--filter="direction=INGRESS AND allow-list:tcp:443"Cách sửa: Tạo rule allow với priority cao hơn các rule deny hiện tại (số priority nhỏ hơn):
gcloud compute firewall-rules create allow-https \
--direction=INGRESS \
--allow=tcp:443 \
--source-ranges=0.0.0.0/0 \
--target-tags=web-server \
--priority=100Trường hợp 3: Nhầm lẫn giữa Source Tags và Destination Tags
Kịch bản:
Rule: sourceRanges=[10.0.0.0/8], targetTags=["web-server"]Vấn đề: Rule này khớp với traffic đi TỚI các instance có tag "web-server" từ dải IP 10.0.x.x.
Nếu bạn muốn khớp với traffic đi từ các instance có tag "client", bạn phải sử dụng sourceTags thay vì sourceRanges.
Cách sửa:
gcloud compute firewall-rules create allow-from-clients \
--direction=INGRESS \
--allow=tcp:443 \
--source-tags=client # ← Cấu hình Source tags
--target-tags=web-server
--priority=100Trường hợp 4: Rule cụ thể hơn không ghi đè được Priority
Kịch bản:
Rule A: priority=100, action=DENY, protocol=all
Rule B: priority=500, action=ALLOW, protocol=tcp, ports=[443]Vấn đề: Rule B (cụ thể hơn) bị bỏ qua, vì Rule A có priority cao hơn (100 < 500).
Hiểu lầm phổ biến: "Quy tắc allow của tôi cụ thể hơn, nên nó phải được ưu tiên trước."
Thực tế: Priority luôn luôn chiến thắng, bất kể rule có cụ thể ra sao.
Cách sửa: Cấu hình Rule B có priority cao hơn (số nhỏ hơn):
gcloud compute firewall-rules update rule-b --priority=50 # Số nhỏ hơn = ưu tiên cao hơnSử dụng VPC Flow Logs để debug Firewall
VPC Flow Logs hiển thị chính xác rule nào đang được áp dụng:
{
"action": "DENY",
"rule_priority": 1000,
"rule_name": "deny-internal-ssh"
}Quy trình xử lý:
Bị chặn ở chiều Ingress (Ingress denied):
- Kiểm tra Flow Logs của subnet đích (có thể không thấy entry vì bị chặn ở chiều ingress).
- Kiểm tra Flow Logs của subnet nguồn, tìm entry có
action=DENY. - Lấy thông tin
rule_namevàrule_prioritytừ flow log. - Tìm kiếm rule tương ứng:
gcloud compute firewall-rules describe [rule_name]. - Xác minh xem traffic có khớp với sourceRanges, sourceTags, hay ports hay không.
- Nếu rule không chính xác, tiến hành cập nhật hoặc xóa bỏ.
Bị chặn ở chiều Egress (Egress denied):
- Kiểm tra Flow Logs của subnet nguồn, tìm entry có
action=DENYđi kèm egress rule. - Kiểm tra
rule_priority, tìm rule tương ứng. - Xác minh rule destinationRanges và targetTags xem có khớp không.
- Cập nhật rule nếu cần thiết.
- Kiểm tra Flow Logs của subnet nguồn, tìm entry có
Sử dụng Firewall Insights (Công cụ GCP)
GCP cung cấp công cụ Firewall Insights giúp phân tích các rule và đề xuất tối ưu hóa:
gcloud compute firewall-policies rules list \
--firewall-policy=defaultCông cụ có thể phát hiện:
- Các rule quá rộng (ví dụ: allow từ
0.0.0.0/0). - Các rule không được sử dụng (zero traffic).
- Các rule bị xung đột (conflicting rules).
Sử dụng: Nên thường xuyên kiểm tra cấu hình rule bằng Firewall Insights.
Thiết lập Priority: Hướng dẫn Best Practices
Khi tạo nhiều rule, hãy phân chia các dải priority rõ ràng:
Deny all mặc định: 65534 (do hệ thống tạo)
Deny quan trọng (Critical): 1000-2000
Allow cho các service cụ thể: 100-500
Các trường hợp khác: 500-1000Ví dụ:
# Quan trọng: Chỉ cho phép SSH từ dải IP quản trị
gcloud compute firewall-rules create allow-admin-ssh \
--direction=INGRESS \
--allow=tcp:22 \
--source-ranges=203.0.113.0/24 \ # Dải IP Admin
--target-tags=admin-box \
--priority=100
# Service: Cho phép HTTP từ mọi nơi
gcloud compute firewall-rules create allow-http-any \
--direction=INGRESS \
--allow=tcp:80 \
--source-ranges=0.0.0.0/0 \
--target-tags=web-server \
--priority=500
# Service: Cho phép HTTPS từ mọi nơi
gcloud compute firewall-rules create allow-https-any \
--direction=INGRESS \
--allow=tcp:443 \
--source-ranges=0.0.0.0/0 \
--target-tags=web-server \
--priority=500
# Luật chung: Chặn các dải IP xấu đã biết (cập nhật qua CI)
gcloud compute firewall-rules create deny-bad-ips \
--direction=INGRESS \
--allow=all \
--source-ranges=198.51.100.0/24 \
--priority=10000Egress Firewall Rules
Chiều egress thường bị bỏ qua. VPC firewall cũng quản lý cả egress (outbound traffic từ VM).
Hành vi mặc định của Egress
Nếu không có rule egress rõ ràng, mặc định là cho phép toàn bộ outbound. Nhưng nếu bạn đã tạo một rule egress bất kỳ, quy tắc mặc định deny sẽ được áp dụng cho các traffic còn lại.
Kịch bản:
Subnet có rule egress cho phép traffic đến dải IP nội bộ:
Rule: priority=100, action=ALLOW,
direction=EGRESS, destinationRanges=[10.0.0.0/8]
Kết quả: Các VM trong subnet không thể kết nối ra ngoài internet (bị chặn bởi rule default deny)Cách debug Egress Firewall
# Liệt kê tất cả rule egress
gcloud compute firewall-rules list --filter="direction=EGRESS"
# Kiểm tra xem outbound có bị chặn không
# Nếu không có rule allow rõ ràng, hãy kiểm tra flow logs
# Tìm kiếm entry có action=DENY ở chiều egress với rule_name="default-deny-egress"Một số trường hợp đặc biệt (Edge Cases)
Service Accounts và Firewall
Firewall rules không hoạt động dựa trên service account. Các rule chỉ dựa trên dải IP và tags.
Hệ quả: Nếu VM A (chạy service account X) và VM B (chạy service account Y) ở cùng subnet và có cùng tag, firewall rules sẽ áp dụng lên cả hai như nhau.
VPC Service Controls
Đừng nhầm lẫn VPC firewall rules với VPC Service Controls (Firewall Policies).
- VPC Firewall Rules: Quản lý kết nối ở mức độ VM.
- VPC Service Controls: Quản lý chính sách truy cập ở mức độ service (như GCS buckets, BigQuery datasets).
Cả hai hoạt động độc lập. Một gói tin có thể đi qua VPC firewall bình thường nhưng vẫn bị chặn bởi VPC Service Controls.
Custom Routes + Firewall
Firewall hoạt động độc lập với routing. Traffic có thể có route hợp lệ nhưng vẫn bị chặn bởi firewall, hoặc ngược lại có rule firewall cho phép nhưng không có route trả về (packet bị drop).
Best Practices
1. Sử dụng Service Accounts + IAM để kiểm soát truy cập ứng dụng
Các rule dựa trên IP/tag thường không đủ chi tiết. Để kiểm soát truy cập ở mức độ ứng dụng, hãy sử dụng service accounts kết hợp Cloud IAM:
# Thay vì dùng firewall rule, hãy dùng IAM
gcloud projects add-iam-policy-binding my-project \
--member=serviceAccount:app@my-project.iam.gserviceaccount.com \
--role=roles/compute.instanceAdmin.v12. Định kỳ kiểm tra bằng Firewall Insights
Hãy định kỳ audit lại các rule bằng Firewall Insights:
# Liệt kê các rule có lượng traffic lớn
gcloud compute firewall-policies rules list \
--firewall-policy=default3. Đặt tên Rule rõ nghĩa
Tên firewall rule nên mô tả rõ mục đích sử dụng của nó:
TỐT: allow-internal-mysql
XẤU: rule14. Kiểm tra trước khi thay đổi bằng Connectivity Tests
Trước khi áp dụng thay đổi firewall, hãy xác thực bằng Connectivity Tests:
# Trước: Xác thực kết nối trước khi tắt rule cũ
gcloud compute network-management connectivity-tests create pre-change-test \
--source-instance=... \
--destination-instance=...
# Thực hiện thay đổi cấu hình
# Sau: Xác thực lại sau khi thay đổi
gcloud compute network-management connectivity-tests create post-change-test \
--source-instance=... \
--destination-instance=...5. Sử dụng Firewall Policies cho các quy tắc ở mức Organization
Để áp dụng các rule chung cho nhiều VPC khác nhau:
# Tạo firewall policy ở mức organization
gcloud compute firewall-policies create org-deny-low-priority \
--description="Organization-level deny rules"
# Áp dụng chính sách cho các project mục tiêu
gcloud compute firewall-policies associations create \
--firewall-policy=org-deny-low-priority \
--target-resource=projects/my-project