mirror of
https://github.com/NewFuture/DDNS.git
synced 2022-04-19 20:24:44 +00:00
feat(dnsprovider): support custom callback api (#170)
* feat(dnsprovider): support custom callback api * feat(callback): shouldn't try to parsing return close #163
This commit is contained in:
+2
-1
@@ -21,7 +21,8 @@ a = Analysis(['../run.py'],
|
||||
'dns.dnspod_com',
|
||||
'dns.dnscom',
|
||||
'dns.cloudflare',
|
||||
'dns.huaweidns'
|
||||
'dns.huaweidns',
|
||||
'dns.callback'
|
||||
],
|
||||
hookspath=[],
|
||||
runtime_hooks=[],
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
- [x] 可设置定时任务
|
||||
- [x] TTL 配置支持
|
||||
- [x] 本地文件缓存(减少 API 请求)
|
||||
- [x] 地址变更时触发自定义回调API(与 DDNS 功能互斥)
|
||||
|
||||
## 使用
|
||||
|
||||
@@ -83,6 +84,7 @@
|
||||
- [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`字段,为待更新的域名,详细参照配置说明
|
||||
|
||||
@@ -109,7 +111,7 @@ python run.py -c /path/to/config.json
|
||||
| :----: | :---------: | :------: | :---------: | :---------------: | ----------------------------------------------------------------------------------------------------------- |
|
||||
| id | string | √ | 无 | api 访问 ID | Cloudflare 为邮箱(使用 Token 时留空)<br>HE.net 可留空 |
|
||||
| token | string | √ | 无 | api 授权 token | 部分平台叫 secret key , **反馈粘贴时删除** |
|
||||
| dns | string | No | `"dnspod"` | dns 服务商 | 阿里`alidns`,<br>dns.com 为`dnscom`,<br>DNSPOD 国际版`dnspod_com`,<br>HE.net 为`he`,华为 DNS 为`huaweidns` |
|
||||
| dns | string | No | `"dnspod"` | dns 服务商 | 阿里`alidns`,<br>dns.com 为`dnscom`,<br>DNSPOD 国际版`dnspod_com`,<br>HE.net 为`he`,华为 DNS 为`huaweidns`,<br>自定义回调为`callback` |
|
||||
| ipv4 | array | No | `[]` | ipv4 域名列表 | 为`[]`时,不会获取和更新 IPv4 地址 |
|
||||
| ipv6 | array | No | `[]` | ipv6 域名列表 | 为`[]`时,不会获取和更新 IPv6 地址 |
|
||||
| index4 | string\|int | No | `"default"` | ipv4 获取方式 | 可设置`网卡`,`内网`,`公网`,`正则`等方式 |
|
||||
@@ -133,6 +135,19 @@ python run.py -c /path/to/config.json
|
||||
- 字符串`"shell:xxx"`: 使用系统 shell 运行`xxx`,并把结果 stdout 作为目标 IP
|
||||
- `false`: 强制禁止更新 ipv4 或 ipv6 的 DNS 解析
|
||||
|
||||
#### 自定义回调配置说明
|
||||
|
||||
- `id` 字段填写回调地址,以 HTTP 或 HTTPS 开头,推荐采用 HTTPS 方式的回调 API ,当 `token` 字段非空且 URL 参数包含下表所示的常量字符串时,常量会被程序替换为实际值
|
||||
- `token` 字段为 POST 参数,本字段为空或不存在则使用 GET 方式发起回调,回调参数采用 JSON 格式编码,当 JSON 的首层参数值包含下表所示的常量字符串时,常量会被程序替换为实际值
|
||||
|
||||
| 常量名称 | 常量内容 | 说明 |
|
||||
| ---------------- | ---------------------- | -------- |
|
||||
| `__DOMAIN__` | DDNS 域名 | |
|
||||
| `__RECORDTYPE__` | DDNS 记录类型 | |
|
||||
| `__TTL__` | DDNS TTL | |
|
||||
| `__TIMESTAMP__` | 请求发起时间戳 | 包含小数 |
|
||||
| `__IP__` | 获取的对应类型的IP地址 | |
|
||||
|
||||
#### 配置示例
|
||||
|
||||
```json
|
||||
@@ -140,7 +155,7 @@ python run.py -c /path/to/config.json
|
||||
"$schema": "https://ddns.newfuture.cc/schema/v2.8.json",
|
||||
"id": "12345",
|
||||
"token": "mytokenkey",
|
||||
"dns": "dnspod 或 dnspod_com 或 alidns 或 dnscom 或 cloudflare 或 he 或 huaweidns",
|
||||
"dns": "dnspod 或 dnspod_com 或 alidns 或 dnscom 或 cloudflare 或 he 或 huaweidns 或 callback",
|
||||
"ipv4": ["ddns.newfuture.cc", "ipv4.ddns.newfuture.cc"],
|
||||
"ipv6": ["ddns.newfuture.cc", "ipv6.ddns.newfuture.cc"],
|
||||
"index4": 0,
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
# coding=utf-8
|
||||
"""
|
||||
Custom Callback API
|
||||
自定义回调接口解析操作库
|
||||
|
||||
@author: 老周部落
|
||||
"""
|
||||
|
||||
from json import loads as jsondecode, dumps as jsonencode
|
||||
from logging import debug, info, warning
|
||||
from time import time
|
||||
|
||||
try:
|
||||
# python 2
|
||||
from httplib import HTTPSConnection, HTTPConnection
|
||||
from urlparse import urlparse, parse_qsl
|
||||
from urllib import urlencode
|
||||
except ImportError:
|
||||
# python 3
|
||||
from http.client import HTTPSConnection, HTTPConnection
|
||||
from urllib.parse import urlencode, urlparse, parse_qsl
|
||||
|
||||
__author__ = '老周部落'
|
||||
|
||||
class Config:
|
||||
ID = None # 自定义回调 URL
|
||||
TOKEN = None # 使用 JSON 编码的 POST 参数
|
||||
PROXY = None # 代理设置
|
||||
TTL = None
|
||||
|
||||
def request(method, action, param=None, **params):
|
||||
"""
|
||||
发送请求数据
|
||||
"""
|
||||
if param:
|
||||
params.update(param)
|
||||
|
||||
URLObj = urlparse(Config.ID)
|
||||
params = dict((k, params[k]) for k in params if params[k] is not None)
|
||||
info("%s/%s : %s", URLObj.netloc, action, params)
|
||||
|
||||
if Config.PROXY:
|
||||
if URLObj.netloc == "http":
|
||||
conn = HTTPConnection(Config.PROXY)
|
||||
else:
|
||||
conn = HTTPSConnection(Config.PROXY)
|
||||
conn.set_tunnel(URLObj.netloc, URLObj.port)
|
||||
else:
|
||||
if URLObj.netloc == "http":
|
||||
conn = HTTPConnection(URLObj.netloc, URLObj.port)
|
||||
else:
|
||||
conn = HTTPSConnection(URLObj.netloc, URLObj.port)
|
||||
|
||||
headers = {}
|
||||
|
||||
if method == "GET":
|
||||
if params:
|
||||
action += '?' + urlencode(params)
|
||||
params = ""
|
||||
else:
|
||||
headers["Content-Type"] = "application/x-www-form-urlencoded"
|
||||
|
||||
params = urlencode(params)
|
||||
|
||||
conn.request(method, action, params, headers)
|
||||
response = conn.getresponse()
|
||||
res = response.read().decode('utf8')
|
||||
conn.close()
|
||||
if response.status < 200 or response.status >= 300:
|
||||
warning('%s : error[%d]:%s', action, response.status, res)
|
||||
raise Exception(res)
|
||||
else:
|
||||
debug('%s : result:%s', action, res)
|
||||
return data
|
||||
|
||||
def replace_params(domain, record_type, ip, params):
|
||||
"""
|
||||
替换定义常量为实际值
|
||||
"""
|
||||
dict = {"__DOMAIN__": domain, "__RECORDTYPE__": record_type, "__TTL__": Config.TTL, "__TIMESTAMP__": time(), "__IP__": ip}
|
||||
for key, value in params.items():
|
||||
if dict.get(value):
|
||||
params[key] = dict.get(value)
|
||||
return params
|
||||
|
||||
def update_record(domain, value, record_type="A"):
|
||||
"""
|
||||
更新记录
|
||||
"""
|
||||
info(">>>>>%s(%s)", domain, record_type)
|
||||
|
||||
result = {}
|
||||
|
||||
if not Config.TOKEN: # 此处使用 TOKEN 参数透传 POST 参数所用的 JSON
|
||||
method = "GET"
|
||||
URLObj = urlparse(Config.ID)
|
||||
path = URLObj.path
|
||||
query = dict(parse_qsl(URLObj.query))
|
||||
params = replace_params(domain, record_type, value, query)
|
||||
else:
|
||||
method = "POST"
|
||||
URLObj = urlparse(Config.ID)
|
||||
path = URLObj.path
|
||||
params = replace_params(domain, record_type, value, jsondecode(Config.TOKEN))
|
||||
|
||||
res = request(method, path, params)
|
||||
|
||||
if res:
|
||||
result = "Callback Request Success!\n" + res
|
||||
else:
|
||||
result = "Callback Request Fail!\n"
|
||||
|
||||
return result
|
||||
+3
-2
@@ -34,7 +34,7 @@
|
||||
"$id": "/properties/dns",
|
||||
"type": "string",
|
||||
"title": "DNS Provider",
|
||||
"description": "dns服务商:阿里为alidns,DNS.COM为dnscom,DNSPOD国际版为(dnspod_com),cloudflare,HE.net为he",
|
||||
"description": "dns服务商:阿里为alidns,DNS.COM为dnscom,DNSPOD国际版为(dnspod_com),cloudflare,HE.net为he,华为DNS为huaweidns,自定义回调为callback",
|
||||
"default": "dnspod",
|
||||
"examples": [
|
||||
"dnspod",
|
||||
@@ -48,7 +48,8 @@
|
||||
"dnspod_com",
|
||||
"dnscom",
|
||||
"he",
|
||||
"huaweidns"
|
||||
"huaweidns",
|
||||
"callback"
|
||||
]
|
||||
},
|
||||
"ipv4": {
|
||||
|
||||
Reference in New Issue
Block a user