TL;DR
Cloudflare Access là ZTNA cốt lõi của Cloudflare One: nó đứng trước ứng dụng nội bộ, xác thực người dùng qua IdP (Okta, Entra ID, Google), đánh giá chính sách (group, posture, network), và quyết định chuyển tiếp request hay từ chối. Thay VPN cho private app là trường hợp sử dụng bắt đầu rõ nhất, ROI nhanh, rủi ro thấp, khung cho các tính năng khác của Cloudflare One.
Bài này đi qua:
- Vì sao Access khác VPN ở blast radius.
- 4 object cấu hình (Application, Policies, IdP, Session).
- Luồng login thực tế với IdP và Tunnel.
- 5 bước thiết lập đầu-cuối.
- Thứ tự đánh giá chính sách (Include → Exclude → Require).
- Truy nguyên 6 trường hợp thường gặp nhất.
- Đánh đổi khi chuyển từ VPN sang Access.
Luận điểm chính:
VPN cho người dùng vào network. Access cho người dùng vào ứng dụng. Khác biệt một từ nhưng khác biệt phạm vi ảnh hưởng một bậc, và đây là lý do ZTNA đáng thay VPN, không phải vì độ trễ tốt hơn.
Bài này là Part 4 của Cloudflare One Handbook.
Dành cho ai
- Kỹ sư nền tảng đang muốn thay VPN cho 1-10 ứng dụng nội bộ.
- Kỹ sư bảo mật viết design doc cho ZTNA pilot.
- Ops/Trưởng nhóm IT cần biết cấu hình Access trông thế nào trong thực tế.
Bạn nên đã đọc:
Sau bài này, bạn sẽ:
- Hiểu Access khác VPN ở đâu, khi nào chọn Access.
- Biết 4 object và cách chúng liên hệ với nhau.
- Cấu hình được Access application đầu tiên end-to-end trong ~30 phút (IdP sẵn có + public DNS zone).
- Biết cách viết chính sách tận dụng Include/Exclude/Require đúng ngữ nghĩa.
- Có phiếu tra cứu truy nguyên cho 6 triệu chứng phổ biến nhất.
Bài này không nói về gì
- Không đi sâu thiết lập cho từng IdP cụ thể (Part 5 sẽ bàn về Okta/Entra/Google mapping).
- Không bàn SCIM (Part 7).
- Không bàn Tunnel kiến trúc deep-dive (Part 8).
- Không bàn Terraform/chính sách-dưới-dạng-mã (bài riêng sau).
Bài này là hướng dẫn happy-path + khái niệm chính + các cạm bẫy phổ biến. Mục tiêu: sau khi đọc, bạn có app đầu tiên chạy sau ZTNA.
Khái niệm
- ZTNA (Zero Trust Network Access): danh mục sản phẩm thay VPN cho truy cập ứng dụng nội bộ. Xem Part 2.
- Application: đối tượng trong Cloudflare Access đại diện cho một tài nguyên (hostname). Phạm vi đánh giá chính sách.
- Policy: quy tắc quyết định ai được qua Access đến Application. Một Application có thể có nhiều chính sách (được đánh giá theo thứ tự, cho phép nếu khớp một cái).
- Identity provider (IdP): nguồn xác thực người dùng. Cloudflare Access không tự quản lý mật khẩu, nó tin IdP.
- Session: trạng thái sau khi đăng nhập thành công. Biểu diễn bằng JWT cookie
CF_Authorizationký bởi Cloudflare. - Origin: máy chủ thật sự host ứng dụng. Cloudflare Access proxy tới origin sau khi chính sách pass.
- Tunnel: cách khuyến nghị đưa origin vào phạm vi Cloudflare mà không mở public IP (cách khác: public IP với firewall rule chỉ whitelist dải IP Cloudflare, nhưng phức tạp hơn).
Access khác VPN ở đâu: phạm vi ảnh hưởng
Cả VPN và Access đều “cho người dùng vào thứ gì đó”. Khác biệt nằm ở người dùng vào cái gì:
VPN
- Người dùng đăng nhập → được cấp IP trong subnet nội bộ.
- Từ IP đó, người dùng thấy mọi app trong subnet: có thể ping, TCP connect, DNS lookup.
- Cho phép/chặn ở tầng network (firewall rule, ACL). App không biết.
- Nếu laptop người dùng nhiễm mã độc sau khi đã login VPN, mã độc có truy cập toàn bộ network.
Access
- Người dùng truy cập
app.example.com→ Cloudflare đứng trước, xác thực + chính sách. - Người dùng chỉ thấy hostname cụ thể đã được phép. Các app khác không ping được, không mở TCP được: không tồn tại từ góc nhìn người dùng.
- Cho phép/chặn ở tầng ứng dụng theo từng app.
- Laptop nhiễm mã độc: mã độc chỉ truy cập được app mà người dùng được phép, không phải toàn network.
Cái gì KHÔNG phải lợi thế của Access
Một số luận điệu tiếp thị tự nhận:
- “ZTNA nhanh hơn VPN”: không phải luôn đúng. Access qua browser có thêm chặng qua Cloudflare edge, có thể chậm hơn VPN trực tiếp tới datacenter nếu người dùng đã ở gần datacenter. Với người dùng phân tán toàn cầu, Access nhanh hơn, do network anycast, không phải do ZTNA-as-protocol.
- “Không cần client”: đúng cho app HTTP qua browser. Sai cho SSH, RDP, ứng dụng nặng, vẫn cần WARP hoặc phương án render qua browser.
- “Thay hoàn toàn VPN”: không thay VPN cho trường hợp sử dụng ở mức network (site-to-site, lab network). Access thay VPN cho người dùng → truy cập ứng dụng. VPN/SD-WAN vẫn đủ dùng cho kết nối chi nhánh.
Chọn Access khi bài toán là người dùng-tới-ứng dụng. Giữ VPN/SD-WAN khi bài toán là network site-to-site.
Giải phẫu: 4 đối tượng
Cloudflare Access UI có hàng chục menu, nhưng 90% cấu hình xoay quanh 4 đối tượng:
Application
Đối tượng cha. Xác định tài nguyên bạn muốn bảo vệ. Trường chính:
- Application type: Self-hosted (HTTP/HTTPS app của bạn) | SaaS (Okta, AWS Console với Cloudflare là IdP front) | Private Network (non-HTTP qua WARP) | Infrastructure (SSH, RDP, VNC, Kubernetes). Bài này tập trung Self-hosted.
- Application domain: hostname người dùng gõ vào browser:
app.example.com. Phải trong zone bạn quản lý trên Cloudflare DNS. - Session duration: bao lâu thì bắt xác thực lại. Mặc định 24h. App nhạy cảm nên đặt ngắn (15m-1h).
- App launcher: có hiện trong portal Cloudflare Access (
<team>.cloudflareaccess.com) không. - CORS / custom header / identity in header: nâng cao: chuyển tiếp thông tin người dùng tới origin qua header.
Policies
Đối tượng con của Application. Quy tắc thực sự được đánh giá. Một app có thể có nhiều chính sách; thứ tự đánh giá là: Service Auth → Bypass → Allow/Block (theo thứ tự trong UI). Khi khớp Allow hoặc Block, dừng, không xét chính sách sau.
Mỗi chính sách có 3 phần:
- Include: Ai được xem xét cho quy tắc này?
- Exclude: Ai bị loại trừ bất kể include?
- Require: Điều kiện bổ sung phải TẤT CẢ thỏa.
Chi tiết thứ tự đánh giá ở phần sau.
Identity providers (IdPs)
Đối tượng độc lập với Application, cấu hình cấp account, sau đó ánh xạ vào từng Application.
- Hỗ trợ: Okta, Entra ID (Azure AD), Google Workspace, SAML tổng quát, OIDC tổng quát, GitHub, AD, Facebook, LinkedIn, one-time PIN (không cần IdP).
- Một tài khoản Cloudflare có thể có nhiều IdP cùng lúc: ví dụ Okta cho nhân viên + GitHub cho nhân sự thuê ngoài.
- Mỗi Application chọn IdP nào áp dụng (mặc định: tất cả).
Session
Sau khi xác thực thành công, Cloudflare đặt cookie CF_Authorization cho subdomain của app, JWT ký bởi Cloudflare. Browser gửi cookie này cho mỗi request tiếp theo; Access xác minh chữ ký + hạn, chuyển tiếp tới origin nếu hợp lệ.
Origin có thể đọc JWT để biết identity người dùng (Cloudflare cũng chuyển tiếp qua header Cf-Access-Authenticated-User-Email và JWT trong header Cf-Access-Jwt-Assertion). Dùng để tùy biến UI (“Hi Alice”) hoặc RBAC cấp app.
Luồng đăng nhập: đầu-cuối
Khi người dùng truy cập app.example.com lần đầu (chưa có cookie), luồng đầy đủ như sau:
Bước chi tiết
① GET app.example.com
Browser gửi request. Cloudflare DNS resolve hostname này tới Cloudflare edge (vì bạn đã proxy DNS record qua Cloudflare, orange cloud).
② Cloudflare trả 302 → IdP
Edge không thấy cookie CF_Authorization → kích hoạt Access. Trả redirect tới URL đăng nhập IdP (endpoint authorize SAML/OIDC).
③ IdP xác thực + trả assertion
Người dùng đăng nhập vào Okta/Entra. IdP redirect browser về URL callback Cloudflare với SAML assertion hoặc OIDC code. Cloudflare đổi code → nhận claim (email, groups, v.v.).
④ Kiểm tra posture (nếu chính sách yêu cầu)
Nếu chính sách có require: device_posture, Cloudflare truy vấn WARP client để lấy trạng thái posture hiện tại. Nếu WARP không cài / không enroll → posture unknown → chính sách thất bại.
⑤ Set-Cookie CF_Authorization
Nếu tất cả Include + !Exclude + Require đều pass → Cloudflare cấp JWT, đặt cookie phạm vi .example.com, redirect browser về URL app gốc.
⑥ Browser thử lại với cookie
GET lần 2, cookie đi kèm. Cloudflare xác minh chữ ký + hạn JWT.
⑦ Chuyển tiếp qua Tunnel tới origin
Cloudflare edge reverse-proxy tới connector cloudflared chạy ở network origin. Origin trả response, Cloudflare stream về browser.
Phiên kế tiếp
Trong session_duration, cookie hợp lệ → mọi request đi thẳng từ ⑦. Hết phiên → quay lại ②.
Với WARP + thiết bị quản lý
Đường tắt: nếu người dùng đã enroll WARP, Cloudflare edge nhận identity từ phiên WARP → bỏ qua IdP redirect (bước ②-③). Độ trễ cảm nhận tốt hơn, và đồng thời tín hiệu posture sẵn có thời gian thực.
5 bước thiết lập đầu-cuối
Mục tiêu: bạn có gitlab.internal.example.com chạy ở VPC AWS (không public), muốn bảo vệ bằng Access. Điều kiện tiên quyết:
- Zone
example.comđã thêm vào Cloudflare với DNS proxy (orange cloud). - Origin
gitlab.internal.example.comđã resolve được từ trong VPC (ví dụ qua Route 53 private zone). - IdP đã có (dùng Okta làm ví dụ, thiết lập OIDC app trên Okta trước).
Bước 1: Kết nối IdP (once per account)
Cloudflare dashboard → Zero Trust → Settings → Authentication → Add new → chọn Okta → nhập:
- Client ID (từ Okta app)
- Client Secret
- Okta domain (e.g.
yourcompany.okta.com)
Lưu. Cloudflare xác minh kết nối. Từ nay, Access application mới sẽ thấy Okta là IdP khả dụng.
Bước 2: Cài cloudflared connector ở origin
Cloudflare dashboard → Zero Trust → Networks → Tunnels → Create a tunnel.
Chọn Cloudflared, đặt tên (ví dụ prod-internal), Next. Cloudflare sinh command cài đặt:
# Example: Debian/Ubuntu host inside VPC
curl -L https://pkg.cloudflare.com/install.sh | sudo bash
sudo apt-get install cloudflared
sudo cloudflared service install eyJhIjoi...long-token...
sudo systemctl status cloudflared
Connector bắt đầu → dashboard hiện “Healthy”. Đây là chỉ-chiều-ra, không cần mở inbound port ở VPC.
Bước 3: Thêm public hostname vào Tunnel
Cùng Tunnel vừa tạo → tab Public Hostname → Add a public hostname:
- Subdomain:
gitlab - Domain:
example.com
(Cloudflare tự tạo DNS recordCNAME gitlab.example.com → <tunnel>.cfargotunnel.com, proxied) - Service:
http://gitlab.internal:80(URL origin từ bên trong VPC mà connector reach được)
Lưu. Kiểm thử ngoài Access, mở browser truy cập https://gitlab.example.com, sẽ thấy GitLab. Nhưng chưa có Access → chưa an toàn.
Bước 4: Tạo Access Application + Policy
Zero Trust → Access → Applications → Add an application → Self-hosted.
- Application name:
GitLab Internal - Session duration: 1 hour
- Application domain:
gitlab.example.com(chính hostname Tunnel trả ra) - Identity providers: Okta (tick)
Next → Policies:
Policy 1, Cho phép engineer
- Name:
Engineering only - Action:
Allow - Session duration: inherit
- Include:
emails_ending_in: @example.comgroups: [Engineering, Platform](group từ Okta claim)
- Require:
device_posture: [disk_encrypted](tùy chọn nếu WARP đã triển khai)
Lưu.
Bước 5: Kiểm thử luồng
Mở browser incognito → https://gitlab.example.com.
- Bạn nên thấy trang đăng nhập Cloudflare Access → chọn Okta → redirect tới trang đăng nhập Okta.
- Sau khi đăng nhập, redirect về Cloudflare → xác minh chính sách.
- Nếu bạn ở group Engineering → tới trang đăng nhập GitLab.
- Nếu người dùng ngoài group → trang “Access denied” từ Cloudflare.
Kiểm tra log:
- Zero Trust → Logs → Access: mọi sự kiện đăng nhập (cho phép/từ chối + lý do).
- Networks → Tunnels → Metrics: tình trạng connector.
- Analytics → Gateway: nếu chính sách Gateway cũng được áp dụng.
Thứ tự đánh giá chính sách: quan trọng
Đây là chỗ nhiều nhóm bị lỗi. Hiểu đúng luồng đánh giá sẽ tránh 80% chính sách sai.
3 giai đoạn trong một chính sách
Include (logic OR), ít nhất một rule khớp thì người dùng nằm trong phạm vi của chính sách.
include:
- emails_ending_in: @example.com
- groups: [Contractors]
→ Thành công nếu email người dùng @example.com HOẶC người dùng thuộc group Contractors.
Exclude (nếu khớp thì từ chối ngay)
exclude:
- emails: [ex-employee@example.com, revoked@example.com]
- country: [KP, RU]
→ Nếu email người dùng khớp OR country khớp → từ chối chính sách này (không tiếp tục xét chính sách khác).
Require (logic AND), TẤT CẢ phải thỏa.
require:
- device_posture: [disk_encrypted]
- mfa_method: [FIDO2]
→ Người dùng phải có cả disk_encrypted AND FIDO2 MFA. Thiếu 1 → thất bại.
Giữa các chính sách của cùng Application
Application có thể có nhiều chính sách, thứ tự quan trọng. Cloudflare đánh giá từ trên xuống:
- Chính sách 1 (thứ tự 1):
AllowEngineering - Chính sách 2 (thứ tự 2):
Bypass(không auth) từ IP văn phòng - Chính sách 3 (thứ tự 3):
Blockeveryone
Cloudflare đánh giá chính sách theo thứ tự ưu tiên action: Service Auth → Bypass chạy trước, rồi tới Allow/Block (theo thứ tự trong UI). Khi khớp một chính sách Allow hoặc Block, dừng đánh giá. Trong thực tế:
- Nếu có Bypass khớp → qua Access, không cần xác thực.
- Nếu chính sách Allow hoặc Block khớp đầu tiên → quyết định đó thắng.
- Nếu không chính sách nào khớp → từ chối mặc định.
Thứ tự khuyến nghị viết chính sách
- Bypass rule (nếu có, endpoint công khai, path healthcheck), ở TRÊN CÙNG.
- Allow rule cụ thể (admin trước, sau đến người dùng), theo thứ tự từ hẹp đến rộng.
- Block rule tường minh (từ chối theo quốc gia, dải IP, group cấm).
- Từ chối mặc định, không cần viết, là phương án dự phòng mặc định.
Sai lầm phổ biến
- Chính sách Allow rộng trước Block hẹp: Allow
@example.comở thứ tự 1, BlockSuspended-usersở thứ tự 2. Người dùng Suspended mà email@example.comvẫn được Allow vì khớp trước → không bao giờ chạm tới Block. - Require thiếu device_posture cho app nhạy cảm: admin panel chỉ kiểm tra email domain, không kiểm tra thiết bị quản lý → nhân sự thuê ngoài cài mã độc vẫn vào được.
- Session duration quá dài: 30 ngày cho admin panel = nếu laptop mất 30 ngày đó, kẻ tấn công vẫn vào được. Admin panel nên đặt 30 phút - 1h.
Truy nguyên: 6 trường hợp phổ biến
1. “Người dùng bị redirect loop giữa Cloudflare và Okta”
Nguyên nhân thường: URL callback OIDC sai, hoặc lệch đồng hồ giữa Okta và Cloudflare (timestamp JWT không hợp lệ).
Kiểm tra:
- Okta OIDC app → Login redirect URIs → phải có URL callback Cloudflare chính xác.
- Dev tools browser → Network → xem URL trả 302, copy callback, so sánh.
2. “Người dùng đăng nhập thành công nhưng vẫn bị từ chối”
Group claim không khớp.
Kiểm tra:
- Zero Trust → Logs → Access → bấm sự kiện từ chối → xem tab “Identity”.
- Xác minh tên group Okta trả về chính xác giống cấu hình chính sách. Okta có thể trả “Engineering-VN” nhưng chính sách viết “Engineering”.
Khắc phục: hoặc sửa chính sách, hoặc sửa quy ước đặt tên group ở Okta (Part 5 sẽ đi sâu).
3. “502 Bad Gateway sau khi Access pass”
Chính sách pass nhưng origin không phản hồi. Tunnel hoặc origin có vấn đề.
Kiểm tra:
- Networks → Tunnels → [tunnel name] → Metrics → trạng thái connector Healthy?
- Nếu Healthy: vào host origin,
curl http://gitlab.internal:80, origin có up không? - Kiểm tra
cloudflaredlog:journalctl -u cloudflared -n 100.
4. “Kiểm tra posture luôn thất bại”
WARP chưa enroll, hoặc posture checker chưa trả về.
Kiểm tra:
- Người dùng có cài WARP + enrolled vào tổ chức đúng không? (biểu tượng WARP trên status bar)
- Loại posture có khớp thực tế không? (ví dụ
disk_encryptedcho Windows kiểm tra BitLocker, người dùng Mac FileVault cần rule riêng). - Zero Trust → Settings → WARP Client → Device enrollment permissions: thiết bị có trong danh sách không.
5. “Người dùng đăng nhập một lần rồi không cần đăng nhập nữa: thời gian bao lâu?”
TTL cookie CF_Authorization = session_duration của Application. Mặc định 24h. Với app nhạy cảm, đặt về 1h hoặc thấp hơn.
Đăng xuất thủ công: https://<team>.cloudflareaccess.com/cdn-cgi/access/logout.
6. “Access chặn toàn bộ người dùng sau khi cập nhật chính sách”
Kiểm tra thứ tự chính sách, xem có Block rule nào chuyển lên trên Allow không? Dashboard có toggle được bật/tắt, có thể nhầm tắt chính sách Allow.
Cách khắc phục nhanh: tắt chính sách vừa cập nhật, traffic quay về trạng thái trước. Sau đó truy nguyên cẩn thận.
Đánh đổi
| Quyết định | Option A | Option B | Khuyến nghị |
|---|---|---|---|
| Session duration | Ngắn (1h) | Dài (30 ngày) | Ngắn cho admin/prod app, dài cho app năng suất. Mặc định 24h ổn cho hầu hết |
| Bypass cho IP tin cậy | Có | Không | Chỉ dùng cho endpoint healthcheck / giám sát. Không dùng cho IP văn phòng, IP có thể bị giả mạo |
| Yêu cầu device posture | Mọi app | Chỉ app nhạy cảm | Tùy giai đoạn triển khai. Posture cho mọi app = ma sát cao trước khi WARP triển khai. Bắt đầu chỉ với app nhạy cảm |
| IdP: một hay nhiều | Một IdP cho tất cả | Nhiều IdP mỗi app | Một IdP chính + phương án dự phòng One-time PIN cho nhà cung cấp. Nhiều IdP khó kiểm toán |
| Hiển thị app launcher | Hiện tất cả app | Ẩn mặc định | Hiện, người dùng biết họ có quyền gì, giảm ticket “app này ở đâu” |
| Số replica Tunnel | 1 | 2+ | Luôn 2+ cho production, khác node/AZ. Một replica hỏng = gián đoạn |
Danh sách kiểm tra: trước khi đưa Access vào production
- Quy ước đặt tên group IdP đã chuẩn hóa.
- Kiểm thử chính sách với ít nhất 3 người dùng khác nhau (nhân viên, nhân sự thuê ngoài, trường hợp biên).
- Tunnel có ≥2 replica connector ở ít nhất 2 host/AZ khác nhau.
- Session duration khớp mức nhạy cảm của app.
- Audit log đã cấu hình chuyển tiếp về SIEM (nếu có).
- Trang Access denied có link hỗ trợ (email hỗ trợ / runbook).
- URL đăng xuất đã tài liệu hóa cho người dùng.
- Kế hoạch khôi phục: nếu Access hỏng, mở lại app qua VPN tạm thời thế nào?
- Bypass cho công cụ healthcheck / giám sát đã có và đã kiểm thử.
- Chính sách SCIM cho off-boarding (Part 7): hoặc ít nhất đã có quy trình dọn group thủ công.
Bài học thực tế
- Luôn có 1 Access application
sandboxđể kiểm thử chính sách trước production. Đừng chỉnh chính sách production trực tiếp: một typo trong tên group khóa toàn bộ kỹ sư. - “Mô hình 1 chính sách cho tất cả” không mở rộng được. Khi app > 20, chính sách > 100, không thể rà soát bằng mắt. Bắt đầu chính sách-dưới-dạng-mã (Terraform) sớm, không chờ 100 rule.
- Kiểm thử lại mỗi quý với nhân sự đang làm. Group IdP trôi, vòng đời người dùng trôi: chính sách tưởng đúng nay không còn đúng.
- Đừng dùng Access làm firewall. Access lọc theo identity + chính sách. Nếu bạn cần lọc theo traffic pattern (rate limit, bot detection, malware payload): dùng WAF hoặc Gateway.
Kết luận
Cloudflare Access là thành phần nền tảng của Cloudflare One. Tạo app đầu tiên mất 30 phút thật, nhưng để đạt mức trưởng thành chính sách (chính sách-dưới-dạng-mã, SCIM, posture tích hợp, pipeline audit) mất 3-6 tháng. Đừng nhầm hai số đó.
Nếu phải nhớ một câu:
Access không thay VPN vì nhanh hơn. Access thay VPN vì phạm vi ảnh hưởng nhỏ hơn, mỗi app một chính sách, một quyết định, một log. VPN không cho bạn thứ đó dù có cài SSO trước mặt.
Trong Part 5 mình sẽ đi sâu tích hợp IdP, Okta, Entra ID, Google Workspace, SAML tổng quát, với 4 ma trận thiết lập + cạm bẫy mỗi cái.
Tài liệu tham khảo
Trong series này: