diff --git a/README.md b/README.md index 612596c..19edfac 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ -[DDNS](https://github.com/NewFuture/DDNS) -=================== +# [DDNS](https://github.com/NewFuture/DDNS) ->自动更新DNS解析 到本机IP地址,支持 ipv4和ipv6 以 本地(内网)IP 和 公网IP。 ->代理模式,支持自动创建域名记录。 +> 自动更新 DNS 解析 到本机 IP 地址,支持 ipv4 和 ipv6 以 本地(内网)IP 和 公网 IP。 +> 代理模式,支持自动创建域名记录。 [![PyPI](https://img.shields.io/pypi/v/ddns.svg?label=DDNS&style=social)](https://pypi.org/project/ddns/) [![Build Status](https://travis-ci.com/NewFuture/DDNS.svg?branch=master)](https://travis-ci.com/NewFuture/DDNS) @@ -14,44 +13,44 @@ Build Details -* Linux Python (2和3): [![Travis build](https://img.shields.io/travis/com/NewFuture/DDNS/master.svg?label=python2%2Cpython3&logo=ubuntu&logoColor=white)](https://travis-ci.com/NewFuture/DDNS) -* Windows Python3.7: [![Build Status](https://dev.azure.com/NewFuture-CI/ddns-ci/_apis/build/status/NewFuture.DDNS?branchName=master&jobName=Windows&configuration=Python37)](https://dev.azure.com/NewFuture-CI/ddns-ci/_build/latest?definitionId=2&branchName=master) -* Windows Python2.7: [![Build Status](https://dev.azure.com/NewFuture-CI/ddns-ci/_apis/build/status/NewFuture.DDNS?branchName=master&jobName=Windows&configuration=Python27)](https://dev.azure.com/NewFuture-CI/ddns-ci/_build/latest?definitionId=2&branchName=master) -* Mac OSX Python3.7: [![Build Status](https://dev.azure.com/NewFuture-CI/ddns-ci/_apis/build/status/NewFuture.DDNS?branchName=master&jobName=MacOS&configuration=Python37)](https://dev.azure.com/NewFuture-CI/ddns-ci/_build/latest?definitionId=2&branchName=master) -* Mac OSX Python2.7: [![Build Status](https://dev.azure.com/NewFuture-CI/ddns-ci/_apis/build/status/NewFuture.DDNS?branchName=master&jobName=MacOS&configuration=Python27)](https://dev.azure.com/NewFuture-CI/ddns-ci/_build/latest?definitionId=2&branchName=master) +- Linux Python (2 和 3): [![Travis build](https://img.shields.io/travis/com/NewFuture/DDNS/master.svg?label=python2%2Cpython3&logo=ubuntu&logoColor=white)](https://travis-ci.com/NewFuture/DDNS) +- Windows Python3.7: [![Build Status](https://dev.azure.com/NewFuture-CI/ddns-ci/_apis/build/status/NewFuture.DDNS?branchName=master&jobName=Windows&configuration=Python37)](https://dev.azure.com/NewFuture-CI/ddns-ci/_build/latest?definitionId=2&branchName=master) +- Windows Python2.7: [![Build Status](https://dev.azure.com/NewFuture-CI/ddns-ci/_apis/build/status/NewFuture.DDNS?branchName=master&jobName=Windows&configuration=Python27)](https://dev.azure.com/NewFuture-CI/ddns-ci/_build/latest?definitionId=2&branchName=master) +- Mac OSX Python3.7: [![Build Status](https://dev.azure.com/NewFuture-CI/ddns-ci/_apis/build/status/NewFuture.DDNS?branchName=master&jobName=MacOS&configuration=Python37)](https://dev.azure.com/NewFuture-CI/ddns-ci/_build/latest?definitionId=2&branchName=master) +- Mac OSX Python2.7: [![Build Status](https://dev.azure.com/NewFuture-CI/ddns-ci/_apis/build/status/NewFuture.DDNS?branchName=master&jobName=MacOS&configuration=Python27)](https://dev.azure.com/NewFuture-CI/ddns-ci/_build/latest?definitionId=2&branchName=master) ------------- +--- ## Features -* 兼容和跨平台: - * [x] 可执行文件(无需python环境) - * [x] 多系统兼容 ![cross platform](https://img.shields.io/badge/platform-windows_%7C%20linux_%7C%20osx-success.svg?style=social) - * [x] python2和python3支持 ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ddns.svg?style=social) - * [x] PIP安装 ![PyPI - Wheel](https://img.shields.io/pypi/wheel/ddns.svg?style=social) -* 域名支持: - * [x] 多个域名支持 - * [x] 多级域名解析 - * [x] 自动创建新记录 -* IP类型: - * [x] 内网IP - * [x] 公网IP - * [x] ipv6支持 - * [x] 正则选取支持(@rufengsuixing) -* 网络代理: - * [x] http代理支持 - * [x] 多代理自动切换 -* 服务商支持: - * [x] [DNSPOD](https://www.dnspod.cn/) - * [x] [阿里DNS](http://www.alidns.com/) - * [x] [DNS.COM](https://www.dns.com/)(@loftor-git) - * [x] [DNSPOD国际版](https://www.dnspod.com/) - * [x] [CloudFlare](https://www.cloudflare.com/)(@tongyifan) -* 其他: - * [x] 可设置定时任务 - * [x] 本地文件缓存(减少API请求) +- 兼容和跨平台: + - [x] 可执行文件(无需 python 环境) + - [x] 多系统兼容 ![cross platform](https://img.shields.io/badge/platform-windows_%7C%20linux_%7C%20osx-success.svg?style=social) + - [x] python2 和 python3 支持 ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/ddns.svg?style=social) + - [x] PIP 安装 ![PyPI - Wheel](https://img.shields.io/pypi/wheel/ddns.svg?style=social) +- 域名支持: + - [x] 多个域名支持 + - [x] 多级域名解析 + - [x] 自动创建新记录 +- IP 类型: + - [x] 内网 IP + - [x] 公网 IP + - [x] ipv6 支持 + - [x] 正则选取支持(@rufengsuixing) +- 网络代理: + - [x] http 代理支持 + - [x] 多代理自动切换 +- 服务商支持: + - [x] [DNSPOD](https://www.dnspod.cn/) + - [x] [阿里 DNS](http://www.alidns.com/) + - [x] [DNS.COM](https://www.dns.com/)(@loftor-git) + - [x] [DNSPOD 国际版](https://www.dnspod.com/) + - [x] [CloudFlare](https://www.cloudflare.com/)(@tongyifan) +- 其他: + _ [x] 可设置定时任务 + _ [x] 本地文件缓存(减少 API 请求) ## 使用 @@ -59,29 +58,29 @@ 根据需要选择一种方式: `二进制`版,`pip`版,或者`源码`运行 -* #### pip安装(需要pip或easy_install) _beta_ - 1. 安装ddns: `pip install ddns` 或 `easy_install ddns` - 2. 运行: `ddns` -* #### 二进制版(单文件,无需python) - * Windows [ddns.exe](https://github.com/NewFuture/DDNS/releases/latest) - * Linux (仅Ubuntu测试) [ddns](https://github.com/NewFuture/DDNS/releases/latest) - * Mac OSX [ddns-oxs](https://github.com/NewFuture/DDNS/releases/latest) -* #### 源码运行(无任何依赖, 需python环境) - 1. clone 或者[下载此仓库](https://github.com/NewFuture/DDNS/archive/master.zip)并解压 - 2. 运行./run.py (widnows 双击`run.bat`或者运行`python run.py`) +- #### pip 安装(需要 pip 或 easy*install) \_beta* + 1. 安装ddns: `pip install ddns` 或 `easy_install ddns` + 2. 运行: `ddns` +- #### 二进制版(单文件,无需 python) + * Windows [ddns.exe](https://github.com/NewFuture/DDNS/releases/latest) + * Linux (仅Ubuntu测试) [ddns](https://github.com/NewFuture/DDNS/releases/latest) + * Mac OSX [ddns-oxs](https://github.com/NewFuture/DDNS/releases/latest) +- #### 源码运行(无任何依赖, 需 python 环境) + 1. clone 或者[下载此仓库](https://github.com/NewFuture/DDNS/archive/master.zip)并解压 + 2. 运行./run.py (widnows 双击`run.bat`或者运行`python run.py`) ### ② 快速配置 1. 申请 api `token`,填写到对应的`id`和`token`字段: - * [DNSPOD(国内版)创建token](https://support.dnspod.cn/Kb/showarticle/tsid/227/) - * [阿里云accesskey](https://help.aliyun.com/knowledge_detail/38738.html) - * [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-) + + - [DNSPOD(国内版)创建 token](https://support.dnspod.cn/Kb/showarticle/tsid/227/) + - [阿里云 accesskey](https://help.aliyun.com/knowledge_detail/38738.html) + - [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-) 2. 修改配置文件,`ipv4`和`ipv6`字段,为待更新的域名,详细参照配置说明 - ## 详细配置
@@ -89,70 +88,63 @@ config.json 配置文件 -* 首次运行会自动生成一个模板配置文件 -* 可以使用 `-c`使用指定的配置文件 (默认读取当前目录的 config.json) -* 推荐使用vscode等支持JsonSchema的编辑器编辑配置文件 +- 首次运行会自动生成一个模板配置文件 +- 可以使用 `-c`使用指定的配置文件 (默认读取当前目录的 config.json) +- 推荐使用 vscode 等支持 JsonSchema 的编辑器编辑配置文件 ```bash ddns -c path/to/config.json # 或者源码运行 -python run.py -c /path/to/config.json +python run.py -c /path/to/config.json ``` #### 配置参数表 -| key | type | required | default | description | tips | -| :---: | :----: | :------: | :-----: | :---------: | ------- | -| id | string | √ | 无 | api访问ID | cloudflare为邮箱 | -| token | string | √ | 无 | api授权token | 也叫secret key, **反馈粘贴时删除** | -| dns | string | No |`"dnspod"`| dns 服务商 | 阿里`alidns`,
dns.com为`dnscom`,
DNSPOD国际版`dnspod_com`| -| ipv4 | array | No | `[]` | ipv4 域名列表 | 为`[]`时,不会获取和更新IPv4地址 | -| ipv6 | array | No | `[]` | ipv6 域名列表 | 为`[]`时,不会获取和更新IPv6地址 | -| index4|string\|int|No |`"default"`| ipv4 获取方式 | 可设置`网卡`,`内网`,`公网`,`正则`等方式 | -| index6|string\|int|No |`"default"`| ipv6 获取方式 | 可设置`网卡`,`内网`,`公网`,`正则`等方式 | -| proxy | string | No | 无 | http代理`;`分割 | 多代理逐个尝试直到成功,`DIRECT`为直连| -| debug | bool | No | `false` | 是否开启调试 | 运行异常时,打开调试输出,方便诊断错误 | -| cache | bool | No | `true` | 是否缓存记录 | 正常情况打开避免频繁更新 | +| key | type | required | default | description | tips | +| :----: | :---------: | :------: | :---------: | :--------------: | ----------------------------------------------------------------- | +| id | string | √ | 无 | api 访问 ID | cloudflare 为邮箱 | +| token | string | √ | 无 | api 授权 token | 也叫 secret key, **反馈粘贴时删除** | +| dns | string | No | `"dnspod"` | dns 服务商 | 阿里`alidns`,
dns.com 为`dnscom`,
DNSPOD 国际版`dnspod_com` | +| ipv4 | array | No | `[]` | ipv4 域名列表 | 为`[]`时,不会获取和更新 IPv4 地址 | +| ipv6 | array | No | `[]` | ipv6 域名列表 | 为`[]`时,不会获取和更新 IPv6 地址 | +| index4 | string\|int | No | `"default"` | ipv4 获取方式 | 可设置`网卡`,`内网`,`公网`,`正则`等方式 | +| index6 | string\|int | No | `"default"` | ipv6 获取方式 | 可设置`网卡`,`内网`,`公网`,`正则`等方式 | +| proxy | string | No | 无 | http 代理`;`分割 | 多代理逐个尝试直到成功,`DIRECT`为直连 | +| debug | bool | No | `false` | 是否开启调试 | 运行异常时,打开调试输出,方便诊断错误 | +| cache | bool | No | `true` | 是否缓存记录 | 正常情况打开避免频繁更新 | +#### index4 和 index6 参数说明 -#### index4和index6参数说明 - -* 数字(`0`,`1`,`2`,`3`等): 第i个网卡ip -* 正则表达(如`"192.*"`): 提取`ifconfig`/`ipconfig`中与之匹配的首个IP地址,**注意json转义**(`\`要写成`\\`) - * `"192.*"`表示192开头的所有ip - * 如果想匹配`10.00.xxxx`应该写成`"10\\.00\\..*"`(`"\\"`json转义成`\`) -* 字符串`"default"`(或者无此项): 系统访问外网默认IP -* 字符串`"public"`: 使用公网ip(使用公网API查询) -* 字符串`"cmd:xxxx"`: 执行命令`xxxx`的stdout输出结果作为目标IP -* 字符串`"shell:xxx"`: 使用系统shell运行`xxx`,并把结果stdout作为目标IP -* `false`: 强制禁止更新ipv4或ipv6的DNS解析 +- 数字(`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 + - 如果想匹配`10.00.xxxx`应该写成`"regex:10\\.00\\..\*"`(`"\\"`json 转义成`\`) +- 字符串`"cmd:xxxx"`: 执行命令`xxxx`的 stdout 输出结果作为目标 IP +- 字符串`"shell:xxx"`: 使用系统 shell 运行`xxx`,并把结果 stdout 作为目标 IP +- `false`: 强制禁止更新 ipv4 或 ipv6 的 DNS 解析 #### 配置示例 ```json { - "$schema": "https://ddns.newfuture.cc/schema/v2.json", - "id": "12345", - "token": "mytokenkey", - "dns": "dnspod 或 dnspod_com 或 alidns 或 dnscom 或 cloudflare", - "ipv4": [ - "ddns.newfuture.cc", - "ipv4.ddns.newfuture.cc" - ], - "ipv6": [ - "ddns.newfuture.cc", - "ipv6.ddns.newfuture.cc" - ], - "index4": 0, - "index6": "public", - "proxy": "127.0.0.1:1080;DIRECT", - "debug": false + "$schema": "https://ddns.newfuture.cc/schema/v2.json", + "id": "12345", + "token": "mytokenkey", + "dns": "dnspod 或 dnspod_com 或 alidns 或 dnscom 或 cloudflare", + "ipv4": ["ddns.newfuture.cc", "ipv4.ddns.newfuture.cc"], + "ipv6": ["ddns.newfuture.cc", "ipv6.ddns.newfuture.cc"], + "index4": 0, + "index6": "public", + "proxy": "127.0.0.1:1080;DIRECT", + "debug": false } ```
- ## 定时任务
@@ -162,8 +154,8 @@ python run.py -c /path/to/config.json #### windows -* [推荐]以系统身份运行,右键"以管理员身份运行"`task.bat`(或者在管理员命令行中运行) -* 以当前用户身份运行定时任务,双击或者运行`task.bat` (执行时会闪黑框) +- [推荐]以系统身份运行,右键"以管理员身份运行"`task.bat`(或者在管理员命令行中运行) +- 以当前用户身份运行定时任务,双击或者运行`task.bat` (执行时会闪黑框) #### linux @@ -178,15 +170,15 @@ python run.py -c /path/to/config.json 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 即可 -使用系统自带的IE浏览器访问一次对应的API即可 -* alidns打开: -* cloudflare打开: -* dns.com打开: -* dnspod.cn打开: -* dnspod国际版: +- alidns 打开: +- cloudflare 打开: +- dns.com 打开: +- dnspod.cn 打开: +- dnspod 国际版:
@@ -197,9 +189,9 @@ python run.py -c /path/to/config.json 1. 先确认排查是否是系统/网络环境问题 2. 在[issues](https://github.com/NewFuture/DDNS/issues)中搜索是否有类似问题 -3. 前两者均无法解决或者确定是bug,[在此新建issue](https://github.com/NewFuture/DDNS/issues/new) - * [ ] 开启debug配置 - * [ ] 附上这些内容 **运行版本和方式**,**系统环境**, **出错日志**,**去掉id/token**的配置文件 - * [ ] 源码运行注明使用的python环境 +3. 前两者均无法解决或者确定是 bug,[在此新建 issue](https://github.com/NewFuture/DDNS/issues/new) + - [ ] 开启 debug 配置 + - [ ] 附上这些内容 **运行版本和方式**,**系统环境**, **出错日志**,**去掉 id/token**的配置文件 + - [ ] 源码运行注明使用的 python 环境 diff --git a/run.py b/run.py index 93b6d54..fec3176 100755 --- a/run.py +++ b/run.py @@ -83,13 +83,17 @@ def get_ip(ip_type): index = get_config('index' + ip_type, "default") if index is False: # disabled return False - elif str(index).isdigit(): # local eth + elif str(index).isdigit(): # 数字 local eth value = getattr(ip, "local_v" + ip_type)(index) elif index.startswith('cmd:'): # cmd value = check_output(index[4:]).strip() elif index.startswith('shell:'): # shell value = check_output(index[6:], shell=True).strip() - elif any((c in index) for c in '*.:'): # regex + elif index.startswith('url:'): # 自定义 url + value = getattr(ip, "public_v" + ip_type)(index[4:]) + elif index.startswith('regex:'): # 正则 regex + value = getattr(ip, "regex_v" + ip_type)(index[6:]) + elif any((c in index) for c in '*.:'): # 兼容 regex value = getattr(ip, "regex_v" + ip_type)(index) else: value = getattr(ip, index + "_v" + ip_type)() diff --git a/schema/v2.json b/schema/v2.json index 34bcc14..644af91 100644 --- a/schema/v2.json +++ b/schema/v2.json @@ -33,18 +33,8 @@ "title": "DNS Provider", "description": "dns服务商:阿里为alidns,DNS.COM为dnscom,DNSPOD国际版为dnspod_com,cloudflare", "default": "dnspod", - "examples": [ - "dnspod", - "alidns", - "cloudflare" - ], - "enum": [ - "dnspod", - "alidns", - "cloudflare", - "dnspod_com", - "dnscom" - ] + "examples": ["dnspod", "alidns", "cloudflare"], + "enum": ["dnspod", "alidns", "cloudflare", "dnspod_com", "dnscom"] }, "ipv4": { "$id": "/properties/ipv4", @@ -57,10 +47,7 @@ "title": "ipv4 domain for DDNS", "type": "string", "pattern": "^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,18}$", - "examples": [ - "newfuture.cc", - "ipv4.example.newfuture.cc" - ] + "examples": ["newfuture.cc", "ipv4.example.newfuture.cc"] } }, "ipv6": { @@ -74,62 +61,48 @@ "title": "The ipv6 domain for DDNS", "type": "string", "pattern": "^([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}$", - "examples": [ - "newfuture.cc", - "ipv6.example.newfuture.cc" - ] + "examples": ["newfuture.cc", "ipv6.example.newfuture.cc"] } }, "index4": { "$id": "/properties/index4", - "type": [ - "string", - "integer", - "boolean" - ], + "type": ["string", "integer", "boolean"], "title": "IPv4 address Setting", - "description": "本机 IPv4 获取方式:default默认请求IP,public公网,数字表示网卡,正则提取IPconfig", + "description": "本机 IPv4 获取方式\n`default`默认请求IP\n`public`公网\n数字表示网卡\n`url:http://myip.com`从URL的返回结果中提取\n`reg:xxx`正则提取IPconfig\n`cmd:xxx`或`shell:xx`命令行提取", "default": "default", "examples": [ "default", "public", 0, 1, - "192\\\\.168\\\\..*", + "regex:192\\\\.168\\\\..*", + "url:https://ipinfo.io/ip", false ] }, "index6": { "$id": "/properties/index6", - "type": [ - "string", - "integer", - "boolean" - ], + "type": ["string", "integer", "boolean"], "title": "IPv6 address Setting", - "description": "本机 IPv6 获取方式:default默认请求IP,public公网,数字表示网卡,正则提取IPconfig", + "description": "本机 IPv6 获取方式:`default`默认请求IP\n`public`公网\n数字表示网卡\n`url:http://myip.com`从URL的返回结果中提取\n`reg:xxx`正则提取IPconfig\n`cmd:xxx`或`shell:xx`命令行提取", "default": "default", "examples": [ "default", "public", 0, 1, - "2404:f801:10:.*", + "regex:2404:f801:10:.*", + "url:https://api6.ipify.org/", false ] }, "proxy": { "$id": "/properties/proxy", - "type": [ - "string", - "null" - ], + "type": ["string", "null"], "title": "HTTP Proxy Setting", "description": "DIRECT表示直连,多个代理分号(;)分割,逐个尝试直到成功", "pattern": "^[a-zA-Z0-9\\-;_:\\.]*$", - "examples": [ - "127.0.0.1:1080;DIRECT" - ], + "examples": ["127.0.0.1:1080;DIRECT"], "default": "null" }, "debug": { @@ -138,10 +111,7 @@ "title": "Enable Debug Mode", "description": "是否启用调试模式显示更多信息", "default": false, - "examples": [ - false, - true - ] + "examples": [false, true] }, "cache": { "$id": "/properties/cache", @@ -149,15 +119,9 @@ "title": "Enable Cache", "description": "是否使用缓存", "default": true, - "examples": [ - false, - true - ] + "examples": [false, true] } }, - "required": [ - "id", - "token" - ], + "required": ["id", "token"], "additionalProperties": false -} \ No newline at end of file +} diff --git a/util/ip.py b/util/ip.py index 6cfcfc8..4b4dc08 100644 --- a/util/ip.py +++ b/util/ip.py @@ -7,10 +7,15 @@ from socket import socket, getaddrinfo, gethostname, AF_INET, AF_INET6, SOCK_DGR from logging import info, debug, error try: # python2 - from urllib2 import urlopen + from urllib2 import urlopen, Request except ImportError: # python3 - from urllib.request import urlopen + from urllib.request import urlopen, Request + +# IPV4正则 +IPV4_REG = r'((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])' +# IPV6正则 +IPV6_REG = r'(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' def default_v4(): # 默认连接外网的ipv4 @@ -41,21 +46,27 @@ def local_v4(i=0): # 本地ipv4地址 return info[int(i)][-1][0] -def public_v4(url="http://v4.ipv6-test.com/api/myip.php"): # 公网IPV4地址 +def _open(url, reg): try: - return urlopen(url, timeout=60).read().decode('utf8') + debug("open: %s", url) + res = urlopen( + Request(url, headers={'User-Agent': 'curl/7.63.0-ddns'}), timeout=60 + ).read().decode('utf8') + debug("response: %s", res) + return compile(reg).search(res).group() except Exception as e: error(e) -def public_v6(url="http://v6.ipv6-test.com/api/myip.php"): # 公网IPV6地址 - try: - return urlopen(url, timeout=60).read().decode('utf8') - except Exception as e: - error(e) +def public_v4(url="https://ipv4.ip.sb", reg=IPV4_REG): # 公网IPV4地址 + return _open(url, reg) -def ip_regex_match(parrent_regex, match_regex): +def public_v6(url="http://ipv6.ip.sb", reg=IPV6_REG): # 公网IPV6地址 + return _open(url, reg) + + +def _ip_regex_match(parrent_regex, match_regex): ip_pattern = compile(parrent_regex) matcher = compile(match_regex) @@ -76,7 +87,7 @@ def regex_v4(reg): # ipv4 正则提取 regex_str = r'IPv4 .*: ((?:\d{1,3}\.){3}\d{1,3})\W' else: regex_str = r'inet (?:addr\:)?((?:\d{1,3}\.){3}\d{1,3})[\s/]' - return ip_regex_match(regex_str, reg) + return _ip_regex_match(regex_str, reg) def regex_v6(reg): # ipv6 正则提取 @@ -84,4 +95,4 @@ def regex_v6(reg): # ipv6 正则提取 regex_str = r'IPv6 .*: ([\:\dabcdef]*)?\W' else: regex_str = r'inet6 (?:addr\:)?([\:\dabcdef]*)?[\s/%]' - return ip_regex_match(regex_str, reg) + return _ip_regex_match(regex_str, reg)