需求
自己有一个树莓派,在家可以拿到公网IPv6地址。
但IPv6地址经常变化,所以需要将IPv6地址映射到域名上。这样后面配置各种服务会方便很多。
参考内容:
[1] 知乎专栏, "基于 Cloudflare DNS API 部署 IPv6 DDNS", https://zhuanlan.zhihu.com/p/69379645
[2] Cloudflare API v4 Documentation, "Update DNS Record", https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record
[3] Cloudflare API v4 Documentation, "List DNS Records", https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records
本文基本上是按照文章[1]做的,只是稍有一些细节的更新。除此之外具体的API细节还参考了官方的API Doc[2, 3]。
需求资源
- 一个域名,并且已经托管到Cloudflare。我们这里假设是
114514.love
。 - 拥有公网IPv6的一个server。我的是一台装好了官方系统的Raspberry Pi 3B。
主要流程
1. 获取相关的Key
进入cloudflare的主页 -> 左侧Websites -> 点击中间的域名,进入域名设置部分。Overview的右侧有一栏是API,在这里看到ZoneID和AccountID。而API Key则需要点击API token的获取,会要求验证密码。
请务必保存好自己的这些Key,并记录下如下内容:
- 你注册Cloudflare的邮箱。例:
senpei@imn.org
- Zone ID。每一个域名为一个Zone,这个ID则代表了是哪个域名下。比如我们假设这里Zone ID是
Sleep-Black_Tea-ZoneID
。 - API token。通过上面Get your API token获取到。我们假设咱们的token是
nnnaaaAAAA!!!-APIToken
。 - 除此之外我们还需要一个DNS Record ID。请参考下面的过程获取到这个ID。我们先假设这个ID是
OneSummerDREAM-RecordID
。
2. 添加AAAA记录并获取其ID
进入cloudflare的主页 -> 左侧Websites -> 点击中间的域名,进入域名设置部分。点击DNS,右侧选择Add record。我们增加一条DNS解析记录。如下图所示(图是P的)。
解释一下每个部分的含义:
- Type:AAAA表示为ipv6的解析。
- Name:这里写了summer,那么我们之后使用域名的时候就是输入
summer.114514.love
。 - Content: 这里先写一个空白的v6地址。之后我们会使用自己的API对其进行修改。
- Proxy Status:把橘红色可以点掉,我们这里只需要它做DNS解析。
- TTL:可以设置一个你认为合适的时间。时间越长,DNS服务更新的就越慢。
搞定了之后,我们需要参考官方API文档[2]里面的内容,使用GET方法获得这个summer.114514.love
所对应的Record ID。你可以使用任何一种你习惯的方式。官方样例里面直接用的是curl。既然我们都在树莓派下是一个linux环境,那么这里就直接运行curl进行结果的获取:
curl -X GET "https://api.cloudflare.com/client/v4/zones/Sleep-Black_Tea-ZoneID/dns_records?type=AAAA&name=summer.114514.love&page=1&per_page=100&order=type&direction=desc&match=all" \
-H "X-Auth-Email: senpei@imn.org" \
-H "X-Auth-Key: nnnaaaAAAA!!!-APIToken" \
-H "Content-Type: application/json"
url里面具体的参数请参考doc里面的说明。总之应该可以拿到一个返回值的结果,结果直接打印在terminal里面会比较乱,但整理之后应该大概长成下面这个样子:
{
"success": true,
"errors": [],
"messages": [],
"result": [
{
"id": "OneSummerDREAM-RecordID",
"zone_id": "Sleep-Black_Tea-ZoneID",
"zone_name": "114514.love",
"name": "summer.114514.love",
"type": "AAAA",
"content": "::1",
... # 以下省略
}
]
}
我们需要的是result下面的id,这个就是该条目的Identifier。请记录下来。
3. 写DNS更新脚本并定时运行
更新现有的DNS条目可以参考官方文档[3]。写一个PUT即可完成。我们本地的脚本需要完成的工作为:
- 获取本机的IPv6地址。
- 调用官方给的API,用PUT更新上去。
- 能跑通后,把这个脚本设成每x分钟运行一次。
当然更优的方式是保存下来IPv6地址,只在变化的时候运行更新脚本。不过我懒了暂时没写这个。由于个人更熟悉Python操作,所以这个脚本我是用的Python写的,放出来仅供参考。Python版本3.6,由于用到了f-string更低的版本请自行修改。
import request
def update_addr(ipv6):
email = 'senpei@imn.org'
zone_id = 'Sleep-Black_Tea-ZoneID'
api_key = 'nnnaaaAAAA!!!-APIToken'
record_id = 'OneSummerDREAM-RecordID'
url_target = f'https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records/{record_id}'
headers = {
'X-Auth-Email': email,
'X-Auth-Key': api_key,
'Content-type': 'application/json',
}
data = {
'type': 'AAAA',
'name': 'blackpi.100097.xyz',
'content': ipv6,
'ttl': 300,
'proxied': False,
}
resp = requests.put(url_target, headers=headers, json=data)
return resp
而其中ipv6的地址则是使用了正则表达式获取:
import os
import re
def get_ipv6():
command = 'ip -6 addr show dev eth0 | grep global'
x = os.popen(command).read()
result = re.findall(r'(([a-f0-9]{1,4}:){7}[a-f0-9]{1,4})', x, re.I)
ipv6 = result[0][0]
return ipv6
以上。