From 3caaf6eaa5aacfd0886b578592d837c833494a3b Mon Sep 17 00:00:00 2001 From: New Future Date: Tue, 3 Jun 2025 20:48:18 +0800 Subject: [PATCH 1/2] fix GitHub publish --- .github/release.md | 6 +++--- .github/workflows/publish.yml | 17 +++++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.github/release.md b/.github/release.md index 82eb9ca61..228ffb9b5 100644 --- a/.github/release.md +++ b/.github/release.md @@ -7,7 +7,7 @@ | Docker | `newfuture/ddns:${BUILD_VERSION}` 8种架构| | Windows | [64位(x64)](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-windows-x64.exe) / [32位(x86)](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-windows-x86.exe) / [arm64](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-windows-arm64.exe) | | Linux | [64位(x64)](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-linux-x64) / [arm64](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-linux-arm64) | -| Mac OS X | [Apple Silicon (ARM64)](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-arm64.app) / [Intel x64](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-x64.app) | +| Mac OS X | [Apple Silicon (ARM64)](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-arm64) / [Intel x64](https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-x64) | | Python/PIP | any | ## Docker (推荐) ![Docker Image Size (latest by date)](https://img.shields.io/docker/image-size/newfuture/ddns/${BUILD_VERSION}?style=flat-square)[![Docker Platforms](https://img.shields.io/badge/arch-amd64%20%7C%20arm64%20%7C%20arm%2Fv7%20%7C%20arm%2Fv6%20%7C%20ppc64le%20%7C%20s390x%20%7C%20386%20%7C%20mips64le-blue?logo=docker&style=flat-square)](https://hub.docker.com/r/newfuture/ddns) @@ -60,10 +60,10 @@ curl -sSL https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/c ```sh # 命令行下载 # arm64 -curl https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-arm64.app -#SLo ddns && chmod +x ddns +curl https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-arm64 -#SLo ddns && chmod +x ddns # intel x64 -curl https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-x64.app -#SLo ddns && chmod +x ddns +curl https://github.com/NewFuture/DDNS/releases/download/${BUILD_VERSION}/ddns-mac-x64 -#SLo ddns && chmod +x ddns ``` ## 使用PIP 安装 ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ddns/${BUILD_VERSION}.svg?style=flat-square) ![PyPI - Wheel](https://img.shields.io/pypi/wheel/ddns.svg?style=flat-square) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f5fb6c2be..faab6d668 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -163,14 +163,15 @@ jobs: - run: ./dist/ddns || test -e config.json - run: ./dist/ddns -h - - run: mv ./dist/ddns ./dist/ddns-ubuntu24.04-${{ runner.arch }} + - run: mv ./dist/ddns ./dist/ddns-ubuntu24.04-${{ matrix.arch }} if: runner.os == 'Linux' - - run: mv ./dist/ddns ./dist/ddns-mac-${{ runner.arch }}.app + - run: mv ./dist/ddns ./dist/ddns-mac-${{ matrix.arch }} if: runner.os == 'macOS' - - run: mv ./dist/ddns.exe ./dist/ddns-windows-${{ runner.arch }}.exe + - run: mv ./dist/ddns.exe ./dist/ddns-windows-${{ matrix.arch }}.exe if: runner.os == 'Windows' - - name: Upload files - run: gh release upload ${{ github.ref_name }} dist/ddns* --clobber + - name: Upload binary + run: gh release upload ${{ github.ref_name }} dist/ddns* + shell: bash env: GH_TOKEN: ${{ github.token }} @@ -207,9 +208,9 @@ jobs: - run: ./dist/ddns || test -e config.json - run: ./dist/ddns -h - - run: mv ./dist/ddns ./dist/ddns-linux-${{ runner.arch }} - - name: Upload files - run: gh release upload ${{ github.ref_name }} dist/ddns* --clobber + - run: sudo mv ./dist/ddns ./dist/ddns-linux-$(echo "${{ runner.arch }}" | tr '[:upper:]' '[:lower:]') + - name: Upload binary + run: gh release upload ${{ github.ref_name }} dist/ddns* env: GH_TOKEN: ${{ github.token }} From 3b7d291bd513c927c357f3e6bb3a98f42fbf2b30 Mon Sep 17 00:00:00 2001 From: New Future Date: Tue, 3 Jun 2025 21:33:05 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BC=98=E5=8C=96ico=20(#467)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Optimize ico * Update readme * Flatten badge --- README.md | 188 +++++++++++++++++++++++++--------------------------- favicon.ico | Bin 54886 -> 13623 bytes 2 files changed, 91 insertions(+), 97 deletions(-) diff --git a/README.md b/README.md index dc73ad986..3f1358e61 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,75 @@ # [](https://ddns.newfuture.cc) [DDNS](https://github.com/NewFuture/DDNS) -> 自动更新 DNS 解析 到本机 IP 地址,支持 ipv4 和 ipv6 以 本地(内网)IP 和 公网 IP。 -> 代理模式,支持自动创建域名记录。 +> 自动更新 DNS 解析 到本机 IP 地址,支持 IPv4 和 IPv6,本地(内网)IP 和公网 IP。 +> 代理模式,支持自动创建 DNS 记录。 -[![PyPI](https://img.shields.io/pypi/v/ddns.svg?label=DDNS&style=social)](https://pypi.org/project/ddns/) -[![Docker Image Version](https://img.shields.io/docker/v/newfuture/ddns?label=Docker:newfuture/ddns&sort=semver&style=social)](https://hub.docker.com/r/newfuture/ddns)[![Docker Pulls](https://img.shields.io/docker/pulls/newfuture/ddns?style=social)](https://hub.docker.com/r/newfuture/ddns) -[![PyPi version](https://img.shields.io/pypi/v/ddns.svg?style=social)](https://pypi.org/project/ddns/) +[![Github Release](https://img.shields.io/github/v/release/NewFuture/DDNS?&logo=github&style=flatten +)](https://github.com/NewFuture/DDNS/releases/latest) +[![PyPI](https://img.shields.io/pypi/v/ddns.svg?label=ddns&logo=pypi&style=flatten)](https://pypi.org/project/ddns/) +[![Docker Image Version](https://img.shields.io/docker/v/newfuture/ddns?label=newfuture/ddns&logo=docker&&sort=semver&style=flatten)](https://hub.docker.com/r/newfuture/ddns) [![Build Status](https://github.com/NewFuture/DDNS/actions/workflows/build.yml/badge.svg?event=push)](https://github.com/NewFuture/DDNS/actions/workflows/build.yml) -[![Publish Status](https://github.com/NewFuture/DDNS/actions/workflows/publish.yml/badge.svg)](https://github.com/NewFuture/DDNS/releases/latest) +[![Publish](https://github.com/NewFuture/DDNS/actions/workflows/publish.yml/badge.svg)](https://github.com/NewFuture/DDNS/actions/workflows/publish.yml) --- ## Features - 兼容和跨平台: - - [Docker (@NN708)](https://hub.docker.com/r/newfuture/ddns) [![Docker Image Size](https://img.shields.io/docker/image-size/newfuture/ddns/latest?style=social)](https://hub.docker.com/r/newfuture/ddns)[![Docker Platforms](https://img.shields.io/badge/arch-amd64%20%7C%20arm64%20%7C%20arm%2Fv7%20%7C%20arm%2Fv6%20%7C%20ppc64le%20%7C%20s390x%20%7C%20386%20%7C%20mips64le-blue?logo=docker&style=flat-square)](https://hub.docker.com/r/newfuture/ddns) - - [PIP 安装 (兼容Python2)](https://pypi.org/project/ddns/) ![PyPI - Wheel](https://img.shields.io/pypi/wheel/ddns.svg?style=social) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ddns.svg?style=social) + - [Docker (@NN708)](https://hub.docker.com/r/newfuture/ddns) [![Docker Image Size](https://img.shields.io/docker/image-size/newfuture/ddns/latest?logo=docker&style=social)](https://hub.docker.com/r/newfuture/ddns)[![Docker Platforms](https://img.shields.io/badge/arch-amd64%20%7C%20arm64%20%7C%20arm%2Fv7%20%7C%20arm%2Fv6%20%7C%20ppc64le%20%7C%20s390x%20%7C%20386%20%7C%20mips64le-blue?style=social)](https://hub.docker.com/r/newfuture/ddns) + - [PIP 安装 (兼容Python2)](https://pypi.org/project/ddns/) ![PyPI - Wheel](https://img.shields.io/pypi/wheel/ddns.svg?logo=pypi&style=social) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ddns.svg?style=social) - [二进制文件](https://github.com/NewFuture/DDNS/releases/latest) ![cross platform](https://img.shields.io/badge/system-windows_%7C%20linux_%7C%20mac-success.svg?style=social) - 域名支持: - 多个域名支持 - 多级域名解析 - - 自动创建新记录 + - 自动创建新 DNS 记录 - IP 类型: - 内网 IPv4 / IPv6 - 公网 IPv4 / IPv6 (支持自定义 API) - - 自定义命令(shell) - - 正则选取支持(@rufengsuixing) + - 自定义命令(shell) + - 正则选取支持 (@rufengsuixing) - 网络代理: - http 代理支持 - 多代理自动切换 - 服务商支持: - [DNSPOD](https://www.dnspod.cn/) - [阿里 DNS](http://www.alidns.com/) - - [DNS.COM](https://www.dns.com/)(@loftor-git) + - [DNS.COM](https://www.dns.com/) (@loftor-git) - [DNSPOD 国际版](https://www.dnspod.com/) - - [CloudFlare](https://www.cloudflare.com/)(@tongyifan) - - [HE.net](https://dns.he.net/)(@NN708) (不支持自动创建记录) - - [华为云](https://huaweicloud.com/)(@cybmp3) + - [CloudFlare](https://www.cloudflare.com/) (@tongyifan) + - [HE.net](https://dns.he.net/) (@NN708) (不支持自动创建记录) + - [华为云](https://huaweicloud.com/) (@cybmp3) - 其他: - 可设置定时任务 - TTL 配置支持 - - 本地文件缓存(减少 API 请求) - - 地址变更时触发自定义回调API(与 DDNS 功能互斥) + - 本地文件缓存(减少 API 请求) + - 地址变更时触发自定义回调 API(与 DDNS 功能互斥) ## 使用 ### ① 安装 -根据需要选择一种方式: `二进制`版,`pip`版,`源码`运行,或者`Docker`. +根据需要选择一种方式:`二进制`版、`pip`版、`源码`运行,或者 `Docker`。 -推荐docker版,兼容性最佳,体积小,性能优化。 +推荐 Docker 版,兼容性最佳,体积小,性能优化。 -- #### pip 安装(需要 pip 或 easy_install) +- #### pip 安装(需要 pip 或 easy_install) 1. 安装 ddns: `pip install ddns` 或 `easy_install ddns` 2. 运行: `ddns` -- #### 二进制版(单文件,无需 python) +- #### 二进制版(单文件,无需 python) - Windows [ddns.exe](https://github.com/NewFuture/DDNS/releases/latest) - - Linux (仅 Ubuntu 测试) [ddns](https://github.com/NewFuture/DDNS/releases/latest) + - Linux(仅 Ubuntu 测试) [ddns](https://github.com/NewFuture/DDNS/releases/latest) - Mac OSX [ddns-mac](https://github.com/NewFuture/DDNS/releases/latest) -- #### 源码运行(无任何依赖, 需 python 环境) +- #### 源码运行(无任何依赖,需 python 环境) - 1. clone 或者[下载此仓库](https://github.com/NewFuture/DDNS/archive/master.zip)并解压 - 2. 运行./run.py (widnows 双击`run.bat`或者运行`python run.py`) + 1. clone 或者 [下载此仓库](https://github.com/NewFuture/DDNS/archive/master.zip) 并解压 + 2. 运行 ./run.py(windows 双击 `run.bat` 或者运行 `python run.py`) -- #### Docker(需要安装 Docker) +- #### Docker(需要安装 Docker) - 使用环境变量: @@ -83,7 +84,7 @@ newfuture/ddns ``` - - 使用配置文件(docker 工作目录`/ddds/`,默认配置位置`/ddns/config.json`): + - 使用配置文件(docker 工作目录 `/ddns/`,默认配置位置 `/ddns/config.json`): ```sh docker run -d \ @@ -94,34 +95,32 @@ ### ② 快速配置 -1. 申请 api `token`,填写到对应的`id`和`token`字段: +1. 申请 api `token`,填写到对应的 `id` 和 `token` 字段: - [DNSPOD(国内版)创建 token](https://support.dnspod.cn/Kb/showarticle/tsid/227/) - [阿里云 accesskey](https://help.aliyun.com/document_detail/87745.htm) - [DNS.COM API Key/Secret](https://www.dns.com/member/apiSet) - [DNSPOD(国际版)](https://www.dnspod.com/docs/info.html#get-the-user-token) - - [CloudFlare API Key](https://support.cloudflare.com/hc/en-us/articles/200167836-Where-do-I-find-my-Cloudflare-API-key-) (除了`email + API KEY`,也可使用`Token`需要列出 Zone 权限) - - [HE.net DDNS 文档](https://dns.he.net/docs.html)(仅需将设置的密码填入`token`字段,`id`字段可留空) + - [CloudFlare API Key](https://support.cloudflare.com/hc/en-us/articles/200167836-Where-do-I-find-my-Cloudflare-API-key-)(除了 `email + API KEY`,也可使用 `Token`,需要列出 Zone 权限) + - [HE.net DDNS 文档](https://dns.he.net/docs.html)(仅需将设置的密码填入 `token` 字段,`id` 字段可留空) - [华为 APIKEY 申请](https://console.huaweicloud.com/iam/)(点左边访问密钥,然后点新增访问密钥) - 自定义回调的参数填写方式请查看下方的自定义回调配置说明 -2. 修改配置文件,`ipv4`和`ipv6`字段,为待更新的域名,详细参照配置说明 +2. 修改配置文件,`ipv4` 和 `ipv6` 字段,为待更新的域名,详细参照配置说明 ## 详细配置 所有字段可通过三种方式进行配置 -1. 命令行参数 `ddns --key=value` (`ddns -h` 查看详情),优先级最高 -2. JSON配置文件(值为null认为是有效值,会覆盖环境变量的设置,如果没有对应的key则会尝试试用环境变量) -3. 环境变量DDNS_前缀加上key 全大写或者全小写,点转下划线 (`${ddns_id}` 或 `${DDNS_ID}`,`${DDNS_LOG_LEVEL}`) +1. 命令行参数 `ddns --key=value`(`ddns -h` 查看详情),优先级最高 +2. JSON 配置文件(值为 null 认为是有效值,会覆盖环境变量的设置,如果没有对应的 key 则会尝试使用环境变量) +3. 环境变量 DDNS_ 前缀加上 key 全大写或者全小写,点转下划线(`${ddns_id}` 或 `${DDNS_ID}`,`${DDNS_LOG_LEVEL}`)
- -config.json 配置文件 - +config.json 配置文件 - 首次运行会自动生成一个模板配置文件 -- 可以使用 `-c`使用指定的配置文件 (默认读取当前目录的 config.json) +- 可以使用 `-c` 使用指定的配置文件(默认读取当前目录的 config.json) - 推荐使用 vscode 等支持 JsonSchema 的编辑器编辑配置文件 ```bash @@ -132,40 +131,40 @@ python run.py -c /path/to/config.json #### 配置参数表 -| key | type | required | default | description | tips | -| :----: | :----------------: | :------: | :---------: | :---------------: | ----------------------------------------------------------------------------------------------------------- | -| id | string | √ | 无 | api 访问 ID | Cloudflare 为邮箱(使用 Token 时留空)
HE.net 可留空
华为云为 Access Key ID (AK) | -| token | string | √ | 无 | api 授权 token | 部分平台叫 secret key , **反馈粘贴时删除** | -| dns | string | No | `"dnspod"` | dns 服务商 | 阿里 DNS 为`alidns`,
Cloudflare 为 `cloudflare`,
dns.com 为 `dnscom`,
DNSPOD 国内为 `dnspod`,
DNSPOD 国际版为 `dnspod_com`,
HE.net 为`he`,
华为 DNS 为`huaweidns`,
自定义回调为`callback` | -| ipv4 | array | No | `[]` | ipv4 域名列表 | 为`[]`时,不会获取和更新 IPv4 地址 | -| ipv6 | array | No | `[]` | ipv6 域名列表 | 为`[]`时,不会获取和更新 IPv6 地址 | -| index4 | string\|int\|array | No | `"default"` | ipv4 获取方式 | 可设置`网卡`,`内网`,`公网`,`正则`等方式 | -| index6 | string\|int\|array | No | `"default"` | ipv6 获取方式 | 可设置`网卡`,`内网`,`公网`,`正则`等方式 | -| ttl | number | No | `null` | DNS 解析 TTL 时间 | 不设置采用 DNS 默认策略 | -| proxy | string | No | 无 | http 代理`;`分割 | 多代理逐个尝试直到成功,`DIRECT`为直连 | -| ~~debug~~ | bool | No | `false` | 是否开启调试 | v4 中弃用,请改用log.level=DEBUG | -| cache | string\|bool | No | `true` | 是否缓存记录 | 正常情况打开避免频繁更新,默认位置为临时目录下`ddns.cache`,
也可以指定一个具体文件实现自定义文件缓存位置 | -| log | {"level":string,"file":string} | No | `null` | 日志配置(可选) | 日志配置,日志级别和路径(默认命令行),
例如: `{ "level": "DEBUG", "file": "/path/to/logfile.log" }` | +| key | type | required | default | description | tips | +| :------: | :----------------: | :------: | :---------: | :---------------: | ----------------------------------------------------------------------------------------------------------- | +| id | string | √ | 无 | api 访问 ID | Cloudflare 为邮箱(使用 Token 时留空)
HE.net 可留空
华为云为 Access Key ID (AK) | +| token | string | √ | 无 | api 授权 token | 部分平台叫 secret key,**反馈粘贴时删除** | +| dns | string | No | `"dnspod"` | dns 服务商 | 阿里 DNS 为 `alidns`,Cloudflare 为 `cloudflare`,dns.com 为 `dnscom`,DNSPOD 国内为 `dnspod`,DNSPOD 国际为 `dnspod_com`,HE.net 为 `he`,华为云为 `huaweidns`,自定义回调为 `callback` | +| ipv4 | array | No | `[]` | ipv4 域名列表 | 为 `[]` 时,不会获取和更新 IPv4 地址 | +| ipv6 | array | No | `[]` | ipv6 域名列表 | 为 `[]` 时,不会获取和更新 IPv6 地址 | +| index4 | string\|int\|array | No | `"default"` | ipv4 获取方式 | 可设置 `网卡`、`内网`、`公网`、`正则` 等方式 | +| index6 | string\|int\|array | No | `"default"` | ipv6 获取方式 | 可设置 `网卡`、`内网`、`公网`、`正则` 等方式 | +| ttl | number | No | `null` | DNS 解析 TTL 时间 | 不设置采用 DNS 默认策略 | +| proxy | string\|array | No | 无 | http 代理 `;` 分割 | 多代理逐个尝试直到成功,`DIRECT` 为直连 | +| ~~debug~~| bool | No | `false` | 是否开启调试 | v4 中弃用,请改用 log.level=DEBUG | +| cache | string\|bool | No | `true` | 是否缓存记录 | 正常情况打开避免频繁更新,默认位置为临时目录下 `ddns.cache`,也可以指定一个具体路径 | +| log | {"level":string,"file":string} | No | `null` | 日志配置(可选) | 日志配置,日志级别和路径(默认命令行),例如:`{ "level": "DEBUG", "file": "dns.log" }` | #### index4 和 index6 参数说明 -- 数字(`0`,`1`,`2`,`3`等): 第 i 个网卡 ip -- 字符串`"default"`(或者无此项): 系统访问外网默认 IP -- 字符串`"public"`: 使用公网 ip(使用公网 API 查询,url 的简化模式) -- 字符串`"url:xxx"`: 打开 URL `xxx`(如:`"url:http://ip.sb"`),从返回的数据提取 IP 地址 -- 字符串`"regex:xxx"` 正则表达(如`"regex:192.*"`): 提取`ifconfig`/`ipconfig`中与之匹配的首个 IP 地址,**注意 json 转义**(`\`要写成`\\`) - - `"192.*"`表示 192 开头的所有 ip (注意`regex:`不可省略) - - 如果想匹配`10.00.xxxx`应该写成`"regex:10\\.00\\..*"` (`"\\"` json 转义成`\`) -- 字符串`"cmd:xxxx"`: 执行命令`xxxx`的 stdout 输出结果作为目标 IP -- 字符串`"shell:xxx"`: 使用系统 shell 运行`xxx`,并把结果 stdout 作为目标 IP -- `false`: 强制禁止更新 ipv4 或 ipv6 的 DNS 解析 -- 列表:依次执行列表中的index规则,并将最先获得的结果作为目标 IP - - 例如`["public", "regex:172\\..*"]`将先查询公网API,未获取到IP后再从本地寻找172开头的IP +- 数字(`0`,`1`,`2`,`3`等):第 i 个网卡 ip +- 字符串 `"default"`(或者无此项):系统访问外网默认 IP +- 字符串 `"public"`:使用公网 ip(使用公网 API 查询,url 的简化模式) +- 字符串 `"url:xxx"`:打开 URL `xxx`(如:`"url:http://ip.sb"`),从返回的数据提取 IP 地址 +- 字符串 `"regex:xxx"` 正则表达(如 `"regex:192.*"`):提取 `ifconfig`/`ipconfig` 中与之匹配的首个 IP 地址,**注意 json 转义**(`\`要写成`\\`) + - `"192.*"` 表示 192 开头的所有 ip(注意 `regex:` 不可省略) + - 如果想匹配 `10.00.xxxx` 应该写成 `"regex:10\\.00\\..*"`(`"\\"` json 转义成 `\`) +- 字符串 `"cmd:xxxx"`:执行命令 `xxxx` 的 stdout 输出结果作为目标 IP +- 字符串 `"shell:xxx"`:使用系统 shell 运行 `xxx`,并把结果 stdout 作为目标 IP +- `false`:强制禁止更新 ipv4 或 ipv6 的 DNS 解析 +- 列表:依次执行列表中的 index 规则,并将最先获得的结果作为目标 IP + - 例如 `["public", "regex:172\\..*"]` 将先查询公网 API,未获取到 IP 后再从本地寻找 172 开头的 IP #### 自定义回调配置说明 -- `id` 字段填写回调地址,以 HTTP 或 HTTPS 开头,推荐采用 HTTPS 方式的回调 API ,当 `token` 字段非空且 URL 参数包含下表所示的常量字符串时,常量会被程序替换为实际值 -- `token` 字段为 POST 参数,本字段为空或不存在则使用 GET 方式发起回调,回调参数采用 JSON 格式编码,当 JSON 的首层参数值包含下表所示的常量字符串时,常量会被程序替换为实际值 +- `id` 字段填写回调地址,以 HTTP 或 HTTPS 开头,推荐采用 HTTPS 方式的回调 API ,当 `token` 字段非空且 URL 参数包含下表所示的常量字符串时,会自动替换为实际内容。 +- `token` 字段为 POST 参数,本字段为空或不存在则使用 GET 方式发起回调,回调参数采用 JSON 格式编码,当 JSON 的首层参数值包含下表所示的常量字符串时,会自动替换为实际内容。 | 常量名称 | 常量内容 | 说明 | | ---------------- | ---------------------- | -------- | @@ -173,7 +172,7 @@ python run.py -c /path/to/config.json | `__RECORDTYPE__` | DDNS 记录类型 | | | `__TTL__` | DDNS TTL | | | `__TIMESTAMP__` | 请求发起时间戳 | 包含小数 | -| `__IP__` | 获取的对应类型的IP地址 | | +| `__IP__` | 获取的对应类型的 IP 地址 | | #### 配置示例 @@ -192,36 +191,34 @@ python run.py -c /path/to/config.json "log": { "level": "DEBUG", "file": "dns.log" - }, + } } ``` -
## 定时任务
- -可以通过脚本设置定时任务(默认每5分钟检查一次ip,自动更新) - +可以通过脚本设置定时任务(默认每 5 分钟检查一次 IP,自动更新) #### Windows -- [推荐]以系统身份运行,右键"以管理员身份运行"`task.bat`(或者在管理员命令行中运行) -- 以当前用户身份运行定时任务,双击或者运行`task.bat` (执行时会闪黑框) +- [推荐] 以系统身份运行,右键“以管理员身份运行”`task.bat`(或者在管理员命令行中运行) +- 以当前用户身份运行定时任务,双击或运行 `task.bat`(执行时会闪黑框) #### Linux -- 使用init.d和crontab: -`sudo ./task.sh` -- 使用systemd: - - ```bash - 安装: - sudo ./systemd.sh install - 卸载: - sudo ./systemd.sh uninstall - ``` +- 使用 init.d 和 crontab: + ```bash + sudo ./task.sh + ``` +- 使用 systemd: + ```bash + 安装: + sudo ./systemd.sh install + 卸载: + sudo ./systemd.sh uninstall + ``` 该脚本安装的文件符合 [Filesystem Hierarchy Standard (FHS)](https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard): 可执行文件所在目录为 `/usr/share/DDNS` @@ -229,17 +226,16 @@ python run.py -c /path/to/config.json #### Docker -Docker镜像在无额外参数的情况下,已默认启用每5分钟执行一次的定时任务 +Docker 镜像在无额外参数的情况下,已默认启用每 5 分钟执行一次的定时任务 +
## FAQ
+Windows Server [SSL: CERTIFICATE_VERIFY_FAILED] - Windows Server [SSL: CERTIFICATE_VERIFY_FAILED] - - -> Windows Server 默认安全策略会禁止任何未添加的信任 ssl 证书,可手动添加一下对应的证书 [#56](https://github.com/NewFuture/DDNS/issues/56#issuecomment-487371078) +> Windows Server 默认安全策略会禁止任何未添加的信任 SSL 证书,可手动添加一下对应的证书 [#56](https://github.com/NewFuture/DDNS/issues/56#issuecomment-487371078) 使用系统自带的 IE 浏览器访问一次对应的 API 即可 @@ -249,18 +245,16 @@ Docker镜像在无额外参数的情况下,已默认启用每5分钟执行一 - dnspod.cn 打开: - dnspod 国际版: - 华为 DNS -
+
- - 问题排查反馈 - +问题排查反馈 1. 先确认排查是否是系统/网络环境问题 -2. 在[issues](https://github.com/NewFuture/DDNS/issues)中搜索是否有类似问题 -3. 前两者均无法解决或者确定是 bug,[在此新建 issue](https://github.com/NewFuture/DDNS/issues/new) +2. 在 [issues](https://github.com/NewFuture/DDNS/issues) 中搜索是否有类似问题 +3. 前两者均无法解决或者确定是 bug,[在此新建 issue](https://github.com/NewFuture/DDNS/issues/new) - [ ] 开启 debug 配置 - - [ ] 附上这些内容 **运行版本和方式**,**系统环境**, **出错日志**,**去掉 id/token**的配置文件 + - [ ] 附上这些内容 **运行版本和方式**、**系统环境**、**出错日志**、**去掉 id/token** 的配置文件 - [ ] 源码运行注明使用的 python 环境 -
+ \ No newline at end of file diff --git a/favicon.ico b/favicon.ico index 77835601df1d8d0f0ddc189328c10b94c43c25d4..d7ce20b4106162480563782a3fd369808dc7dc05 100644 GIT binary patch delta 10848 zcmbuFcT^Ky*XYkA5FpZ}O9{Of>7YR99YPfa0R^Q=7ZDLAAPAx;NJn}H1+gH~c~H7k z0Tn@d6)94JwA}c-?|0X|f8KRxt;t!xGiR5XoJ`K%XD_}$)_TeV00AVxVE(pbU>N~` zA^-r3{SUjN0pLcGI!FfuFyNIi0QYGUb;LD@L_jRfch|8Y=ai$XxzrF>; zkt#s!P6x!+7(lEG1;jVLfLQJTh=mq_n4t!UiP9hmlH!F404BDPP6A0g^8k_5!bIo) zGEn=M4=^O&my?sDr}&o_0Ezz|c(Q*v;(s&wUk;OD`g?usf5ry`eG(sHNCy7ZcNHon z@%(@6!6X3;>aWp!#LIt`k{prvmysL)!%zP5YsmKc^}Bx!kZt_sJ(2>z@t4_2CrmuS z{fCb#T8Kv#q&qpPsHmv=SH=JJLDG-#CiVCMAT&jU|0*E$kZhAWfEeil0q|q~D)vLj z0*KU408R%oWE(_3a$+Gc`1JO7tI z|405<#{54DPH>2UzX}$B#9xJqR{ZXbcT>EdNfRzb7S%)Hno`UH?mg zmik(ts-JTOkS3R*j;8f($6uEpq)aF>l7}L;lp{v3=lKh~W~^>xFoUdR>}kdUhz~HsPr2kOmAkbPjHGhwXu_FL3?l#$E##?HU?14iVf4 z!!&W>3+>H~E4LJQ9&?bpv;@*E{eX|@snw>sR6dw{OSd}bCA2l~HG7OZi`;Xn-d^c_ zw%)mCm!&r}(GcAK$9+llhWXD+2hW9hL^-+WPmb-0gHv_2Q+z|1(jRr^rEd-kcW+jx zfOPgS%B>-%jfsYqshb-^dy?ATp-;s z+)9&x21-|V&Q8AvZB8vWa|P&2YSbO?E)!WF3}&LBAdnvL&3MbqATzX=sK#^9-xPG2 za^uPG&;!M((&peNB2&M!>Wa&p|DD;J3+nV)UPCB}@oM;KJp5 z5Ci0ZE|V-lih<2p!U;U^)aK{d2cmI0$=^7ZRq_2w7DhFD1l!uH$8wRXeBT%OATAKQ zWbjRKNDRnd+0PDL%R2n9G{r<8s-B}tcyjYj2h%1_Zdsc=OzDu;@u-$aSrTX(fk%U6 z+EDvmqJ7uK7i^;C@cLSKme`mnJ}uDv^3sou;@bvW!KkP{7*86x|A3V&;`(pcqHtxx z#d3UJ?c@UCj`zv~%Rv=j(j%rSd|jkkhE1b%kslG)nWmyUpWH8WlI96ykdVNINVj35 z{edoIq4D+Y^K24QeGg46`16wkX+S_kD{J#ab^}ka-(uzMopq}(4Ft)T&jWYP7dfOT zohnCw7!_Cq@hD}~Glw_oFnHbNX)U*qicMSYFAf*TXoKS_fj16}yb;^(uS8`$ubi;>m8b$=5hqHX=EM zDS$J*^N)#SN;1@DRnWI3W8HM=zKr_7Aj&yL#wpitIb#_(1;g;>~DCzHZHtS%Qmom>P945pYtIT5Y6 zp{c4}*G-zCC(*-77g)jW3+2gn2yCJ>ZF@H}=mVZotvfnXW&Yub-5W2tmWmk(WOiZ#vZC>Cnovq~Ey^b|_rJV|*Edkp zLAZ{!VbQmZLO2l4yj*#0m## zx2!RQ6Gu?)f~z+8pVY5`+n&GZK+mY5NIZiSI>tK5SY$Lu=P>`?RmaB#PcpV24jUHS zg`iq`2qpu0bgB=2bI6t@s#M~^tg@h|P+&Ga1;Biiw4BzWZYkNa;+DyKg^lOU47WCd zgfd0A4F=#R7_2H4Y+f+!rCk7UZ(5^C3k0+LTtrSfr#-J=MF!$i0siaIl_3$p8EDD% z%9?Jdy;5;pQ2-4T#@<<6=by0=ozsuHQ~mkH%Q^mY$bZv7)W$@wmCATa1b>Fgz_)dFRRUpW8FY#P z0QC6__F;7o%`o_OdayZ)1DrV8IRYEOl<>SIPrIpcuJsq}DUATIYqJh! zv4e-A->;DKdIqeiiFA&BG9 z5XD}T{>%t~o}I1Yi2s5ntXc7r8Yg?k!*!BYjUrb9U>`}a=F=BByyK#X~)4eKHAy}s4w z=S5w71{r9G#+N-`>%v~7RZLCURv#_(mJg@YnutgkKbQCYY(XRp=-bL2Jl?u;7tcTY zl%rN?N=5eP+{zU(5$5(Ym3-45HM$z8)*e&O-CUR4ze~ux{k#N$$$e@|_7uXSr#zW( z;7R1y_0LMWA*-Q;^ld*EuZ~6G9|ES<`HDjgXP;1L-?0dU0Xw;XYO(-uA3L<_iHiMG z-chWXk%aZG~n zl-tHc>E~~14{6JG3<9?Y?*3r%^ZEjW#tp*z%vwFp9L2#uVp)V#?ojDKYj3D;fIM8; zM?=*(Lp;LbvcZws2(6ZWQ)p~Z`kNa`+V0N*b~QQo<`TDP^Wx_HZST0!g&iI*TB3fJ}}i@~OS_pskuz_mV9pi$00cztG~frl;l(70N&45*KUmGGhDop#1Pc&c>nFp zT8=!>JOd&V=`@J3oxSwkX%&NM$-{T1M)y#-I|Hw@*#LgiY3dMOEZCrHcn<4l;2 zuY@q+TNq7HwD5yx2@t@qd!?VbmA;kTK*)j54^A|M1_ux-=YR4sep`)V_c0#U(uI~~ z<*0%6{(vSIl^#w+rB zq2JJfNI#UfDP)SwK3qJi7#51RX&uLn1w(fP#J-W?vl_KBhu&>CWfqP(SM%M9lo9A_7#E0CFrvVEf0G+J4Jjx_g( zj?&u$X@8!7-aPYJp9q6*N$dL7u1pHU5izV^7Z{(+bmXqol3$%l+4jMWV87>mJwaVn zS>W0bZGQ*sq=Y{=8i3d7XzM^ zM7av0ZeZ2Cz91`y6lCe8#~*S*y(Z`;M{XQrVHsef(BAuiJMr#(x!&|q_qo(fFJ)@M%AZQ+R@-$7iWP6i#_zz+x=lCO-Xd*Ktt%efv{FIlxO{(=KM#7 zPL+rlQH{hjm@VFNOD;rM@(j)R) zve}7L5Y}VPsp#B|)-TOs1E0@`lU3;kUjW#JTbE!H9^q{o-@IH^U}9~t`&4Cj93<%Q zp9YaxC*NULW->tlmXX7p)eP5I?I+!Pvl9%>XLyvUURbW3v8_2+qS2JL@ zoXIc^wT^$vg$hIX(7+LOIxH>yxS_T{rDWg1h4{(_8eo=SWYoc1o$P7Xc$h`5z02pD$~OsQvwu*>ZSjN^oowN>CSRxTv}*4ls=$6M^%r zQW2Z$z6~u9qQ4!lBbgkT*HMEW|FBA#jds-olnIuJYxmD4zFtHC#I4vXh292#q@*b7 zPE84{xtXF6i!Q;Z}@j0U5mx8jj2W_@aDzF0V%d z?k=l>Svia2y%MJRsfgUmj6Dd@=XYNe%YckWLqMbF_9-Ob^yx@eW(6X6s`LFwU@&&W z{P^;2`*W^9iE7d(+>(}*>PW~mcnI)1*t5uf1+%Eyve(|C z514>XgoHE#kKae*!hdc|W{1+B`xQg!a)ZC!>ZSqQ@6+lg3Kqg}3tCk1HC_xLVM2i= z(gOgKIlWh`7PcGNi3>x0H$_f^K^32swEZC`tr><+-YareJScEx;*%*f$QgR7(HekC z8&`nOTF<}MS<`pn4}hm@ z$g9ZnR)Znrl4CJY?ZlX>;X!Gv(_5PS<0JbgQuRInpLtBUMS}!?IDU^^+Ny+F-_vAFMBKKqe~Q5S z%{Q;v+K;g;Nh1n7lw>;~U-TejT_G{(d4i-On|+fPx&_>8>AqDFi;gY-$Kd?sKHn;>}P6 zc&!(Acz}`1{8;G(C8kRkGanBD@_>vXB$H`?Vnu$QRs`SgV7?$yR1r{|w5XGQg+%~< zOWlq?;L-kRM-x3^)R#q&%f|9OvfJmm!D_IbV0y_w<7{+40yyrx7eGE$pa20O5o{+T zLTJ!cGd=YDJ(lhRuku*xKduJu4*=GYNu@7hmFMiB4%n2}x}p>`%2DuwG@n9|@8)xn z0Gi))TgXYotE!lx^Dds34wZb5h21+Liu?4&09!^ISaq{xSrP$Ea3xF^=)voNDR&z1 zJ{?v6%&+`WUU;A;N8-6osRFa4kaB6lHB8swN1=NYGUupKL%O$@t8*JSCg)bx)UA50 zdsX-pPU$f4^(ahOC=D+Y6Om^Bh$D_j5$+~OjY3#AIhYc5`%Js~$3h+MUyACw{ONl7 z#+|Arnyz|VySUAoaJEng1Kvlip4=(h>I~!d^lDBf(7ih)flQqhM&Kg!@;O>>a7%o{ zt}w~1UYwv=zP3SBqPW{~F5#}-wSxG>%=_kL1;xpq%DY@?<}*>i+GB_k8#mM&j?1f{ z0+d*01ir``A2&AmB>^tFW;PmP+hL4oWvUkicF%P;ohVS}bLkO|t?`y_(Z5*9_;b0J@d#}4YB536N)-~i!;1@2TUaPcCJOl+MSuPGs}v3_O_W?ZfrrRci3ONsZgi}==~ z06xa1-jzlH=P>9oxPO1Gi%<80O8ZBq@RGr|p0%G!|EYyA`TXUE5{D3tDGhj?tjPed z&6gik3IM-7luYZxCWqc38?(6Dv6n*2oqU8!o5!P+cuVd+!w7^3E%>oHAWT?2^Wld- zllu?bd%iG#i@Hzta*?|uRN$Jaf9Vg9C@&*T|iXt4Og2d-i=k zCoRnv^dvPiaqdeFG6(%?1`eksyK5gbCz^9-Io|3&&hp%6E#AFd&8wGA(AW`oUsk%bkUO|+NjY(dXWvolcvBY1Mc>P9?ISCj!5q=f%oqBHh!-6#wg2~ZA*&K zdL8F1UC6t&w0=z0R^G(arSWi|>C~e2NHg<;kHC2w_fY6HIWQ=1W*NQwb3z##h?Si! zg!Kv^yZdsbO`*Wm?`5_=bHZl%XWBUr8~pQ76mM@tjpx!E*C|4vOSG%7($b{VlhJa{ zPNM@lODj@Ev;y?vYd%QeU&2w&Vth6!GjBwB?1?}25i$;7b-P{}xSj@D>s)m_gR9_b z#Z|6J4268KXvrcm=a)ag#QA3G(!yebb(&nSMSrCuL%WEEAn%dc=>-Xzudft1<8QWa z@>CDGS4wd}k33oz&$*EN4rRK#EnY;5cL^?OCNG z;fMIsNwMb!r@h_?ru%%46nyU<#x#S!zV$>|AV&4NECL(gyHFjo?P|xMVqe-3p+M_C z4rOHCqe#SnykW2&WL~%GVu6*S_;tw0Ie6)i@Yc#g<+rU+76KqE9D{Z9ov3Cm<#t4{ zQ4A*7M?SQce58Gf3Bq{5z-`b$2uI!ZYpPj^)=wpG_4q+jeU_F0HK^2uQc-?3Bjaha z`0ML*${J(pWZVGPg=FCtAk*}YNM>{C40G^lTj~6M%Pjk_bYt@S*OV*jaoYn0@!NY! zd(=t{lQhH)-@%n5Z?zL4{yO{6Tc56<1TEDi6%RZ42=pWHsc~=wU|jrNKf3WUK2-kF zs+#tyH`Z)f`K(*xv&|p(J|ZyOm#*arT<*GlrhE%zyM@5E41SqpyHc6gm32hlGR-j` z8Y=ok>BTvbmZ@igX=#tYHF5ICe1}krF2b>ou6h?W!HfW><1R&oh)wU^W}J!%T?^|} zmmnx@SmxNrQNrH9uJ91eRPUFxB?ZTa5R3E;E{bB4EL!`es7D_qq}q-mz>ABjE7q5y zDB3T>;Rj4l-q#U74$FhQsf-KXxhHT;oAVn*L>A}|eegENhP9^QSL}0A`t)YZNEh*- zb!t^(<>mvU;)A5^(f}p6d`AFkb-xLBFkSxq*~Wnprk-hhnPqqzQ1CkM2$NVbU1t5|;X~n3AmxFzx4HCHW42m?ltk22ao@yP9mVzcT$KdO22t(lxlIqYe@hr$FAGkb!j ze(N^2kOiJaDz~gm@ynqb5=2g4NqA$`EeSJxoM3EwPjgG|CXix+j7)W0{e@dHWYtL&M8)*?OkDrZy_cZAb%-i`-Jh~_% zHbAIoJ!%w3Sl>{Z46Tq}-S`IZdXOcV)oHDC)&rbO>zFO_5)ydY*G0wjj-{dV;g(ba zt06Qkf|X<5Zz9%hOm>!SG6Otg(K|N}Dj>4)5*l>WxHQ}SDYf8PxIlKf0okA{li!lM zr7n-5o=`E=U(SNGx7=fK&&QT^1V}P7|4C8Ush1WzV0Z{hBEW2R>K9}h`ElyP7eTr? zT#AFKpw~ak*Xu2J+eM8ujLyL^3Uft#9lU`l-N&U{?R-E_Ebo>XxZ=LjgibE-h_086 zZm3a{7EMBjXxKF{?w-stv^rWvJjKwHoiW!R0k2Xh^LEBzi5+rk(}}JGTvi;@y;nJt z3npa4!ozyk zwiuvgg5qTE=*U;nXnnnsua(a;8>H8M=5Zs-K@9-b*=6&?JPX&n*fcU8Q`h4@sW3kP zgVuSj%S~^2$*z4+icX~vofB7B&!S_ZDON&Q{Afu|JGDzUJDdL0<@Aup&F+_P3nfrM zhVnmKLH7Dy#aS?K!b7L~V)@k0Ot@RRk@cf>gZ&N0o^0p#?EP{nuN`Hcv&n^I{hrxS zUC#Q9V*-fZj9NTdRcpidv1)mgrpXjim9ZoHg8ZQ8Ff9(>)%6lLuCF5Xv}*cbaxTrO zKDVqn;KY#=bZ~ZV^n7m=`YD0|I*_hd6Dys=S;XzFe0a){AZZ9W=r>eu}Cr?$wFMPh#>4tPdQ&!=nMrJcJydCZ}hoT%$y zO?Zob+Rl%ENPvEG^%Y>mViUt()!cE7F0wYVMgn?Y;qo=-N_|&~WyB|5E(l+4a8S3< zO4?6>D=9?ofp_PX{pc8F7)2BQY|5nG)~rSWoC3zMT3hon+Rt{8Wt8FLzQXVDT_$G^ z`mOL`?lf70kJ^0)^bj;+Y{-2;30^oL2Tg);Dn{%u^^LK(av&XB0hEUkNj>8Uz&yL0_GJ|AVZ@Sy8+N*5&B9$8 zq4+iEc?FQ+E1x>WH7UT3Bi-IxF}kUD7!H=aE0B0$lp;Rj_lw47y%-^HZ2}cV7G@*kqJ$VZa97V^ z6wD8En$M(q8XJ!Lo|&lbX?^r%*%JY7L5Nnt!c(X_m;)04D4YyoQZd1sDNd}KaU5^R zxDfz1@=RWSq9(-nDZY7!XOrSs(K)>O8<8(wV=4y{0K${?k=Z9*8hK_)XBVSKWJM4t zNh{x^x@&u?^t8KuO`kQrxx!B6MkWH!L_a7&>$p6pkK_%~v^~WpN-;9!u=y0=+V+Q% z3I~!isHEyp0x&t?y}B~t<3p-KK4FIs{A3uIEr&1k;hNi5dR#0z^;vd0T3?Sv z1%Q~NIkGS40F@u%v-Xnghg5S@_k?>QeVkD1QEKerzlE^r0LgxGJDhRIyVvSL<3L60Lq{7X*2AdL-GczQA=cb~-cLUc4{ktFJ#dwYsmt&~4UEPrJ`m z_%~-C^rR~+(jaX@u>pyX#!885_RZ3_?Xc4)cu)^d(Y*5*-V|0Z6uw|sC-1xy$Ps)B zd=_ZDGOA^6`SlEqme}XI3sV7i=}?^~@hFQ>ZEC@&`JUwU3J`qqz7MYRUdr6t>s5KZP3&mAYjPb0v^cWA$6t^QUgEy9xFiN=k~e5PwR0e)s*;I z91@06l)}MNeo->B}Qj@taU|du9LeTr=teWhl*Btu(2iWzE=8poU+0{}zNf()fgp9Jf(kQ|FBT z4*&cROe9{P7Wf(btra+@T{Y&G?{7*-$GDB|~;31bWKn-pT>x$1l1G%xe;@5y@AwDoDjYu09N{ z5m7W|qX4*$NXpBB_vE5I{r>=LYOX2aIv9L=yMo>g;G%y8p%g&b2STd80&u^m+V++m zP|EF~>PZ3+Z-JEzz^Vjg-9mxR#2QH?x53ylY)u1jW|P=+4}lLhwv9A`{aDri0Er+K8;X8s-<3Zw{b&T11iqJ^8p;DLak z{ZeV)dLDa$H3NBeV4b@6kS@$ABg*pw9P&Bi#Afb9rkX16HF!)7CchoK`qGZsV3GLx zqhJ)+tMD^rmIrn-;St5}N8K7oq4n=);K!&nzQTn-DmO{9zx65Oy9Hm;Gjibj@wodq zWDsHhc>Q}Vk|L*BvR6I)PYoOz)=OPy2$WZc$0fx*YwC8_KTFOoI2E?dtF|V zd70B=+WyBIzh}U2y10g)y=2UxrSfz0zv*hP^L_q4w4h^R%D3uO?%ypW7AUsb;^k>$ zXy1ZuD#G^XRSDMKJMj^RKhzEihib#4{#=Lh6rwK`E^Q|E#7n>WrAa|UdcG^u z_7QMn5S{(Srmh(pV8D{%?dJ-rKjW_jom!a$V8-$v#hA;lsyAEmY-cW?0n?3Q!@vL5 zCF!51zu9Z-r3*6^<4RE=n(g7O(2rVqlSsU${vXl=SqL$C?1!Phz1qLNYw>veX{2vn z1cXIur5jKZ=qKu8?i=(7FZ{d~PwW;u`LmY1PMV6O{i$4kXMIvx+1JGCN7i$AdD8E! zNagQ#*R7AFf;BFxUIPVM15$O{|1lK)e;E7!H#CBX^mjWud{>>cFee>`x@J06TFy}9 F{{oZXSvmj! literal 54886 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 c>3p>ZASuw|J{9G*Y1J;4;3*UegFUf