Mạng ở nhà đa số sử dụng IP động, do đó tên miền cần phải được tự động cập nhật mỗi khi Public IP thay đổi để tránh kết nối bị lỗi. Chỉ cần dùng 1 bash script chạy trên linux để tự động cập nhật IP động cho tên miền qua dịch vụ CloudFlare. Nhờ vậy tên miền luôn được trỏ đến IP mới nhất được cấp cho modem mạng ở nhà. Như thế chỉ cần mua tên miền, tài khoản cloudflare miển phí không cần phải gia hạn hằng tháng noip (không thì tốn 24$).
Trước khi tạo script cần phải có 1 số thông tin
- auth_token: Cloudflare API Token
- zone_identifier: Zone ID
- record_name: Tên miền
Tạo Cloudflare API Token
Truy cập vào trangCloudflare API Tokenđể tạo Token mới





Bạn cần lưu lại Token vừa mới tạo để lưu vào script đã tạo. Token này sẽ không hiện ra lại trên Cloudflare vì lý do bảo mật. Nếu bạn quên lưu, cần phải xoá Token và tạo lại cái mới.
Tìm thông tin Zone ID
Từ trang chủ Cloudflare, bạn bấm vào tên miền muốn sử dụng để cập nhật IP. Sau đó kéo xuống dưới sẽ thấy mục Zone ID. Lưu lại thông số này để điền vào script

Tạo A Record cho tên miền
Ví dụ mình muốn sử dụng tên miềnalibaba.thuanbui.me
để truy cập đến homelab ở nhà. Bấm vào Add record và tạo một A record mới.
- Name: điền vào
alibaba
- IPv4: điền tạm
1.1.1.1
, thông số này sẽ được tự động cập nhật về IP của modem sau khi chạy script.

Tạo script
cd ~
mkdir cloudflare
cd cloudflare
nano cloudflare.sh
Nội dung https://thuanbui.me/cap-nhat-ip-dong-cho-ten-mien-qua-cloudflare-de-truy-cap-homelab-tai-nha/:
#!/bin/bash
# Forked from benkulbertis/cloudflare-update-record.sh
# CHANGE THESE
# API Token (Recommended) #####
auth_token=“LrAB–xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx”
# Domain and DNS record for synchronization zone_identifier=“48bxxxxxxxxxxxxxxxxxxxx60”
# Can be found in the “Overview” tab of your domain record_name=“alibaba.thuanbui.me” # Which record you want to be synced
# DO NOT CHANGE LINES BELOW # SCRIPT START
echo -e “Check Initiated”
# Check for current external network IP
ip=$(curl -s4 https://icanhazip.com/)
if [[ ! -z “${ip}“ ]]; then echo -e ” > Fetched current external network IP: ${ip}“
else >&2 echo -e “Network error, cannot fetch external network IP.”
fi
# The execution of update
if [[ ! -z “${auth_token}“ ]]; then header_auth_paramheader=( -H ‘”Authorization: Bearer ‘${auth_token}‘”‘ ) else header_auth_paramheader=( -H ‘”X-Auth-Email: ‘${auth_email}‘”‘ -H ‘”X-Auth-Key: ‘${auth_key}‘”‘ ) fi
# Seek for the record
seek_current_dns_value_cmd=( curl -s -X GET ‘”https://api.cloudflare.com/client/v4/zones/’${zone_identifier}‘/dns_records?name=’${record_name}‘&type=A”‘ “${header_auth_paramheader[@]}“ -H ‘”Content-Type: application/json”‘ ) record=`eval ${seek_current_dns_value_cmd[@]}`
# Can’t do anything without the record
if [[ -z “${record}“ ]]; then >&2 echo -e “Network error, cannot fetch DNS record.” exit 1 elif [[ “${record}“ == *‘”count”:0’* ]]; then >&2 echo -e “Record does not exist, perhaps create one first?” exit 1 fi # Set the record identifier from result record_identifier=`echo “${record}” | sed ‘s/.*”id”:”//;s/”.*//’`
# Set existing IP address from the fetched record
old_ip=`echo “${record}” | sed ‘s/.*”content”:”//;s/”.*//’` echo -e ” > Fetched current DNS record value : ${old_ip}“
# Compare if they’re the same
if [ “${ip}“ == “${old_ip}“ ]; then echo -e “Update for A record ‘${record_name} (${record_identifier})’ cancelled.\\n Reason: IP has not changed.” exit 0 else echo -e ” > Different IP addresses detected, synchronizing…” fi # The secret sause for executing the update json_data_v4=“‘”‘{“id”:“‘${zone_identifier}‘”,“type”:“A”,“proxied”:true,“name”:“‘${record_name}‘”,“content”:“‘${ip}‘”,“ttl”:120}‘”‘” update_cmd=( curl -s -X PUT ‘”https://api.cloudflare.com/client/v4/zones/’${zone_identifier}‘/dns_records/’${record_identifier}‘”‘ “${header_auth_paramheader[@]}“ -H ‘”Content-Type: application/json”‘ )
# Execution result
update=`eval ${update_cmd[@]} –data $json_data_v4`
# The moment of truth
case “$update“ in *‘”success”:true’*) echo -e “Update for A record ‘${record_name} (${record_identifier})’ succeeded.\\n – Old value: ${old_ip}\\n + New value: ${ip}“;; *) >&2 echo -e “Update for A record ‘${record_name} (${record_identifier})’ failed.\\nDUMPING RESULTS:\\n${update}“ exit 1;;
esac
Mặc định, script này sẽ kích hoạt chế độ proxy trên Cloudflare nhằm mục đích ẩn IP của modem, giảm nguy cơ bị tấn công vào mạng nhà. Nếu vì lý do nào đó không muốn ẩn IP của mình thì có thể thay đổi thông số"proxied":true
thành"proxied":false
Thiết lập quyền thực thi cho file cloudflare.sh
chmod +X cloudflare.sh
Chạy thử xem nào: ./cloudflare.sh
Quay lại Cloudflare, tên miềnalibaba.thuanbui.me
, mình thấy đã được tự động cập nhật với IP mới. Ngon lành!
Thiết lập chạy tự động
Việc thiết lập cron để script tự động hay rc.local có vẽ không được khi máy chưa có vô mạng, nên một dịch vụ riêng để chạy với systemd. Với một dịch vụ systemd làm cho service hợp lệ và hoạt động sau khi có mạng.
Bây giờ bạn đã tạo file service: sudo nano /etc/systemd/system/cloudflare.service
[Unit] Description=Update ip to dns cloudflare service. After=network-online.target [Service] Type=oneshot User=root ExecStart= /bin/bash /home/user/cloudflare/cloudflare.sh RemainAfterExit=yes [Install] WantedBy=network-online.target
Kích hoạt cho dịch vụ khởi động cùng hệ thống:
sudo systemctl enable cloudflare.service sudo systemctl start cloudflare.service sudo systemctl stop cloudflare.service
Lưu ý: After=network.target không chạy được do máy khởi động lên là systemd đã chạy nên gây ra lỗi phần này, nên thay bằng:
[Unit] Wants=network.target network-online.target After=network.target network-online.target
Mục tiêunetwork-online
là nó không tồn tại trừ khi bạn đang sử dụng một phương pháp “modern” để nâng cấp mạng của mình, nhưNetworkManagerhoặcsystemd-networkd.
Nếu bạn không làm điều đó thìsystemdsẽ tính ra rằngnetwork-online
không bao giờ có thể đạt được mục tiêu và bỏ qua nó dưới dạng tệpWant
.
Tôi đang sử dụngifupdowntrên máy chủ vì nó vẫn thực hiện mọi thứ tôi cần. Đểifupdownhỗ trợnetwork-online
mục tiêu trên Debian, bạn nên kích hoạt dịch vụ ifupdown-wait-online
:
sudo systemctl kích hoạt ifupdown-wait-online.service
Điều này sẽ đưa vàonetwork-online
trạng thái “đạt được mục tiêu” khi mọi giao diện được đánh dấu là “tự động” trong/etc/network/interfacesđều hoạt động.
Vi du nhu:
[Unit] Description=ChatGPT assistant Wants=network-online.target After=network-online.target After=multi-user.target [Service] Type=simple User=pi WorkingDirectory=/home/pi ExecStartPre=/bin/sh -c 'until ping -c1 google.com; do sleep 1; done;' ExecStart=/usr/bin/python3 /home/pi/chat.py [Install] WantedBy=multi-user.target
Sau do cho systemd biet service moi:
sudo systemctl daemon-reload
Kiem tra xem chay : systemctl start chat.service
Thiết lập SSL miễn phí.
Đầu tiên bạn cần đảm bảo rằng website đã thêm vào CloudFlare và bật Proxy (đám mây màu vàng) thành công.
Tiếp đó, bạn truy cập vàoSSL/TLS=>Overview=> chọnFlexiblelà hoàn tất và bạn không cần làm gì thêm.
chứng chỉ do chính CloudFlare cung cấp.
Bước 1: Chọn kiểu SSL
Bạn truy cập vàoSSL/TLS=>Overview=> chọnFullhoặcFull(strict).

Bước 2: Tạo chứng chỉ SSL
Bạn truy cập vàoSSL/TLS=>Origin Server=>Create Certificate

ChọnGenerate private key and CSR with Cloudflare, rồi nhấnCreate.


Lúc này CloudFlare sẽ cung cấp cho bạn 2 nội dungOrigin CertificatevàPrivate Key. Bạn tiến hành copy và lưu lại nội dung 2 File này (quan trọng), sau khi đã lưu xong bạn chọnOK.

Copy nội dung vào 2 file cert.pem và privatekey.key
- sudo nano /home/user/ssl/cert.pem
- sudo nano /home/user/ssl/privatekey.key
- sudo chmod -R 755 /home/user/ssl
Tiếp đó bạn cần chờ vài phút để CloudFlare duyệt chứng chỉ. Nếu hiển thị như hình bên dưới là chứng chỉ đã được cấp phát và có thể sử dụng.

Bước 3: Cài đặt chứng chỉ lên máy chủ.
Thiết lập nội dung vô tên miền
sudo nano /etc/nginx/sites-available/your_domain
Nội dung https://www.digitalocean.com/community/tutorials/how-to-host-a-website-using-cloudflare-and-nginx-on-ubuntu-22-04:
server {
listen 80;
listen [::]:80;
server_name your_domain;
return 302 https://$server_name$request_uri;
}
server {
# SSL configuration
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /home/user/ssl/cert.pem;
ssl_certificate_key /home/user/ssl/privatekey.key;
server_name your_domain;
root /var/www/your_domain/html;
index index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ =404;
}
}
sudo nginx -t
Không có báo lỗi thì bắt đầu cho chạy:
sudo ln -s /etc/nginx/sites-available/your_domain /etc/nginx/sites-enabled/
sudo systemctl restart nginx
Lưu ý proxied":true
bật Proxy (đám mây màu vàng)
SSL cho noip hơi tốn tiền
RapidSSL Basic DV tốn $20, không thì mua No-IP Vital Encrypt DV giảm còn $8.
Tạo CSR thông tin tên miền.
Sử dụngTrình hướng dẫn DigiCert OpenSSL CSRđể tạo lệnh OpenSSL nhằm tạo Nginx CSR của bạn. Chỉ cần điền vào biểu mẫu, nhấp vàoTạorồi dán lệnh OpenSSL tùy chỉnh vào thiết bị đầu cuối của bạn.
Hoặc dùng công cụCsrgenerator.Comđể bắt đầu tạo.
LƯU Ý:Sau khi tạo CSR sẽ cóPRIVATE KEY đây là khóa đi kèm nên bạn phải lưu giữ không được làm mất. Vì khi mất KEY bạn sẽ không import được chứng chỉ CRT (Certificate) vào server/hosting được mà phải làm lại từ đầu. Sau khi có thông tin CSR, bạn có thể bắt đầu các thao tác chứng thực chứng chỉ SSL. File này có thể dùng cho lần tạo chứng thực sau này hết hạn.
1 File key chỉ chứa: —–BEGIN PRIVATE KEY—– cho đến —–END PRIVATE KEY—–. Nạp vào ssl_certificate_key.
Còn 1 file pem lấy từ No-IP Vital Encrypt DV thì Download Certificate chọn Chuỗi PEM (Khuyến nghị) Bao gồm tất cả các chứng chỉ cần thiết trong một tệp. Định dạng này bao gồm các chứng chỉ CA trung gian và được các máy chủ web phổ biến hỗ trợ để tích hợp dễ dàng nhất. Nó chứa toàn bộ 3 —–BEGIN CERTIFICATE—– —–END CERTIFICATE—–. File này nạp vào ssl_certificate
Cách 2 dùng câu lệnh openssl req –new –newkey rsa:2048 –nodes –keyout domain.key –out domain.csr
- Tiến trình bắt đầu quá trình tạo hai tệp sau:
- Tệp khóa riêng: Được sử dụng để tạo CSR trở lên để bảo mật và xác minh các kết nối bằng chứng chỉ.
- Tệp Yêu cầu ký chứng chỉ (CSR): Được sử dụng để đặt hàng chứng chỉ SSL của bạn và sau đó để mã hóa các tin nhắn mà chỉ khóa riêng tương ứng của nó mới có thể giải mã.
- Khi được nhắc vềCommon Name(tên miền), hãy nhập tên miền đủ điều kiện (FQDN) cho trang web mà bạn sắp bảo mật.
Lưu ý:Nếu bạn đang tạo Nginx CSR chochứng chỉ Wildcard, hãy đảm bảo tên chung của bạn bắt đầu bằng dấu hoa thị (ví dụ:*.example.com).
- Khi được nhắc, hãy nhập thông tin tổ chức của bạn, bắt đầu bằng thông tin địa lý của bạn.
Lưu ý:Có thể bạn đã thiết lập thông tin mặc định.
- Bây giờ, tệp .csr của bạn sẽ được tạo.
Nạp CSR vào download CRT.
- Bạn cần ghép tệp chứng chỉ chính (your_domain_name.crt) và tệp chứng chỉ trung gian (DigiCertCA.crt) thành một tệp .pem.
- Để nối các tập tin, hãy chạy lệnh sau:
cat your_domain_name.crt DigiCertCA.crt >> bundle.crt
- add the lines in bold below:
server {
listen 443;
ssl on;
ssl_certificate /etc/ssl/bundle.crt
ssl_certificate_key /etc/ssl/your_domain_name.key;
server_name your.domain.com;
access_log /var/log/nginx/nginx.vhost.access.log;
error_log /var/log/nginx/nginx.vhost.error.log;
location / {
root /home/www/public_html/your.domain.com/public/;
index index.html;
}
}
Chạy lệnh sau để khởi động lại Nginx: sudo /etc/init.d/nginx restart
Mở trình duyệt web và truy cập trang web của bạn bằng https. Trình duyệt sẽ đưa ra cảnh báo nếu chứng chỉ trung gian của bạn chưa được cài đặt. Bạn sẽ không nhận được bất kỳ cảnh báo hoặc lỗi nào của trình duyệt.
- Nếu bạn ngay lập tức nhận được thông báo trình duyệt về việc trang web không khả dụng thì Nginx có thể chưa được nghe trên cổng 443.
- Nếu yêu cầu web của bạn mất nhiều thời gian và hết thời gian, tường lửa có thể đang chặn lưu lượng truy cập trên cổng TCP 443 tới máy chủ web.
- Nếu bạn nhận được cảnh báo “không đáng tin cậy”, hãy xem chứng chỉ để xem đó có phải là chứng chỉ bạn mong đợi hay không.
- Khi bạn xem chứng chỉ, hãy kiểm tra cáctrường Chủ đề,Nhà phát hànhvà Hợplệ cho
- Nếu bạn phải nối các tệp chứng chỉ thì chứng chỉ chính của bạn (ví dụ:your_domain_name.crt) có thể không được kết hợp chính xác với chứng chỉ trung gian.
Để biết thêm thông tin, hãy xemtài liệu Nginx SSL.
Bài viết liên quan: