Blog / Linux/ Set Up Dynamic DNS (DDNS) on CentOS Using DNSPod for External Access

Set Up Dynamic DNS (DDNS) on CentOS Using DNSPod for External Access

centos系统利用dnspod 动态解析域名ddns外网穿透

Prerequisites

Before you begin, ensure you have the following:

  • A server or virtual machine running CentOS.
  • A domain hosted on DNSPod.
  • Your DNSPod API Token (ID and Token). You can create this in the 'API Keys' section of the DNSPod control panel.

Create the DDNS Script

First, create a shell script to dynamically update DNS records.

  1. Create the script file using a text editor:

    vim /root/ddns.sh
  2. Copy and paste the following script content into the file. Read the comments to understand each section.

    #!/bin/sh
    
    # Global variables
    arPass=arMail=""
    
    # Get public IP address
    arIpAdress() {
        local inter="http://members.3322.org/dyndns/getip"
        wget --quiet --no-check-certificate --output-document=- $inter
    }
    
    # Query domain IP
    # Parameter: Domain to query
    arNslookup() {
        local dnsvr="114.114.114.114"
        nslookup ${1} $dnsvr | tr -d 'n[:blank:]' | awk -F':' '{print $6}'
    }
    
    # Call API
    # Parameters: API endpoint, POST data
    arApiPost() {
        local agent="Ddns/3.08"
        local inter="https://dnsapi.cn/${1:?'Info.Version'}"
        local param="login_token=${arID},${arToken}&format=json&${2}"
        wget --quiet --no-check-certificate --output-document=- --user-agent=$agent --post-data $param $inter
    }
    
    # Update DNS record
    # Parameters: Root domain, Subdomain
    arDdnsUpdate() {
        local domainID recordID recordRS recordCD
        # Get domain ID
        domainID=$(arApiPost "Domain.Info" "domain=${1}")
        domainID=$(echo $domainID | sed 's/.*"id":"([0-9]*)".*/1/')
        # Get record ID
        recordID=$(arApiPost "Record.List" "domain_id=${domainID}&sub_domain=${2}")
        recordID=$(echo $recordID | sed 's/.+[{"id":"([0-9]+)".+/1/')
        # Update record IP
        recordRS=$(arApiPost "Record.Ddns" "domain_id=${domainID}&record_id=${recordID}&sub_domain=${2}&record_line=默认")
        recordCD=$(echo $recordRS | sed 's/.+{"code":"([0-9]+)".+/1/')
        # Output IP if successful
        if [ "$recordCD" == "1" ]; then
            echo $recordRS | sed 's/.+,"value":"([0-9.]+)".+/1/'
            return 1
        fi
        # Output error message
        echo $recordRS | sed 's/.+,"message":"([^"]+)".+/1/'
    }
    
    # Check and update if IP changed
    # Parameters: Root domain, Subdomain
    arDdnsCheck() {
        local postRS
        local hostIP=$(arIpAdress)
        local lastIP=$(arNslookup "${2}.${1}")
        echo "hostIP: ${hostIP}"
        echo "lastIP: ${lastIP}"
        if [ "$lastIP" != "$hostIP" ]; then
            postRS=$(arDdnsUpdate $1 $2)
            echo "postRS: ${postRS}"
            if [ $? -ne 1 ]; then
                return 0
            fi
        fi
        return 1
    }
    
    ###################################################
    
    # Set user parameters
    arID="YOUR_API_ID"
    arToken="YOUR_API_TOKEN"
    # Replace YOUR_API_ID and YOUR_API_TOKEN with your actual DNSPod API credentials
    
    # Check and update domain
    # Format: arDdnsCheck "root_domain" "subdomain"
    # Example: Update lab.example.com
    arDdnsCheck "example.com" "lab"

Configure Script Parameters

Modify these three key sections at the end of the script:

  1. API Credentials: Replace the values of arID and arToken with your actual DNSPod API ID and Token.
  2. Target Domain: Change the parameters of the arDdnsCheck function. The first parameter is your root domain (e.g., example.com), the second is the subdomain or host record (e.g., lab). The script will update the A record for lab.example.com.
  3. (Optional) Add More Domains: Duplicate the arDdnsCheck line to set up DDNS for multiple subdomains or different domains.

Set Script Permissions and Cron Job

1. Grant Execute Permission

After saving the script, make it executable:

chmod +x /root/ddns.sh

2. Add to Cron (Scheduled Task)

To have the script check and update IP regularly, add it to the system's cron. This command sets it to run every 5 minutes:

echo "*/5 * * * * root /root/ddns.sh" >> /etc/crontab

Note: Ensure the script path /root/ddns.sh matches your actual location.

After adding, the cron service will load the new configuration. Monitor execution via the log:

tail -f /var/log/cron

Common Issues and Solutions

Issue 1: "nslookup: command not found"

Symptom: Error when running the script:

./ddns.sh: line 24: nslookup: command not found

Cause: DNS query tools are not installed.

Solution: Install the appropriate package:

  • CentOS / RHEL / Fedora:
    yum -y install bind-utils
  • Ubuntu / Debian:
    sudo apt-get install dnsutils

Issue 2: "Domain id invalid"

Symptom: Script returns error: postRS: Domain id invalid.

Cause: The regex for extracting the domain ID in older scripts may not match the JSON format returned by the DNSPod API.

Solution: The script provided here uses the corrected expression: sed 's/.*"id":"([0-9]*)".*/1/'. If you obtained the script elsewhere, ensure this line matches the one above.

How the Script Works

  1. Get Public IP: Queries an external service (http://members.3322.org/dyndns/getip) to obtain the server's current public IP address.
  2. Query Current DNS Record: Uses nslookup to find the IP address currently associated with the specified domain.
  3. Compare IPs: If the public IP differs from the DNS record IP, it calls the DNSPod API to update.
  4. Update via API: Sends a request to DNSPod's Record.Ddns endpoint to update the A record value for the domain.

This process implements Dynamic DNS (DDNS) using DNSPod, ensuring your domain always points to your changing public IP address, suitable for home broadband or servers with dynamic IPs.

Post a Comment

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