Tự động cập nhật IP động cho tên miền bằng Cloudflare API

5/5 - (1 vote)

Bản ghi DNS trên Cloudflare hiện đang tĩnh và không hoạt động tốt với các địa chỉ IP động. Bây giờ, để giải quyết vấn đề đó, bạn cần thiết lập DNS động. Dành cho những bạn đang dùng dịch vụ của Cloudflare, Cloudflare đã cung cấp API cho phép bạn quản lý bản ghi DNS theo lập trình.

Đa số các bạn có homelab đều thuê Internet dùng IP động, nên khi IP trên router bị thay đổi bạn sẽ phải truy cập vào bản ghi DNS trên Cloudflare để thay đổi IP thủ công.

MỤC LỤC

Hướng dẫn tự động cập nhật IP động Cloudflare API

1. Thêm đoạn script tự động cập nhật IP vào máy chủ Linux

				
					$ mkdir cloudflare-ddns.sh
$ chmod 744 cloudflare-ddns.sh

				
			

Thêm đoạn phía dưới vào tệp cloudflare-ddns.sh

				
					#!/bin/bash

# Forked from benkulbertis/cloudflare-update-record.sh
# CHANGE THESE

# API Token (Recommended)
#####                                                                             #####
# WARNING: If you put any value inside the API Token variable,                        #
#            the script will automatically use the token and omit the Global API key, #
#            regardless if the Global API key is defined or not.                      #
#####                                                                             #####
auth_token="xxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

# Domain and DNS record for synchronization
zone_identifier="f1nd7h3fuck1n6z0n31d3n71f13r4l50" # Can be found in the "Overview" tab of your domain
record_name="ipv4.example.org"                     # 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":false,"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
				
			

Source code: Link

Bạn phải sửa 3 thông tin sau trong đoạn mã:

  • auth_token: API Token được tạo từ Cloudflare
  • zone_identifier: Có thể tìm thấy trong “Overview” tab tên miền của bạn
  • record_name: Tên miền muốn cập nhật IP động

Mặc định, script sẽ không bật Proxy Cloudflare. Nếu bạn muốn bật Proxy Cloudflare thì thay đổi thông số “proxied”:false thành “proxied”:true trong đoạn script.

2. Tạo Cloudflare API Token

Chọn hình Profile phía trên bên phải > My Profile.

Chọn API tab  > Create Token.

Use template.

Chọn tên Miền ở mục Zone Resources Continue to summary.

Create Token.

Token này chỉ xem được lúc vừa tạo xong và sẽ không thể xem lại trên Cloudflare vì bảo mật. Nếu mất Token thì phải tạo lại Token mới.

Sao chép API Tokens và dán vào auth_token trong đoạn script.

Quay lại API Tokens tab và xác nhận sự tồn tại của mã API Tokens bạn đã tạo.

3. Thông tin Zone Identifier

Chọn tên miền trong Websites tab.

Cuộn xuống phía dưới, mục API. Lúc này, sao chép Zone ID và dán vào zone_identifier trong đoạn script.

4. Tạo A Record cho tên miền

IPv4 address hãy đặt sang một dãy IP khác với WAN IP, để kiểm tra script ở bước 6.

Sau khi tạo thành công A record sẽ giống như hình.

5. Script hoàn chỉnh

Mặc định, script sẽ không bật Proxy Cloudflare. Nếu bạn muốn bật Proxy Cloudflare thì thay đổi thông số “proxied”:false thành “proxied”:true trong đoạn script.

				
					#!/bin/bash

# Forked from benkulbertis/cloudflare-update-record.sh
# CHANGE THESE

# API Token (Recommended)
#####                                                                             #####
# WARNING: If you put any value inside the API Token variable,                        #
#            the script will automatically use the token and omit the Global API key, #
#            regardless if the Global API key is defined or not.                      #
#####                                                                             #####
auth_token="rwchQxtxxxxxxxxxxxxxxxx_xxxxxEID4zgVofyO"

# Domain and DNS record for synchronization
zone_identifier="b4nd7h3fuck1n6z0n31d3n71f13r4l50" # Can be found in the "Overview" tab of your domain
record_name="htctips.net"                     # 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
				
			

6. Thử nghiệm

Hãy nhớ thêm quyền thực thi cho tệp.

				
					$ chmod 744 cloudflare-ddns.sh

				
			

Bắt đầu thử nghiệm:

				
					$ ./cloudflare-ddns.sh
Check Initiated
  > Fetched current external network IP: 221.133.111.151
  > Fetched current DNS record value   : 111.111.111.111
  > Different IP addresses detected, synchronizing...
Update for A record 'htctips.net (82xxxxxxxxxxxxxxxxxxxxxxxxxxxxe5)' succeeded.
  - Old value: 111.111.111.111
  + New value: 221.133.111.151

				
			

Quay lại, kiểm tra DNS Record trên Cloudflare sẽ nhìn thấy bị thay đổi sang địa chỉ IP mới.

7. Thiết lập crontab tự động

Tốt hơn bạn nên để nó tự động chạy lệnh thay vì lệnh chạy thủ công.

				
					$ crontab -e
				
			

Script sẽ tự động chạy sau mỗi 10 phút.

Thêm vào dòng cuối cùng:

				
					*/10 * * * * /root/cloudflare-ddns.sh

				
			

Chúc các bạn thực hiện thành công tự động cập nhật IP động cho tên miền bằng Cloudflare API sau bài viết này! Mọi thắc mắc vui lòng comment phía dưới bài viết hoặc liên hệ mình nhé!

Source: benkulbertis

Leave a Reply

Your email address will not be published. Required fields are marked *