Tự động cập nhật IP động lên Cloudflare với Custom Domain (Cloudflare DDNS Script)
Khi bạn tự vận hành một máy chủ hoặc hệ thống Home Lab tại nhà (như Raspberry Pi, Mini PC chạy Ubuntu, Docker, NAS...), bạn sẽ đối mặt với vấn đề đường truyền mạng gia đình sử dụng IP Public động. IP này sẽ liên tục thay đổi sau vài ngày hoặc mỗi khi Router nhà mạng khởi động lại.
Nếu bạn muốn truy cập các dịch vụ nội bộ này từ bên ngoài bằng tên miền riêng (ví dụ: ssh.yourdomain.com, status.yourdomain.com) thay vì ghi nhớ địa chỉ IP, bạn bắt buộc phải có cơ chế cập nhật tự động địa chỉ IP mới lên Cloudflare mỗi khi có sự thay đổi. Giải pháp tốt nhất chính là sử dụng Cloudflare DDNS Bash Script kết hợp với Cron Job.
Bài viết này sẽ hướng dẫn chi tiết từ A-Z cách tạo API Token, viết Script cập nhật IP tự động và lập lịch chạy trên Linux một cách an toàn và chuyên nghiệp nhất.
1. Cơ chế hoạt động của Cloudflare DDNS Script
Hệ thống hoạt động dựa trên các bước đơn giản nhưng vô cùng hiệu quả:
- Lấy IP Public hiện tại: Máy chủ tại nhà sử dụng lệnh
curlgọi tới các dịch vụ bên ngoài (nhưapi.ipify.orghoặcicanhazip.com) để lấy IP WAN thực tế. - Lấy IP đang cấu hình trên Cloudflare: Script gọi tới Cloudflare API v4 để kiểm tra xem bản ghi DNS của tên miền hiện đang trỏ về IP nào.
- So sánh:
- Nếu hai địa chỉ IP trùng nhau: Kết thúc (không làm gì cả để tránh lãng phí tài nguyên mạng và API call limit).
- Nếu IP khác nhau (nhà mạng vừa đổi IP): Script sẽ gửi yêu cầu
PATCH/PUTlên API Cloudflare để cập nhật IP mới ngay lập tức.
- Lập lịch: Sử dụng Cron Job của Linux để tự động thực thi script này mỗi 5 phút.
2. Các bước chuẩn bị trên tài khoản Cloudflare
Trước khi viết script, bạn cần lấy 3 thông tin quan trọng từ tài khoản Cloudflare của mình: Zone ID, Record ID (ID bản ghi DNS), và API Token có quyền ghi DNS.
Bước 1: Lấy Zone ID của tên miền
- Đăng nhập vào bảng điều khiển Cloudflare.
- Chọn tên miền của bạn (ví dụ:
yourdomain.com). - Tại trang tổng quan (Overview), kéo xuống cột bên phải, bạn sẽ thấy mục Zone ID. Hãy sao chép chuỗi mã này lại.
Bước 2: Tạo API Token an toàn
Để bảo mật, chúng ta không dùng Global API Key (vì lộ Key này sẽ mất toàn quyền kiểm soát tài khoản). Thay vào đó, hãy tạo một API Token chỉ có quyền chỉnh sửa DNS trên một Zone cụ thể:
- Nhấp vào ảnh đại diện của bạn ở góc trên bên phải -> chọn My Profile.
- Chọn tab API Tokens -> nhấn Create Token.
- Tìm dòng Edit zone DNS và nhấn Use template.
- Tại mục Permissions, đảm bảo cấu hình là:
Zone|DNS|Edit. - Tại mục Zone Resources, chọn:
Include|Specific zone| Chọn tên miền của bạn (ví dụ: yourdomain.com). - Nhấn Continue to summary -> Create Token.
- Sao chép mã API Token hiển thị trên màn hình. (Mã này chỉ hiển thị một lần duy nhất).
3. Tạo bản ghi DNS ban đầu trên Cloudflare
Trước khi chạy script cập nhật, bản ghi DNS đó phải tồn tại sẵn trên Cloudflare.
- Vào mục DNS -> Records trên Cloudflare.
- Nhấn Add record để tạo bản ghi mới:
- Type:
A - Name: Điền subdomain bạn muốn trỏ (Ví dụ:
sshhoặc@cho domain gốc). - IPv4 address: Nhập tạm một IP bất kỳ (Ví dụ:
1.1.1.1). Script sẽ tự động cập nhật về IP thật sau. - Proxy status: Tắt đám mây màu cam (DNS Only - màu xám) nếu bạn cần cấu hình VPN, SSL ACME Challenge hoặc các dịch vụ không đi qua cổng HTTP/HTTPS.
- Type:
Hình 1: Tạo bản ghi loại A với IP nháp trước khi đồng bộ.
4. Viết Bash Script cập nhật DDNS tự động
Chúng ta sẽ chia cấu hình thành 2 phần: File chứa thông tin nhạy cảm (cloudflare-ddns.conf) và Script thực thi chính (cloudflare-ddns.sh).
Bước 1: Tạo file cấu hình cloudflare-ddns.conf
Tạo file để lưu trữ các thông tin cấu hình bảo mật:
# Thông tin xác thực Cloudflare
TOKEN="MÃ_API_TOKEN_BƯỚC_2"
ZONE_ID="MÃ_ZONE_ID_BƯỚC_1"
# Danh sách các bản ghi cần đồng bộ định dạng: RECORD_label="RECORD_ID:TÊN_MIỀN"
RECORD_ssh="mã_record_id:ssh.yourdomain.com"
RECORD_apex="mã_record_id:yourdomain.com"
(Lưu ý: Để lấy được RECORD_ID, bạn có thể thực hiện lệnh gọi API GET DNS Records của Cloudflare, hoặc sau khi chạy script lần đầu, script có thể báo lỗi nhưng có kèm ID bản ghi).
Bước 2: Viết Script thực thi cloudflare-ddns.sh
Tạo file script chính với nội dung xử lý tối ưu sau:
#!/usr/bin/env bash
# Tự động cập nhật IP động lên Cloudflare API v4
# Lưu script tại ~/ddns/cloudflare-ddns.sh
set -euo pipefail
CONFIG="/home/username/ddns/cloudflare-ddns.conf"
LOG="/home/username/ddns/ddns.log"
[ -f "$CONFIG" ] || { echo "$(date -Is) ERROR: Không tìm thấy file cấu hình tại $CONFIG" >> "$LOG"; exit 1; }
set -a; source "$CONFIG"; set +a
log() { echo "$(date -Is) $*" >> "$LOG"; }
# 1. Lấy địa chỉ IP Public IPv4 hiện tại của mạng nhà
CUR_IP="$(curl -s -4 --max-time 15 https://api.ipify.org || true)"
if [ -z "$CUR_IP" ]; then
log "WARN: Không thể lấy IP Public hiện tại (Kết nối mạng bị gián đoạn?)"
exit 0
fi
# Đọc tất cả các bản ghi cấu hình trong file conf
RECORDS=()
for line in $(grep -E '^RECORD_[A-Za-z0-9_]+=' "$CONFIG" | sed 's/^RECORD_[^=]*=//'); do
RECORDS+=("$line")
done
if [ "${#RECORDS[@]}" -eq 0 ]; then
log "ERROR: Không có bản ghi nào được định nghĩa trong file cấu hình"
exit 1
fi
# 2. Vòng lặp kiểm tra và cập nhật cho từng bản ghi
for entry in "${RECORDS[@]}"; do
RECORD_ID="${entry%%:*}"
RECORD_NAME="${entry##*:}"
# Truy vấn IP hiện tại trên Cloudflare DNS
DNS_IP="$(curl -s --max-time 15 "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" -H "Authorization: Bearer $TOKEN" | python3 -c 'import sys,json;print(json.load(sys.stdin)["result"]["content"])' 2>/dev/null || true)"
# Nếu IP trùng nhau thì bỏ qua không cập nhật
if [ "$CUR_IP" = "$DNS_IP" ]; then
continue
fi
log "Phát hiện đổi IP cho $RECORD_NAME: $DNS_IP -> $CUR_IP. Đang đồng bộ..."
# Gửi yêu cầu cập nhật lên Cloudflare API
RESP="$(curl -s --max-time 20 -X PATCH "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" --data "{"content":"$CUR_IP","ttl":120,"proxied":false}")"
if echo "$RESP" | grep -q '"success":true'; then
log "Đồng bộ thành công: $RECORD_NAME hiện tại trỏ về -> $CUR_IP"
else
log "ERROR: Cập nhật thất bại cho $RECORD_NAME: $(echo "$RESP" | head -c 300)"
fi
done
Bước 3: Cấp quyền thực thi và test thử
- Cấp quyền chạy cho file script:
chmod +x /home/username/ddns/cloudflare-ddns.sh - Chạy kiểm tra thử bằng tay:
/home/username/ddns/cloudflare-ddns.sh - Theo dõi file log xem quá trình đồng bộ:
cat /home/username/ddns/ddns.log
Hình 2: Kiểm tra bản ghi trên bảng điều khiển Cloudflare đã được tự động cập nhật IP mới.
5. Lập lịch tự động chạy bằng Cron Job (Tự động 24/7)
Để hệ thống hoàn toàn tự động bám đuổi IP mà không cần bạn can thiệp thủ công:
- Mở trình soạn thảo Crontab của Linux bằng lệnh:
crontab -e - Thêm dòng sau vào cuối file để chạy script tự động mỗi 5 phút một lần:
*/5 * * * * /bin/bash /home/username/ddns/cloudflare-ddns.sh >/dev/null 2>&1 - Lưu lại và thoát ra. Dịch vụ cron daemon sẽ tự động nạp lịch mới và thực thi định kỳ.
6. Tổng kết & Lưu ý bảo mật
- API Token Scope: Luôn cấu hình Token giới hạn trong quyền
DNS:Editvà chỉ áp dụng cho đúng domain cần thiết, không cấp quá nhiều quyền thừa. - Log rotation: File log
ddns.logghi lại nhật ký thay đổi IP. Bạn nên cấu hìnhlogrotatetrên Linux để quản lý dung lượng file log tránh đầy ổ cứng về lâu dài. - TTL thấp: Cấu hình bản ghi có TTL thấp (
120giây) giúp tốc độ cập nhật DNS diễn ra nhanh hơn khi IP bị đổi đột ngột.
Giờ đây, bạn có thể hoàn toàn yên tâm chạy Web Server, Home Lab tại nhà mà không lo ngại vấn đề rớt kết nối do nhà mạng reset IP nữa! Chúc các bạn thực hiện thành công.