Dùng Cloudflare Tunnel Trên VPS Để Ẩn Origin Và Không Mở Port Inbound

Cài Cloudflare Tunnel trên VPS để xuất bản web/app qua kết nối outbound, ẩn origin, giảm port inbound và quản lý truy cập an toàn hơn.

Nếu bạn đang public một dashboard, website nội bộ hoặc ứng dụng trên VPS, cách truyền thống là mở port firewall và trỏ DNS thẳng về IP origin. Cloudflare Tunnel cho phép `cloudflared` chủ động tạo kết nối outbound tới Cloudflare, nhờ đó origin không cần nhận kết nối trực tiếp từ Internet. Bài viết này hướng dẫn mô hình triển khai, cài đặt, cấu hình ingress, chạy service và các lưu ý bảo mật quan trọng.

Điểm quan trọng Hãy lựa chọn dịch vụ dựa trên nhu cầu sử dụng thực tế và theo dõi tài nguyên thường xuyên để có hiệu quả tốt nhất.

Khi chạy một ứng dụng trên VPS, mô hình quen thuộc là mở port 80/443 hoặc port riêng, sau đó trỏ DNS về IP public. Cách này đơn giản nhưng origin vẫn lộ ra Internet và bạn phải kiểm soát firewall, TLS, bot scan và truy cập trực tiếp vào IP.

Cloudflare Tunnel giải quyết bài toán theo hướng khác: daemon cloudflared trên VPS chủ động tạo kết nối outbound-only tới mạng Cloudflare. Cloudflare nhận request từ người dùng và chuyển qua tunnel về origin, thay vì người dùng kết nối trực tiếp vào IP VPS.

Điều này giúp bạn:

  • không cần mở inbound port cho web app trong nhiều trường hợp;
  • giảm việc lộ origin IP;
  • đưa WAF/CDN/Access vào trước ứng dụng;
  • xuất bản dashboard nội bộ mà không phải public trực tiếp port quản trị.

Tuy vậy, Tunnel không phải “tắt hết firewall rồi quên”. Bạn vẫn cần quản lý tài khoản, TLS, Access policy, update hệ thống và backup.

Cloudflare Tunnel hoạt động thế nào?

Mô hình cơ bản:

  1. VPS chạy cloudflared;
  2. cloudflared tạo kết nối outbound tới Cloudflare;
  3. hostname, ví dụ app.example.com, được gắn với tunnel;
  4. Cloudflare nhận request và chuyển tới service local như http://localhost:3000;
  5. origin không cần nhận kết nối trực tiếp từ Internet cho service đó.

Cloudflare hiện mô tả Tunnel là kết nối outbound-only và không cần public IP cho origin trong mô hình phù hợp.

Khi nào Cloudflare Tunnel phù hợp?

Một số use case thực tế:

  • dashboard quản trị nội bộ;
  • Grafana, Portainer, admin panel;
  • ứng dụng staging;
  • API nội bộ cần thêm lớp Access;
  • web app tự host;
  • origin muốn ẩn IP và chỉ nhận traffic qua Cloudflare.

Nếu mục tiêu của bạn là quản trị VPS riêng qua mạng mesh giữa các thiết bị, Tailscale có thể phù hợp hơn. Xem bài Cài Tailscale trên VPS Ubuntu.

Khi nào không nên dùng Tunnel?

Tunnel không phải lựa chọn lý tưởng cho mọi protocol.

Bạn cần đọc giới hạn khi dùng:

  • VoIP/SIP hoặc protocol server-initiated;
  • workload cần source IP gốc ở tầng TCP;
  • ứng dụng phụ thuộc inbound networking trực tiếp;
  • mô hình compliance đặc thù.

Với HTTP, Cloudflare có header để truyền thông tin client IP. Với non-HTTP protocol, origin không nhất thiết nhìn thấy source IP gốc như kết nối trực tiếp.

Chuẩn bị trước khi cài

Bạn cần:

  • VPS Linux có quyền sudo;
  • domain đã quản lý trên Cloudflare;
  • service local đang chạy, ví dụ localhost:3000;
  • quyền tạo tunnel trong Cloudflare dashboard;
  • giữ nguyên đường SSH hiện tại trong lúc cấu hình.

Kiểm tra service local:

curl -I http://127.0.0.1:3000

Nếu service chưa hoạt động local, Tunnel cũng không thể sửa lỗi ứng dụng đó.

Cài cloudflared

Cloudflare cung cấp package và hướng dẫn cài chính thức cho Linux. Hãy dùng repository/package tương ứng distro của bạn thay vì tải binary ngẫu nhiên từ nguồn thứ ba.

Sau khi cài:

cloudflared --version

Tạo tunnel

Với locally-managed tunnel, đăng nhập:

cloudflared tunnel login

Lệnh sẽ mở quy trình xác thực trong trình duyệt.

Tạo tunnel:

cloudflared tunnel create my-app

Sau đó bạn sẽ có tunnel UUID và file credentials JSON.

Kiểm tra danh sách:

cloudflared tunnel list

Tạo file cấu hình

Ví dụ ~/.cloudflared/config.yml:

tunnel: YOUR_TUNNEL_UUID
credentials-file: /home/admin/.cloudflared/YOUR_TUNNEL_UUID.json

ingress:
  - hostname: app.example.com
    service: http://127.0.0.1:3000
  - service: http_status:404

Rule cuối http_status:404 đóng vai trò catch-all.

Validate cấu hình:

cloudflared tunnel ingress validate

Nếu dùng HTTPS local origin với chứng chỉ hợp lệ:

service: https://127.0.0.1:8443

Không nên đặt noTLSVerify: true để “cho chạy được” rồi bỏ quên. Cloudflare cũng khuyến nghị chỉ dùng như biện pháp tạm thời khi đang xử lý lỗi certificate trust.

Tạo DNS route

Gắn hostname vào tunnel:

cloudflared tunnel route dns my-app app.example.com

Sau đó kiểm tra DNS trong dashboard.

Chạy thử tunnel

cloudflared tunnel run my-app

Mở:

https://app.example.com

Nếu ứng dụng hoạt động, mới chuyển sang chạy service lâu dài.

Cài cloudflared thành systemd service

Cloudflare hỗ trợ chạy cloudflared như service trên Linux.

Nếu config nằm trong home của user:

sudo cloudflared --config /home/admin/.cloudflared/config.yml service install

Kiểm tra:

sudo systemctl status cloudflared

Khởi động nếu cần:

sudo systemctl start cloudflared

Sau khi sửa config:

sudo systemctl restart cloudflared

Có thể đóng port 80/443 public không?

Chỉ nên cân nhắc sau khi xác nhận:

  1. tunnel hoạt động ổn định;
  2. hostname truy cập được;
  3. service local bind đúng interface;
  4. có console dự phòng;
  5. firewall không chặn outbound cần thiết của cloudflared;
  6. không còn dịch vụ khác cần port public đó.

Kiểm tra port listen:

sudo ss -tulnp

Nếu app chỉ cần truy cập qua Tunnel, một cách an toàn là bind app vào localhost:

127.0.0.1:3000

thay vì 0.0.0.0:3000.

Đừng nhầm Tunnel với Access

Cloudflare Tunnel tạo đường kết nối từ Cloudflare tới origin.

Cloudflare Access mới là lớp kiểm soát ai được phép truy cập ứng dụng dựa trên identity/policy.

Nếu bạn public một dashboard quản trị qua Tunnel nhưng không có login hoặc Access policy, URL vẫn có thể được người khác truy cập nếu họ biết hostname.

Với ứng dụng nội bộ, nên kết hợp:

  • Tunnel;
  • Access policy;
  • MFA/identity provider;
  • application authentication nếu phù hợp.

Bảo vệ origin khỏi bypass

Một lợi ích quan trọng của Tunnel là giảm khả năng attacker truy cập thẳng origin bằng IP public.

Tuy nhiên, nếu trên cùng VPS vẫn còn Nginx hoặc app listen trên 0.0.0.0 và firewall vẫn mở port, attacker vẫn có thể bypass Cloudflare bằng IP.

Kiểm tra:

sudo ss -tulnp
sudo ufw status numbered

Nếu không cần inbound trực tiếp, đóng rule tương ứng sau khi test đầy đủ.

Tunnel có thay reverse proxy Nginx không?

Không hoàn toàn.

Bạn vẫn có thể dùng Nginx local để:

  • route nhiều app;
  • gzip/compression;
  • rewrite;
  • auth nội bộ;
  • cache;
  • serve static file;
  • terminate TLS nội bộ.

Sau đó Tunnel trỏ vào Nginx:

service: http://127.0.0.1:8080

Nếu bạn đang dùng reverse proxy, xem thêm bài Cài Nginx reverse proxy trên VPS Ubuntu.

Nhiều hostname trên một tunnel

Ví dụ:

ingress:
  - hostname: app.example.com
    service: http://127.0.0.1:3000
  - hostname: grafana.example.com
    service: http://127.0.0.1:3001
  - hostname: api.example.com
    service: http://127.0.0.1:8080
  - service: http_status:404

Một tunnel có thể route nhiều service, nhưng hãy quản lý policy và naming rõ ràng.

High availability cho Tunnel

Nếu workload quan trọng, có thể chạy thêm replica của cloudflared trên host khác trỏ vào cùng tunnel.

Mỗi replica tạo thêm kết nối tới Cloudflare, giúp giảm single point of failure ở daemon hoặc host connector.

Nhưng cần nhớ: nếu backend app chỉ chạy trên một VPS duy nhất, app vẫn là single point of failure.

Xử lý lỗi thường gặp

502 Bad Gateway

Thường do Cloudflare tới được tunnel nhưng cloudflared không tới được origin local.

Kiểm tra:

curl -I http://127.0.0.1:3000
sudo journalctl -u cloudflared -n 100 --no-pager

Tunnel connected nhưng hostname không mở được

Kiểm tra:

  • DNS route;
  • hostname trong ingress;
  • catch-all rule;
  • service local;
  • Access policy nếu có.

Redirect loop

Nếu origin tự redirect HTTP → HTTPS nhưng Tunnel đang trỏ vào HTTP sai cách, có thể xảy ra loop.

Kiểm tra scheme giữa service: và origin thực tế.

TLS certificate error ở origin

Nếu trỏ tới HTTPS local origin, certificate phải hợp lệ cho hostname/origin name được dùng. Ưu tiên sửa certificate chain/name thay vì tắt verification lâu dài.

Trường hợp thực tế: publish Grafana mà không mở port 3000

Giả sử Grafana chạy local:

ss -tulnp | grep 3000

Bạn cấu hình:

- hostname: grafana.example.com
  service: http://127.0.0.1:3000

Sau đó:

  • không mở inbound port 3000;
  • dùng Cloudflare Access trước Grafana;
  • giữ Grafana authentication;
  • chỉ public hostname qua Tunnel.

Mô hình này phù hợp hơn việc mở thẳng 3000/tcp cho toàn Internet.

Checklist triển khai an toàn

  • App chạy ổn định trên localhost.
  • Tunnel đã tạo và route DNS đúng.
  • Có catch-all 404.
  • cloudflared chạy dưới systemd.
  • Origin service bind localhost nếu phù hợp.
  • Firewall không mở dư port.
  • Có Access policy cho app nội bộ.
  • Không dùng noTLSVerify lâu dài.
  • Có monitoring cho cloudflared service.
  • Có console VPS dự phòng.

FAQ

Cloudflare Tunnel có cần mở port inbound không?

Trong mô hình Tunnel tiêu chuẩn, cloudflared tạo kết nối outbound nên bạn không cần mở inbound port cho service được publish qua tunnel.

Tunnel có làm VPS không cần IP public không?

Có thể trong kiến trúc phù hợp, miễn VPS vẫn có outbound Internet để cloudflared kết nối Cloudflare.

Cloudflare Tunnel có miễn phí không?

Cloudflare có nhiều tính năng Tunnel/Zero Trust với điều kiện gói khác nhau và có thể thay đổi. Hãy kiểm tra pricing chính thức trước khi triển khai thương mại.

Tunnel có thay VPN không?

Cho web app nội bộ kết hợp Access, có thể thay một số use case VPN. Nhưng với full private network access hoặc client-to-network, cần xem Cloudflare One/Tailscale/WireGuard tùy nhu cầu.

Có nên chạy Tunnel cho SSH/RDP không?

Có thể, nhưng luồng truy cập và source IP behavior khác HTTP. Hãy thiết kế policy, client và Access phù hợp thay vì chỉ đổi port.

Kết luận

Cloudflare Tunnel là một cách hiệu quả để đưa web app từ VPS ra Internet mà không cần public trực tiếp origin port. Giá trị lớn nhất là mô hình outbound-only, khả năng ẩn origin và tích hợp với lớp bảo vệ Cloudflare.

Hãy triển khai theo thứ tự: app local ổn định → tunnel → DNS → systemd → Access policy → mới cân nhắc đóng inbound port cũ.

Nếu bạn đang xây dựng dashboard, staging hoặc web app trên VPS, có thể tham khảo các gói VPS tại HUONG CLOUD và lựa chọn tài nguyên dựa trên workload thực tế.

Nguồn tham khảo

Kết luận

Nếu chưa chắc cấu hình hoặc loại dịch vụ nào phù hợp, hãy gửi nhu cầu thực tế để đội ngũ hỗ trợ tư vấn trước khi mua.

Chưa biết nên chọn gói nào?

Xem bảng giá VPS hoặc liên hệ đội ngũ hỗ trợ để chọn cấu hình phù hợp.

Xem bảng giá VPS →