Cloudflare đứng giữa người dùng và máy chủ của bạn. Nó ẩn IP thật, cache file tĩnh ở gần người dùng, và lọc bớt truy cập xấu trước khi tới VPS. Gói miễn phí đã đủ cho phần lớn website nhỏ. Bài này giúp bạn đưa tên miền lên Cloudflare, cấu hình SSL Full (strict) đúng chuẩn, lấy lại IP thật của khách trên Nginx, cache hợp lý cho WordPress và chặn bot cơ bản.

Bạn cần chuẩn bị:

  • Tài khoản Cloudflare và quyền đổi nameserver của tên miền example.com.
  • Website chạy trên VPS dùng Nginx, IP 203.0.113.10, đã hoạt động bình thường.
  • Danh sách bản ghi DNS hiện tại (A, CNAME, MX, TXT) để đối chiếu.

Bước 1: Thêm tên miền và kiểm tra bản ghi DNS

Trong Cloudflare, chọn thêm tên miền (Add a domain), nhập example.com và chọn gói Free. Cloudflare sẽ quét và nhập các bản ghi DNS sẵn có. Đừng tin hoàn toàn kết quả quét. Hãy so với danh sách bản ghi cũ, nhất là MX, TXT (SPF, DKIM, DMARC) và các tên miền phụ.

Trong bảng DNS, cột Proxy status có hai trạng thái:

Trạng tháiÝ nghĩaDùng cho
Proxied (đám mây cam)Đi qua Cloudflare, ẩn IP gốc@, www của website
DNS only (đám mây xám)Chỉ phân giải DNS, lộ IP thậtmail, FTP, SSH, dịch vụ không phải HTTP

Proxy của Cloudflare chỉ chuyển tiếp HTTP/HTTPS trên một số cổng nhất định. Bản ghi cho mail server phải để DNS only, nếu không email sẽ không hoạt động.

Bước 2: Đổi nameserver

Cloudflare cấp hai nameserver dạng ten.ns.cloudflare.com. Vào trang quản lý tên miền ở nơi đăng ký, thay nameserver cũ bằng hai giá trị này. Nếu đang bật DNSSEC tại nơi đăng ký, hãy tắt trước khi đổi, rồi bật lại trong Cloudflare sau khi tên miền đã Active. Kiểm tra:

dig +short NS example.com @1.1.1.1

Khi Cloudflare báo tên miền Active, website đã đi qua proxy. Xác nhận bằng header:

curl -sI https://example.com | grep -i -E 'server|cf-ray'

Bước 3: Tạo chứng chỉ Origin CA cho máy chủ gốc

SSL Full (strict) yêu cầu máy chủ gốc có chứng chỉ hợp lệ. Bạn có thể dùng Let's Encrypt, hoặc chứng chỉ Origin CA miễn phí của Cloudflare với thời hạn dài. Vào SSL/TLS, Origin Server, chọn Create Certificate, giữ mặc định (RSA, hostname example.com và *.example.com). Cloudflare hiển thị chứng chỉ và private key. Private key chỉ hiện một lần, hãy lưu ngay.

sudo mkdir -p /etc/ssl/cloudflare
sudo nano /etc/ssl/cloudflare/example.com.pem
sudo nano /etc/ssl/cloudflare/example.com.key
sudo chmod 600 /etc/ssl/cloudflare/example.com.key

Khai báo trong server block Nginx:

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name example.com www.example.com;

    ssl_certificate     /etc/ssl/cloudflare/example.com.pem;
    ssl_certificate_key /etc/ssl/cloudflare/example.com.key;

    root /var/www/example.com;
    # ... phần cấu hình còn lại
}

Chỉ thị http2 on; có từ Nginx 1.25.1. Nếu Nginx cũ hơn, dùng listen 443 ssl http2;.

sudo nginx -t && sudo systemctl reload nginx

Bước 4: Bật SSL Full (strict) và HTTPS bắt buộc

Vào SSL/TLS, Overview, chọn chế độ Full (strict). Sau đó, trong SSL/TLS, Edge Certificates:

  • Bật Always Use HTTPS để chuyển mọi yêu cầu HTTP sang HTTPS.
  • Đặt Minimum TLS Version là TLS 1.2.
  • Chỉ bật HSTS khi chắc chắn mọi tên miền phụ đều chạy HTTPS ổn định, vì trình duyệt sẽ ghi nhớ và khó quay lại.

Bước 5: Khôi phục IP thật của khách trên Nginx

Khi đi qua proxy, Nginx chỉ thấy IP của Cloudflare. Log, fail2ban và plugin bảo mật sẽ sai. Dùng module realip (có sẵn trong gói Nginx của Ubuntu) để đọc header CF-Connecting-IP. Tạo file cấu hình từ danh sách IP chính thức của Cloudflare:

{
  for ip in $(curl -s https://www.cloudflare.com/ips-v4) $(curl -s https://www.cloudflare.com/ips-v6); do
    echo "set_real_ip_from $ip;"
  done
  echo "real_ip_header CF-Connecting-IP;"
} | sudo tee /etc/nginx/conf.d/cloudflare-realip.conf
sudo nginx -t && sudo systemctl reload nginx

Danh sách IP thỉnh thoảng thay đổi. Hãy chạy lại đoạn lệnh này định kỳ, ví dụ mỗi tháng.

Bước 6: Chỉ cho Cloudflare truy cập cổng web

Nếu IP gốc đã lộ trước đây, kẻ tấn công vẫn có thể gọi thẳng vào VPS. Giới hạn cổng 80, 443 chỉ nhận kết nối từ Cloudflare:

for ip in $(curl -s https://www.cloudflare.com/ips-v4) $(curl -s https://www.cloudflare.com/ips-v6); do
  sudo ufw allow proto tcp from "$ip" to any port 80,443
done
sudo ufw delete allow 80/tcp
sudo ufw delete allow 443/tcp
sudo ufw delete allow 'Nginx Full'
sudo ufw status numbered

Lệnh delete có thể báo không tìm thấy quy tắc nếu bạn chưa từng thêm, điều đó không sao. Lưu ý: nếu muốn gia hạn Let's Encrypt bằng HTTP-01, yêu cầu vẫn đi qua Cloudflare nên vẫn chạy được. Nếu dùng Origin CA thì không cần Certbot.

Bước 7: Cache hợp lý cho WordPress

Mặc định Cloudflare cache file tĩnh, không cache HTML. Vào Caching, Cache Rules, tạo các quy tắc theo thứ tự:

Quy tắc 1, bỏ qua cache cho trang động: chọn Edit expression và nhập:

(http.request.uri.path contains "/wp-admin") or (http.request.uri.path contains "/wp-login.php") or (http.cookie contains "wordpress_logged_in") or (http.cookie contains "woocommerce_items_in_cart")

Hành động: Bypass cache.

Quy tắc 2, cache file tĩnh lâu hơn:

(http.request.uri.path.extension in {"css" "js" "jpg" "jpeg" "png" "webp" "svg" "woff2"})

Hành động: Eligible for cache, đặt Edge TTL theo nhu cầu. Nếu tên file không đổi khi cập nhật, hãy chọn TTL ngắn hoặc nhớ Purge cache sau khi sửa CSS, JS.

Muốn cache cả HTML cho khách chưa đăng nhập, tạo thêm quy tắc Eligible for cache cho http.host eq "example.com" và đặt sau quy tắc bypass. Hãy thử kỹ với giỏ hàng, form và trang thành viên trước khi dùng thật.

Bước 8: Chặn bot cơ bản

Vào Security, Bots và bật Bot Fight Mode. Sau đó tạo quy tắc WAF tùy chỉnh (gói Free có giới hạn số quy tắc). Ví dụ thách thức các truy cập vào trang đăng nhập từ ngoài Việt Nam, trừ bot đã xác minh:

(http.request.uri.path in {"/wp-login.php" "/xmlrpc.php"} and ip.src.country ne "VN" and not cf.client.bot)

Hành động: Managed Challenge. Nếu bạn hoặc quản trị viên hay đi nước ngoài, cân nhắc điều kiện khác, ví dụ chỉ chặn xmlrpc.php.

Kiểm tra lại

  • curl -sI https://example.com có server: cloudflare và cf-ray.
  • File tĩnh có header cf-cache-status: HIT sau vài lần tải: curl -sI https://example.com/wp-includes/css/dist/block-library/style.min.css | grep -i cf-cache.
  • Trang /wp-admin có cf-cache-status: BYPASS hoặc DYNAMIC.
  • Access log Nginx hiện IP thật của khách, không phải IP Cloudflare.
  • Gọi thẳng IP gốc bị từ chối: curl -I --resolve example.com:443:203.0.113.10 https://example.com từ máy ngoài không trả kết quả.

Lỗi thường gặp và cách xử lý

ERR_TOO_MANY_REDIRECTS

Thường do chế độ SSL đang là Flexible trong khi máy chủ gốc ép HTTPS. Chuyển sang Full (strict).

Lỗi 526 Invalid SSL certificate

Chế độ Full (strict) nhưng chứng chỉ gốc không hợp lệ, hết hạn hoặc không khớp tên miền. Kiểm tra đường dẫn trong ssl_certificate và tên miền trên chứng chỉ.

Lỗi 521 hoặc 522

Cloudflare không kết nối được máy chủ gốc. Kiểm tra Nginx còn chạy, cổng 443 có mở cho dải IP Cloudflare, và IP trong bản ghi A đúng.

Đã sửa giao diện mà khách vẫn thấy bản cũ

Vào Caching, Configuration, chọn Purge cache theo URL hoặc Purge Everything. Khi đang phát triển, bật Development Mode để tạm bỏ qua cache.