Gecko-ddns 是一个用现代 C++23 编写的高性能动态 DNS (DDNS) 客户端,支持多平台、多服务商、IPv6 优先。名称取自壁虎(Gecko)— 轻巧灵活,适应各种环境。
- 多平台:Linux、FreeBSD、OpenBSD、macOS
- 多服务商:Cloudflare、阿里云 DNS(架构易扩展)
- IPv6 优先:支持从网卡或 HTTP API 获取 IPv6 地址,自动过滤链路本地/ULA/环回地址
- 并发更新:多条 DNS 记录同时更新
- 缓存机制:IP 未变化时不触发 API 调用
- 敏感信息管理:
environment集中定义,通过$变量名引用,日志自动脱敏 - 代理支持:Cloudflare 支持 HTTP/SOCKS5 代理(仅 Cloudflare)
- 连接池:CURL 连接池 + TCP Keepalive
./build.sh # 编译 2.0 版本
./build.sh 2.0 # 或显式指定版本FreeBSD 建议先安装系统依赖,避免构建时从 GitHub 下载(网络不稳定时可能失败):
sudo pkg install nlohmann-json argparse未安装时 CMake 会自动回退到从 GitHub 获取这两个头文件库。
验证:
./build/gecko-ddns versioncp config.example.json config.json完整配置说明见下方 配置 一节。
./build/gecko-ddns run -c config.json -d /etc/gecko-ddns配置文件为 JSON 格式。以下示例使用 JSONC 语法(带注释)讲解字段,实际使用时请复制 config.example.json 并填入自己的值。
| Cloudflare | 阿里云 | |
|---|---|---|
| 认证 | API Token | AccessKey ID + Secret |
| 权限 | Zone:DNS:Edit |
AliyunDNSFullAccess |
| 代理 | ✅ HTTP/SOCKS5 | ✅ HTTP/SOCKS5 |
| Zone ID | 留空自动获取 | — |
gecko-ddns <command> [options]
| 命令 | 说明 |
|---|---|
run |
执行 DDNS 更新 |
version |
显示版本信息 |
run 命令参数:
| 参数 | 简写 | 默认值 | 说明 |
|---|---|---|---|
--config |
-c |
无 | 配置文件路径 |
--dir |
-d |
配置目录 | 工作目录(存放缓存文件 cache.lastip) |
--ignore-cache |
-i |
false | 忽略缓存,强制更新 |
--timeout |
-t |
300 | 超时时间(秒) |
/etc/systemd/system/gecko-ddns.service:
[Unit]
Description=Gecko-ddns DDNS Client
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/local/bin/gecko-ddns run -c /etc/gecko-ddns/config.json
WorkingDirectory=/etc/gecko-ddns
[Install]
WantedBy=multi-user.target/etc/systemd/system/gecko-ddns.timer:
[Unit]
Description=Run Gecko-ddns DDNS every 10 minutes
Requires=gecko-ddns.service
[Timer]
OnBootSec=5min
OnUnitActiveSec=10min
Unit=gecko-ddns.service
[Install]
WantedBy=timers.target启用:
sudo systemctl daemon-reload
sudo systemctl enable --now gecko-ddns.timer*/10 * * * * /usr/local/bin/gecko-ddns run -c /etc/gecko-ddns/config.json -d /etc/gecko-ddns >> /var/log/gecko-ddns.log 2>&1/Library/LaunchDaemons/com.gecko-ddns.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.gecko-ddns</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/gecko-ddns</string>
<string>run</string>
<string>-c</string>
<string>/etc/gecko-ddns/config.json</string>
</array>
<key>StartInterval</key>
<integer>600</integer>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>加载:
sudo launchctl load /Library/LaunchDaemons/com.gecko-ddns.plist| 平台 | IPv6 获取(网卡) | IPv6 获取(HTTP API) | 状态 |
|---|---|---|---|
| Linux | ✅ Netlink 原生 | ✅ | 完整支持 |
| FreeBSD | ✅ Netlink 原生 | ✅ | 完整支持 |
| OpenBSD | ✅ ioctl | ✅ | 完整支持 |
| macOS | ❌ | ✅ | 仅 HTTP API |
项目更名:alasia → gecko-ddns
新增 OpenBSD 支持
- 通过
SIOCGIFALIFETIME_IN6ioctl 获取 IPv6 地址和生命周期 - 支持 SLAAC 临时地址和 autoconf 地址的 pltime/vltime 识别
FreeBSD 使用 Netlink
- 通过 FreeBSD 14+ 原生 Netlink socket(
RTM_GETADDR/RTM_NEWADDR)获取 IPv6 地址和生命周期 - 与
ifconfig使用相同的内核路径获取地址信息,结果更准确
平台代码独立
- Linux、FreeBSD、OpenBSD 各平台 IPv6 获取逻辑分离到独立文件
- 新增平台只需添加源文件 + CMake 分支即可接入
| 错误 | 解决方案 |
|---|---|
Config: record[0]: cloudflare.api_token is not set |
检查 environment 中变量是否定义,引用名是否正确 |
Failed to get current IP |
检查网卡名(ip addr),确保 IPv6 已启用,或改用 urls API 方式 |
Invalid API Token |
检查 Token 和 Zone:DNS:Edit 权限 |
InvalidSignature |
检查 AccessKey,确保系统时间准确(NTP 同步) |
日志默认输出到 stdout,systemd 用户可通过 journalctl -u gecko-ddns.service -f 查看。
欢迎提交 Issue 和 Pull Request。
项目采用 MIT License — 详见 LICENSE 文件。
{ // ── env ──────────────────────────────────────────────── // 敏感信息集中存放,通过 $变量名 在 records 中引用。 // 仅支持 $name 语法,不支持 ${name} 或系统环境变量。 "env": { "cf_token": "your_cloudflare_api_token", "cf_zone": "your_cloudflare_zone_id", "ak_id": "your_aliyun_access_key_id", "ak_secret": "your_aliyun_access_key_secret" }, // ── ip_source ────────────────────────────────────────── // interface 优先;fallback_urls 永不使用代理。 "ip_source": { "interface": "eth0", "fallback_urls": [ "https://ipv6.icanhazip.com", "https://6.ipw.cn" ] }, // ── proxy ────────────────────────────────────────────── // 全局代理(可选),仅用于 DNS API 请求(Cloudflare)。 // 不影响 ip_source 的 IP 探测。 "proxy": "", // ── records ──────────────────────────────────────────── // 各 provider 字段平铺,运行期按 provider 校验。 "records": [ { "provider": "cloudflare", "zone": "example.com", "name": "www", "type": "AAAA", "ttl": 300, "proxied": false, "use_proxy": false, "api_token": "$cf_token", "zone_id": "$cf_zone" }, { "provider": "aliyun", "zone": "example.cn", "name": "www", "type": "AAAA", "ttl": 600, "use_proxy": false, "access_key_id": "$ak_id", "access_key_secret": "$ak_secret" } ] }