自动更新动态域名解析的脚本

wen 实用脚本 2

本文目录导读:

自动更新动态域名解析的脚本

  1. 方案一:Linux / macOS (Bash 脚本 + Crontab)
  2. 方案二:Windows (PowerShell 脚本 + 任务计划程序)
  3. 方案三:跨平台 Python 脚本
  4. 通用建议:

这里为您提供几个常用的自动更新动态域名解析(DDNS)的脚本,涵盖 Linux (Bash)Windows (PowerShell) 以及 Python(跨平台)版本,您可以根据自己的操作系统和路由器/服务器环境选择使用。


Linux / macOS (Bash 脚本 + Crontab)

适用场景: 树莓派、NAS、云服务器等运行 Linux 的主机。

  1. 创建脚本文件 (update_ddns.sh)

    #!/bin/bash
    # ========== 配置区(请修改为您自己的信息) ==========
    # 以阿里云为例(其他服务商类似),也可以替换为DNSPod、Cloudflare等API
    ACCESS_KEY_ID="你的AccessKeyId"
    ACCESS_KEY_SECRET="你的AccessKeySecret"
    DOMAIN="example.com"           # 根域名
    RR="www"                       # 主机记录 (www, @, nas)
    # =================================================
    # 获取当前公网IP
    # 方法1:使用 ip.sb
    CURRENT_IP=$(curl -s https://ip.sb)
    # 方法2:使用 icanhazip (备用)
    # CURRENT_IP=$(curl -s https://icanhazip.com)
    # 检查IP是否正确获取
    if [ -z "$CURRENT_IP" ]; then
        echo "$(date): 获取IP失败,退出。"
        exit 1
    fi
    echo "$(date): 检测到当前公网IP为 $CURRENT_IP"
    # 这里需要调用对应DNS服务商的API进行比对和更新。
    # 下述代码以阿里云DNS API为例(需要计算签名,过程较为复杂)。
    # 为了简化,这里使用阿里云CLI工具(假设已配置好aliyun CLI)。
    # 查询当前解析记录
    OLD_IP=$(aliyun alidns DescribeDomainRecords --DomainName "$DOMAIN" --RRKeyWord "$RR" --Type A --query "DomainRecords.Record[0].Value" --output cols=Value rows=Records)
    echo "$(date): 旧IP为 $OLD_IP"
    if [ "$CURRENT_IP" == "$OLD_IP" ]; then
        echo "$(date): IP没有变化,无需更新。"
    else
        echo "$(date): IP发生变化,正在更新DNS记录..."
        RECORD_ID=$(aliyun alidns DescribeDomainRecords --DomainName "$DOMAIN" --RRKeyWord "$RR" --Type A --query "DomainRecords.Record[0].RecordId" --output cols=RecordId rows=Records)
        # 执行更新
        aliyun alidns UpdateDomainRecord --RecordId "$RECORD_ID" --RR "$RR" --Type A --Value "$CURRENT_IP"
        echo "$(date): DNS更新完成!"
    fi
  2. 赋予执行权限

    chmod +x update_ddns.sh
  3. 添加定时任务 (Crontab): 每5分钟检查一次(建议最小间隔5分钟,避免API请求频繁):

    crontab -e

    添加以下行:

    */5 * * * * /path/to/your/update_ddns.sh >> /var/log/ddns.log 2>&1

Windows (PowerShell 脚本 + 任务计划程序)

适用场景: 运行 Windows 10/11 或 Windows Server 的主机。

  1. 创建脚本文件 (update_ddns.ps1)

    # 以 DNSPod(腾讯云)为例(免费且API简单,兼容性好)
    $DNSPodToken = "你的TokenID,你的TokenKey"  # "12345,abcdefghijklmn"
    $Domain = "example.com"
    $SubDomain = "www"  # 如果要解析根域名,留空 ""
    # 获取当前公网IP
    $CurrentIP = Invoke-RestMethod -Uri "https://ip.sb" -Method Get | Select-Object -ExpandProperty Content
    # 备用获取方式: $CurrentIP = (Invoke-RestMethod -Uri "https://api.ipify.org")
    Write-Host "检测到当前IP: $CurrentIP"
    # 获取DNS记录列表(DNSPod API)
    $RecordApi = "https://dnsapi.cn/Record.List"
    $Body = @{
        login_token = $DNSPodToken
        format = "json"
        domain = $Domain
        sub_domain = $SubDomain
    }
    $Records = Invoke-RestMethod -Uri $RecordApi -Method Post -Body $Body
    $Record = $Records.records | Where-Object { $_.type -eq "A" } | Select-Object -First 1
    if ($nil -eq $Record) {
        Write-Host "未找到A记录,创建新记录..."
        $CreateApi = "https://dnsapi.cn/Record.Create"
        $CreateBody = @{
            login_token = $DNSPodToken
            format = "json"
            domain = $Domain
            sub_domain = $SubDomain
            record_type = "A"
            record_line = "默认"
            value = $CurrentIP
        }
        Invoke-RestMethod -Uri $CreateApi -Method Post -Body $CreateBody | Out-Null
    }
    else {
        if ($Record.value -eq $CurrentIP) {
            Write-Host "IP未变化,跳过更新。"
        }
        else {
            Write-Host "IP已变化,从 $($Record.value) 更新为 $CurrentIP ..."
            $UpdateApi = "https://dnsapi.cn/Record.Modify"
            $UpdateBody = @{
                login_token = $DNSPodToken
                format = "json"
                domain = $Domain
                record_id = $Record.id
                sub_domain = $SubDomain
                record_type = "A"
                record_line = "默认"
                value = $CurrentIP
            }
            Invoke-RestMethod -Uri $UpdateApi -Method Post -Body $UpdateBody | Out-Null
        }
    }
    Write-Host "脚本执行完成。"
  2. 设置任务计划程序

    • 打开“任务计划程序”。
    • 创建任务 -> 触发器 -> 新建 -> 选择“按预定计划” -> 设置为“重复任务间隔 5 分钟”。
    • 操作 -> 新建 -> 程序填写 powershell.exe,参数添加:-ExecutionPolicy Bypass -File "C:\路径\update_ddns.ps1"

跨平台 Python 脚本

适用场景: 任何安装了 Python 3 的系统,配合系统自带的任务调度器。

import requests
import time
import logging
# ========== 配置区(请修改) ==========
# 以 Cloudflare 为例(免费、稳定、API文档清晰)
API_TOKEN = "你的Cloudflare API Token"  # 需要 Zone.DNS Edit 权限
ZONE_ID = "你的Zone ID"  # 在Cloudflare域名概览页面
RECORD_NAME = "www.example.com"  # 完整解析记录名称
# ==================================
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
def get_public_ip():
    """获取公网IPv4地址"""
    try:
        # 使用多个备用源
        for source in ['https://api.ipify.org', 'https://ip.sb', 'https://icanhazip.com']:
            try:
                ip = requests.get(source, timeout=10).text.strip()
                if ip and '.' in ip:  # 简单IPv4判断
                    return ip
            except Exception as e:
                logging.warning(f"从 {source} 获取失败: {e}")
                continue
        raise Exception("所有IP源均失败")
    except Exception as e:
        logging.error(f"获取公网IP失败: {e}")
        return None
def get_dns_record(record_name, zone_id, api_token):
    """获取当前DNS解析记录"""
    headers = {
        "Authorization": f"Bearer {api_token}",
        "Content-Type": "application/json"
    }
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records"
    params = {"name": record_name}
    try:
        response = requests.get(url, headers=headers, params=params, timeout=10)
        response.raise_for_status()
        data = response.json()
        if data["success"] and data["result"]:
            record = data["result"][0]
            return record
        else:
            logging.warning(f"未找到记录: {data.get('errors')}")
    except Exception as e:
        logging.error(f"查询DNS记录失败: {e}")
    return None
def update_dns_record(record, new_ip, zone_id, api_token):
    """更新DNS解析记录"""
    headers = {
        "Authorization": f"Bearer {api_token}",
        "Content-Type": "application/json"
    }
    data = {
        "type": "A",
        "name": record["name"],
        "content": new_ip,
        "ttl": record["ttl"],
        "proxied": record["proxied"]
    }
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records/{record['id']}"
    try:
        response = requests.put(url, headers=headers, json=data, timeout=10)
        response.raise_for_status()
        if response.json()["success"]:
            logging.info(f"更新成功:{record['name']} -> {new_ip}")
        else:
            logging.error(f"更新失败:{response.json()['errors']}")
    except Exception as e:
        logging.error(f"API请求异常: {e}")
def main():
    current_ip = get_public_ip()
    if not current_ip:
        logging.error("无法获取公网IP,退出。")
        return
    record = get_dns_record(RECORD_NAME, ZONE_ID, API_TOKEN)
    if not record:
        logging.error(f"无法获取记录 {RECORD_NAME},请检查配置。")
        return
    # 不强制代理 (Cloudflare Proxy)
    if record["content"] != current_ip:
        logging.info(f"IP变更: {record['content']} -> {current_ip}")
        update_dns_record(record, current_ip, ZONE_ID, API_TOKEN)
    else:
        logging.info(f"IP未发生变化: {current_ip}")
if __name__ == "__main__":
    main()

使用方式

  1. 将上述代码保存为 ddns_update.py,安装依赖:pip install requests
  2. 手动运行测试:python ddns_update.py
  3. 设置定时任务:
    • Linuxcrontab -e 添加 */5 * * * * /usr/bin/python3 /path/to/ddns_update.py >> /var/log/ddns.log 2>&1
    • Windows:使用“任务计划程序”创建每小时或每5分钟的基本任务。

通用建议:

  1. 日志记录:无论哪个方案,建议将输出重定向到日志文件,方便排查问题。
  2. 双栈支持:如果同时需要使用 IPv6,需要额外获取 IPv6 地址并添加 AAAA 记录,上述脚本主要以 IPv4 为例。
  3. API 选择
    • 国内环境:推荐使用 DnsPod(腾讯云)阿里云,速度较快且 API 免费。
    • 国际环境:推荐使用 Cloudflare,API 稳定,且可以免费启用 CDN 代理(但会将真实 IP 隐藏)。
  4. 密钥安全:脚本中的 API Token / Secret 请注意权限最小化,避免泄露牵连主账号安全。

抱歉,评论功能暂时关闭!