DDNS动态域名解析方案对比与实战配置

本文详解DDNS工作原理、主流方案对比,以及在各种场景下的实战配置。

前言

家里的宽带IP是动态的,每次重启光猫IP就变了。想从外面访问家里的服务器,怎么办?

DDNS(Dynamic DNS) 就是解决这个问题的:自动检测IP变化,自动更新域名解析。

今天来聊聊各种DDNS方案的选择和配置。


一、DDNS原理

1.1 动态IP的问题

运营商给家庭宽带分配的通常是动态公网IP:

  • IP地址会变化(重启、租期到期)
  • 无法用固定IP访问

1.2 DDNS如何解决

复制代码
┌─────────────┐    IP变化     ┌─────────────┐
│   家庭路由   │ ──检测到──→  │ DDNS客户端  │
│  IP:1.2.3.4 │              │            │
└─────────────┘              └──────┬──────┘
                                    │ 调用API更新
                                    ↓
                            ┌─────────────┐
                            │  DNS服务商   │
                            │ example.com │
                            │  → 1.2.3.4  │
                            └─────────────┘

工作流程:

  1. DDNS客户端定期检测本机公网IP
  2. 发现IP变化后,调用DNS服务商API
  3. 更新域名的A记录
  4. 域名始终指向当前IP

二、DDNS方案对比

2.1 免费DDNS服务

服务 域名 优点 缺点
No-IP xxx.ddns.net 免费、客户端多 需每月确认
DuckDNS xxx.duckdns.org 完全免费 域名不好看
Dynu xxx.dynu.net 免费、功能全 速度一般
FreeDNS 多种子域名 选择多 稳定性一般

2.2 国内DNS服务商

服务商 支持DDNS API调用 适合场景
阿里云DNS 有官方API 有自己域名
腾讯云DNS 有官方API 有自己域名
Cloudflare 有API 海外访问
华为云DNS 有API 华为云用户

2.3 路由器内置

很多路由器/光猫内置DDNS功能:

  • 花生壳
  • No-IP
  • 自定义

三、阿里云DDNS配置

3.1 前置条件

  1. 有一个域名(托管在阿里云)
  2. 创建AccessKey

3.2 获取AccessKey

  1. 登录阿里云控制台
  2. 右上角头像 → AccessKey管理
  3. 创建AccessKey,保存好ID和Secret

3.3 使用Shell脚本

bash 复制代码
#!/bin/bash
# aliyun-ddns.sh

# 配置区
ACCESS_KEY_ID="your_access_key_id"
ACCESS_KEY_SECRET="your_access_key_secret"
DOMAIN="example.com"
SUBDOMAIN="home"  # 完整域名是 home.example.com

# 获取当前公网IP
get_current_ip() {
    curl -s http://ip.3322.net || \
    curl -s http://ifconfig.me || \
    curl -s http://ipinfo.io/ip
}

# 获取当前DNS记录
get_dns_ip() {
    aliyun alidns DescribeDomainRecords \
        --DomainName "$DOMAIN" \
        --RRKeyWord "$SUBDOMAIN" \
        --Type "A" 2>/dev/null | \
        jq -r '.DomainRecords.Record[0].Value'
}

# 更新DNS记录
update_dns() {
    local record_id=$1
    local ip=$2
    aliyun alidns UpdateDomainRecord \
        --RecordId "$record_id" \
        --RR "$SUBDOMAIN" \
        --Type "A" \
        --Value "$ip"
}

# 主逻辑
current_ip=$(get_current_ip)
dns_ip=$(get_dns_ip)

if [ "$current_ip" != "$dns_ip" ]; then
    echo "$(date): IP changed from $dns_ip to $current_ip"
    record_id=$(aliyun alidns DescribeDomainRecords \
        --DomainName "$DOMAIN" \
        --RRKeyWord "$SUBDOMAIN" | \
        jq -r '.DomainRecords.Record[0].RecordId')
    update_dns "$record_id" "$current_ip"
    echo "DNS updated successfully"
else
    echo "$(date): IP unchanged ($current_ip)"
fi

3.4 使用第三方工具(推荐)

ddns-go 是一个优秀的开源DDNS工具:

bash 复制代码
# 下载
wget https://github.com/jeessy2/ddns-go/releases/download/v5.6.0/ddns-go_5.6.0_linux_x86_64.tar.gz
tar xf ddns-go*.tar.gz

# 运行
./ddns-go

# 访问 http://localhost:9876 配置

ddns-go优点:

  • Web界面配置
  • 支持多种DNS服务商
  • 支持IPv6
  • 支持Webhook通知

四、腾讯云DDNS配置

4.1 获取密钥

  1. 登录腾讯云控制台
  2. 访问密钥管理
  3. 创建API密钥

4.2 Python脚本

python 复制代码
#!/usr/bin/env python3
# tencent_ddns.py

import json
import requests
from tencentcloud.common import credential
from tencentcloud.dnspod.v20210323 import dnspod_client, models

# 配置
SECRET_ID = "your_secret_id"
SECRET_KEY = "your_secret_key"
DOMAIN = "example.com"
SUBDOMAIN = "home"

def get_current_ip():
    """获取当前公网IP"""
    services = [
        'http://ip.3322.net',
        'http://ifconfig.me',
        'http://ipinfo.io/ip'
    ]
    for service in services:
        try:
            resp = requests.get(service, timeout=5)
            return resp.text.strip()
        except:
            continue
    return None

def get_dns_record():
    """获取DNS记录"""
    cred = credential.Credential(SECRET_ID, SECRET_KEY)
    client = dnspod_client.DnspodClient(cred, "")
    
    req = models.DescribeRecordListRequest()
    req.Domain = DOMAIN
    req.Subdomain = SUBDOMAIN
    
    resp = client.DescribeRecordList(req)
    if resp.RecordList:
        return resp.RecordList[0]
    return None

def update_dns_record(record_id, ip):
    """更新DNS记录"""
    cred = credential.Credential(SECRET_ID, SECRET_KEY)
    client = dnspod_client.DnspodClient(cred, "")
    
    req = models.ModifyRecordRequest()
    req.Domain = DOMAIN
    req.RecordId = record_id
    req.SubDomain = SUBDOMAIN
    req.RecordType = "A"
    req.RecordLine = "默认"
    req.Value = ip
    
    client.ModifyRecord(req)
    print(f"Updated {SUBDOMAIN}.{DOMAIN} to {ip}")

if __name__ == "__main__":
    current_ip = get_current_ip()
    record = get_dns_record()
    
    if record and record.Value != current_ip:
        update_dns_record(record.RecordId, current_ip)
    else:
        print(f"IP unchanged: {current_ip}")

4.3 安装依赖

bash 复制代码
pip install tencentcloud-sdk-python requests

五、Cloudflare DDNS配置

5.1 获取API Token

  1. 登录Cloudflare
  2. My Profile → API Tokens
  3. Create Token → Edit zone DNS

5.2 使用Shell脚本

bash 复制代码
#!/bin/bash
# cloudflare-ddns.sh

# 配置
CF_API_TOKEN="your_api_token"
CF_ZONE_ID="your_zone_id"
CF_RECORD_NAME="home.example.com"

# 获取当前IP
CURRENT_IP=$(curl -s http://ipinfo.io/ip)

# 获取DNS记录ID
RECORD_ID=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records?name=$CF_RECORD_NAME" \
    -H "Authorization: Bearer $CF_API_TOKEN" \
    -H "Content-Type: application/json" | jq -r '.result[0].id')

# 获取当前DNS记录的IP
DNS_IP=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$RECORD_ID" \
    -H "Authorization: Bearer $CF_API_TOKEN" \
    -H "Content-Type: application/json" | jq -r '.result.content')

# 更新DNS
if [ "$CURRENT_IP" != "$DNS_IP" ]; then
    echo "Updating DNS: $DNS_IP -> $CURRENT_IP"
    curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$CF_ZONE_ID/dns_records/$RECORD_ID" \
        -H "Authorization: Bearer $CF_API_TOKEN" \
        -H "Content-Type: application/json" \
        --data "{\"type\":\"A\",\"name\":\"$CF_RECORD_NAME\",\"content\":\"$CURRENT_IP\",\"ttl\":120,\"proxied\":false}"
    echo "DNS updated"
else
    echo "IP unchanged: $CURRENT_IP"
fi

六、定时任务配置

6.1 Cron定时执行

bash 复制代码
# 编辑crontab
crontab -e

# 每5分钟检查一次
*/5 * * * * /path/to/ddns-script.sh >> /var/log/ddns.log 2>&1

6.2 Systemd Timer

bash 复制代码
# /etc/systemd/system/ddns.service
[Unit]
Description=DDNS Update Service

[Service]
Type=oneshot
ExecStart=/path/to/ddns-script.sh

# /etc/systemd/system/ddns.timer
[Unit]
Description=DDNS Update Timer

[Timer]
OnBootSec=1min
OnUnitActiveSec=5min

[Install]
WantedBy=timers.target
bash 复制代码
systemctl enable ddns.timer
systemctl start ddns.timer

七、路由器DDNS配置

7.1 OpenWrt内置DDNS

bash 复制代码
# 安装ddns脚本
opkg update
opkg install ddns-scripts luci-app-ddns

# Web界面配置
# Services → Dynamic DNS

7.2 常见路由器

华硕路由器:

  • 外部网络 → DDNS → 选择服务商配置

小米路由器:

  • 高级设置 → DDNS → 配置账号

TP-Link:

  • 应用管理 → DDNS → 配置

八、没有公网IP怎么办

8.1 检测是否有公网IP

bash 复制代码
# 方法1:比较内外网IP
# 路由器WAN口IP
route -n | grep UG

# 公网IP
curl ip.3322.net

# 如果两个IP不一样,说明没有公网IP

8.2 替代方案

如果运营商没有给公网IP(大内网),DDNS就没用了。替代方案:

  1. 向运营商申请公网IP:打客服电话,说要监控/远程办公

  2. 使用组网软件:如星空组网,不需要公网IP也能远程访问

    • 安装客户端
    • 登录同一账号
    • 通过虚拟IP访问
  3. 内网穿透:frp、ngrok等


九、DDNS + 端口映射

有了DDNS域名,还需要配置端口映射才能访问内网服务:

复制代码
互联网 → home.example.com:8080 → 路由器:8080 → 内网服务器:80

路由器端口映射配置:

  • 外部端口:8080
  • 内部IP:192.168.1.100
  • 内部端口:80
  • 协议:TCP

安全建议:

  • 不要映射22端口到公网
  • 使用非标准端口
  • 配合fail2ban等安全措施
  • 或者用组网软件替代端口映射,更安全

十、总结

DDNS方案选择建议:

场景 推荐方案
快速体验 DuckDNS(完全免费)
有自己域名 ddns-go + 阿里云/腾讯云
海外访问 Cloudflare
路由器方案 OpenWrt ddns-scripts
无公网IP 组网软件(如星空组网)

DDNS虽然能解决动态IP问题,但还要配合端口映射使用,有一定安全风险。如果不想折腾,直接用组网软件可能是更简单的选择。


参考资料

  1. ddns-go: https://github.com/jeessy2/ddns-go
  2. 阿里云DNS API: https://help.aliyun.com/document_detail/29739.html
  3. Cloudflare API: https://api.cloudflare.com/

💡 提示:DDNS更新有延迟(取决于TTL设置),建议TTL设置短一些(如120秒)。但太短会增加DNS查询次数。

相关推荐
捷米研发三部7 小时前
Profinet转ModbusTCP网关:实现西门子1200PLC与打标卡稳定通讯
网络
課代表8 小时前
Windows 系统中查看已保存的WiFi密码
网络·windows·wifi·路由·netsh·无线·命令提示符
猫天意8 小时前
【即插即用模块】AAAI2026 | MHCB+DPA:特征提取+双池化注意力,涨点必备,SCI保二争一!彻底疯狂!!!
网络·人工智能·深度学习·算法·yolo
她是太阳,好耀眼i8 小时前
配置FTP目录文件以http网址方式访问并下载
网络·网络协议·http
chenyuhao20248 小时前
Linux系统编程:Ext文件系统
linux·运维·服务器·开发语言·网络·c++·后端
忆_恒心9 小时前
eNSP仿真模拟之VLAN技术(下)
网络·计算机网络·vlan·虚拟局域网
毕设源码-郭学长9 小时前
【开题答辩全过程】以 基于微服务的网络运维管理系统设计与实现为例,包含答辩的问题和答案
运维·网络·微服务
sc.溯琛9 小时前
数据链路层复习总结
网络·网络协议·智能路由器
开开心心_Every9 小时前
Word转PDF工具,免费生成图片型文档
网络·笔记·pdf·word·powerpoint·excel·azure