goddns 是一个用 Go 编写的轻量级动态 DNS (DDNS) 客户端,支持多域名、多服务商、IPv6,具备跨平台能力和丰富的日志输出。
| 功能 | 说明 |
|---|---|
| 🌐 多域名支持 | 一条配置可更新多个 DNS 记录 |
| ☁️ 多服务商 | 支持 Cloudflare、阿里云 DNS |
| 🔒 安全性 | 强制使用环境变量,禁止明文密钥 |
| 🚀 并发更新 | 多个域名并行更新,提高效率 |
| 📦 IPv6 支持 | 原生支持 IPv6,多平台接口获取 |
| 🔄 IP 缓存 | 避免重复 API 调用 |
| 🎨 彩色日志 | 终端下日志分级彩色显示,支持文件输出 |
| 🌍 代理支持 | HTTP(S)/SOCKS5 代理,记录级控制 |
# 基础构建
go build -o goddns ./cmd/goddns
# 带版本信息构建
go build -ldflags "-X main.version=v2.0.0" -o goddns ./cmd/goddns
# 使用构建脚本
chmod +x build.sh
./build.sh v2.0.0创建 config.json:
{
"general": {
"get_ip": {
"interface": "eth0",
"urls": ["https://ipv6.icanhazip.com"]
},
"work_dir": "/var/lib/goddns",
"log_output": "shell"
},
"records": [
{
"provider": "cloudflare",
"zone": "example.com",
"record": "dev",
"cloudflare": {
"api_token": "${CLOUDFLARE_API_TOKEN}"
}
}
]
}export CLOUDFLARE_API_TOKEN="your_api_token_here"# 运行
./goddns run -f config.json
# 忽略缓存强制更新
./goddns run -f config.json -i
# 查看版本
./goddns version
⚠️ 重要:出于安全考虑,goddns 禁止在配置文件中明文存储密钥信息。所有敏感信息必须使用环境变量引用。
❌ 错误示例(会被拒绝执行):
{
"cloudflare": {
"api_token": "your_actual_token_here"
}
}✅ 正确示例:
{
"cloudflare": {
"api_token": "${CLOUDFLARE_API_TOKEN}",
"zone_id": "${CLOUDFLARE_ZONE_ID:-}"
}
}{
"general": {
"get_ip": {
"interface": "eth0",
"urls": [
"https://ipv6.icanhazip.com",
"https://6.ipw.cn"
]
},
"work_dir": "/var/lib/goddns",
"log_output": "shell",
"proxy": ""
},
"records": [
{
"provider": "cloudflare",
"zone": "example.com",
"record": "dev",
"ttl": 180,
"proxied": false,
"use_proxy": false,
"cloudflare": {
"api_token": "${CLOUDFLARE_API_TOKEN}",
"zone_id": "${CLOUDFLARE_ZONE_ID:-}"
}
},
{
"provider": "aliyun",
"zone": "example.cn",
"record": "www",
"ttl": 600,
"aliyun": {
"access_key_id": "${ALIYUN_ACCESS_KEY_ID}",
"access_key_secret": "${ALIYUN_ACCESS_KEY_SECRET}"
}
}
]
}| 字段 | 类型 | 说明 | 示例 |
|---|---|---|---|
get_ip.interface |
string | 本地网卡名(优先使用) | eth0 |
get_ip.urls |
[]string | 外部 IP 检测 API 列表(降级) | ["https://ipv6.icanhazip.com"] |
work_dir |
string | 缓存文件目录 | /var/lib/goddns |
log_output |
string | 日志输出,shell 表示终端 |
shell 或文件路径 |
proxy |
string | 全局代理(可选) | socks5://127.0.0.1:1080 |
| 字段 | 类型 | 说明 | 必填 |
|---|---|---|---|
provider |
string | 服务商:cloudflare 或 aliyun |
✅ |
zone |
string | 主域名 | ✅ |
record |
string | 子域名/记录名(@ 表示根域) |
✅ |
ttl |
int | DNS 记录 TTL(秒) | ❌ |
proxied |
bool | Cloudflare 代理模式 | ❌ |
use_proxy |
bool | 是否使用全局代理 | ❌ |
| 字段 | 类型 | 说明 |
|---|---|---|
cloudflare.api_token |
string | API Token(环境变量引用) |
cloudflare.zone_id |
string | Zone ID(可选,留空自动获取) |
cloudflare.ttl |
int | TTL(可选,覆盖记录级) |
cloudflare.proxied |
bool | 代理模式(可选,覆盖记录级) |
| 字段 | 类型 | 说明 |
|---|---|---|
aliyun.access_key_id |
string | AccessKey ID(环境变量引用) |
aliyun.access_key_secret |
string | AccessKey Secret(环境变量引用) |
aliyun.ttl |
int | TTL(可选,覆盖记录级) |
| 特性 | Cloudflare | 阿里云 |
|---|---|---|
| IPv6 支持 | ✅ | ✅ |
| 代理支持 | ✅ | ❌ |
| 自动获取 ZoneID | ✅ | ✅ |
| API 认证 | API Token | AccessKey |
| 变量名 | 说明 | 示例 |
|---|---|---|
CLOUDFLARE_API_TOKEN |
Cloudflare API Token | your_token_here |
CLOUDFLARE_ZONE_ID |
Cloudflare Zone ID(可选) | abc123xyz |
ALIYUN_ACCESS_KEY_ID |
阿里云 AccessKey ID | LTAI1234567890 |
ALIYUN_ACCESS_KEY_SECRET |
阿里云 AccessKey Secret | your_secret_here |
# 设置环境变量
export CLOUDFLARE_API_TOKEN="your_token_here"
export ALIYUN_ACCESS_KEY_ID="LTAI1234567890"
export ALIYUN_ACCESS_KEY_SECRET="your_secret_here"
# 运行
./goddns run -f config.json支持 ${VAR:-default} 语法:
{
"cloudflare": {
"zone_id": "${CLOUDFLARE_ZONE_ID:-}"
}
}${VAR}- 使用环境变量值${VAR:-default}- 未设置或为空时使用默认值${VAR-default}- 未设置时使用默认值
# /etc/goddns/goddns.env
CLOUDFLARE_API_TOKEN="your_token_here"
ALIYUN_ACCESS_KEY_ID="LTAI1234567890"
ALIYUN_ACCESS_KEY_SECRET="your_secret_here"
# 设置权限(仅 root 可读)
chmod 600 /etc/goddns/goddns.env# /etc/systemd/system/goddns.service
[Unit]
Description=Dynamic DNS client
After=network.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/goddns run -f /etc/goddns/config.json
EnvironmentFile=/etc/goddns/goddns.env# /etc/systemd/system/goddns.timer
[Unit]
Description=Run goddns every 5 minutes
[Timer]
OnBootSec=5min
OnUnitActiveSec=5min
Persistent=true
[Install]
WantedBy=timers.targetsudo systemctl daemon-reload
sudo systemctl enable --now goddns.timer创建运行脚本:
#!/bin/bash
# /etc/goddns/run-goddns.sh
# 设置 PATH 环境变量(cron 环境中可能需要)
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# 配置路径
GODDNS_BIN="/usr/local/bin/goddns"
GODDNS_CONFIG="/etc/goddns/config.json"
GODDNS_ENV="/etc/goddns/goddns.env"
LOG_FILE="/var/log/goddns-cron.log"
# 加载环境变量文件(如果存在)
if [ -f "$GODDNS_ENV" ]; then
set -a
source "$GODDNS_ENV"
set +a
fi
# 运行 goddns
"$GODDNS_BIN" run -f "$GODDNS_CONFIG"
# 记录退出状态
EXIT_CODE=$?
if [ $EXIT_CODE -eq 0 ]; then
echo "$(date): goddns executed successfully" >> "$LOG_FILE"
else
echo "$(date): goddns failed with exit code $EXIT_CODE" >> "$LOG_FILE"
fi
exit $EXIT_CODE设置权限并配置 crontab:
chmod +x /etc/goddns/run-goddns.sh
crontab -e
# 添加:*/5 * * * * /etc/goddns/run-goddns.sh >> /var/log/goddns-cron.log 2>&1crontab -e
# 添加环境变量和任务
CLOUDFLARE_API_TOKEN="your_token_here"
ALIYUN_ACCESS_KEY_ID="LTAI1234567890"
ALIYUN_ACCESS_KEY_SECRET="your_secret_here"
# 每 5 分钟执行一次(推荐)
*/5 * * * * /usr/local/bin/goddns run -f /etc/goddns/config.json >> /var/log/goddns-cron.log 2>&1
# 每小时执行一次
# 0 * * * * /usr/local/bin/goddns run -f /etc/goddns/config.json >> /var/log/goddns-cron.log 2>&1
# 每天执行一次
# 0 0 * * * /usr/local/bin/goddns run -f /etc/goddns/config.json >> /var/log/goddns-cron.log 2>&1# ┌───────────── 分钟 (0 - 59)
# │ ┌───────────── 小时 (0 - 23)
# │ │ ┌───────────── 日期 (1 - 31)
# │ │ │ ┌───────────── 月份 (1 - 12)
# │ │ │ │ ┌───────────── 星期几 (0 - 7) (星期日=0 或 7)
# │ │ │ │ │
# * * * * * 命令
常用配置示例:
*/5 * * * *- 每 5 分钟*/10 * * * *- 每 10 分钟0 * * * *- 每小时整点0 */2 * * *- 每 2 小时0 0 * * *- 每天午夜0 0 * * 0- 每周日凌晨@reboot- 系统启动时执行
注意:cron 环境与交互式 shell 不同,建议使用绝对路径,并确保环境变量文件权限正确(
chmod 600)。
| 平台 | 状态 | 说明 |
|---|---|---|
| Linux | ✅ | 使用 netlink 接口 |
| FreeBSD | ✅ | 使用 ioctl 接口 |
| OpenBSD | ✅ | 使用 ioctl 接口 |
| macOS | 暂无支持,欢迎提交 PR |
goddns/
├── cmd/goddns/ # 主程序入口
│ ├── main.go
│ └── cmd.go
├── internal/
│ ├── config/ # 配置管理
│ │ ├── config.go
│ │ └── config_test.go
│ ├── log/ # 日志系统
│ │ └── log.go
│ ├── platform/ifaddr/ # 平台相关网络工具
│ │ ├── linux_netlink.go
│ │ ├── freebsd_ioctl.go
│ │ ├── openbsd_ioctl.go
│ │ ├── shared.go
│ │ ├── shared_test.go
│ │ └── util.go
│ └── provider/ # DNS 服务商实现
│ ├── provider.go
│ ├── factory/
│ ├── cloudflare/
│ └── aliyun/
├── config.example.json # 配置示例
├── .env.example # 环境变量示例
├── build.sh # 构建脚本
└── README.md
访问 Cloudflare Dashboard,创建具有 Zone:DNS:Edit 权限的 Token。
访问 阿里云 RAM 控制台 创建 AccessKey。
- Cloudflare:Dashboard → Overview 右侧,或留空自动获取
- 阿里云:不需要
{
"general": {
"proxy": "socks5://127.0.0.1:1080"
},
"records": [
{
"use_proxy": true
}
]
}注意:仅 Cloudflare 支持代理,阿里云不支持。
采用 BSD 3-Clause License - 详见 LICENSE 文件。
欢迎提交 Issue 和 Pull Request!